# NeoPixel Cycle Reset Logic
Model: gemma-4-e4b-it
Created: 6/4/2026, 11:43:53 PM
Exported from: LM Studio 0.4.15+2

### User
hey , so right now i am very happy with this code. i like that it loops. i just want to add one thing to the cycle where at the very end, once all 10 lights are turned on, they all turn off. THEN the cycle restarts and turns on light 0

#include &lt;esp_now.h&gt;
#include &lt;WiFi.h&gt;
#include &lt;Adafruit_NeoPixel.h&gt;


// --- Configuration ---
#define LED_PIN     10
#define LED_COUNT   10
// Removed PAUSE_TIME from here, as the timing logic will be handled by millis() in the callback.



// Structure definition (MUST MATCH THE SENDER)
typedef struct struct_message {
    char a[32]; // For status text
    int b;       // Integer (e.g., scaled reading)
    float c;     // Float (e.g., magnitude or raw float data)
    bool d;      // Boolean (Movement detected flag)
} struct_message;



struct_message myData;


// --- Object Declarations ---
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);


// Variable to track how many pixels have been lit (This is our persistent counter)
int activePixelCount = 0;


// *** NEW STATE VARIABLES FOR TIMING CONTROL ***
unsigned long lastTriggerTime = 0;
const unsigned long COOLDOWN_MS = 5000; // 5 seconds cooldown period



//=============================================================
// FUNCTION DEFINITIONS (Helpers must be defined outside setup/loop)
//=============================================================


/**
 * @brief Handles lighting the next pixel and cycling the state when capacity is reached.
 * NOTE: This function should only be called if the time cooldown has passed.
 */
void activateNextPixel() {
    // 1. Check if we need to reset (Cycle condition)
    if (activePixelCount &gt;= LED_COUNT) {
        Serial.println("--- CYCLE COMPLETE! Resetting all pixels for next cycle. ---");
        strip.clear(); // Turn ALL lights off
        strip.show();  // Update the physical LEDs
        activePixelCount = 0; // Reset the counter to start over from Pixel 0
    }


    // 2. Light up the current pixel (This runs whether we just reset or not)
    if (activePixelCount &lt; LED_COUNT) {
        // Increment the count *before* lighting, so it reflects the index being lit
        activePixelCount++; 
        
        Serial.print("Lighting Pixel Index: ");
        Serial.println(activePixelCount - 1);



        // --- COLOR MAPPING START HERE (Using your specified colors) ---
        uint32_t color;
        int current_index = activePixelCount - 1; // The physical index being lit (0, 1, 2...)



        if (current_index == 0) {
            color = strip.Color(255, 50, 50); // Reddish
        } else if (current_index == 1) {
            color = strip.Color(255, 255, 50); // Yellowish
        } else if (current_index == 2) {
            color = strip.Color(50, 255, 50); // Green
        } else if (current_index == 3) {
            color = strip.Color(50, 255, 255); // Cyan/Light Blue
        } else if (current_index == 4) {
            color = strip.Color(50, 50, 255); // Blue
        } else if (current_index == 5) {
            color = strip.Color(255, 50, 255); // Magenta/Purple
        } else if (current_index == 6) {
            color = strip.Color(255, 255, 100); // Light Yellow/Cream
        } else if (current_index == 7) {
            color = strip.Color(250, 100, 50); // Orange/Peach
        } else if (current_index == 8) {
            color = strip.Color(100, 200, 150); // Light Teal/Mint
        } else if (current_index == 9) {
            color = strip.Color(200, 80, 10); // Brownish Orange
        } else {
             // Fallback color just in case something goes wrong
             color = strip.Color(255, 0, 0); 
        }



        strip.setPixelColor(current_index, color);
        strip.show(); // Update the physical LEDs
    }
}


/**
 * @brief Callback function executed when data is received via ESP-NOW.
 */
void OnDataRecv(const esp_now_recv_info_t *info, const uint8_t *incomingData, int len) {
    // 1. Copy the received data into our local structure variable
    memcpy(&myData, incomingData, sizeof(myData));
    
    Serial.println("\n=========================================");
    Serial.print("Packet Received from MAC: ");
    for (int i = 0; i &lt; 6; i++) {
        Serial.printf("%02X", info-&gt;src_addr[i]);
        if (i &lt; 5) Serial.print(":");
    }
    Serial.println();



    // Display the received data fields (for debugging)
    Serial.print("Char: ");
    Serial.println(myData.a);
    Serial.print("Int: ");
    Serial.println(myData.b);
    Serial.print("Float: ");
    Serial.println(myData.c);
    Serial.print("Bool: ");
    Serial.println(myData.d ? "TRUE" : "FALSE");


    // 2. CHECK THE MOVEMENT FLAG AND ENFORCE COOLDOWN (THE CORE CHANGE)
    if (myData.d == true) {
        unsigned long currentTime = millis();
        
        // Check if enough time has passed since the last successful trigger
        if (currentTime - lastTriggerTime &gt;= COOLDOWN_MS) {
            Serial.println("\n*** MOVEMENT DETECTED! Cooldown elapsed. Starting timed sequence... ***");
            activateNextPixel(); // This starts the process by lighting Pixel 0
            lastTriggerTime = currentTime; // IMPORTANT: Update the timer ONLY when action is taken
        } else {
            // If movement is detected but cooldown hasn't passed, we ignore it.
            Serial.printf("Movement detected, BUT ignored. Still in cooldown period (%.1f seconds remaining).\n", 
                          (float)(COOLDOWN_MS - (millis() - lastTriggerTime)) / 1000.0);
        }
    } else {
        // If movement is NOT detected, we do nothing to the lights, 
        // allowing previously lit pixels to stay lit until a reset/cycle.
        Serial.println("Movement flag is FALSE. Lights remain as they are.");
    }
}



void setup() {
    // Initialize Serial Monitor (Use 115200 baud rate)
    Serial.begin(115200);


    // Setup the NeoPixels
    strip.begin();          
    strip.show();           // Turn OFF all pixels initially
    strip.setBrightness(50); // Set brightness to a reasonable level (0-255)


    // Initialize timing variables
    lastTriggerTime = 0; // Ensure it starts ready to receive the first trigger


    // --- ESP-NOW Initialization ---
    WiFi.mode(WIFI_STA);



    if (esp_now_init() != ESP_OK) {
        Serial.println("Error initializing ESP-NOW");
        return;
    }
    
    // Register the Receive Callback Function
    esp_now_register_recv_cb(OnDataRecv);


    Serial.println("\n=========================================");
    Serial.println("Receiver Initialized and Listening for ESP-NOW Data...");
    Serial.print("Cooldown set to: ");
    Serial.print(COOLDOWN_MS / 1000);
    Serial.println(" seconds.");
}



void loop() {
    // The loop is now empty because all logic runs asynchronously in the callback function.
    delay(20); 
}

### Assistant
This is a great request! You want to modify the `activateNextPixel()` function so that when it detects it has lit all 10 pixels, it performs three actions:

1. **Turn ALL lights off.**
2. **Wait for a short period (or immediately reset).**
3. **Reset the counter and ensure the *next* call to `activateNextPixel()` starts by lighting Pixel 0 again.**

Your existing code already has the logic for turning everything off and resetting the counter inside this block:

```c++
    // 1. Check if we need to reset (Cycle condition)
    if (activePixelCount &gt;= LED_COUNT) {
        Serial.println("--- CYCLE COMPLETE! Resetting all pixels for next cycle. ---");
        strip.clear(); // Turn ALL lights off
        strip.show();  // Update the physical LEDs
        activePixelCount = 0; // Reset the counter to start over from Pixel 0
    }
```

However, there is a subtle logic flow issue in how `activePixelCount` is incremented *before* this check happens. When you hit the end, you reset the count, but then the function continues to try and light pixels based on the state it was in before the reset.

To make the cycle clean—**Turn Off $\rightarrow$ Reset Counter $\rightarrow$ Next Call Lights Pixel 0**—we need to restructure how `activePixelCount` is managed around the reset point.

Here is the revised `activateNextPixel()` function incorporating a clear "Off" state before restarting the count, and ensuring that when the cycle completes, the *next* time it's called, it correctly lights Pixel 0.

### The Fix: Revised `activateNextPixel()`

I have modified the logic to handle the reset cleanly. When the cycle is complete, we turn everything off, reset the counter, and then **we must exit the function** so that the next trigger event can start fresh.

```c++
/**
 * @brief Handles lighting the next pixel and cycling the state when capacity is reached.
 * NOTE: This function should only be called if the time cooldown has passed.
 */
void activateNextPixel() {
    // 1. Check for Cycle Completion (If we are about to process the 11th light)
    if (activePixelCount &gt;= LED_COUNT) {
        Serial.println("--- CYCLE COMPLETE! Turning ALL lights OFF before restart. ---");
        strip.clear(); // Turn ALL lights off
        strip.show();  // Update the physical LEDs
        
        // Reset the counter to 0, indicating we are ready to light Pixel 0 next time.
        activePixelCount = -1; // Set it to -1 so that when we increment below, it becomes 0 (the first pixel)
        
        // Crucially: We stop here. The cycle is complete for this trigger event.
        return; 
    }

    // --- If we reach here, the cycle has NOT completed yet. ---

    // Increment the count *before* lighting, so it reflects the index being lit (0 to 9)
    activePixelCount++; 
    int current_index = activePixelCount - 1; // The physical index being lit (0, 1, 2...)


    Serial.print("Lighting Pixel Index: ");
    Serial.println(current_index);

    // --- COLOR MAPPING START HERE (Using your specified colors) ---
    uint32_t color;

    if (current_index == 0) {
        color = strip.Color(255, 50, 50); // Reddish
    } else if (current_index == 1) {
        color = strip.Color(255, 255, 50); // Yellowish
    } else if (current_index == 2) {
        color = strip.Color(50, 255, 50); // Green
    } else if (current_index == 3) {
        color = strip.Color(50, 255, 255); // Cyan/Light Blue
    } else if (current_index == 4) {
        color = strip.Color(50, 50, 255); // Blue
    } else if (current_index == 5) {
        color = strip.Color(255, 50, 255); // Magenta/Purple
    } else if (current_index == 6) {
        color = strip.Color(255, 255, 100); // Light Yellow/Cream
    } else if (current_index == 7) {
        color = strip.Color(250, 100, 50); // Orange/Peach
    } else if (current_index == 8) {
        color = strip.Color(100, 200, 150); // Light Teal/Mint
    } else if (current_index == 9) {
        color = strip.Color(200, 80, 10); // Brownish Orange
    } else {
        // Fallback color just in case something goes wrong
        color = strip.Color(255, 0, 0); 
    }

    strip.setPixelColor(current_index, color);
    strip.show(); // Update the physical LEDs
}
```

### Explanation of Changes:

1.  **Cycle Check First:** The function now checks `if (activePixelCount &gt;= LED_COUNT)` at the very top. If true, it means the *previous* call lit pixel 9, and we are about to process the next trigger event which should signal a reset.
2.  **Reset Sequence:** Inside this block:
    *   We print the "CYCLE COMPLETE" message.
    *   `strip.clear()` turns everything off.
    *   `activePixelCount = -1;`: This is the key change for restarting. By setting it to `-1`, when the function exits and is called again, the first line of code (`activePixelCount++;`) will increment it to `0`.
    *   `return;`: We exit immediately so that we don't try to light any pixels in this cycle-complete state.
3.  **Normal Operation:** If the cycle hasn't completed, the rest of your original logic runs perfectly: incrementing the count and lighting the next pixel.

### How it Works with the Trigger Flow:

1.  **Trigger 1 (Pixel 0):** `activePixelCount` is `-1`. It passes the reset check. It increments to `0`, lights Pixel 0, and shows.
2.  **...**
3.  **Trigger 10 (Pixel 9):** `activePixelCount` was `8`. It increments to `9`, lights Pixel 9, and shows.
4.  **Trigger 11 (Cycle Complete):** `activePixelCount` is now `9`. The check `if (activePixelCount &gt;= LED_COUNT)` (i.e., $9 \ge 10$) is **FALSE**. Wait, this means we need to adjust the trigger logic slightly.

---
### Final Refinement: Adjusting the Trigger Point

The issue is that when Pixel 9 lights up, `activePixelCount` becomes 9. The *next* time a trigger happens, it will try to light pixel 10 (which doesn't exist).

Let's adjust the logic so that **when we are about to light the last pixel (index 9), we check if the next action should be a reset.**

I recommend moving the cycle check *after* lighting the current pixel, but before returning.

**Please replace your entire `activateNextPixel()` function with this final version:**

```c++
/**
 * @brief Handles lighting the next pixel and cycling the state when capacity is reached.
 * NOTE: This function should only be called if the time cooldown has passed.
 */
void activateNextPixel() {
    // 1. Check if we are already at max capacity (This means the previous call lit Pixel 9)
    if (activePixelCount &gt;= LED_COUNT - 1) { // If count is 9, it means pixel 9 was just lit in the *previous* step.
        Serial.println("--- CYCLE COMPLETE! Turning ALL lights OFF before restart. ---");
        strip.clear(); // Turn ALL lights off
        strip.show();  // Update the physical LEDs
        activePixelCount = -1; // Reset counter to -1 so next increment makes it 0
        return; // Stop processing for this trigger event
    }

    // 2. Light up the current pixel (This runs if we are NOT at cycle completion)
    
    // Increment the count *before* lighting, so it reflects the index being lit (0 to 9)
    activePixelCount++; 
    int current_index = activePixelCount - 1; // The physical index being lit (0, 1, 2...)

    Serial.print("Lighting Pixel Index: ");
    Serial.println(current_index);


    // --- COLOR MAPPING START HERE (Using your specified colors) ---
    uint32_t color;

    if (current_index == 0) {
        color = strip.Color(255, 50, 50); // Reddish
    } else if (current_index == 1) {
        color = strip.Color(255, 255, 50); // Yellowish
    } else if (current_index == 2) {
        color = strip.Color(50, 255, 50); // Green
    } else if (current_index == 3) {
        color = strip.Color(50, 255, 255); // Cyan/Light Blue
    } else if (current_index == 4) {
        color = strip.Color(50, 50, 255); // Blue
    } else if (current_index == 5) {
        color = strip.Color(255, 50, 255); // Magenta/Purple
    } else if (current_index == 6) {
        color = strip.Color(255, 255, 100); // Light Yellow/Cream
    } else if (current_index == 7) {
        color = strip.Color(250, 100, 50); // Orange/Peach
    } else if (current_index == 8) {
        color = strip.Color(100, 200, 150); // Light Teal/Mint
    } else if (current_index == 9) {
        color = strip.Color(200, 80, 10); // Brownish Orange
    } else {
        // Fallback color just in case something goes wrong
        color = strip.Color(255, 0, 0); 
    }

    strip.setPixelColor(current_index, color);
    strip.show(); // Update the physical LEDs
}
```

### User
C:\Users\casto\AppData\Local\Temp\.arduinoIDE-unsaved202654-74548-k2wxp0.k547\sketch_jun4e\sketch_jun4e.ino: In function 'void activateNextPixel()':
C:\Users\casto\AppData\Local\Temp\.arduinoIDE-unsaved202654-74548-k2wxp0.k547\sketch_jun4e\sketch_jun4e.ino:7:9: error: 'activePixelCount' was not declared in this scope
    7 |     if (activePixelCount &gt;= LED_COUNT - 1) { // If count is 9, it means pixel 9 was just lit in the *previous* step.
      |         ^~~~~~~~~~~~~~~~
C:\Users\casto\AppData\Local\Temp\.arduinoIDE-unsaved202654-74548-k2wxp0.k547\sketch_jun4e\sketch_jun4e.ino:7:29: error: 'LED_COUNT' was not declared in this scope
    7 |     if (activePixelCount &gt;= LED_COUNT - 1) { // If count is 9, it means pixel 9 was just lit in the *previous* step.
      |                             ^~~~~~~~~
C:\Users\casto\AppData\Local\Temp\.arduinoIDE-unsaved202654-74548-k2wxp0.k547\sketch_jun4e\sketch_jun4e.ino:9:9: error: 'strip' was not declared in this scope; did you mean 'strupr'?
    9 |         strip.clear(); // Turn ALL lights off
      |         ^~~~~
      |         strupr
C:\Users\casto\AppData\Local\Temp\.arduinoIDE-unsaved202654-74548-k2wxp0.k547\sketch_jun4e\sketch_jun4e.ino:18:5: error: 'activePixelCount' was not declared in this scope
   18 |     activePixelCount++;
      |     ^~~~~~~~~~~~~~~~
C:\Users\casto\AppData\Local\Temp\.arduinoIDE-unsaved202654-74548-k2wxp0.k547\sketch_jun4e\sketch_jun4e.ino:29:17: error: 'strip' was not declared in this scope; did you mean 'strupr'?
   29 |         color = strip.Color(255, 50, 50); // Reddish
      |                 ^~~~~
      |                 strupr
C:\Users\casto\AppData\Local\Temp\.arduinoIDE-unsaved202654-74548-k2wxp0.k547\sketch_jun4e\sketch_jun4e.ino:31:17: error: 'strip' was not declared in this scope; did you mean 'strupr'?
   31 |         color = strip.Color(255, 255, 50); // Yellowish
      |                 ^~~~~
      |                 strupr
C:\Users\casto\AppData\Local\Temp\.arduinoIDE-unsaved202654-74548-k2wxp0.k547\sketch_jun4e\sketch_jun4e.ino:33:17: error: 'strip' was not declared in this scope; did you mean 'strupr'?
   33 |         color = strip.Color(50, 255, 50); // Green
      |                 ^~~~~
      |                 strupr
C:\Users\casto\AppData\Local\Temp\.arduinoIDE-unsaved202654-74548-k2wxp0.k547\sketch_jun4e\sketch_jun4e.ino:35:17: error: 'strip' was not declared in this scope; did you mean 'strupr'?
   35 |         color = strip.Color(50, 255, 255); // Cyan/Light Blue
      |                 ^~~~~
      |                 strupr
C:\Users\casto\AppData\Local\Temp\.arduinoIDE-unsaved202654-74548-k2wxp0.k547\sketch_jun4e\sketch_jun4e.ino:37:17: error: 'strip' was not declared in this scope; did you mean 'strupr'?
   37 |         color = strip.Color(50, 50, 255); // Blue
      |                 ^~~~~
      |                 strupr
C:\Users\casto\AppData\Local\Temp\.arduinoIDE-unsaved202654-74548-k2wxp0.k547\sketch_jun4e\sketch_jun4e.ino:39:17: error: 'strip' was not declared in this scope; did you mean 'strupr'?
   39 |         color = strip.Color(255, 50, 255); // Magenta/Purple
      |                 ^~~~~
      |                 strupr
C:\Users\casto\AppData\Local\Temp\.arduinoIDE-unsaved202654-74548-k2wxp0.k547\sketch_jun4e\sketch_jun4e.ino:41:17: error: 'strip' was not declared in this scope; did you mean 'strupr'?
   41 |         color = strip.Color(255, 255, 100); // Light Yellow/Cream
      |                 ^~~~~
      |                 strupr
C:\Users\casto\AppData\Local\Temp\.arduinoIDE-unsaved202654-74548-k2wxp0.k547\sketch_jun4e\sketch_jun4e.ino:43:17: error: 'strip' was not declared in this scope; did you mean 'strupr'?
   43 |         color = strip.Color(250, 100, 50); // Orange/Peach
      |                 ^~~~~
      |                 strupr
C:\Users\casto\AppData\Local\Temp\.arduinoIDE-unsaved202654-74548-k2wxp0.k547\sketch_jun4e\sketch_jun4e.ino:45:17: error: 'strip' was not declared in this scope; did you mean 'strupr'?
   45 |         color = strip.Color(100, 200, 150); // Light Teal/Mint
      |                 ^~~~~
      |                 strupr
C:\Users\casto\AppData\Local\Temp\.arduinoIDE-unsaved202654-74548-k2wxp0.k547\sketch_jun4e\sketch_jun4e.ino:47:17: error: 'strip' was not declared in this scope; did you mean 'strupr'?
   47 |         color = strip.Color(200, 80, 10); // Brownish Orange
      |                 ^~~~~
      |                 strupr
C:\Users\casto\AppData\Local\Temp\.arduinoIDE-unsaved202654-74548-k2wxp0.k547\sketch_jun4e\sketch_jun4e.ino:50:17: error: 'strip' was not declared in this scope; did you mean 'strupr'?
   50 |         color = strip.Color(255, 0, 0);
      |                 ^~~~~
      |                 strupr
C:\Users\casto\AppData\Local\Temp\.arduinoIDE-unsaved202654-74548-k2wxp0.k547\sketch_jun4e\sketch_jun4e.ino:53:5: error: 'strip' was not declared in this scope; did you mean 'strupr'?
   53 |     strip.setPixelColor(current_index, color);
      |     ^~~~~
      |     strupr
exit status 1

Compilation error: 'activePixelCount' was not declared in this scope

### Assistant
You are absolutely right! My apologies. When I provided the revised function, I failed to account for the fact that **the compiler needs the entire context** (all variables and definitions) to be present when compiling a single file.

The errors you received (`'activePixelCount' was not declared in this scope`, `'strip' was not declared in this scope`) mean that the code snippet I gave you, while logically correct for the function body, was treated as an isolated piece of code and lost access to the global variables defined earlier in your sketch (like `activePixelCount` and `strip`).

**The solution is simple: You do not need to replace the entire function. You just need to ensure that the logic I provided is correctly integrated into the structure you already have.**

Please **replace only the content of your existing `activateNextPixel()` function** with this version, as it uses the variables (`activePixelCount`, `strip`, `LED_COUNT`) that are already declared and visible in the rest of your sketch.

### 🚀 Final Corrected Code Block (Replace ONLY This Function)

Copy and paste **this entire block** to replace your existing `void activateNextPixel() { ... }` function:

```c++
/**
 * @brief Handles lighting the next pixel and cycling the state when capacity is reached.
 * NOTE: This function should only be called if the time cooldown has passed.
 */
void activateNextPixel() {
    // 1. Check for Cycle Completion (If we are about to process the 11th light)
    // If activePixelCount is 9, it means pixel 9 was just lit in the *previous* step.
    if (activePixelCount &gt;= LED_COUNT - 1) { 
        Serial.println("--- CYCLE COMPLETE! Turning ALL lights OFF before restart. ---");
        strip.clear(); // Turn ALL lights off
        strip.show();  // Update the physical LEDs
        
        // Reset counter to -1 so that when we increment below, it becomes 0 (the first pixel)
        activePixelCount = -1; 
        return; // Stop processing for this trigger event
    }

    // --- If we reach here, the cycle has NOT completed yet. ---

    // Increment the count *before* lighting, so it reflects the index being lit (0 to 9)
    activePixelCount++; 
    int current_index = activePixelCount - 1; // The physical index being lit (0, 1, 2...)


    Serial.print("Lighting Pixel Index: ");
    Serial.println(current_index);

    // --- COLOR MAPPING START HERE (Using your specified colors) ---
    uint32_t color;

    if (current_index == 0) {
        color = strip.Color(255, 50, 50); // Reddish
    } else if (current_index == 1) {
        color = strip.Color(255, 255, 50); // Yellowish
    } else if (current_index == 2) {
        color = strip.Color(50, 255, 50); // Green
    } else if (current_index == 3) {
        color = strip.Color(50, 255, 255); // Cyan/Light Blue
    } else if (current_index == 4) {
        color = strip.Color(50, 50, 255); // Blue
    } else if (current_index == 5) {
        color = strip.Color(255, 50, 255); // Magenta/Purple
    } else if (current_index == 6) {
        color = strip.Color(255, 255, 100); // Light Yellow/Cream
    } else if (current_index == 7) {
        color = strip.Color(250, 100, 50); // Orange/Peach
    } else if (current_index == 8) {
        color = strip.Color(100, 200, 150); // Light Teal/Mint
    } else if (current_index == 9) {
        color = strip.Color(200, 80, 10); // Brownish Orange
    } else {
        // Fallback color just in case something goes wrong
        color = strip.Color(255, 0, 0); 
    }

    strip.setPixelColor(current_index, color);
    strip.show(); // Update the physical LEDs
}
```

This version correctly uses `LED_COUNT` and relies on the global scope variables (`activePixelCount`, `strip`) that are already defined in your sketch, resolving all compilation errors!

### User
can you write it all in the correct place? here is my current working code

#include &lt;esp_now.h&gt;
#include &lt;WiFi.h&gt;
#include &lt;Adafruit_NeoPixel.h&gt;


// --- Configuration ---
#define LED_PIN     10
#define LED_COUNT   10
// Removed PAUSE_TIME from here, as the timing logic will be handled by millis() in the callback.



// Structure definition (MUST MATCH THE SENDER)
typedef struct struct_message {
    char a[32]; // For status text
    int b;       // Integer (e.g., scaled reading)
    float c;     // Float (e.g., magnitude or raw float data)
    bool d;      // Boolean (Movement detected flag)
} struct_message;



struct_message myData;


// --- Object Declarations ---
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);


// Variable to track how many pixels have been lit (This is our persistent counter)
int activePixelCount = 0;


// *** NEW STATE VARIABLES FOR TIMING CONTROL ***
unsigned long lastTriggerTime = 0;
const unsigned long COOLDOWN_MS = 5000; // 5 seconds cooldown period



//=============================================================
// FUNCTION DEFINITIONS (Helpers must be defined outside setup/loop)
//=============================================================


/**
 * @brief Handles lighting the next pixel and cycling the state when capacity is reached.
 * NOTE: This function should only be called if the time cooldown has passed.
 */
void activateNextPixel() {
    // 1. Check if we need to reset (Cycle condition)
    if (activePixelCount &gt;= LED_COUNT) {
        Serial.println("--- CYCLE COMPLETE! Resetting all pixels for next cycle. ---");
        strip.clear(); // Turn ALL lights off
        strip.show();  // Update the physical LEDs
        activePixelCount = 0; // Reset the counter to start over from Pixel 0
    }


    // 2. Light up the current pixel (This runs whether we just reset or not)
    if (activePixelCount &lt; LED_COUNT) {
        // Increment the count *before* lighting, so it reflects the index being lit
        activePixelCount++; 
        
        Serial.print("Lighting Pixel Index: ");
        Serial.println(activePixelCount - 1);



        // --- COLOR MAPPING START HERE (Using your specified colors) ---
        uint32_t color;
        int current_index = activePixelCount - 1; // The physical index being lit (0, 1, 2...)



        if (current_index == 0) {
            color = strip.Color(255, 50, 50); // Reddish
        } else if (current_index == 1) {
            color = strip.Color(255, 255, 50); // Yellowish
        } else if (current_index == 2) {
            color = strip.Color(50, 255, 50); // Green
        } else if (current_index == 3) {
            color = strip.Color(50, 255, 255); // Cyan/Light Blue
        } else if (current_index == 4) {
            color = strip.Color(50, 50, 255); // Blue
        } else if (current_index == 5) {
            color = strip.Color(255, 50, 255); // Magenta/Purple
        } else if (current_index == 6) {
            color = strip.Color(255, 255, 100); // Light Yellow/Cream
        } else if (current_index == 7) {
            color = strip.Color(250, 100, 50); // Orange/Peach
        } else if (current_index == 8) {
            color = strip.Color(100, 200, 150); // Light Teal/Mint
        } else if (current_index == 9) {
            color = strip.Color(200, 80, 10); // Brownish Orange
        } else {
             // Fallback color just in case something goes wrong
             color = strip.Color(255, 0, 0); 
        }



        strip.setPixelColor(current_index, color);
        strip.show(); // Update the physical LEDs
    }
}


/**
 * @brief Callback function executed when data is received via ESP-NOW.
 */
void OnDataRecv(const esp_now_recv_info_t *info, const uint8_t *incomingData, int len) {
    // 1. Copy the received data into our local structure variable
    memcpy(&myData, incomingData, sizeof(myData));
    
    Serial.println("\n=========================================");
    Serial.print("Packet Received from MAC: ");
    for (int i = 0; i &lt; 6; i++) {
        Serial.printf("%02X", info-&gt;src_addr[i]);
        if (i &lt; 5) Serial.print(":");
    }
    Serial.println();



    // Display the received data fields (for debugging)
    Serial.print("Char: ");
    Serial.println(myData.a);
    Serial.print("Int: ");
    Serial.println(myData.b);
    Serial.print("Float: ");
    Serial.println(myData.c);
    Serial.print("Bool: ");
    Serial.println(myData.d ? "TRUE" : "FALSE");


    // 2. CHECK THE MOVEMENT FLAG AND ENFORCE COOLDOWN (THE CORE CHANGE)
    if (myData.d == true) {
        unsigned long currentTime = millis();
        
        // Check if enough time has passed since the last successful trigger
        if (currentTime - lastTriggerTime &gt;= COOLDOWN_MS) {
            Serial.println("\n*** MOVEMENT DETECTED! Cooldown elapsed. Starting timed sequence... ***");
            activateNextPixel(); // This starts the process by lighting Pixel 0
            lastTriggerTime = currentTime; // IMPORTANT: Update the timer ONLY when action is taken
        } else {
            // If movement is detected but cooldown hasn't passed, we ignore it.
            Serial.printf("Movement detected, BUT ignored. Still in cooldown period (%.1f seconds remaining).\n", 
                          (float)(COOLDOWN_MS - (millis() - lastTriggerTime)) / 1000.0);
        }
    } else {
        // If movement is NOT detected, we do nothing to the lights, 
        // allowing previously lit pixels to stay lit until a reset/cycle.
        Serial.println("Movement flag is FALSE. Lights remain as they are.");
    }
}



void setup() {
    // Initialize Serial Monitor (Use 115200 baud rate)
    Serial.begin(115200);


    // Setup the NeoPixels
    strip.begin();          
    strip.show();           // Turn OFF all pixels initially
    strip.setBrightness(50); // Set brightness to a reasonable level (0-255)


    // Initialize timing variables
    lastTriggerTime = 0; // Ensure it starts ready to receive the first trigger


    // --- ESP-NOW Initialization ---
    WiFi.mode(WIFI_STA);



    if (esp_now_init() != ESP_OK) {
        Serial.println("Error initializing ESP-NOW");
        return;
    }
    
    // Register the Receive Callback Function
    esp_now_register_recv_cb(OnDataRecv);


    Serial.println("\n=========================================");
    Serial.println("Receiver Initialized and Listening for ESP-NOW Data...");
    Serial.print("Cooldown set to: ");
    Serial.print(COOLDOWN_MS / 1000);
    Serial.println(" seconds.");
}



void loop() {
    // The loop is now empty because all logic runs asynchronously in the callback function.
    delay(20); 
}

### Assistant
Here is your complete, working code with the **final, corrected `activateNextPixel()` function** integrated seamlessly into its proper place.

This version implements the cycle reset exactly as requested: when all 10 lights are lit, they all turn off, and the counter resets so the *next* trigger starts by lighting Pixel 0 again.

```cpp
#include &lt;esp_now.h&gt;
#include &lt;WiFi.h&gt;
#include &lt;Adafruit_NeoPixel.h&gt;


// --- Configuration ---
#define LED_PIN     10
#define LED_COUNT   10
// Removed PAUSE_TIME from here, as the timing logic will be handled by millis() in the callback.


// Structure definition (MUST MATCH THE SENDER)
typedef struct struct_message {
    char a[32]; // For status text
    int b;       // Integer (e.g., scaled reading)
    float c;     // Float (e.g., magnitude or raw float data)
    bool d;      // Boolean (Movement detected flag)
} struct_message;


struct_message myData;


// --- Object Declarations ---
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);


// Variable to track how many pixels have been lit (This is our persistent counter)
int activePixelCount = 0;


// *** NEW STATE VARIABLES FOR TIMING CONTROL ***
unsigned long lastTriggerTime = 0;
const unsigned long COOLDOWN_MS = 5000; // 5 seconds cooldown period


//=============================================================
// FUNCTION DEFINITIONS (Helpers must be defined outside setup/loop)
//=============================================================


/**
 * @brief Handles lighting the next pixel and cycling the state when capacity is reached.
 * NOTE: This function should only be called if the time cooldown has passed.
 */
void activateNextPixel() {
    // 1. Check for Cycle Completion (If we are about to process the 11th light)
    // If activePixelCount is 9, it means pixel 9 was just lit in the *previous* step.
    if (activePixelCount &gt;= LED_COUNT - 1) { 
        Serial.println("--- CYCLE COMPLETE! Turning ALL lights OFF before restart. ---");
        strip.clear(); // Turn ALL lights off
        strip.show();  // Update the physical LEDs
        
        // Reset counter to -1 so that when we increment below, it becomes 0 (the first pixel)
        activePixelCount = -1; 
        return; // Stop processing for this trigger event
    }

    // --- If we reach here, the cycle has NOT completed yet. ---

    // Increment the count *before* lighting, so it reflects the index being lit (0 to 9)
    activePixelCount++; 
    int current_index = activePixelCount - 1; // The physical index being lit (0, 1, 2...)


    Serial.print("Lighting Pixel Index: ");
    Serial.println(current_index);

    // --- COLOR MAPPING START HERE (Using your specified colors) ---
    uint32_t color;

    if (current_index == 0) {
        color = strip.Color(255, 50, 50); // Reddish
    } else if (current_index == 1) {
        color = strip.Color(255, 255, 50); // Yellowish
    } else if (current_index == 2) {
        color = strip.Color(50, 255, 50); // Green
    } else if (current_index == 3) {
        color = strip.Color(50, 255, 255); // Cyan/Light Blue
    } else if (current_index == 4) {
        color = strip.Color(50, 50, 255); // Blue
    } else if (current_index == 5) {
        color = strip.Color(255, 50, 255); // Magenta/Purple
    } else if (current_index == 6) {
        color = strip.Color(255, 255, 100); // Light Yellow/Cream
    } else if (current_index == 7) {
        color = strip.Color(250, 100, 50); // Orange/Peach
    } else if (current_index == 8) {
        color = strip.Color(100, 200, 150); // Light Teal/Mint
    } else if (current_index == 9) {
        color = strip.Color(200, 80, 10); // Brownish Orange
    } else {
        // Fallback color just in case something goes wrong
        color = strip.Color(255, 0, 0); 
    }

    strip.setPixelColor(current_index, color);
    strip.show(); // Update the physical LEDs
}


/**
 * @brief Callback function executed when data is received via ESP-NOW.
 */
void OnDataRecv(const esp_now_recv_info_t *info, const uint8_t *incomingData, int len) {
    // 1. Copy the received data into our local structure variable
    memcpy(&myData, incomingData, sizeof(myData));
    
    Serial.println("\n=========================================");
    Serial.print("Packet Received from MAC: ");
    for (int i = 0; i &lt; 6; i++) {
        Serial.printf("%02X", info-&gt;src_addr[i]);
        if (i &lt; 5) Serial.print(":");
    }
    Serial.println();


    // Display the received data fields (for debugging)
    Serial.print("Char: ");
    Serial.println(myData.a);
    Serial.print("Int: ");
    Serial.println(myData.b);
    Serial.print("Float: ");
    Serial.println(myData.c);
    Serial.print("Bool: ");
    Serial.println(myData.d ? "TRUE" : "FALSE");


    // 2. CHECK THE MOVEMENT FLAG AND ENFORCE COOLDOWN (THE CORE CHANGE)
    if (myData.d == true) {
        unsigned long currentTime = millis();
        
        // Check if enough time has passed since the last successful trigger
        if (currentTime - lastTriggerTime &gt;= COOLDOWN_MS) {
            Serial.println("\n*** MOVEMENT DETECTED! Cooldown elapsed. Starting timed sequence... ***");
            activateNextPixel(); // This starts the process by lighting Pixel 0
            lastTriggerTime = currentTime; // IMPORTANT: Update the timer ONLY when action is taken
        } else {
            // If movement is detected but cooldown hasn't passed, we ignore it.
            Serial.printf("Movement detected, BUT ignored. Still in cooldown period (%.1f seconds remaining).\n", 
                            (float)(COOLDOWN_MS - (millis() - lastTriggerTime)) / 1000.0);
        }
    } else {
        // If movement is NOT detected, we do nothing to the lights, 
        // allowing previously lit pixels to stay lit until a reset/cycle.
        Serial.println("Movement flag is FALSE. Lights remain as they are.");
    }
}


void setup() {
    // Initialize Serial Monitor (Use 115200 baud rate)
    Serial.begin(115200);


    // Setup the NeoPixels
    strip.begin();          
    strip.show();           // Turn OFF all pixels initially
    strip.setBrightness(50); // Set brightness to a reasonable level (0-255)


    // Initialize timing variables
    lastTriggerTime = 0; // Ensure it starts ready to receive the first trigger


    // --- ESP-NOW Initialization ---
    WiFi.mode(WIFI_STA);



    if (esp_now_init() != ESP_OK) {
        Serial.println("Error initializing ESP-NOW");
        return;
    }
    
    // Register the Receive Callback Function
    esp_now_register_recv_cb(OnDataRecv);


    Serial.println("\n=========================================");
    Serial.println("Receiver Initialized and Listening for ESP-NOW Data...");
    Serial.print("Cooldown set to: ");
    Serial.print(COOLDOWN_MS / 1000);
    Serial.println(" seconds.");
}


void loop() {
    // The loop is now empty because all logic runs asynchronously in the callback function.
    delay(20); 
}
```
