How does millis and while work in this code

unsigned long previousMillis = 0;
const long interval = 1000;
unsigned long temp = 0;

void setup() {
  Serial.begin(115200);
}

void loop() {
  unsigned long currentMillis = millis();
  temp = currentMillis;
  
  Serial.println("Hello world");
  millisAsDelay();
  //delay(1000);
                  
}

void millisAsDelay(){  
  while (millis() < temp + interval) {
    previousMillis = temp;
  }
}

i’ve mashed together a code to make a substitute for delay() function, but i dont understand how it works. it basically prints after every 1sec. how does the while loop works in code?

Actually, you have implemented while-do loop in the millisAsDelay() subfunction. This link describing the working principle of millis() function may help you to find the answer for yourself.

Avoid the use of 'while' unless you know what pitfalls can occur.

'while' can lead to blocking code.

Learning how to make a timer properly with the millis() BWD technique is something you must master.

Lots of examples on this website.

Do you understand what happens in the code below?

unsigned long previousMillis_A;
unsigned long previousMillis_B;

const unsigned long interval_A = 1000;
const unsigned long interval_B = 3000;

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  unsigned long currentMillis = millis();

  //***********************************
  if (currentMillis - previousMillis_A >= interval_A)
  {
    previousMillis_A = currentMillis;
    Serial.println("Hello world");
  }
  
  //***********************************
  if (currentMillis - previousMillis_B >= interval_B)
  {
    previousMillis_B = currentMillis;
    Serial.println("Good bye world");
  }
  
  //***********************************
   
} //END of loop()

larryd:
Avoid the use of ‘while’ unless you know what pitfalls can occur.

‘while’ can lead to blocking code.

Learning how to make a timer properly with the millis() BWD technique is something you must master.

Lots of examples on this website.

Do you understand what happens in the code below?

unsigned long previousMillis_A;

unsigned long previousMillis_B;

const unsigned long interval_A = 1000;
const unsigned long interval_B = 3000;

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  unsigned long currentMillis = millis();

//***********************************
  if (currentMillis - previousMillis_A >= interval_A)
  {
    previousMillis_A = currentMillis;
    Serial.println(“Hello world”);
  }
 
  //***********************************
  if (currentMillis - previousMillis_B >= interval_B)
  {
    previousMillis_B = currentMillis;
    Serial.println(“Good bye world”);
  }
 
  //***********************************
 
} //END of loop()

i just got the basics of it, the if statement displays “hello world” after it detects that the difference of currentMillis and previousA is 1000 or greater, the same with the other if statement it displays “good bye world” with 3000 difference

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

UKHeliBob:
Have you read and understood Using millis() for timing. A beginners guide ?

yep got the basics of it. but still don’t know how to use it on program that i’m trying to do:

#include <FastLED.h>
#define NUM_LEDS 30 
#define DATA_PIN 5

CRGB leds[NUM_LEDS];

const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];

//temporary
char pointerToEffect[numChars] = {0};
int firstData = 0;
int secondData = 0;
int thirdData = 0;
int fourthData = 0;
int fifthData = 0;
int sixthData = 0;

boolean newData = false;

unsigned long previousMillis = 0;
const long interval = 1000;
//unsigned long temp = 0;

void setup() {
  Serial.begin(9600);
  LEDS.addLeds<WS2812,DATA_PIN,RGB>(leds,NUM_LEDS);
  LEDS.setBrightness(250);
}

void loop() {
  unsigned long currentMillis = millis();
  //temp = currentMillis;

  recvWithStartEndMarkers();

  if (newData == true) {
       strcpy(tempChars, receivedChars);
       parseData();
       //showNewData();
       setAll(0,0,0);
       newData = false;
  }

    switch(pointerToEffect[0]) {
       case 'a':
         //Twinkle - Color (red, green, blue), count, speed delay, only one twinkle (true/false)
         twinkle(secondData, thirdData, fourthData, fifthData, sixthData);
         showNewData();
         break;
 
       case 'b':
         //first data is ratioPercent, second is delaySpeed
         //65, 85
         cylon(secondData);
         break;
      
    }      
}

/////////////////////////////////////////////////////////////////////////////////////

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;
 
    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

/////////////////////////////////////////////////////////////////////////////

void parseData() {      // split the data into its parts

    char * strtokIndx;

    strtokIndx = strtok(tempChars,",");
    strcpy(pointerToEffect, strtokIndx);
 
    strtokIndx = strtok(NULL, ",");
    firstData = atoi(strtokIndx);

    strtokIndx = strtok(NULL, ",");
    secondData = atoi(strtokIndx);

    strtokIndx = strtok(NULL, ",");
    thirdData = atoi(strtokIndx);

    strtokIndx = strtok(NULL, ",");
    fourthData = atoi(strtokIndx);

    strtokIndx = strtok(NULL, ",");
    fifthData = atoi(strtokIndx);

    strtokIndx = strtok(NULL, ",");
    sixthData = atoi(strtokIndx);
}

//////////////////////////////////////////////
//tester
//////////////////////////////////////////////

void showNewData() {
        Serial.print("Pointer to effect ");
        Serial.println(pointerToEffect);
        Serial.print("First data ");
        Serial.println(firstData);
        Serial.print("Second data ");
        Serial.println(secondData);
        Serial.print("Third data ");
        Serial.println(thirdData);
        Serial.print("Fourth data ");
        Serial.println(fourthData);
        Serial.print("Fifth data ");
        Serial.println(fifthData);
        Serial.print("Sixth data ");
        Serial.println(sixthData);
}

///////////////////////////////
//All LED effect functions here
///////////////////////////////

void fadeall(int ratioPercent) { for(int i = 0; i < NUM_LEDS; i++) { leds[i].fadeToBlackBy(ratioPercent); } }

void cylon(int delaySpeed) { 
  static uint8_t hue = 0;
  for(int i = 0; i < NUM_LEDS; i++) {
    leds[i] = CHSV(hue++, 255, 255);
    FastLED.show(); 
    fadeall(firstData);
    delay(delaySpeed);
  }
  
  for(int i = (NUM_LEDS)-1; i >= 0; i--) {
    leds[i] = CHSV(hue++, 255, 255);
    FastLED.show();
    fadeall(firstData);
    delay(delaySpeed);
  }
}

void twinkle(byte red, byte blue, byte green, int count, int speedDelay) {
   
  // byte red, byte blue, byte green, int count, int speedDelay, boolean onlyOne
  // red = second data, blue = third data, green = fourth data, count = fifth, speedDelay = sixth data onlyOne = dependent on first data
  //byte red = 0xff;
  //byte blue = 0x00;
  //byte green = 0x00;
  //int count = 5;
  //int speedDelay = 500;
  boolean onlyOne = true;
  

  if (firstData == 1){
    onlyOne = true;
    }
  else if (firstData == 0){
    onlyOne = false;
    }

  
  setAll(0,0,0);
  
  for (int i=0; i<count; i++) {
     setPixel(random(NUM_LEDS),red,green,blue);
     FastLED.show();
     delay(speedDelay);
     if(onlyOne) {
       setAll(0,0,0);
     }
   }
 
  delay(speedDelay);
}

/*void millisAsDelay(){  
  while (millis() < temp + interval) {
    previousMillis = temp;
  }
} */

////////////////
//Set all pixel
///////////////

void setPixel(int Pixel, byte red, byte green, byte blue) {
   leds[Pixel].r = red;
   leds[Pixel].g = green;
   leds[Pixel].b = blue;
}

// Set all LEDs to a given color and apply it (visible)
void setAll(byte red, byte green, byte blue) {
  for(int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue);
    }
  FastLED.show();
}

im trying to make it so that when a new data is received it applies that effect immediately without waiting for the previous effect to finish. i’ve tried to do it using only a single effect but does it so fast that it ruins the selected effect. here’s the code:

#include <FastLED.h>
#define NUM_LEDS 30 
#define DATA_PIN 5

CRGB leds[NUM_LEDS];

int period = 1000;
unsigned long previousMillis = 0;
unsigned long previousMillis2 = 0;
unsigned long currentMillis;

void setup() { 
	LEDS.addLeds<WS2812,DATA_PIN,RGB>(leds,NUM_LEDS);
	LEDS.setBrightness(255);
}

void fadeall() { for(int i = 0; i < NUM_LEDS; i++) { leds[i].fadeToBlackBy(25); } }

void loop() { 
	static uint8_t hue = 0;
  currentMillis = millis();

  if(currentMillis - previousMillis >= period){
	  for(int i = 0; i < NUM_LEDS; i++) {
		  leds[i] = CHSV(125, 255, 255);
		  FastLED.show(); 
		  fadeall();
	  }
    previousMillis = currentMillis;
  }
      
		
  
  if(currentMillis - previousMillis2 >= period){
	  for(int i = (NUM_LEDS)-1; i >= 0; i--) {
		  leds[i] = CHSV(hue++, 255, 255);
		  FastLED.show();
		  fadeall();
	  }
    previousMillis2 = currentMillis;
  }
}

millis() is a delaying action and should be used in your code. What I take it that you want is a way to interrupt and reset the delaying action upon receipt of new data.

something like

bool stopAction = false;

void codeGotNewStuff(), stopAction = true

void Doing_the_millis_thing()

doDasMilliStopHere

no

check stopAction do things if true on ignore if false

yes continue the millis() thing.

Here is a simplified version of your code that does the same thing the same way. I just removed some unnecessary variables, made ‘temp’ a local variable, and moved the delay loop into loop() to make it easier to see what is going on.

const long interval = 1000;
void setup()
{
  Serial.begin(115200);
}


void loop()
{
  Serial.println("Hello world");

  unsigned long temp = millis();  // This should probably have been in millisAsDelay()


  // Start of millisAsDelay()

  while (millis() < temp + interval)
  {
    // Do Nothing
  }
  // End of millisAsDelay()

}

It becomes clear that you are delaying by setting ‘temp’ to millis() and then sitting in a loop doing nothing until it is no longer true that millis() is less than temp+interval.

WARNING: There is a problem in the code that will bite you in about 47 days. When millis() gets very close to rolling over to 0, ‘temp + interval’ will be a small number because it has rolled over while millis() will be a very large number, The delay will not happen and, for that ‘interval’, the “Hello world” will output repeatedly as fast as it can.

To avoid such problems, always subtract ‘temp’ from millis():

  while (millis() - temp < interval)
  {
    // Do Nothing
  }

johnwasser:

  while (millis() - temp < interval)

{
    // Do Nothing
  }

‘Do Nothing’ or the MCU actually checks if there is something to do; if not, it evaluates the argument of the while() structure; if there is something to do – that is done and then the argument of the while() structure is evaluated.

Idahowalker:
millis() is a delaying action and should be used in your code. What I take it that you want is a way to interrupt and reset the delaying action upon receipt of new data.

something like

bool stopAction = false;

void codeGotNewStuff(), stopAction = true

void Doing_the_millis_thing()

doDasMilliStopHere

no

check stopAction do things if true on ignore if false

yes continue the millis() thing.

this is i think the outline of what im trying to do. the stopAction is what i think is missing. whats the purpose the void Doing_the_millis_thing(), is it to make it like a delay that executes first, then next do the selected effect, then back and forth? can you please explain this outline?

GolamMostafa:
'Do Nothing' or the MCU actually checks if there is something to do; if not, it evaluates the argument of the while() structure; if there is something to do -- that is done and then the argument of the while() structure is evaluated.

the 'do nothing' is like still executed right? the logic is that 'while this is true do nothing' in manner that it checks everytime that function is called? please correct me if i'm wrong