Modulo Question - Intervall/Frequency

Hi Community,

im going crazy so i have to ask!

I found the Modulo Method and i have some Questions:

  1. Why is here every 40 millis happening something? Isnt it every 40 millis a “0”?
  mill_akt = millis() % 40;
  if (mill_akt < mill_alt) {
    setLEDs();
    sdim++;
    if (sdim > 24) {
      sdim = 0;
    }
  }
  1. And when/why do i divide it before sometimes?
void setup(){
   pinMode(LED_BUILTIN, OUTPUT);
}

void loop(){
   digitalWrite (LED_BUILTIN, (millis() / 1000 % 2);
}
  1. How is it possible to blink every 650 millis/ 1,5Hz? Is it like:
do_something = millis() % 650;

Sorry for my confusion but every time i thought i got it its getting more worse :astonished: :wink:

I understood what modulo is doing with the math but there are still the three questions.

Thanks a lot!

Z

  1. Why is here every 40 millis happening something? Isnt it every 40 millis a "0"?

Something is happening every millisecond, not every 40. The result varies from 0 to 39 sequentially once every millisecond. A test for zero would look like:

  if (mill_akt == 0) {
  1. And when/why do i divide it before sometimes?

Have you tried dividing by different numbers? :wink:

For 3. you could

digitalWrite (LED_BUILTIN,  millis % (650 * 2) >= 650 );

You should also note that using the modulo operator with millis() may not be entirely satisfactory for small values because other code might take longer than the timing period and testing the result of modulo is looking for an exact match, usually zero. There is also the problems that millis() skips some values under certain circumstances and that modulo can take some time to execute

A more satisfactory way is to use subtraction of a saved value of millis() (the start time) from the current value of millis() and testing whether a period is elapsed

blink every 650 millis/ 1,5Hz?

It depends a little what you mean by that, if you want every “On” to be 1.5 Hz then it could be digitalWrite (LED_BUILTIN, (millis() % 650) / (650 / 2)

testing the result of modulo is looking for an exact match, usually zero.

You should not really test the result exactly, rather test for bounds to the result, or divide the result. There are disadvantages to using modulo, that is true, but there are also advantages, particularly when you may want more than 2 possible output states (for instance with a cylon pattern on ledstrip)

There is also the problems that millis() skips some values under certain circumstances

True ! keep in mind though that for visual effects this is not an issue, at those speeds your mind will fill in the blanks.

modulo can take some time to execute

it is considerably slower than subtraction and compare.

A more satisfactory way is to use subtraction of a saved value of millis() (the start time) from the current value of millis() and testing whether a period is elapsed

But for a square wave at a frequency, you should then add the cycle length to the start time as well, to make sure the frequency stays as close to the desired one as possible, and though you make sure that you do have every state-change, your timing may be just as much incorrect. It does depend on what you want to use the result for and why. There is also the option of using a timing interrupt

Boooom - mind blowing! :kissing:

First: Thanks for the answers!

@aarg

  1. thanks that is what i supected! so i have every multiple of 40 a “0” and in the other cases something between 1-39. So i was right with my thoughts. It was from another German threat and they wrote “there is happening something every 40 millis”. But i didnt get it what they wrote.

@everybody

Can somebody explain what is happening here in detail. I don’t get the multiply by 2 no matter what i do…im sorry.

digitalWrite (LED_BUILTIN,  millis % (650 * 2) >= 650 );

or

digitalWrite (LED_BUILTIN, (millis() % 650) / (650 / 2)

I understand the reason why substraction/storing method is a good solution and the thing with skipping. On the first look i think the modulo method should be the easiest way to modify the code and the skipping is not a problem for the indicator.

The background infos are - Its from the ClickButton library. I’m doing a indicator for my motorbike and i need 1,5Hz frequency. The buttons should have multiple functions, thats the reason for the ClickButton library. Here a part of the code.

void loop()
{

  //Blinkersektion
  
  // Go through each button and set the corresponding LED function
  for (int i=0; i<BlinkButtons; i++)
  {
    // Update state of all buttons
    BlinkButton[i].Update();
  
    // Save click codes in LEDfunction, as clicks counts are reset at next Update()
    if (BlinkButton[i].clicks != 0) BlinkLEDfunction[i] = BlinkButton[i].clicks;
  

    // Simply toggle LED on single clicks
    // (Cant use LEDfunction like the others here,
    //  as it would toggle on and off all the time)
    if(BlinkButton[i].clicks == 1) BlinkLedState[i] = !BlinkLedState[i];

    // blink faster if double clicked
    if(BlinkLEDfunction[i] == 2) BlinkLedState[i] = (millis()/500)%2;

    // blink even faster if triple clicked
    if(BlinkLEDfunction[i] == 3) BlinkLedState[i] = (millis()/200)%2;

    // slow blink (must hold down button. 1 second long blinks)
    if(BlinkLEDfunction[i] == -1) BlinkLedState[i] = (millis()/1000)%2;

    // slower blink (must hold down button. 2 second loong blinks)
    if(BlinkLEDfunction[i] == -2) BlinkLedState[i] = (millis()/2000)%2;

    // even slower blink (must hold down button. 3 second looong blinks)
    if(BlinkLEDfunction[i] == -3) BlinkLedState[i] = (millis()/3000)%2;
  }

Ok, let me explain my algorithm. I take the modulo of millis() by 650 (is that correct grammar in English ?) which results in a value between 0 - 649, now if i divide this value by half of 650 (= 325) any value below that will result in '0' and the other values will result in '1'
If you would want the duty cycle to be more than 50%, dividing 650 by 3 will cause in the result of the modulo to be divided by 216, and the possible results are '0', '1' & '2'
In my algorithm the total cycle is 650ms (with Aarg's it is 1300ms, and a state change every 650ms) I hope that did not confuse you, a wave of 1.5Hz has a cycle of 667ms, how you want it is up to you.(millis()/2000)%2;this is of course a perfectly good algorithm as well, resulting in 2000ms on, 2000ms off.

Thanks a lot for the explanation!

I perfectly understood your example. This helps a lot.

Your cycle ist 650 ms when i divide by 3 i can do the half an so on. So it doesnt care if i write (650/2) or 325 its only more easier when i want to change the values?!
When i want to blink in 1,5hz so the light will be on for 650ms and off for 650ms. that is one cycle?

The only confusion is still the multiplication/devision:

digitalWrite (LED_BUILTIN,  millis % (650 * 2) >= 650 );
(millis()/2000)%2;

In the first, Why is it multiplicate by 2? And why is the cycle 1300ms? - I get between 0-649 by the modulo then i multiplicate it by 2. When the result of the modulo is 325, multiplicated by 2 the result is >= 650 so in this moment its true.
So its the same like your cycle isnt it?

In the second, why is it devided by 2000? isnt millis() go on until 4billionwhatever and then resetting to zero?

Thank a lot four your patience and help !

Z

PS. i got the second example! its all about the integer and that there are no decimals! so i get the 2000 ms!

still the understanding problem of the first: why multiplicated by 2?!?

gnom:
PS. i got the second example! its all about the integer and that there are no decimals! so i get the 2000 ms!

still the understanding problem of the first: why multiplicated by 2?!?

I assumed you wanted a full cycle of 1300ms, you could make it more generic by dividing:

const int CYCLE_INTERVAL = 1300;
const int ON_DURATION = CYCLE_INTERVAL / 2; // for a square wave
...
digitalWrite (LED_BUILTIN,  millis % CYCLE_INTERVAL < ON_DURATION );

You can vary the pulse length:

const int CYCLE_INTERVAL = 1300;
const int ON_DURATION = CYCLE_INTERVAL / 10; // for a beacon pulse 10% duty cycle
...
digitalWrite (LED_BUILTIN,  millis % CYCLE_INTERVAL < ON_DURATION );

How does it work? It effectively sets up a repeating counter that rolls over after some maximum value, that creates a time frame. After that, you can use the timer value to control multiple synchronized events, for example here is a beacon that alternates with the one above:

const int CYCLE_INTERVAL = 1300;
const int ON_DURATION = CYCLE_INTERVAL / 10; // for a beacon pulse 10% duty cycle
const int DURATION2_OFFSET = CYCLE_INTERVAL / 2; // for a second beacon pulse 10% duty cycle
...
int counter = millis % CYCLE_INTERVAL;
digitalWrite (LED_BUILTIN, counter  < ON_DURATION );
digitalWrite (LED_2,  counter >= DURATION2_OFFSET and counter >= DURATION2_OFFSET + ON_DURATION);

So it doesnt care if i write (650/2) or 325 its only more easier when i want to change the values?!

Pretty much yeah. I think Aarg has covered it more or less no ?

void loop(){
   digitalWrite (LED_BUILTIN, (millis() / 1000 % 2);
}

/* whoops! mismatched parentheses */

//  Perhaps this was meant:
void loop(){
   digitalWrite (LED_BUILTIN, millis() / 1000 % 2);
}

This is using % 2 to extract the LSB - ie the LED will change state every second as the number
of seconds changes from odd to even to odd to even ... The LSB is 1 for odd, 0 for even.

Another common way to do this is

void loop(){
   digitalWrite (LED_BUILTIN, (millis() / 1000) & 1);
}

Although its probably better to stick to the standard approach for timing regular events:

void loop()
{
  static unsigned long timestamp = 0L ;
  if (millis() - timestamp >= 1000)
  {
    timestamp += 1000 ;
    digitalWrite (LED_BUILTIN, !digitalRead (LED_BUILTIN)) ;
  }
}

As this will work as millis() wraps round, and only does the work when its needed,
in general the work to be done could have side-effects and cost processor time, so
only do it when scheduled.

You are the best! Thanks a lot!

Whatever "LSB" is :smiley:

Least Significant Byte (for LSB) or Least Significant bit (for lsb)

modulo millis() is only good for casual things like a blinking LED. There will be timing glitches the rollover of millis(), whenever a non-power of two is used as a divisor.

modulo millis() is only good for casual things like a blinking LED. There will be timing glitches the rollover of millis(), whenever a non-power of two is used as a divisor.

I would like to dispute that. The system is much more versatile than an elapsed time function, particularly if the results required are not boolean. (eg when FI a specific led needs to light up as a result of the time that has elapsed)The timing glitches at millis() rool-over show up every 50 days or so and can be counter-acted. So for an animated blinker (as is seen so often these days) it is definitely the way to go.

Thanks for all the knowledge, i think i got it!

PS. @Deva_Rishi why you "like to dispute that"? Isnt it the same like you said? millis() & modulo is good for blinking lights or stuff which is not 100% all the time?!

why you "like to dispute that"?

Simply because he stated that 'it is only good for casual things' That is just no true imho

Oh i see it was the “only” yeah i also think there a many roads leading to rome. But first i wanna say thank you for the help! It was a little step for the members with big karma and many posts but a big step for me!

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