How to make arduino do 2 things at once

Hello all!

I am kinda new to arduino.
I am using it with 8 relè board; relays are connected to a line of lamps. The lamps should switch on in sequence and very fast.
I used a for cicle like that:

#define DELAYTIME 50
int tempo[8]={100,90,80,70,50,50,50,40};

 for (int i=0; i<8; i++)
    {
      digitalWrite(i,HIGH);
      delay(DELAYTIME);
      digitalWrite(i,LOW);
      delay(tempo[i]);
}

I should have that exact time sequence in switching lamps on but the problem is that laps take their time to warm up and light on; so what I get is that no lamp switch on at all.

I think I should find a way to do 2 for cycles at once. . . the first one just switch on lamps with the needed delays; the second cycle starts a bit after the first (enough time to warm lamps up) and the just switch off lamps with the same delay they were switched on.

My problem is that if I write 2 for cycles in serie, the second starts when the first is finisched and not just a bit after the first is started.
Then I would tweak the start delay of the second cycle to do the best to have lamps fully bright.

I hope I was able to explain my problem and I hope also there is a solution!

Thank you so much

Mic

Usual advice:

  1. get rid of all calls to “delay()”
  2. read the blink without delay example, without delay.

Drop all use of delay(). See blink without delay - in examples.

Mark

But at some point the millis(); will roll over. Something like 70 days I believe? How does one make up for that? currentMillis will be less than previousMillis after the rollover thus leaving you with a value that is less than interval because technically it will be negative. Or....if it is unsigned it will be far greater than interval thus meaning you never met your interval. Course the next question you need to ask is...are you really planning on running it for over 70 days?

But at some point the millis(); will roll over. Something like 70 days I believe? How does one make up for that?

Not a problem.

My only gripe is if(currentMillis - previousMillis > interval) { should be if(currentMillis - previousMillis >= interval) {

JHawk88: But at some point the millis(); will roll over. Something like 70 days I believe? How does one make up for that? currentMillis will be less than previousMillis after the rollover thus leaving you with a value that is less than interval because technically it will be negative. Or....if it is unsigned it will be far greater than interval thus meaning you never met your interval. Course the next question you need to ask is...are you really planning on running it for over 70 days?

You can rest assured that your unsigned variable will never be negative. But you need to rethink the next statement there. Will it really be larger than the interval? Have another look at how unsigned math works.

If we are working with unsigned bytes (I know they're longs for time variables but just for demo purposes) then we have from 0 to 255. If our interval is 20, the old time is 245 and the new time is 5 then what happens?

5 - 245 = 15 Not time yet. Everything is fine.

The only time you would have a rollover issue is if your timing interval was more than 50 days. If you want to make something happen every 60 days, then you'll have to get creative with rollovers. But as long as the interval is less than 50 days it works out fine.

If you want to get the whole 49 days, 17 hours, 2 minutes and 47.296 seconds possible then unlike the official example in the IDE you have to use unsigned long for -all- of the time variables. The ones to 'fix' (add unsigned in front of long) in the example are

long previousMillis = 0;        // will store last time LED was updated

long interval = 1000;           // interval at which to blink (milliseconds)

Morris Dovey put up a timer library that uses 64-bit unsigned long long variables good for well over 500,000 years using micros() instead of millis(). I don't remember where to find it though.

Here is a sketch that uses unsigned math and shows the results in DEC, HEX and BIN.

unsigned long a, b, c;

void setup() {
  Serial.begin( 9600 );
  a = 0xffffff00UL;
  b = 0x10UL;
  Serial.println( "\n unsigned math\n" );
  Serial.print( "a = ");
  Serial.print( a, DEC );
  Serial.print( " = 0x");
  Serial.print( a, HEX );
  Serial.print( " = 0b");
  Serial.println( a, BIN );
  Serial.print( "b = ");
  Serial.print( b, DEC );
  Serial.print( " = 0x");
  Serial.print( b, HEX );
  Serial.print( " = 0b");
  Serial.println( b, BIN );
  if ( b >= a ) Serial.println( "b >= a" );
  else          Serial.println( "a > b" );
  c = a - b;
  Serial.print( "a - b = ");
  Serial.print( c, DEC );
  Serial.print( " = 0x");
  Serial.print( c, HEX );
  Serial.print( " = 0b");
  Serial.println( c, BIN );
  c = b - a;
  Serial.print( "b - a = ");
  Serial.print( c, DEC );
  Serial.print( " = 0x");
  Serial.print( c, HEX );
  Serial.print( " = 0b");
  Serial.println( c, BIN );
  c = b - (b + 1);
  Serial.print( "b - (b + 1) = ");
  Serial.print( c, DEC );
  Serial.print( " = 0x");
  Serial.print( c, HEX );
  Serial.print( " = 0b");
  Serial.println( c, BIN );
  
  while( 1 );
}

void loop() {};

You can rest assured that your unsigned variable will never be negative. But you need to rethink the next statement there. Will it really be larger than the interval? Have another look at how unsigned math works.

If we are working with unsigned bytes (I know they're longs for time variables but just for demo purposes) then we have from 0 to 255. If our interval is 20, the old time is 245 and the new time is 5 then what happens?

5 - 245 = 15 Not time yet. Everything is fine.

The only time you would have a rollover issue is if your timing interval was more than 50 days. If you want to make something happen every 60 days, then you'll have to get creative with rollovers. But as long as the interval is less than 50 days it works out fine.

That's the problem though, you are working with unsigned bytes and your logic structure needs to account for the roll over. if(currentMillis - previousMillis >= interval) { But currentMillis has rolled over and your previous millis is, say, stuck at 65,000, well do the logic there. When is CurrentMillis-previousMillis going to be >= the interval (which = 1000)? Never... that value is going to be negative. Here's what I don't know, that value will be negative but does the chip read the logic as unsigned? Although it could be something like -64000, the value is actually 4294902296 when it is unsigned (assuming it is a long). So it is instantly greater than the interval and you will miss an iteration. Or...it is signed and you will never recover. So, no, everything is not fine.

So, no, everything is not fine

And what do you perceive the problem (if there is one) to be?

JHawk88: Never... that value is going to be negative.

Not it won't, because it will be unsigned. If you don't believe us, do the math yourself on a calculator.

Please run the sketch I put up in reply #6 and you will see what happens at rollover. Change the numbers, ask about HEX if you need as that is just an easy way to read bits.

Computer binary maths are not the same as paper and pencil decimal maths.

UGH....one of those moments. My newbiness couldn't overcome currentMillis = 999 and previousMillis = 0xFFFFFFFF. But I see it now. My apologies. Thank you for the patience.

You mention: switching lamps on but the problem is that laps take their time to warm up and light on; so what I get is that no lamp switch on at all.

Don't use incandescent bulbs, use LED bulbs. They are fast on.

http://www.gammon.com.au/blink

Be sure to go to Nick’s link. It is the best starting tutorial I know on doing more than one thing at a time. You will know why as well as what and how.

JHawk88:
UGH…one of those moments. My newbiness couldn’t overcome currentMillis = 999 and previousMillis = 0xFFFFFFFF. But I see it now. My apologies. Thank you for the patience.

Yes, the bits. Takes time to learn but well worth it.

HEX is base 16. 1 hex digit can be decimal 0 to 15 as hex 0 to 9 or A to F where A=10, F=15.
But the bits, there are 4 and with practice it’s easier to read hex than binary.

bits high to low = 8 4 2 1 so binary 1111 = 1x8 + 1x4 + 1x2 + 1x1, binary 0011 = 1x2 + 1x1.

0 0000 0 — 0x0 is no bits set
1 0001 1
2 0010 2
3 0011 3
4 0100 4
5 0101 5
6 0110 6
7 0111 7
8 1000 8
9 1001 9
A 1010 10
B 1011 11
C 1100 12
D 1101 13
E 1110 14
F 1111 15 — 0xF is all bits set

If you run Windows, open the calculator and under View change it to Scientific.
You now can switch between HEX, DEC, OCT and BIN. In HEX the A to F keys are active.

Every text character is 8-bit ASCII, even the unprintable ones. They all take 2 hex digits.

Once you know bits you can start to get into bit shifting and bit logic and do bit masking. With those you can change or read the pins on a PORT all at the same time in less than 1 millionth of a second. To get closer to the metal you need solder.

Just take care when shifting bits right (high to low). If the high bit (bit 7 of a byte or short, bit 15 of an unsigned int or int) is 1 then as the bits shift right, the new high bit will be 1. That ‘fill’ doesn’t happen with left-shift, just right-shift.