Millis() function not behaving as expected

Hello,

I am making a program where LED strips need to operate in 2 modes.
First, measures some values from the analog pin and depending on how high the value is, that's how much LEDs change color.
The other one is just fading lights in 2 colors.
The two functions work separately but from the first function to switch to the nect function, the value of the analog pin shouldn't exceed 160 for 5s. I am trying to achieve this with millis() bur for some reason it doesn't work.
It eighter changes to the other function immediately or it doesn't change at all.
Any help on that can be the problem is useful.

#include <FastLED.h>

unsigned long interval_ms = 5000;
unsigned long lastExecutedMillis = 0; // vairable to save the last executed time


#define LED_PIN1    2
#define LED_PIN2    3
#define LED_PIN3    4
#define LED_PIN4    5
#define NUM_LEDS    25

CRGB leds[NUM_LEDS];

void setup() {

  FastLED.addLeds<WS2812B, LED_PIN1, GRB>(leds, NUM_LEDS);
  FastLED.addLeds<WS2812B, LED_PIN2, GRB>(leds, NUM_LEDS);
  FastLED.addLeds<WS2812B, LED_PIN3, GRB>(leds, NUM_LEDS);
  FastLED.addLeds<WS2812B, LED_PIN4, GRB>(leds, NUM_LEDS);
  Serial.begin(115200);
  for(int i = 0; i < NUM_LEDS ; i++){
    leds[i] = CRGB(0, 0, 0);
    FastLED.show();
  }
}

void loop() {
  static int state = 1;
  static int last_val = 0;
  int voltage = analogRead(A0);
  Serial.println(voltage);

  int value = map(voltage, 140, 420, 1, NUM_LEDS);
  switch(state){
      case 0:
        measure_mode(value);
        if(voltage > 160){
           lastExecutedMillis = millis(); // save the last executed time
           Serial.println("here");
          }
        if (millis() - lastExecutedMillis >= 5000) {
          state = 1;  
          //Serial.println("there");
        }
        break;
      case 1:
        standby_mode();
        
        if(voltage > 160){
            state = 0;
        }
        break;
    } 
}


void measure_mode(int value){
    if(value >= 0 && value < NUM_LEDS){
      //lastExecutedMillis = millis(); // save the last executed time
      for(int i = 0; i < value ; i++){
        leds[i] = CRGB(204, 230, 255);
        FastLED.show();
      }
      for(int i = NUM_LEDS; i > value+1 ; i--){
        leds[i] = CRGB(242, 107, 107);
        FastLED.show();
      }
    }
    else{
      if(value < 0){
        for(int i = NUM_LEDS; i > 0 ; i--){
          leds[i] = CRGB(242, 107, 107);
          FastLED.show();
        }
      }
      else if(value > NUM_LEDS){
          for(int i = 0; i < NUM_LEDS ; i++){
          leds[i] = CRGB(204, 230, 255);
          FastLED.show();
        }
      }
    }
}

void standby_mode(){
  static int i = 0;
  static int dir = 0;
  static int color = 0;
  if(i < 244 && dir == 0){
    for(int j = 0; j < NUM_LEDS; j++){
      if(color == 0){
        leds[j] = CHSV(201, 94, i);
      }
      else if(color == 1){
        leds[j] = CHSV(0, 100, i);  
      }
    }
    i++;
    if(i == 244){
      dir = 1;
      i = 0;
      }
    FastLED.show();
  }
  else if(i < 244 && dir == 1){
    for(int j = 0; j < NUM_LEDS; j++){
      if(color == 0){
        leds[j] = CHSV(201, 94, (244 - i));
      }
      else if(color == 1){
        leds[j] = CHSV(0, 100, (244 - i));  
      }
    }
    i++;
    if(i == 244){
      dir = 0;
     i = 0;
      if(color == 0){
        color = 1;  
      }
      else if (color == 1){
        color = 0;  
      }
    }
    FastLED.show();
   }
}

Your topic was MOVED to its current forum category as it is more suitable than the original

You save the value value of millis() in lastExecutedMillis, which is good. Then next time around you again save the new value of millis() in lastExecutedMillis so lastExecutedMillis never gets chance to be much less than millis(), certainly not 5000 less. You need a way of only saving it once.

Have you read Using millis() for timing. A beginners guide ?

I suggest that you use more cases, so that as soon as case 0 has saved millis() you move to case 1 and in case 1 you do the timeout.

And well done for posting your code correctly :smiley:

But the new value is saved in lastExecutedMillis only when the value on the analog pin exceeds 160. Which id doesn't and still that happens. Until then shouldn't the lastExecutedMillis stay the same?

I know. Every time. What in your code stops it being saved again and again for as long as the analogue pin exceeds 160?

Or have I misunderstood something?

I want millis to be saved at the lastExecutedMillis every time the measured value exceeds 160. In that way it won't go into the next state. But when the measured value is below 160 then I want to stop saving it and from the last save to count 5s until it goes into the function which switches to state 2. The problem is that eighter it immediately goes to state 2 when the value drops below 160 and doesn't wait 5s or never does. It is one of the two things in random.

Hello svetoslav141
Post a timing diagram to see what when shall be happens.
Have a nice day and enjoy coding in C++.

here is a wokwi simulation of your code with a linear potentiometer and a neopixel-ring.
The more important part is the intervalled serial output.
There are two macros that do that
me personal I find these macros very useful as it reduces the code that must be added for serial output

best regards Stefan

OK, I clearly didn't understand properly when I first read it.

However, you say:

But there is no state 2 in your code, only 0 and 1, or did you mean the second state, which is 1?

I can see a possible problem in that in both case 0 and 1 you look for > 160, but this assumes that the the output from analogue read is stable and doesn't jump about in it's reading, which is probably not the case. So, in state 0 it might be just under 160 and move to state 1 where is is just over 160 again even without the input changing. Try making the comparison different in each state, for example in state 1 maybe try > 180 or > 200 so it really has to be much higher than it was in state 0.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.