#include #include #include // ========================= // LED / Button configuration // ========================= #define STATUS_LED_PIN 1 #define LED_PIN 6 #define BUTTON_PIN A0 #define NUM_LEDS 144 #define LED_TYPE WS2812B #define COLOR_ORDER GRB // ========================= // Brightness // 70% of 255 = 178.5 -> 179 // ========================= constexpr uint8_t MAX_BRIGHTNESS = 179; // ========================= // Timing // ========================= constexpr unsigned long PRINT_INTERVAL = 1000; constexpr unsigned long DEBOUNCE_TIME = 50; // ========================= // LED buffer // ========================= CRGB leds[NUM_LEDS]; // ========================= // Stored RGB values // These are the values that are // currently stored from received packets // and will be shown on button press // ========================= uint8_t RED = 0; uint8_t GREEN = 0; uint8_t BLUE = 0; // ========================= // Last received packet values // (for debug / transparency) // ========================= uint8_t lastRxValue1 = 0; uint8_t lastRxValue2 = 0; uint8_t lastRxValue3 = 0; bool lastRxValid1 = false; bool lastRxValid2 = false; bool lastRxValid3 = false; // ========================= // Receive state / debug // ========================= bool newPacketReceived = false; unsigned long packetCounter = 0; unsigned long lastPrintTime = 0; // ========================= // Button state // INPUT_PULLUP: // released = HIGH // pressed = LOW // ========================= bool lastButtonReading = HIGH; bool stableButtonState = HIGH; unsigned long lastDebounceTime = 0; // ========================= // Data packet from master // Must match the sender struct exactly // ========================= struct DataPacket { uint8_t valid1; uint8_t valid2; uint8_t valid3; uint8_t value1; uint8_t value2; uint8_t value3; }; // ========================= // Status LED blink request // We only set a flag in callbacks // and blink later in loop() // ========================= bool blinkRequest = false; // ========================= // Helper: print MAC address // ========================= void printMacAddress(const uint8_t* mac) { for (int i = 0; i < 6; i++) { if (mac[i] < 16) Serial.print("0"); Serial.print(mac[i], HEX); if (i < 5) Serial.print(":"); } Serial.println(); } // ========================= // Update LED strip // ========================= void updateLEDs() { fill_solid(leds, NUM_LEDS, CRGB(RED, GREEN, BLUE)); FastLED.show(); } // ========================= // Short visual feedback // ========================= void runStatusBlinkIfRequested() { if (!blinkRequest) { return; } blinkRequest = false; digitalWrite(STATUS_LED_PIN, HIGH); delay(80); digitalWrite(STATUS_LED_PIN, LOW); } // ========================= // ESP-NOW receive callback // Keep this short // ========================= void onDataRecv(const esp_now_recv_info_t *recvInfo, const uint8_t *incomingData, int len) { if (len != sizeof(DataPacket)) { return; } DataPacket packet; memcpy(&packet, incomingData, sizeof(packet)); // Save received values for debug lastRxValid1 = (packet.valid1 == 1); lastRxValid2 = (packet.valid2 == 1); lastRxValid3 = (packet.valid3 == 1); lastRxValue1 = packet.value1; lastRxValue2 = packet.value2; lastRxValue3 = packet.value3; // Update only values that were actually transmitted // Missing values keep their previous stored state if (packet.valid1) { RED = packet.value1; } if (packet.valid2) { GREEN = packet.value2; } if (packet.valid3) { BLUE = packet.value3; } packetCounter++; newPacketReceived = true; blinkRequest = true; } // ========================= // Button handling // On button press, show the currently // stored RGB values on the LED strip // ========================= void handleButton() { bool reading = digitalRead(BUTTON_PIN); if (reading != lastButtonReading) { lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > DEBOUNCE_TIME) { if (reading != stableButtonState) { stableButtonState = reading; if (stableButtonState == LOW) { Serial.println("Slave button pressed -> showing stored RGB values"); Serial.print("Applying R: "); Serial.print(RED); Serial.print(" | G: "); Serial.print(GREEN); Serial.print(" | B: "); Serial.println(BLUE); Serial.println(); updateLEDs(); digitalWrite(STATUS_LED_PIN, HIGH); delay(120); digitalWrite(STATUS_LED_PIN, LOW); delay(80); digitalWrite(STATUS_LED_PIN, HIGH); delay(120); digitalWrite(STATUS_LED_PIN, LOW); } } } lastButtonReading = reading; } // ========================= // Periodic serial output // ========================= void printStatusIfDue() { unsigned long now = millis(); if (now - lastPrintTime < PRINT_INTERVAL) { return; } lastPrintTime = now; Serial.print("Stored RGB -> R: "); Serial.print(RED); Serial.print(" | G: "); Serial.print(GREEN); Serial.print(" | B: "); Serial.print(BLUE); Serial.print(" | Last packet #: "); Serial.print(packetCounter); Serial.print(" | Button raw: "); Serial.println(digitalRead(BUTTON_PIN)); Serial.print("Last RX packet -> "); Serial.print("S1: "); if (lastRxValid1) Serial.print(lastRxValue1); else Serial.print("not transmitted"); Serial.print(" | S2: "); if (lastRxValid2) Serial.print(lastRxValue2); else Serial.print("not transmitted"); Serial.print(" | S3: "); if (lastRxValid3) Serial.println(lastRxValue3); else Serial.println("not transmitted"); if (newPacketReceived) { Serial.println("New packet has been received and stored."); newPacketReceived = false; } Serial.println(); } // ========================= // ESP-NOW initialization // ========================= bool initEspNowReceiver() { WiFi.mode(WIFI_STA); WiFi.disconnect(); Serial.print("Receiver STA MAC: "); Serial.println(WiFi.macAddress()); if (esp_now_init() != ESP_OK) { Serial.println("ESP-NOW initialization failed"); return false; } if (esp_now_register_recv_cb(onDataRecv) != ESP_OK) { Serial.println("Failed to register receive callback"); return false; } Serial.println("ESP-NOW receiver ready"); return true; } // ========================= // Setup // ========================= void setup() { pinMode(BUTTON_PIN, INPUT_PULLUP); pinMode(STATUS_LED_PIN, OUTPUT); digitalWrite(STATUS_LED_PIN, LOW); Serial.begin(115200); delay(2000); Serial.println(); Serial.println("ESP32-C3 Slave / Receiver"); Serial.println("ESP-NOW + FastLED"); Serial.println(); FastLED.addLeds(leds, NUM_LEDS); FastLED.setBrightness(MAX_BRIGHTNESS); FastLED.clear(); FastLED.show(); if (!initEspNowReceiver()) { Serial.println("Receiver setup failed. Stopping here."); while (true) { delay(1000); } } Serial.println(); Serial.println("System ready."); Serial.println("Waiting for packets..."); Serial.println("Press local button to show currently stored RGB values."); Serial.println(); } // ========================= // Main loop // ========================= void loop() { handleButton(); runStatusBlinkIfRequested(); printStatusIfDue(); }