30 KiB
Particle Boron Security Device Troubleshooting Guide
Comprehensive troubleshooting guide for diagnosing and resolving common issues with the ultra-low-power security device system.
🚨 Quick Diagnostic Checklist
Emergency Troubleshooting (Device Not Responding)
□ Check power LED on Boron (should be solid/breathing)
□ Verify battery voltage (>3.0V for operation)
□ Test microswitch manually (should trigger alarm)
□ Check cellular signal strength (>-85dBm preferred)
□ Verify SIM card seating and activation
□ Try safe mode recovery (SETUP+RESET procedure)
System Health Indicators
✅ HEALTHY SYSTEM:
- Status LED: Occasional brief flashes
- Battery reports: Daily via webhook
- Alarm response: <1 second trigger time
- Cellular connection: <60 seconds to connect
- Sleep current: 130μA ± 20μA
⚠️ WARNING SIGNS:
- No daily battery reports for >48 hours
- Alarm delay >5 seconds
- High power consumption (battery drain)
- Frequent connection failures
- Unexpected device resets
🚨 CRITICAL ISSUES:
- No response to manual testing
- Device constantly resetting
- Power consumption >1mA in sleep
- Complete loss of cellular connectivity
- Mechanical failure of sensors/alarm
🔋 Power and Battery Issues
Problem: High Power Consumption
Symptoms:
- Battery draining faster than expected
- Device feels warm to touch
- Sleep current >200μA
Diagnostic Steps:
# 1. Measure sleep current
# Expected: 130μA ± 20μA
# Use μCurrent Gold or similar precision meter
# 2. Check for software issues
particle serial monitor
# Look for continuous output (should be silent in sleep)
# 3. Verify sleep mode entry
# Device should enter STOP mode within 10 seconds of last activity
Common Causes and Solutions:
Serial Interface Left Open:
// ❌ WRONG - Prevents sleep
void setup() {
Serial.begin(9600); // Remove this line!
// rest of setup
}
// ✅ CORRECT - No serial in production
void setup() {
// Serial.begin(9600); // Commented out
// rest of setup
}
Incorrect Pin Configuration:
// ✅ Add to setup() function
void configurePowerOptimalPins() {
// Configure unused pins to prevent floating
pinMode(A0, INPUT_PULLDOWN);
pinMode(A1, INPUT_PULLDOWN);
pinMode(A2, INPUT_PULLDOWN);
pinMode(A3, INPUT_PULLDOWN);
pinMode(A4, INPUT_PULLDOWN);
pinMode(A5, INPUT_PULLDOWN);
pinMode(D0, INPUT_PULLDOWN);
pinMode(D1, INPUT_PULLDOWN);
pinMode(D4, INPUT_PULLDOWN);
pinMode(D5, INPUT_PULLDOWN);
pinMode(D6, INPUT_PULLDOWN);
pinMode(D8, INPUT_PULLDOWN);
// Keep D2 (sensor), D3 (alarm), D7 (status) as configured
}
Stuck in Active Loop:
// ❌ WRONG - Prevents sleep
void loop() {
while (someCondition) {
// Infinite loop prevents sleep
}
}
// ✅ CORRECT - Always allow sleep
void loop() {
if (someCondition) {
// Handle condition
}
// Loop exits, device can sleep
}
Problem: Battery Not Charging (Solar Setup)
Symptoms:
- Battery level decreasing despite solar panel
- Charge controller not showing charging status
Diagnostic Steps:
# 1. Check solar panel voltage
# Expected: 6V+ in direct sunlight
multimeter across panel terminals
# 2. Check charge controller input/output
# Input: Should match panel voltage
# Output: Should be 4.1-4.2V when charging
# 3. Check battery connection
# Ensure JST connector properly seated
# Verify polarity (red=+, black=-)
Solutions:
- Clean solar panel surface
- Check all connections for corrosion
- Verify charge controller wiring
- Test battery capacity with external charger
Problem: Inaccurate Battery Readings
Symptoms:
- Battery percentage jumps unexpectedly
- Reports 0% or >100% charge
Solution:
// Add battery reading validation
float getValidBatteryLevel() {
float reading = System.batteryCharge();
// Filter obviously invalid readings
if (reading < 0 || reading > 100) {
return lastValidReading; // Use previous value
}
// Filter large jumps (>20% change)
if (abs(reading - lastValidReading) > 20) {
return lastValidReading; // Reject sudden changes
}
lastValidReading = reading;
return reading;
}
📡 Cellular and Connectivity Issues
Problem: Device Won't Connect to Cellular
Symptoms:
- No daily battery reports received
- Events show "Connection timeout" in logs
- Cellular LED patterns indicate no connection
Diagnostic Steps:
Check Signal Strength:
# Use Particle CLI to check signal
particle get YOUR_DEVICE_ID signal
# Expected values:
# >-70dBm: Excellent
# -70 to -85dBm: Good
# -85 to -100dBm: Fair
# <-100dBm: Poor (may not connect)
Check SIM Card Status:
# Verify SIM is active
particle sim list
# Check data usage
particle sim usage YOUR_SIM_ID
Test Manual Connection:
// Add to device code for testing
void testCellularConnection() {
Serial.begin(9600);
Serial.println("Testing cellular connection...");
Cellular.on();
Serial.println("Cellular radio on");
waitFor(Cellular.ready, 60000);
if (Cellular.ready()) {
Serial.println("Cellular ready");
CellularSignal signal = Cellular.RSSI();
Serial.printf("Signal: %d dBm\n", signal.getStrength());
Serial.printf("Quality: %d\n", signal.getQuality());
} else {
Serial.println("Cellular failed to connect");
}
}
Common Solutions:
Poor Signal Strength:
- Relocate device to higher position
- Install external cellular antenna
- Use cellular signal booster
- Switch to different carrier if available
SIM Card Issues:
- Reseat SIM card in holder
- Check SIM activation status
- Verify data plan is active
- Replace SIM if damaged
Network Configuration:
// Force specific network settings if needed
void setNetworkParameters() {
// Set APN if required by carrier
Cellular.setActiveSim(EXTERNAL_SIM);
// Set specific bands if needed
// Cellular.setBandSelect("...");
}
Problem: Slow Cellular Connections
Symptoms:
- Connection takes >2 minutes
- High power consumption during connection
- Timeouts during data transfer
Solutions:
Optimize Connection Sequence:
bool fastCellularConnect() {
unsigned long start = millis();
// Enable cellular with timeout
Cellular.on();
if (!waitFor(Cellular.ready, 30000)) {
Serial.println("Cellular radio timeout");
return false;
}
// Connect to Particle cloud with timeout
Particle.connect();
if (!waitFor(Particle.connected, 60000)) {
Serial.println("Cloud connection timeout");
return false;
}
Serial.printf("Connected in %lu seconds\n", (millis() - start) / 1000);
return true;
}
Use Connection Keep-Alive:
void setup() {
// Maintain network registration between sleeps
Particle.keepAlive(120); // 2 minutes
}
Problem: Data Usage Higher Than Expected
Symptoms:
- Monthly data usage >10MB
- Carrier data overage charges
- Frequent connection events
Analysis:
# Check Particle data usage
particle sim usage YOUR_SIM_ID
# Review webhook frequency
# Should be 1-2 events per day normally
Solutions:
Reduce Message Size:
// Compact data format
String createCompactAlert() {
// Before: "Type:SECURITY_BREACH|Description:Motion detected|Battery:85.2%|Signal:-45dBm"
// After: "T:BREACH|D:Motion|B:85|S:-45"
return String::format("T:%s|D:%s|B:%d|S:%d",
getAlertTypeCode(),
getShortDescription(),
(int)System.batteryCharge(),
Cellular.RSSI().getStrength()
);
}
Batch Multiple Events:
void batchEventReporting() {
static String eventBuffer = "";
eventBuffer += createEventData() + ";";
// Send when buffer reaches size limit or time limit
if (eventBuffer.length() > 200 || shouldSendBatch()) {
Particle.publish("Batch_Events", eventBuffer, PRIVATE);
eventBuffer = "";
}
}
🔧 Hardware Issues
Problem: Microswitch Not Triggering
Symptoms:
- No alarm when switch is manually opened
- Security breaches not detected
- Switch reads same value regardless of position
Diagnostic Steps:
Test Switch Continuity:
# Use multimeter to test switch
# Closed position: 0Ω resistance
# Open position: ∞Ω (no continuity)
Test Boron Input:
// Add diagnostic code
void testMicroswitchInput() {
Serial.begin(9600);
while (true) {
bool switchState = digitalRead(MICROSWITCH_PIN);
Serial.printf("Switch state: %s\n", switchState ? "CLOSED" : "OPEN");
delay(500);
}
}
Common Issues and Solutions:
Wiring Error:
✅ CORRECT NC WIRING:
Microswitch Common → D2 (Boron)
Microswitch NC → GND (Boron)
❌ INCORRECT (NO/Normal Open):
Microswitch Common → D2 (Boron)
Microswitch NO → GND (Boron)
Mechanical Issues:
- Check switch mounting alignment
- Verify actuator travel distance
- Lubricate switch if sticky
- Replace switch if worn out
Electrical Issues:
- Check for loose connections
- Verify wire gauge (22-18 AWG recommended)
- Test for electrical noise/interference
- Add hardware debouncing if needed
Problem: Alarm Not Activating
Symptoms:
- Switch triggers detected but no alarm sound
- Alarm device doesn't activate
- D3 pin voltage incorrect
Diagnostic Steps:
Test GPIO Output:
void testAlarmOutput() {
Serial.begin(9600);
Serial.println("Testing alarm output...");
// Test D3 voltage
digitalWrite(ALARM_PIN, HIGH);
Serial.println("D3 should be 3.3V - measure with multimeter");
delay(5000);
digitalWrite(ALARM_PIN, LOW);
Serial.println("D3 should be 0V - measure with multimeter");
delay(5000);
}
Check Driver Circuit:
For transistor driver circuit:
1. Measure base voltage (should be 3.3V when D3=HIGH)
2. Check transistor collector voltage (should be ~0V when ON)
3. Verify alarm device voltage across terminals
4. Test transistor with known good component
Common Solutions:
Driver Circuit Issues:
Component Checklist:
□ 2N2222 transistor (or equivalent NPN)
□ 1kΩ base resistor
□ Proper ground connections
□ Adequate current rating for alarm device
Voltage Tests:
□ D3 output: 0V (LOW) / 3.3V (HIGH)
□ Base voltage: 0V (OFF) / 3.3V (ON)
□ Collector: VIN (OFF) / ~0V (ON)
□ Emitter: Always 0V (GND)
Alarm Device Issues:
- Check power requirements vs available current
- Verify voltage compatibility
- Test alarm device independently
- Check for blown fuse in alarm circuit
Problem: Status LED Behavior Issues
Symptoms:
- LED constantly on/off
- Unexpected flash patterns
- LED not responding to events
Normal LED Patterns:
Startup: 3 slow blinks (500ms each)
Security Breach: 5 rapid blinks (100ms each)
Daily Report: 2 medium blinks (200ms each)
Cellular Connect: Alternating during connection
Success: 2 quick blinks (100ms each)
Error: 10 rapid blinks (50ms each)
Diagnostic Code:
void testStatusLED() {
Serial.begin(9600);
Serial.println("Testing status LED patterns...");
// Test each pattern
flashStatusLED(3, 500); // Startup pattern
delay(2000);
flashStatusLED(5, 100); // Breach pattern
delay(2000);
flashStatusLED(2, 200); // Report pattern
}
🌐 Webhook and Server Issues
Problem: Webhook Not Receiving Events
Symptoms:
- Particle Console shows events published
- No notifications received
- Webhook service logs show no activity
Diagnostic Steps:
Test Particle Event Publishing:
# Check if device is publishing events
particle subscribe YOUR_DEVICE_ID
# Manually trigger test event
particle publish "Security Alert" "Type:TEST|Desc:Manual test" --private
Test Webhook Endpoint:
# Test webhook health
curl https://webhook.yourdomain.com/health
# Test webhook with manual POST
curl -X POST https://webhook.yourdomain.com/webhook \
-H "Content-Type: application/json" \
-H "User-Agent: ParticleBot/1.0" \
-H "Authorization: Bearer YOUR_PARTICLE_SECRET" \
-d '{"event":"Security Alert","data":"Type:TEST|Desc:Manual webhook test","published_at":"2024-01-07T12:00:00Z","coreid":"test","device_name":"Test Device"}'
Check Webhook Configuration:
Particle Console Webhook Settings:
{
"event": "Security Alert",
"url": "https://webhook.yourdomain.com/webhook",
"headers": {
"Authorization": "Bearer YOUR_SECRET_HERE",
"Content-Type": "application/json",
"User-Agent": "ParticleBot/1.0"
}
}
Common Solutions:
Authentication Issues:
# Verify webhook secret matches
docker exec webhook-service env | grep PARTICLE_WEBHOOK_SECRET
# Check webhook service logs
docker compose logs webhook-service | grep -i auth
SSL/TLS Issues:
# Test SSL certificate
openssl s_client -connect webhook.yourdomain.com:443
# Check certificate expiration
curl -vI https://webhook.yourdomain.com/health
Network Connectivity:
# Test from external network
curl -I https://webhook.yourdomain.com/health
# Check DNS resolution
nslookup webhook.yourdomain.com
Problem: Notifications Not Being Sent
Symptoms:
- Webhook receives events successfully
- No email/SMS notifications received
- Webhook logs show email errors
Diagnostic Steps:
Test SMTP Configuration:
# Test Gmail SMTP from webhook container
docker exec webhook-service python3 -c "
import smtplib
import os
try:
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as server:
server.login(os.environ['SMTP_EMAIL'], os.environ['SMTP_PASSWORD'])
print('SMTP connection successful')
except Exception as e:
print(f'SMTP error: {e}')
"
Common Solutions:
Gmail Authentication Issues:
Common Problems:
□ Using regular password instead of app password
□ App password contains spaces (remove them)
□ 2FA not enabled on Google account
□ App password expired or revoked
Solution:
1. Enable 2FA on Google account
2. Generate new app password at https://myaccount.google.com/apppasswords
3. Use 16-character app password (no spaces)
4. Update .env file with new password
SMS Gateway Issues:
Common Carrier Gateways:
□ Verizon: number@vtext.com
□ AT&T: number@txt.att.net
□ T-Mobile: number@tmomail.net
□ Sprint: number@messaging.sprintpcs.com
Test SMS Gateway:
1. Send test email to your SMS gateway address
2. Verify format: 10-digit number (no dashes/spaces)
3. Check carrier-specific limitations
🔄 Device Reset and Recovery
Safe Mode Recovery
When to Use:
- Device constantly resetting
- Firmware appears corrupted
- Device not responding to OTA updates
Procedure:
# Enter safe mode
1. Hold SETUP button
2. Press and release RESET button (while holding SETUP)
3. Continue holding SETUP until LED breathes magenta
4. Release SETUP button
# Device is now in safe mode (breathing magenta)
# Flash firmware via CLI
particle flash YOUR_DEVICE_ID security_device.ino --target 5.8.0
DFU Mode Recovery
When to Use:
- Safe mode doesn't work
- Device completely unresponsive
- Need to flash system firmware
Procedure:
# Enter DFU mode
1. Hold SETUP and RESET buttons
2. Release RESET while continuing to hold SETUP
3. Wait for LED to blink yellow rapidly
4. Release SETUP button
# Device is now in DFU mode (yellow blinking)
# Flash tinker firmware to reset
particle flash --usb tinker
# Then flash your application
particle flash YOUR_DEVICE_ID security_device.ino
Factory Reset
Complete Device Reset:
# Clear all user firmware and data
particle device doctor YOUR_DEVICE_ID
# This will:
# - Reset device keys
# - Clear user firmware
# - Reset to factory state
# - Require device re-claiming
🔍 Advanced Diagnostics
Real-Time Monitoring Setup
Hardware Debug Setup:
Equipment Needed:
□ Logic analyzer or oscilloscope
□ μCurrent Gold (current measurement)
□ Multimeter
□ USB-to-serial adapter
□ Jumper wires and test probes
Monitoring Points:
□ VIN: Power supply voltage
□ D2: Microswitch state changes
□ D3: Alarm output signal
□ D7: Status LED activity
□ TX/RX: Serial debug output (if enabled)
Software Debug Mode:
// Enable comprehensive debugging (REMOVE in production)
#define DEBUG_MODE
#ifdef DEBUG_MODE
void debugLog(String component, String message) {
String timestamp = String(millis());
Serial.println(timestamp + " [" + component + "] " + message);
}
void debugSystemState() {
debugLog("POWER", "Battery: " + String(System.batteryCharge()) + "%");
debugLog("NETWORK", "Signal: " + String(Cellular.RSSI().getStrength()) + "dBm");
debugLog("GPIO", "D2: " + String(digitalRead(D2)) + ", D3: " + String(digitalRead(D3)));
debugLog("MEMORY", "Free RAM: " + String(System.freeMemory()) + " bytes");
debugLog("SYSTEM", "Uptime: " + String(millis() / 1000) + " seconds");
}
#else
#define debugLog(component, message)
#define debugSystemState()
#endif
Performance Profiling
Power Consumption Profiling:
void profilePowerConsumption() {
unsigned long start, duration;
// Profile cellular connection
start = millis();
Cellular.on();
waitFor(Cellular.ready, 60000);
duration = millis() - start;
debugLog("PROFILE", "Cellular ready: " + String(duration) + "ms");
// Profile cloud connection
start = millis();
Particle.connect();
waitFor(Particle.connected, 60000);
duration = millis() - start;
debugLog("PROFILE", "Cloud connected: " + String(duration) + "ms");
// Profile event publishing
start = millis();
Particle.publish("Test", "data", PRIVATE);
duration = millis() - start;
debugLog("PROFILE", "Event published: " + String(duration) + "ms");
}
Memory Usage Monitoring:
void monitorMemoryUsage() {
static unsigned long lastCheck = 0;
static int minFreeMemory = 999999;
if (millis() - lastCheck > 10000) { // Check every 10 seconds
int freeMemory = System.freeMemory();
if (freeMemory < minFreeMemory) {
minFreeMemory = freeMemory;
}
debugLog("MEMORY", "Free: " + String(freeMemory) +
", Min: " + String(minFreeMemory) + " bytes");
lastCheck = millis();
}
}
Log Analysis and Pattern Detection
Event Pattern Analysis:
# Python script to analyze webhook logs
import re
import json
from datetime import datetime
from collections import defaultdict
def analyze_webhook_logs(log_file):
events = defaultdict(list)
power_data = []
with open(log_file, 'r') as f:
for line in f:
# Parse timestamp and event type
if 'Received webhook:' in line:
timestamp = extract_timestamp(line)
event_data = extract_event_data(line)
events[event_data['type']].append(timestamp)
if 'Batt:' in line:
battery = extract_battery_level(line)
power_data.append((timestamp, battery))
# Analyze patterns
print(f"Security breaches: {len(events['SECURITY_BREACH'])}")
print(f"Daily reports: {len(events['DAILY_BATTERY_REPORT'])}")
print(f"Average time between breaches: {calculate_average_interval(events['SECURITY_BREACH'])}")
# Battery trend analysis
if len(power_data) > 10:
battery_trend = calculate_battery_trend(power_data)
print(f"Battery drain rate: {battery_trend:.2f}% per day")
def extract_battery_level(line):
match = re.search(r'Batt:(\d+\.?\d*)%', line)
return float(match.group(1)) if match else None
# Usage: python analyze_logs.py webhook.log
Network Diagnostics
Cellular Network Analysis:
void analyzeCellularNetwork() {
CellularSignal signal = Cellular.RSSI();
CellularData data = Cellular.getDataUsage();
debugLog("CELLULAR", "Provider: " + Cellular.getOperator());
debugLog("CELLULAR", "Technology: " + String(Cellular.getTechnology()));
debugLog("CELLULAR", "Signal Strength: " + String(signal.getStrength()) + " dBm");
debugLog("CELLULAR", "Signal Quality: " + String(signal.getQuality()));
debugLog("CELLULAR", "Data Used: " + String(data.tx_session + data.rx_session) + " bytes");
// Test connection speed
unsigned long start = millis();
if (Particle.publish("Speed_Test", "test", PRIVATE)) {
unsigned long latency = millis() - start;
debugLog("CELLULAR", "Publish latency: " + String(latency) + "ms");
}
}
DNS and Connectivity Testing:
void testConnectivity() {
// Test different endpoints
String endpoints[] = {
"api.particle.io",
"device.spark.io",
"google.com",
"webhook.yourdomain.com"
};
for (String endpoint : endpoints) {
unsigned long start = millis();
TCPClient client;
if (client.connect(endpoint, 80)) {
unsigned long connectionTime = millis() - start;
debugLog("CONNECTIVITY", endpoint + " connected in " + String(connectionTime) + "ms");
client.stop();
} else {
debugLog("CONNECTIVITY", endpoint + " connection failed");
}
}
}
📊 Preventive Maintenance
Weekly Automated Checks
Device Self-Test Routine:
bool performWeeklyHealthCheck() {
bool allTestsPassed = true;
// Test 1: Battery level check
float battery = System.batteryCharge();
if (battery < 20.0) {
publishAlert("MAINTENANCE", "Low battery: " + String(battery) + "%");
allTestsPassed = false;
}
// Test 2: Cellular signal strength
int signal = Cellular.RSSI().getStrength();
if (signal < -90) {
publishAlert("MAINTENANCE", "Weak signal: " + String(signal) + "dBm");
allTestsPassed = false;
}
// Test 3: Memory usage check
int freeMemory = System.freeMemory();
if (freeMemory < 10000) {
publishAlert("MAINTENANCE", "Low memory: " + String(freeMemory) + " bytes");
allTestsPassed = false;
}
// Test 4: Switch operation test
bool switchState = digitalRead(MICROSWITCH_PIN);
// Record for trend analysis
// Test 5: Alarm circuit test (brief pulse)
digitalWrite(ALARM_PIN, HIGH);
delay(100);
digitalWrite(ALARM_PIN, LOW);
if (allTestsPassed) {
publishAlert("MAINTENANCE", "Weekly health check: PASS");
}
return allTestsPassed;
}
Monthly Maintenance Tasks
Automated Maintenance Reports:
# Server-side maintenance analysis
def generate_monthly_report(device_id, start_date, end_date):
"""Generate comprehensive device health report"""
events = fetch_device_events(device_id, start_date, end_date)
report = {
'device_id': device_id,
'period': f"{start_date} to {end_date}",
'statistics': analyze_device_statistics(events),
'battery_health': analyze_battery_trend(events),
'connectivity': analyze_connectivity_stats(events),
'security_events': count_security_events(events),
'maintenance_needed': identify_maintenance_needs(events),
'recommendations': generate_recommendations(events)
}
return report
def identify_maintenance_needs(events):
"""Identify potential maintenance requirements"""
needs = []
# Check battery degradation
battery_trend = calculate_battery_trend(events)
if battery_trend > 2.0: # >2% per day indicates issues
needs.append("Battery replacement recommended")
# Check false alarm rate
false_alarm_rate = calculate_false_alarm_rate(events)
if false_alarm_rate > 0.1: # >10% false alarms
needs.append("Sensor calibration needed")
# Check connectivity issues
connection_success_rate = calculate_connection_success_rate(events)
if connection_success_rate < 0.95: # <95% success
needs.append("Cellular antenna check recommended")
return needs
Predictive Maintenance
Early Warning System:
void predictiveMaintenance() {
static float batteryHistory[30]; // 30-day history
static int historyIndex = 0;
static bool historyFull = false;
// Record daily battery level
float currentBattery = System.batteryCharge();
batteryHistory[historyIndex] = currentBattery;
historyIndex = (historyIndex + 1) % 30;
if (historyIndex == 0) historyFull = true;
if (historyFull) {
// Calculate battery drain trend
float trend = calculateLinearTrend(batteryHistory, 30);
// Predict battery life remaining
float daysRemaining = currentBattery / abs(trend);
if (daysRemaining < 90) { // Less than 3 months
publishAlert("PREDICTIVE", "Battery replacement needed in " +
String((int)daysRemaining) + " days");
}
}
}
float calculateLinearTrend(float data[], int length) {
// Simple linear regression to find trend
float sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0;
for (int i = 0; i < length; i++) {
sumX += i;
sumY += data[i];
sumXY += i * data[i];
sumX2 += i * i;
}
float slope = (length * sumXY - sumX * sumY) / (length * sumX2 - sumX * sumX);
return slope; // % per day
}
🔧 Field Repair Procedures
Emergency Field Diagnostics
Minimal Equipment Diagnostics:
Required Tools:
□ Multimeter
□ Small screwdriver set
□ Spare battery (charged)
□ Mobile phone with Particle app
Quick Tests (5 minutes):
1. Check battery voltage (>3.0V)
2. Test microswitch continuity
3. Verify alarm device operation
4. Check cellular signal strength via Particle app
5. Attempt manual event trigger
Field Diagnostic Checklist:
□ Visual inspection for physical damage
□ Check all wire connections for looseness
□ Verify enclosure seal integrity
□ Test battery voltage under load
□ Check for signs of water ingress
□ Verify antenna connections (if external)
□ Test switch mechanical operation
□ Check for insect/rodent interference
Remote Diagnostic Commands
Emergency Remote Access:
# Check device vitals
particle get YOUR_DEVICE_ID vitals
# Force connection test
particle function call YOUR_DEVICE_ID testConnection
# Get detailed diagnostics
particle function call YOUR_DEVICE_ID systemDiagnostics
# Force immediate battery report
particle function call YOUR_DEVICE_ID forceBatteryReport
Remote Recovery Commands:
# Safe restart
particle function call YOUR_DEVICE_ID safeRestart
# Force sleep mode
particle function call YOUR_DEVICE_ID forceSleep
# Emergency OTA update
particle flash YOUR_DEVICE_ID firmware_recovery.ino
# Factory reset (last resort)
particle device doctor YOUR_DEVICE_ID
📋 Troubleshooting Decision Tree
Device Issue Reported
│
▼
Is device responsive?
┌─NO─┐ ┌─YES─┐
│ │ │ │
▼ │ ▼ │
Power Check Check specific symptom
│ │ │ │
│ │ ▼ │
│ │ Network Issue?
│ │ ┌─YES─┐ ┌─NO─┐
│ │ │ │ │ │
│ │ ▼ │ ▼ │
│ │ Cellular │Hardware│
│ │Diagnostic│ Check │
│ │ │ │ │ │
│ │ ▼ │ ▼ │
│ │ Signal │Sensor │
│ │ Test │ Test │
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
Replace Check Fix Test Replace
Battery Power Network Switch Component
│ Supply │ │ │
▼ │ ▼ ▼ ▼
Test │ Restart Reset Test
Device ▼ Device System Function
│ Replace │ │ │
▼ Hardware ▼ ▼ ▼
Functional? Works? Works? Works?
│ │ │ │
▼ ▼ ▼ ▼
SUCCESS SUCCESS SUCCESS SUCCESS
📞 Support Escalation
When to Escalate
Level 1: Self-Service (User)
- Basic connectivity issues
- Simple configuration changes
- Battery replacement
- Environmental factors
Level 2: Technical Support
- Persistent connectivity issues
- Hardware component failures
- Firmware corruption
- Complex network problems
Level 3: Engineering Support
- Design modifications needed
- Systematic reliability issues
- Performance optimization
- Custom firmware requirements
Information to Gather Before Escalation
Device Information:
□ Device ID and name
□ Firmware version
□ Hardware revision
□ SIM card ID
□ Installation date
□ Last known working state
□ Environmental conditions
Issue Documentation:
□ Detailed symptom description
□ Frequency of occurrence
□ Steps already attempted
□ Error messages observed
□ Timeline of events
□ Impact on operations
Diagnostic Data:
□ Power consumption measurements
□ Signal strength readings
□ Event logs from webhook
□ Photos of hardware setup
□ Particle Console screenshots
□ Network configuration details
🔍 Quick Reference Summary:
Emergency Contacts:
- Device Issues: Check Particle Community Forum
- Server Issues: Check webhook service logs
- Hardware Issues: Consult wiring diagrams
- Network Issues: Test with Particle CLI
Most Common Issues:
- High power consumption → Check for Serial.begin() in code
- No cellular connection → Check signal strength and SIM status
- Switch not triggering → Verify NC wiring configuration
- No notifications → Check webhook authentication
- Device not sleeping → Remove debug code and configure pins
Recovery Procedures:
- Safe mode: SETUP+RESET → breathing magenta
- DFU mode: SETUP+RESET → yellow blinking
- Factory reset: particle device doctor
- OTA recovery: particle flash via CLI