LED Status Indicators
Esta página aún no está disponible en tu idioma.
LED Status Indicators
Overview
Section titled “Overview”This section covers the LED indicator system that provides visual feedback for the RFID-based check-in/check-out operations. Learning this section will enable you to:
- Design and implement LED status indicators for user feedback
- Handle different LED states (check-in, check-out, error, ready)
- Implement MQTT-controlled LED patterns
- Troubleshoot common LED circuit issues
Prerequisites
Section titled “Prerequisites”Before starting this section, ensure you have:
- LED circuit wired per 05-02
- MQTT communication between ESP32 and Node-RED working
- Check-in/check-out flow implemented (05-08)
- Basic understanding of ESP32 GPIO control
Key Concepts
Section titled “Key Concepts”LED Color Meanings
Section titled “LED Color Meanings”The system uses two LEDs to convey the current state:
| LED Color | State | Meaning |
|---|---|---|
| Green ON | Check-in success | Tag registered, time recording started |
| Red ON | Check-out success | Time recorded in TimeTagger |
| Green blink | System ready | ESP32 connected and waiting |
| Red blink | Error | Connection issue or API failure |
| Both OFF | Deep sleep or idle | No activity or power saving |
User Experience Flow
Section titled “User Experience Flow”User Experience Timeline:1. User approaches reader → Both LEDs OFF (idle)2. User taps RFID tag → Momentary pause3. ✓ Check-in confirmed → GREEN LED for 3 seconds4. User leaves → LEDs OFF5. User returns, taps again → Momentary pause6. ✓ Check-out confirmed → RED LED for 3 seconds7. Recording saved → Quick blink, then OFFImplementation Steps
Section titled “Implementation Steps”Step 1: LED Pin Configuration
Section titled “Step 1: LED Pin Configuration”// LED Pin Definitions#define LED_GREEN 22#define LED_RED 21
// LED Timing Constantsconst unsigned long LED_INDICATE_TIME = 3000; // 3 secondsconst unsigned long BLINK_INTERVAL = 250; // 250ms for blinkingStep 2: LED Control Functions
Section titled “Step 2: LED Control Functions”// LED State Managementenum LEDState { LED_OFF, LED_GREEN_ON, LED_RED_ON, LED_GREEN_BLINK, LED_RED_BLINK, LED_BOTH_BLINK};
LEDState currentLEDState = LED_OFF;unsigned long ledStateStartTime = 0;
void setLED(LEDState state) { currentLEDState = state; ledStateStartTime = millis();
switch (state) { case LED_OFF: digitalWrite(LED_GREEN, LOW); digitalWrite(LED_RED, LOW); break;
case LED_GREEN_ON: digitalWrite(LED_GREEN, HIGH); digitalWrite(LED_RED, LOW); break;
case LED_RED_ON: digitalWrite(LED_GREEN, LOW); digitalWrite(LED_RED, HIGH); break;
case LED_GREEN_BLINK: case LED_RED_BLINK: case LED_BOTH_BLINK: // Blinking is handled in the main loop break; }}
void updateLED() { unsigned long now = millis();
switch (currentLEDState) { case LED_GREEN_ON: case LED_RED_ON: // Auto-turn off after indication time if (now - ledStateStartTime >= LED_INDICATE_TIME) { setLED(LED_OFF); } break;
case LED_GREEN_BLINK: // Blink green (system ready indicator) if ((now / BLINK_INTERVAL) % 2 == 0) { digitalWrite(LED_GREEN, HIGH); } else { digitalWrite(LED_GREEN, LOW); } break;
case LED_RED_BLINK: // Blink red (error indicator) if ((now / BLINK_INTERVAL) % 2 == 0) { digitalWrite(LED_RED, HIGH); } else { digitalWrite(LED_RED, LOW); } break;
case LED_BOTH_BLINK: // Alternate blink (system starting) if ((now / BLINK_INTERVAL) % 2 == 0) { digitalWrite(LED_GREEN, HIGH); digitalWrite(LED_RED, LOW); } else { digitalWrite(LED_GREEN, LOW); digitalWrite(LED_RED, HIGH); } break;
case LED_OFF: default: // Do nothing — LEDs stay off break; }}Step 3: LED Feedback on MQTT Messages
Section titled “Step 3: LED Feedback on MQTT Messages”The ESP32 listens for MQTT feedback from Node-RED and updates LEDs accordingly:
void setup() { pinMode(LED_GREEN, OUTPUT); pinMode(LED_RED, OUTPUT);
// Startup indication setLED(LED_BOTH_BLINK);
// ... rest of setup
// Ready indication setLED(LED_GREEN_BLINK); // Blinking green = system ready}
// MQTT callback for feedbackvoid callback(char* topic, byte* payload, unsigned int length) { // Parse the message String message; for (int i = 0; i < length; i++) { message += (char)payload[i]; }
Serial.print("Feedback received: "); Serial.println(message);
// Parse JSON DynamicJsonDocument doc(256); DeserializationError error = deserializeJson(doc, message);
if (error) { Serial.println("JSON parse error"); setLED(LED_RED_BLINK); return; }
String action = doc["action"] | ""; bool success = doc["success"] | true;
if (success) { if (action == "CHECK_IN") { // Green = checked in setLED(LED_GREEN_ON); Serial.println("✓ Check-in successful"); } else if (action == "CHECK_OUT") { // Red = checked out setLED(LED_RED_ON); Serial.println("✓ Check-out successful"); } } else { // Error state setLED(LED_RED_BLINK); Serial.print("✗ Operation failed: "); Serial.println(doc["error"].as<String>()); }}Step 4: Connection Status Indication
Section titled “Step 4: Connection Status Indication”Indicate WiFi and MQTT connection status through LED patterns:
void setup() { // Startup sequence setLED(LED_BOTH_BLINK);
// Connect to WiFi WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); // Rapid blink during connection attempt digitalWrite(LED_GREEN, !digitalRead(LED_GREEN)); }
// WiFi connected → blink green setLED(LED_GREEN_BLINK);
// Connect to MQTT client.setServer(mqtt_server, 1883); while (!client.connected()) { if (client.connect("ESP32_RFID")) { // MQTT connected → solid brief green setLED(LED_GREEN_ON); delay(500); } else { delay(2000); } }
// System ready setLED(LED_GREEN_BLINK); // Slow blink = waiting for tags}Step 5: Complete LED Management Class
Section titled “Step 5: Complete LED Management Class”For cleaner code organization:
class LEDManager {private: int greenPin; int redPin; LEDState currentState; unsigned long stateStartTime; unsigned long indicationDuration;
public: LEDManager(int gp, int rp) : greenPin(gp), redPin(rp) { pinMode(greenPin, OUTPUT); pinMode(redPin, OUTPUT); currentState = LED_OFF; stateStartTime = 0; indicationDuration = 3000; }
void indicateCheckIn() { setState(LED_GREEN_ON); }
void indicateCheckOut() { setState(LED_RED_ON); }
void indicateError() { setState(LED_RED_BLINK); }
void indicateReady() { setState(LED_GREEN_BLINK); }
void indicateStartup() { setState(LED_BOTH_BLINK); }
void turnOff() { setState(LED_OFF); }
void update() { unsigned long now = millis();
switch (currentState) { case LED_GREEN_ON: case LED_RED_ON: if (now - stateStartTime >= indicationDuration) { turnOff(); } break;
case LED_GREEN_BLINK: if ((now / 250) % 2 == 0) { digitalWrite(greenPin, HIGH); digitalWrite(redPin, LOW); } else { digitalWrite(greenPin, LOW); } break;
case LED_RED_BLINK: if ((now / 250) % 2 == 0) { digitalWrite(redPin, HIGH); digitalWrite(greenPin, LOW); } else { digitalWrite(redPin, LOW); } break;
case LED_BOTH_BLINK: if ((now / 150) % 2 == 0) { digitalWrite(greenPin, HIGH); digitalWrite(redPin, LOW); } else { digitalWrite(greenPin, LOW); digitalWrite(redPin, HIGH); } break;
case LED_OFF: default: digitalWrite(greenPin, LOW); digitalWrite(redPin, LOW); break; } }
private: void setState(LEDState state) { currentState = state; stateStartTime = millis(); }};
// Global instanceLEDManager leds(LED_GREEN, LED_RED);Step 6: Node-RED Side Feedback Generation
Section titled “Step 6: Node-RED Side Feedback Generation”The Node-RED flow sends MQTT feedback messages to control the LEDs:
// Function Node: "Generate LED Feedback"// Creates appropriate feedback message based on operation result
const uid = msg.payload?.uid || "UNKNOWN";const operation = msg.action || "UNKNOWN";const success = msg.success !== false;
if (success) { if (operation === "CHECK_IN") { msg.payload = { action: "CHECK_IN", success: true, name: msg.record?.ds || uid, message: "Time recording started" }; } else if (operation === "CHECK_OUT") { msg.payload = { action: "CHECK_OUT", success: true, name: msg.record?.ds || uid, duration: (msg.record?.t2 - msg.record?.t1) || 0, message: "Time recorded successfully" }; }} else { msg.payload = { action: "ERROR", success: false, uid: uid, error: msg.error || "Unknown error", message: "Operation failed" };}
msg.topic = "asset/tracking/feedback";msg.retain = false;
return msg;Verification
Section titled “Verification”Test the LED system:
// 1. Power on the ESP32// Expected: Both LEDs alternate blink during startup// Then: Green LED blinks slowly (system ready)
// 2. Scan a registered RFID tag (first time)// Expected: Green LED ON for 3 seconds (check-in)
// 3. Scan the same tag again// Expected: Red LED ON for 3 seconds (check-out)
// 4. Disconnect WiFi temporarily// Expected: Red LED blinks (connection error)
// 5. Reconnect WiFi// Expected: Green LED blinks (system ready)Verification Checklist:
- Startup sequence: both LEDs blink
- System ready: green LED slow blink
- Check-in: green LED solid for 3 seconds
- Check-out: red LED solid for 3 seconds
- Error: red LED blink
- WiFi connected: green LED pattern
- WiFi lost: red LED pattern
Troubleshooting
Section titled “Troubleshooting”Issue 1: LEDs Too Dim
Section titled “Issue 1: LEDs Too Dim”Symptom: LEDs barely visible even in indoor lighting
Cause: Resistor value too high
Solution:
// Try lower resistor values:// For 10mA current:// R = (3.3V - 2.0V) / 0.01A = 130Ω → Use 150Ω
// For 15mA (max recommended):// R = (3.3V - 2.0V) / 0.015A = 87Ω → Use 100ΩIssue 2: LEDs Too Bright
Section titled “Issue 2: LEDs Too Bright”Symptom: LEDs are uncomfortably bright
Solution: Increase resistor value or use PWM for software brightness control:
// Software brightness control using PWMvoid setLEDBrightness(int pin, int brightness) { // brightness: 0-255 analogWrite(pin, brightness);}
// Use in setup:// ledcSetup(0, 5000, 8); // Channel 0, 5kHz, 8-bit// ledcAttachPin(LED_GREEN, 0);// ledcWrite(0, 128); // 50% brightnessIssue 3: Wrong LED Lights Up
Section titled “Issue 3: Wrong LED Lights Up”Symptom: Green LED lights up for check-out instead of check-in
Cause: LED wiring reversed (cathode/anode swapped) or code logic error
Solution:
// Verify wiring: LED anode (+) → GPIO via resistor → LED cathode (-) → GND// Check with multimeter: GPIO HIGH should light the LED
// If reversed:// digitalWrite(pin, HIGH) → OFF (if LED wired reversed)// digitalWrite(pin, LOW) → ON// Swap in code:// #define LED_ON LOW// #define LED_OFF HIGHBest Practices
Section titled “Best Practices”- ✅ Recommended: Use consistent LED meanings (green = good, red = bad)
- ✅ Recommended: Include startup test sequence so users know both LEDs work
- ✅ Recommended: Use non-blocking LED control (
millis()instead ofdelay()) - ❌ Avoid: Using
delay()in the LED control code (blocks other operations) - ❌ Avoid: Driving LEDs at maximum current — 10mA is sufficient for indication
Summary
Section titled “Summary”- Green LED: System ready (blink), check-in success (3s solid)
- Red LED: Error (blink), check-out success (3s solid)
- Non-blocking control: Use
millis()timers, notdelay() - MQTT feedback: Node-RED publishes LED commands to
asset/tracking/feedback - Startup sequence: verify both LEDs are functional at power-on
References
Section titled “References”Writing Date: 2026-05-17
Based on Source File: 校正版/10 Time recording witht RFID und TimeTagger.md
Target Audience: Alibaba.com IoT Pre-sales Engineer
Status: ✅ Completed
We provide ESP32 ODM design-to-manufacturing services. From prototype to production — the team behind this tutorial can build it with you.
Talk to us →