Trouble with using multiple millis instances

Hi all,

The title is a bit misleading, but I didn't know how else to describe my problem.

I'm building a modular addressable led light for my kids, its main controller being a Pixelblaze. I'm trying to make everything as "analog" as possible, so that they don't have to use the web interface of the controller to change any settings. The biggest issue to overcome, is letting Pixelblaze know how many leds are connected.

Each "brick" contains 5 leds, a total of 30 bricks can be connected at any time.

An ESP32 is connected to an INA219 that measures the load. When a button is pressed, the following happens(or I want to happen in any case):

  1. ESP32 sends a command to Pixelblaze to turn on the first 5 Leds(Leds1 = 405 in code)
  2. ESP32 measures the load, and if it is above a certain number, the leds exist(power_mW_A > 300 in code)
  3. If they exist, ESP32 sends command to turn on the next 5 leds(Leds1 = 410 in code)
  4. If they don't, ESP32 sends command with amount of leds connected(Leds1 = 0)

etc, until we reach 150 leds or 30 bricks.

I cannot figure out how to properly stop the code from continuing after the number of leds has been determined, if for example I have 10 leds connected, it will keep going until the end, but the goal is to have it stop once there is no more load. I tried moving everything around, so that every next measurement is conditional on whether the previous was a success, but it just doesn't do it, either it gets stuck on the second measurement, or goes all the way to the end.

I also have the feeling that this is the wrong way to do it. When the button is pressed, I'll have to initialize 30 millis instances(double that actually, I have to measure two outputs x 30 bricks), is that meant to be done with a combination of an array and one timer? I don't really have the knowledge on how to do that if it is the proper way, so any help would be appreciated.

I'm pasting only the relevant part of the code, as it's a rather long sketch.

if (button.isPressed()) {
    Leds1 = 405;
    
    ItWasDone = true;
    LedTime_now = millis();
    LedTime_now2 = millis();
    LedTime_now3 = millis();
    LedTime_now4 = millis();
    LedTime_now5 = millis();
  }
  if (ItWasDone && ( millis() - LedTime_now >= LedPeriod) )
  {
    if (power_mW_A > 300) {
    Leds1 = 410;
    ItWasDone = false;
    ItWasDone2 = true;
    } else {
      Leds1 = 0;
    }
    
  

    if (ItWasDone2 && ( millis() - LedTime_now2 >= LedPeriod2) )
  {
    if (power_mW_A > 300) {
     Leds1 = 415;
     ItWasDone2 = false;
     ItWasDone3 = true;
    } else {
      Leds1 = 5;
    }
  }

    if (ItWasDone3 && ( millis() - LedTime_now3 >= LedPeriod3) )
  {
    if (power_mW_A > 300) {
    Leds1 = 420;
    ItWasDone3 = false;
    ItWasDone4 = true;
    } else {
      Leds1 = 10;
    }
  }

    if (ItWasDone4 && ( millis() - LedTime_now4 >= LedPeriod4) )
  {
    if (power_mW_A > 300) {
    Leds1 = 425;
    ItWasDone4 = false;
    ItWasDone5 = true;
    } else {
      Leds1 = 15;
    }
  }

    if (ItWasDone5 && ( millis() - LedTime_now5 >= LedPeriod5) )
  {
    if (power_mW_A > 300) {
    Leds1a = 25;
    } else {
      Leds1 = 20;
    }
    ItWasDone5 = false;
  }

  }

To be frank, the project you want to complete is a bit further than the question you are asking. It appears you have a few problems to work out, the code only being one of them.

  1. How to code a sequence of events and for this, code a simple test of just sequential events, not sensors and everything else. Open a new sketch, just try to get 5 bricks to fire, knowing they are there etc.

  2. How to approach the project. (This is more of a Project Guidance question.) For those of us, myself included, not familiar with Pixelblazes or bricks etc., spell out in plain English what you want to do... for example, "I want my children to be able to add or take away bricks and the bricks that remain attached, light up in a sequential pattern..." but in your own words. Right now, this is an XY problem, because your problem is X and your proposed solution is Y and you are asking about Y. You alluded to this yourself. What if there is a problem with your proposed solution beyond Y, and the forum is able to solve Y, but it does not appear a solution to you because your real problem is X?

Thanks for your reply, and sorry if the explanation wasn't clear.

I know how to fire sequential events, my problem is that I can't figure out how to make them conditional.

In a more simplistic way:

After button is pressed:

Check something.
If something is true, check something2.
IF not, save something's value, exit.

If something2 is true, check something3
If not true, save something2's value, exit.

If something3 is true, check something4.

etc...

So, every next condition can be checked only if the previous is true.

These checks need 250ms to execute(due to the leds having to be turned on and off), so millis or a timer anyway has to be used.

Given my limited knowledge, I don't know if the approach of multiple millis instances is wrong. I don't mind having a long sketch because of this, so if it works I can just go on doing it this way and have 30 millis instances.

Thanks again.

Please post your full code.

  1. Every time that you start numbering variables, it's time to start looking into arrays and maybe structs or classes. Next you can use a loop mechanism (either a for-loop or while-loop or a non-blocking implementation of those).
  2. The use of LedTime_nowX seems redundant; you can simply use LedTime_now everywhere

Use a state machine. This is most frequently done with a switch case

enum EventState : char {WaitingForButton, Intro, Act1, Intermission, Act2, Conclusion} eventSwitch;
unsigned long eventTimestamp;
unsigned long eventInterval;
const unsigned long LED_Periods[] = {500, 200, 300, 400, 356};

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
  bool pushedTheButton = (digitalRead(5) == LOW) ? true : false;
  switch (eventSwitch) {
    case WaitingForButton: {
        if (pushedTheButton) {
          //whatever you need to do
          eventTimestamp = millis();
          eventInterval = LED_Periods[(unsigned char) eventSwitch];
          eventSwitch = Intro;
        }
        break;
      }
    case Intro: {
        // event stuff
        if (millis() - eventTimestamp >= eventInterval) {
          //whatever you need to do
          eventTimestamp = millis();
          eventInterval = LED_Periods[(unsigned char) eventSwitch];
          eventSwitch = Act1;
        }
        break;
      }
    case Act1: {
        // event stuff
        if (millis() - eventTimestamp >= eventInterval) {
          //whatever you need to do
          eventTimestamp = millis();
          eventInterval = LED_Periods[(unsigned char) eventSwitch];
          eventSwitch = Intermission;
        }
        break;
      }
    case Intermission: {
        // event stuff
        if (millis() - eventTimestamp >= eventInterval) {
          //whatever you need to do
          eventTimestamp = millis();
          eventInterval = LED_Periods[(unsigned char) eventSwitch];
          eventSwitch = Act2;
        }
        break;
      }
    case Act2: {
        // event stuff
        if (millis() - eventTimestamp >= eventInterval) {
          //whatever you need to do
          eventTimestamp = millis();
          eventInterval = LED_Periods[(unsigned char) eventSwitch];
          eventSwitch = Conclusion;
        }
        break;
      }
    case Conclusion: {
        // event stuff
        if (millis() - eventTimestamp >= eventInterval) {
          //whatever you need to do
          eventSwitch = WaitingForButton;
        }
        break;
      }
  }
}

Once you have determined the number of bricks, you can increment a counter in each step and take that count against the number determined, as a condition to move to the next state...

With a state machine, each state only needs to worry about what conditions are required to move to the next. and which state to move too.... All other states ignore the state of the button, for example.

1 Like

Here's the code:

[code]
#include <EEPROM.h>

#define EEPROM_SIZE 1

#define RXD2 16   // Serial1 Pins
#define TXD2 17


#include <Wire.h>
#include <Adafruit_INA219.h>

Adafruit_INA219 ina219_A;
Adafruit_INA219 ina219_B(0x41);

float shuntvoltage_A = 0;
float busvoltage_A = 0;
float current_mA_A = 0;
float loadvoltage_A = 0;
float power_mW_A = 0;

float shuntvoltage_B = 0;
float busvoltage_B = 0;
float current_mA_B = 0;
float loadvoltage_B = 0;
float power_mW_B = 0;

//************ SENSOR BOARD START *******************

#define START_BYTES 5
#define LENGTH      98

const byte startMarker[START_BYTES] = {'S', 'B', '1', '.', '0'};

byte receivedBytes[LENGTH];
uint8_t idx = 0;

boolean processData = false;
boolean started     = false;

//************  SENSOR BOARD END  *******************

uint16_t Leds1 = 45;
uint16_t Leds2 = 30;
uint16_t Leds1a = 0;


#include <ezButton.h>

#define DEBOUNCE_TIME 50 // the debounce time in millisecond, increase this time if it still chatters

ezButton button(5); // create ezButton object that attach to pin GPIO5
ezButton button2(23);



int SerialPeriod = 50;  // Serial1 Write interval
unsigned long SerialTime_now = 0;

int inaPeriod = 4000;     //INA219 Serial Print Interval
unsigned long inaTime_now = 0;

int LedPeriod = 250;     // LED Count Interval
int LedPeriod2 = 500;
int LedPeriod3 = 750;
int LedPeriod4 = 1000;
int LedPeriod5 = 1250;
unsigned long LedTime_now;
unsigned long LedTime_now2;
unsigned long LedTime_now3;
unsigned long LedTime_now4;
unsigned long LedTime_now5;
bool ItWasDone = false;
bool ItWasDone2 = false;
bool ItWasDone3 = false;
bool ItWasDone4 = false;
bool ItWasDone5 = false;

int AlarmPeriod = 15000;     // Alarm On
unsigned long AlarmTime_now = 0;
bool AlarmDone = false;

uint16_t Colour1A  = 0;    // COLOURS!!!
uint16_t Colour1B  = 0;
uint16_t Colour1C  = 0;
uint16_t Colour1D  = 0;
uint16_t Colour2A  = 0;
uint16_t Colour2B  = 0;
uint16_t Colour2C  = 0;
uint16_t Colour2D  = 0;


byte header[] = {0x53, 0x42, 0x31, 0x2E, 0x30, 0x00};  //HEADER   SB1.0

byte freq[] =     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,     // FREQUENCY 1/6
                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,    // FREQUENCY 2/6
                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,    // FREQUENCY 3/6
                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,    // FREQUENCY 4/6
                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,    // FREQUENCY 5/6
                   0x00, 0x00, 0x00, 0x00
                  };                                                    // FREQUENCY 6/6

byte audio[] =    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};    // AUDIO ENERGY

byte acc[] =      {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};    //ACCELEROMETER

byte light[] =    {0x00, 0x00};    // LIGHT SENSOR

byte analog[] =  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};    //ANALOG INPUTS

byte end[] =      {0x45, 0x4E, 0x44, 0x00};    // END



//  ***************  POTENTIOMETERS START **********************

const int NINPUTS = 4;
const byte inputPin[NINPUTS] = { 27, 14, 12, 13 };
int reading[NINPUTS];
float smoothedReading[NINPUTS];

void takeReadings() {
  for (int i = 0; i < NINPUTS; i++) {
    reading[i] = analogRead(inputPin[i]);
    smoothedReading[i] = smoothedReading[i] * .85 + reading[i] * .15;
  }
}

// ****************** POTENTIOMETERS END ***********************



void setup() {

  //setCpuFrequencyMhz(40);   // Drop consumption, save the planet:)

  Serial.begin(115200);
  Serial1.begin(115200, SERIAL_8N1, RXD2, TXD2);


  Wire.begin();

  ina219_A.begin();
  ina219_B.begin();

  EEPROM.begin(EEPROM_SIZE);

  Leds1 = EEPROM.read(0);
  //Leds2 = EEPROM.read(1);

  Serial.println(Leds1);

  pinMode(18, OUTPUT);  // SHUT DOWN TRIGGER

  pinMode(5, INPUT_PULLUP);    // LED COUNT BUTTON
  pinMode(23, INPUT_PULLUP);

  pinMode(19, INPUT_PULLUP);    // SENSOR BOARD SELECTOR
  button.setDebounceTime(DEBOUNCE_TIME);

  uint32_t currentFrequency;   //INA219

}

void loop() {

  takeReadings();     // ANALOG INPUT SMOOTHING (Pots 1-4)




  shuntvoltage_A = abs(ina219_A.getShuntVoltage_mV());
  busvoltage_A = ina219_A.getBusVoltage_V();
  current_mA_A = abs(ina219_A.getCurrent_mA());
  power_mW_A = ina219_A.getPower_mW();
  loadvoltage_A = busvoltage_A + (shuntvoltage_A / 1000);

  shuntvoltage_B = abs(ina219_B.getShuntVoltage_mV());
  busvoltage_B = ina219_B.getBusVoltage_V();
  current_mA_B = abs(ina219_B.getCurrent_mA());
  power_mW_B = ina219_B.getPower_mW();
  loadvoltage_B = busvoltage_B + (shuntvoltage_B / 1000);


  //if (loadvoltage_A < 16) {  // BATTERY LOW WARNING
  if (button2.isPressed()) {
    Leds2 = Leds2 + 500;
    //Leds2 = 2000;
    AlarmDone = true;
    AlarmTime_now = millis();
  }

  if (AlarmDone && ( millis() - AlarmTime_now >= AlarmPeriod)) {
    Leds1 = EEPROM.read(0);
    //Leds2 = EEPROM.read(1);
    AlarmDone = false;
  }


  if (loadvoltage_A < 15) {   //  BATTERY LOW SHUT DOWN
    digitalWrite(18, HIGH);
  }



  button.loop(); // LED COUNT BUTTON DEBOUNCE ROUTINE
  button2.loop();
  /*
    if (button.isPressed()) {
      Leds1 = 400;
      //Leds2 = 400;
      //Serial.print("Leds1 = "); Serial.println(Leds1);
      ItWasDone = true;
      LedTime_now = millis();
    }
    if (ItWasDone && ( millis() - LedTime_now >= LedPeriod) )
    {
      Leds1 = power_mW_A / 120;
      Leds1 = (((2 * Leds1) + 5) / 10) * 5;

     // Leds2 = power_mW_B / 120;
     // Leds2 = (((2 * Leds2) + 5) / 10) * 5;
      //EEPROM.write(0, Leds1);
      //EEPROM.write(1, Leds2);
      //EEPROM.commit();
      //Serial.print("Leds1 = "); Serial.println(Leds1);
      ItWasDone = false;
    }
  */
  if (button.isPressed()) {
    Leds1 = 405;
    Serial.println("405");

    ItWasDone = true;
    LedTime_now = millis();
    LedTime_now2 = millis();
    LedTime_now3 = millis();
    LedTime_now4 = millis();
    LedTime_now5 = millis();
  }
  if (ItWasDone && ( millis() - LedTime_now >= LedPeriod) )
  {
    if (power_mW_A > 300) {
      Leds1 = 410;
      ItWasDone = false;
      ItWasDone2 = true;
    } else {
      Leds1 = 0;
    }



    if (ItWasDone2 && ( millis() - LedTime_now2 >= LedPeriod2) )
    {
      if (power_mW_A > 300) {
        Leds1 = 415;
        ItWasDone2 = false;
        ItWasDone3 = true;
      } else {
        Leds1 = 5;
      }
    }

    if (ItWasDone3 && ( millis() - LedTime_now3 >= LedPeriod3) )
    {
      if (power_mW_A > 300) {
        Leds1 = 420;
        ItWasDone3 = false;
        ItWasDone4 = true;
      } else {
        Leds1 = 10;
      }
    }

    if (ItWasDone4 && ( millis() - LedTime_now4 >= LedPeriod4) )
    {
      if (power_mW_A > 300) {
        Leds1 = 425;
        ItWasDone4 = false;
        ItWasDone5 = true;
      } else {
        Leds1 = 15;
      }
    }

    if (ItWasDone5 && ( millis() - LedTime_now5 >= LedPeriod5) )
    {
      if (power_mW_A > 300) {
        Leds1a = 25;
      } else {
        Leds1 = 20;
      }
      ItWasDone5 = false;
    }

  }

  if (digitalRead(19) == HIGH) {  // SENSOR BOARD TRIGGER


    //************  ANALOG INPUT START  ****************

    Colour1A = (analogRead(36)) * 16;
    freq[0] = (Colour1A & 0xFF);
    freq[1] = ((Colour1A >> 8) & 0xFF);

    Colour1B = (analogRead(39)) * 16;
    freq[2] = (Colour1B & 0xFF);
    freq[3] = ((Colour1B >> 8) & 0xFF);

    Colour1C = (analogRead(34)) * 16;
    freq[4] = (Colour1C & 0xFF);
    freq[5] = ((Colour1C >> 8) & 0xFF);

    Colour1D = (analogRead(35)) * 16;
    freq[6] = (Colour1D & 0xFF);
    freq[7] = ((Colour1D >> 8) & 0xFF);

    Colour2A = (analogRead(32)) * 16;
    freq[8] = (Colour2A & 0xFF);
    freq[9] = ((Colour2A >> 8) & 0xFF);

    Colour2B = (analogRead(33)) * 16;
    freq[10] = (Colour2B & 0xFF);
    freq[11] = ((Colour2B >> 8) & 0xFF);

    Colour2C = (analogRead(25)) * 16;
    freq[12] = (Colour2C & 0xFF);
    freq[13] = ((Colour2C >> 8) & 0xFF);

    Colour2D = (analogRead(26)) * 16;
    freq[14] = (Colour2D & 0xFF);
    freq[15] = ((Colour2D >> 8) & 0xFF);

    //***************  ANALOG INPUT END  *****************

  } else {
    SensorBoard();
  }


  uint16_t Pot1A = smoothedReading[0] * 16;
  light[0] = (Pot1A & 0xFF);
  light[1] = ((Pot1A >> 8) & 0xFF);

  uint16_t Pot1B = smoothedReading[1] * 16;
  analog[0] = (Pot1B & 0xFF);
  analog[1] = ((Pot1B >> 8) & 0xFF);

  uint16_t Pot2A = smoothedReading[2] * 16;
  analog[2] = (Pot2A & 0xFF);
  analog[3] = ((Pot2A >> 8) & 0xFF);

  uint16_t Pot2B = smoothedReading[3] * 16;
  analog[4] = (Pot2B & 0xFF);
  analog[5] = ((Pot2B >> 8) & 0xFF);

  analog[6] = (Leds1 & 0xFF); // lower byte    ANALOG 3    LED OUTPUT 1 VALUE
  analog[7] = ((Leds1 >> 8) & 0xFF); // upper byte

  analog[8] = (Leds2 & 0xFF); // lower byte    ANALOG 4    LED OUTPUT 2 VALUE
  analog[9] = ((Leds2 >> 8) & 0xFF); // upper byte

  if ((unsigned long)(millis() - SerialTime_now) > SerialPeriod) {
    SerialTime_now = millis();

    Serial1.write(header, sizeof(header));
    Serial1.write(freq, sizeof(freq));
    Serial1.write(audio, sizeof(audio));
    Serial1.write(acc, sizeof(acc));
    Serial1.write(light, sizeof(light));
    Serial1.write(analog, sizeof(analog));
    Serial1.write(end, sizeof(end));

  }


  if ((unsigned long)(millis() - inaTime_now) > inaPeriod) {
    inaTime_now = millis();
    Serial.print("Shunt Voltage_A: "); Serial.print(shuntvoltage_A); Serial.println(" mV");
    Serial.print("Bus Voltage_A:   "); Serial.print(busvoltage_A); Serial.println(" V");
    Serial.print("Load Voltage_A:  "); Serial.print(loadvoltage_A); Serial.println(" V");
    Serial.print("Current_A:       "); Serial.print(current_mA_A); Serial.println(" mA");
    Serial.print("Power_A:         "); Serial.print(power_mW_A); Serial.println(" mW");
    Serial.println("");

    Serial.print("Shunt Voltage_B: "); Serial.print(shuntvoltage_B); Serial.println(" mV");
    Serial.print("Bus Voltage_B:   "); Serial.print(busvoltage_B); Serial.println(" V");
    Serial.print("Load Voltage_B:  "); Serial.print(loadvoltage_B); Serial.println(" V");
    Serial.print("Current_B:       "); Serial.print(current_mA_B); Serial.println(" mA");
    Serial.print("Power_B:         "); Serial.print(power_mW_B); Serial.println(" mW");
    Serial.println("");


  }


}


void SensorBoard()  //  SENSOR BOARD READ ROUTINE
{
  while (Serial1.available() > 0)                           // Something to receive?
  {
    receivedBytes[idx++] = Serial1.read();                  // Read next byte into array

    if (! started)                                         // Are we still trying to find the start marker?
    {
      if (receivedBytes[idx - 1] != startMarker[idx - 1])  // Check if the byte received matches expected.
        idx = 0;                                           // If not, start over.

      if (idx == START_BYTES)                              // Have we got all 6 bytes?
        started = true;                                    // Then we're started, so will read reset of data.
    }
    else                                                   // We're started.
    {
      if (idx == LENGTH)                                   // Read to the end?
        processData = true;                                // Set the flag so the data gets processed.
    }
  }


  if (processData)                                         // Flag set?
  {
    for (uint8_t x = 0; x < LENGTH; x++)                   // Loop through the array.
    {

      freq[0] = receivedBytes[6];
      freq[1] = receivedBytes[7];
      freq[2] = receivedBytes[8];
      freq[3] = receivedBytes[9];
      freq[4] = receivedBytes[10];
      freq[5] = receivedBytes[11];
      freq[6] = receivedBytes[12];
      freq[7] = receivedBytes[13];
      freq[8] = receivedBytes[14];
      freq[9] = receivedBytes[15];
      freq[10] = receivedBytes[16];
      freq[11] = receivedBytes[17];
      freq[12] = receivedBytes[18];
      freq[13] = receivedBytes[19];
      freq[14] = receivedBytes[20];
      freq[15] = receivedBytes[21];
      freq[16] = receivedBytes[22];
      freq[17] = receivedBytes[23];
      freq[18] = receivedBytes[24];
      freq[19] = receivedBytes[25];
      freq[20] = receivedBytes[26];
      freq[21] = receivedBytes[27];
      freq[22] = receivedBytes[28];
      freq[23] = receivedBytes[29];
      freq[24] = receivedBytes[30];
      freq[25] = receivedBytes[31];
      freq[26] = receivedBytes[32];
      freq[27] = receivedBytes[33];
      freq[28] = receivedBytes[34];
      freq[29] = receivedBytes[35];
      freq[30] = receivedBytes[36];
      freq[31] = receivedBytes[37];
      freq[32] = receivedBytes[38];
      freq[33] = receivedBytes[39];
      freq[34] = receivedBytes[40];
      freq[35] = receivedBytes[41];
      freq[36] = receivedBytes[42];
      freq[37] = receivedBytes[43];
      freq[38] = receivedBytes[44];
      freq[39] = receivedBytes[45];
      freq[40] = receivedBytes[46];
      freq[41] = receivedBytes[47];
      freq[42] = receivedBytes[48];
      freq[43] = receivedBytes[49];
      freq[44] = receivedBytes[50];
      freq[45] = receivedBytes[51];
      freq[46] = receivedBytes[52];
      freq[47] = receivedBytes[53];
      freq[48] = receivedBytes[54];
      freq[49] = receivedBytes[55];
      freq[50] = receivedBytes[56];
      freq[51] = receivedBytes[57];
      freq[52] = receivedBytes[58];
      freq[53] = receivedBytes[59];
      freq[54] = receivedBytes[60];
      freq[55] = receivedBytes[61];
      freq[56] = receivedBytes[62];
      freq[57] = receivedBytes[63];
      freq[58] = receivedBytes[64];
      freq[59] = receivedBytes[65];
      freq[60] = receivedBytes[66];
      freq[61] = receivedBytes[67];
      freq[62] = receivedBytes[68];
      freq[63] = receivedBytes[69];
      audio[0] = receivedBytes[70];
      audio[1] = receivedBytes[71];
      audio[2] = receivedBytes[72];
      audio[3] = receivedBytes[73];
      audio[4] = receivedBytes[74];
      audio[5] = receivedBytes[75];
      acc[0] = receivedBytes[76];
      acc[1] = receivedBytes[77];
      acc[2] = receivedBytes[78];
      acc[3] = receivedBytes[79];
      acc[4] = receivedBytes[80];
      acc[5] = receivedBytes[81];
    }
    started = false;                                       // Start looking for the start marker again.
    processData = false;                                   // Clear the processing flag.
    idx = 0;                                               // Reset the array index to start over.
  }
}

void alarm() {

  Leds1 = 2000;

}

void shutDown() {
  digitalWrite(18, HIGH);
}
[/code]

I tried using only one milli() and have it start again at the end of every if statement, but it wouldn't start over. I'll have to go though it again. At the moment this part of the code is the same as the one I posted in the beginning that obviously doesn't work.

I used switch years ago on a different project(and haven't done any coding since, that's why my questions are so basic), I didn't know it could be used in such a manner.

I'll try to brake it down to see if I understand it correctly:

My intervals are 250ms, so LED_Periods would look like this:

const unsigned long LED_Periods[] = {250, 500, 750, 1000, 1250, 1500 etc};

The sequence is as follows:
Turn on 5 Leds
Measure load
If load exists, Leds are connected, move to the next case.

If it doesn't, stop.
Save the Led number to a variable.
Write that variable to EEPROM.

So using your code, the first 2 cases would be:

switch (eventSwitch) {
case WaitingForButton: {
    if (pushedTheButton) {
      Leds1 = 405;  // Turn on Leds 1-5, everything else off
      eventTimestamp = millis();
      eventInterval = LED_Periods[(unsigned char) eventSwitch];
      eventSwitch = Intro;
    }
    break;
  }
case Intro: {
    // event stuff
    if (millis() - eventTimestamp >= eventInterval) {
      if (power_mW_A > 300) {
        Leds1 = 410;  // Turn on Leds 6-10, everything else off
        eventSwitch = Act1;
      } else {
        Leds1 = 0;  // No Leds found, Leds = 0
        EEPROM.write(0, Leds1);
        EEPROM.commit();
      }
      eventTimestamp = millis();
      eventInterval = LED_Periods[(unsigned char) eventSwitch];
    }
    break;
  }
case Act1: {
    // event stuff
    if (millis() - eventTimestamp >= eventInterval) {
      if (power_mW_A > 300) {
        Leds1 = 410;  // Turn on Leds 6-10, everything else off
        eventSwitch = Intermission;
      } else {
        Leds1 = 5;  // 5 Leds found, Leds = 5
        EEPROM.write(0, Leds1);
        EEPROM.commit();  
      }
      eventTimestamp = millis();
      eventInterval = LED_Periods[(unsigned char) eventSwitch];
    }
    break;
  }

In this manner we move from one case to the next based on the presence of load in the previous case, correct?

Given that the time needed is always 250ms, could I replace

const unsigned long LED_Periods[] = {250, 500, 750, 1000, 1250, 1500 etc};

with

LED_Period = 250;

Yes, bingo... what you were doing wrong the first attempt is synching all at the beginning and then trying to step through many when it's much more straightforward to sync each time, when you get there.

in simplified psuedocode:

if (loadPresent) {
  Leds1 = 410;
  eventSwitch = Act1;
}
else {
//all LEDs off
eventSwitch = WaitingForButton;

I don't understand exactly what 410 and 405 are, if that is an address or a magic number somehow, but it appears to be a lookup table, so why not put those numbers in an array and then index through the array?

In short:

In the other controller, Leds are numbers 1-300, so I keep these numbers reserved for the actual leds.

In order to light specific parts of the leds, I'm using numbers 400 and above. These are my numbers, they could be anything. I chose to start from 400, and go up in increments of 5 to keep it simple and more understandable. In that sense, they could be 401, 402, 403 etc, with every number symbolizing 5 leds.

So the code I've setup in the other controller, goes like this: If you receive number 405, light up the first 5 leds, and switch off the rest.

Then I would have to somehow incorporate the array in the switch? Instead of having 30 cases I'd do it with 1?

are you just trying to figure out how many LED "sets" you have or if they aren't burnt out?

what are you using the time measurements for?

could you summarize what you're trying to do overall?

lots of redundant code that could probably be simplified

Yes, I try to figure out how many sets are connected.

I have to first send the command to the controller to turn on the Leds. Even though this happens quite fast, it's not instantaneous, so I prefer to have a bit of time between each reading, as the sequence is Turn ON, Measure, Turn OFF, Turn ON next, Measure, etc. Once I've figured out the rest of the code, I'll start lowering the measuring intervals and see what's the lowest I can go.

The Leds are addressable, and knowing the exact number makes all the difference with the patterns. I could just turn on all leds, measure current and divide, but the way I've made this, it's kind of a puzzle and they can connect the bricks not only in series, but also in parallel. In that case I'd get false readings, so the only safe way is to turn on 5 leds at a time. I hope it makes sense.

still not sure what your trying to do. but to determine which led "sets" are available, consider

// simulation functions

// -------------------------------------
#define LedCodeOff  0
void
ledWriteCode (
    int   code )
{
    Serial.print ("  ledWriteCode: ");
    Serial.println (code);
}

// -------------------------------------
int
measureCurrent (void)
{
    return random (50, 100);
}

// -----------------------------------------------------------------------------
struct Led  {
    int     code;
    bool    active;
    int     current;
};

Led leds [] = {
    { 405 },
    { 415 },
    { 425 },
    { 435 },
    { 445 },
};
#define Nled    (sizeof(leds)/sizeof(Led))

// -------------------------------------
#define CheckLedsDelay   100
#define MinLedCurrent    60

void
checkLeds (void)
{
    Led *p = leds;
    for (unsigned n = 0; n < Nled; n++, p++)  {
        Serial.print (" checkLeds: ");
        Serial.print (p->code);

        ledWriteCode (p->code);

        p->current = measureCurrent (); 
        if (MinLedCurrent <= p->current)  {
            p->active = true;
            Serial.print (" active");
        }
        else
            Serial.print (" not active");

        ledWriteCode (LedCodeOff);
        delay (CheckLedsDelay);
    }
}

// -----------------------------------------------------------------------------
void
setup ()
{
    Serial.begin (9600);

    checkLeds ();
}

void
loop ()
{
}

This is why I asked you in the beginning to explain what you want to do. Going to a lookup table doesn't change the answer to the above question. I am still unsure if you could use 2 or 31 states... I will describe what I have to assume.... You have bricks of 5 LEDs each. then easily connect to one another and to a controller such that 1 brick connected can only be connected to position 0 and adding another brick would put it in position 1 etc. to a max of 30 bricks. And, you want your kids to put some number of bricks on the tower, then press a button, and that one button will light up the bricks in sequence from the first to the last connected.... You have no other means of detecting the connected bricks save for how much power they draw.... So, if 5 bricks are detected, you want to go from position 0 to position 5. For anything I say below this, is contingent on my understanding of the above, which is why I say it's an xy problem, and it's rather difficult to solve x by talking about y...

I will talk about a 7-segment LED cube (they are called 7-segment, but they also have an 8th "segment" that is the decimal point, usually requires a different current-limitiing resistor, and they come in either common cathode or common anode). each segment might be addressed to 1 bit in an 8-bit register, such that 3 (binary 00000011) would light 2 segments. Now, a if these bits are addressed 0-7 the same as the segments A,B,C,D,E,F,G and DP, then the number 7 would use some of the segments different from the number 2 and so on... and you would organize which value makes a 0 and which makes a 1 and which makes a 2 etc. all the way up to 9 or beyond if you wanted a space or an underscore etc. in a lookup table.... this way the byte value of segments for 0, when indexed by the number 0 would be in the same position, and the byte value for 7 would be in position 7 etc. That's what a lookup table can do...

In your case, if when you push button, you go from 400 to 405, 410,415, 420 etc. and it's the same sequence every time, in other words you push button and measure 5 bricks and now you want to light brick 0, then 1, then 2, then 3, then 4, then 5 and stop, I don't think you want a lookup table... you can accomplish this with 2 constants. The starting value and the increment... You may not even need a switch case....

for (i = 0; i < ledsDetected; ) {
  if (millis() - timeStamp >= 250 {
    timeStamp += 250;
    Leds1 = 400 + (i * 5);
    i++;
  }
}  

This is very rough, but I hope it explains why I can't help you as much until you give a few more details.

Maybe a circuit diagram would help visualize what you are trying to do?
And a link to Pixelblaze and blocks.

I'm having trouble understanding some parts of the code.

In the ledWriteCode bit, "code" represents the number of leds available, correct? Every time current > MinLedCurrent, "code" would be incremented by 1?

In the void checkLeds:

Measuring will go through the whole array, regardless if a set is active or not, correct? I need to have it stop once it gets to an inactive set, then write the led value to EEPROM. I don't want this last bit to happen in the ledWriteCode part, as it would be doing an EEPROM write every time the led count has changed, I only want it to happen at the end of the process.

You are using a delay, I guess I should replace it with millis() as it has to be non-blocking. Can I do that outside loop()?

still not clear what you're trying to do. this is an attempt saying -- "is this what you mean"?

i don't see where in your code your actually turning on a LED or "set"(?) of LEDs. i don't understand what your codes mean.

i say "set" because it's not clear what your controlling. are you really just measuring the current drawn by a single LED?

yes it's going thru an array defining multiple LED "sets". that array of structs also captures the the measured current and whether it measured a current > than some min.

are you just measuring current to determine the # of single (?) LEDs you have?

didn't know about your use of the EEPROM. you can do some analysis and update the EEPROM after the analysis completes.

again, a clear explanation of what your trying to do would help

I think I understand what you’re trying to do.
I didn’t try to understand your existing code…

The Initial phase of operation seems to be ‘discovery’ of how many blocks (or LEDs); are connected. Is this needed every time the device is powered on, or only when the user tells the number of blocks has changed??

I like the basi c idea, but other than measuring the current being drawn, the rest of your code seems far too ‘over thought

Read about arrays, structs, EEPROM and other mid level methods. You may need ro think about distributed power reticulation to the LEDs, so you know what you’re measuring and where.’.

I realize I'm doing a terrible job at explaining what I'm trying to accomplish:)

I'll try to simplify things and kind of take it from the top.

I have an addresable LED controller called Pixelblaze(PB for short). The controller doesn't know how many LEDs are connected to it, you have to let it know via a web interface. I don't want to do it this way, I prefer to just press a button and have this done automatically.

Enter the ESP32. It is connected to Pixelblaze via serial, and sends a packet of data to it every 40ms. Among them, a value that represents the number of LEDs connected.

The ESP32 retrieves the LED value from EEPROM on every boot.

In order to determine how many LEDs are connected, I do the following:

(This is where I'll simplify the description, let's pretend we want to measure 1 LED every time, not 5)

On the PB side, I'm writing code that reads the value from the ESP. If the value is higher than 400, then PB will turn off all LEDs(like all addressable led controllers, it has no feedback loop, so if you tell it to turn on 1000 leds it will send the signal, regardless if they are physically connected or not), and leave on only the ones corresponding to the last 2 digits of the value.

So, if it receives the number 400, all LEDs are OFF. 401: LED 1 is ON, all else OFF. 455: LED 55 is ON, all else OFF, etc.

On the ESP32 side, how do I determine how many LEDs are connected to PB?

The LED strip is connected to a current measuring IC on ESP32. Receiving any value above a minimum, means some(or one) LEDs are ON.

So, in sequence, if I wanted to let Pixelblaze know how many LEDs are connected, I would have the following happen after I press a button(let's assume there are a total of 3 LEDs):

  1. Send value 401. At this moment, PB will have LED no 1 ON, and everything else OFF.
  2. Read current. Is it above the minimum? If it is, we know there is at least 1 LED connected, let's see if there is more.
  3. Send value 402. At this moment, PB will have LED no 2 ON, and everything else OFF.(Previous LED is OFF as well)
  4. Read current. Is it above the minimum? If it is, we know there is at least 2 LEDs connected, let's see if there is more.
  5. Send value 403. At this moment, PB will have LED no 3 ON, and everything else OFF.(Previous LEDs are OFF as well)
    6.Read current. Is it above the minimum? If it is, we know there is at least 3 LEDs connected, let's see if there is more.
  6. Send value 404. At this moment, PB will have LED no 4 ON, and everything else OFF.(Previous LEDs are OFF as well)
  7. Read current. It is below the minimum, therefore there are no more LEDs connected. Time to write the LED value(3) to EEPROM, and send it to PB.

This process should be able to continue for as long as the current measurement is above the minimum, all the way to a predetermined upper limit(let's say 200 LEDs).

I hope it's a bit more clear now.

if all you want to do is determine the # of available LEDs,

  • start at the first, turn it on,
  • check for a current, (don't know if you need a slight delay)
  • turn it off, and
  • repeat for each until you don't see a change in current.

this code can be a simple for loop, similar to what i posted.