Go Down

### Topic: Using millis to blink - unequal intervals? (Read 4266 times)previous topic - next topic

#### STDummy

##### Dec 11, 2011, 11:21 pm
Ok I admit it, I am stupid.  I'm trying to get an Arduino to strobe an LED, ie around 1 second off with a brief tenth second flash.

Using delay - not a problem.  Thing is I want the led flashing to occur whilst the arduino is doing other things,  I've just spent a whole weekend trying to modify various variations of the blink without delay sketch, ie using millis, but I just can't get my head around how to control two processes (ie interval off and interval on), nothing I try seems to work.

I haven't got any code to submit, as its just the blink without delay sketch.  I cannot work out how to make the on and off intervals different from each other, and really don't know where to start.  Does anyone know of any pointers or tutorials that I could read?

If you learn by your mistakes then I am the model pupil

#### PaulS

#1
##### Dec 11, 2011, 11:26 pm
The blink without delay sketch compares the current time minus the last time that an event occurred to an interval.

To have uneven intervals, you must have two different intervals. When the light is on, and you are waiting to turn if off, use one interval. When the light is off, and you are waiting to turn it on, use the other interval.

#### rbtying

#2
##### Dec 11, 2011, 11:28 pm
Something like this should work:

Code: [Select]
`#define PIN 13#define ON_INTERVAL 100#define OFF_INTERVAL 1000uint32_t nextTime;void setup() {  pinMode(PIN, OUTPUT);}void loop() {  uint32_t currentTime = millis();  if (currentTime > nextTime) {    if (digitalRead(PIN)) {      digitalWrite(PIN, LOW);      nextTime = currentTime + OFF_INTERVAL;    } else {      digitalWrite(PIN, HIGH);      nextTime = currentTime + ON_INTERVAL;    }  }}`

#### STDummy

#3
##### Dec 11, 2011, 11:40 pm
Wooh - that was fast!

Thanks to you both guys.  That works well I've never come across "uint32_t" before Aeturnalus - what is it?

Sorry for my lack of knowledge, I'm at the bottom of a very steep looking learning curve with a headache at the moment!!
If you learn by your mistakes then I am the model pupil

#### PaulS

#4
##### Dec 12, 2011, 01:02 am
Quote
I've never come across "uint32_t" before

u = unsigned
int = integer
32 = number of bits
So, it's an unsigned long.

#### westfw

#5
##### Dec 12, 2011, 03:41 am
Quote
So, it's an unsigned long.

On Arduino it's an unsigned long.  uint32_t will always be an unsigned 32bit integer, even on cpus/systems where a "long" is a different size.  (likewise uint16_t, uint8_t)
When writing code that is supposed to behave the same even if it's ported elsewhere, it is a good idea to use these "standardized" types.  It's too bad that they're so ... obscure-looking.

#### GoForSmoke

#6
##### Dec 12, 2011, 07:34 am
One way to handle multiple processes would be to code loop() as a state-engine. One variable holds the state number and each time through loop that number is used in a switch-case to choose which process to run as either in-line code or a function. Some time in the run, state is changed or not depending on what makes the most sense.

That doesn't mean that data capture or critical tasks can't occur before the state switch-case. It's just a way to say, this time through the woods I will take this path. You get flexibility to separate processes and add or cut processes as you will. State engines are great little tools for reducing indent levels and complexity.

2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

#### STDummy

#7
##### Dec 12, 2011, 02:02 pm
Many thanks PaulS and westfw

I do understand the significance of uint32-t now, but as you say westfw, why is it so hidden away  :~

Thanks too GoForSmoke - I'll have to try that approach sometime - when I'm a bit more familiar with Arduino coding (could be some time  )

Cheers Guys
If you learn by your mistakes then I am the model pupil

#### PaulS

#8
##### Dec 12, 2011, 02:09 pm
Quote
I do understand the significance of uint32-t now, but as you say westfw, why is it so hidden away

Because it is not a necessary data type on the Arduino. The likelihood of running the same code on the Arduino, and on some other hardware, and needing the variables to be the same size on both platforms, is pretty slim.

If you do have that need, it is likely that you have the experience to know that the _t types are what you need to use.

#### STDummy

#9
##### Dec 12, 2011, 04:53 pm
Ah right....

I can't see the need for me to use any cross platform code, so in future I'll just use std unsigned long variables and not confuse my tiny brain  XD
If you learn by your mistakes then I am the model pupil

#### rbtying

#10
##### Dec 12, 2011, 05:11 pm
Arduino is beginning to expand to other microcontrollers--it therefore seems to make sense to use more cross-platform-compatible types.

(My own preference for them is a result of hours of debugging computer-to-Arduino communications, where reconstructing things fails miserably unless the width of the various types is easy to figure out)

#### goodman1887

#11
##### Dec 18, 2011, 07:36 pm
Ok,
I am like the first guy who asked the question,  spending at least 20 hours trying to get one led to blink every second for (about250) 59 seconds and  getting another led to blink on the 60th second to get my counter to reset.
I can not even get the first led to blink one tine for that off 750 and on 250.  Let alone for 59 times.
I have been playing with the blink without delay the same as he has.
I tried copying your demonstration into my UNO but the code just came up with a lot of error messages.
What I am trying to do is use the led on function to power 10 ma relays in a deli counter board for a 60 minute clock.  To use a swim practice.
All I have really ben able to do is get 13 to flash at intervals but it occures so fast I can barely see the red led on 13 flash.
I have changed the HIGH duration many many different times but no real change.
Thanks

#### PaulS

#12
##### Dec 18, 2011, 08:18 pm
Quote
I am like the first guy who asked the question

Right no code. Just some confusing set of requirements. Perhaps if we saw some code, we could understand the requirements.

Quote
All I have really ben able to do is get 13 to flash at intervals but it occures so fast I can barely see the red led on 13 flash.

Using what code?

#### runaway_pancake

#13
##### Dec 18, 2011, 08:23 pm
http://arduino.cc/forum/index.php/topic,83626.0.html
"Who is like unto the beast? who is able to make war with him?"
When all else fails, check your wiring!

#### GoForSmoke

#14
##### Dec 19, 2011, 06:13 am
This version takes number input from serial to change the blink rate.
It uses my UNO's on-board led on pin 13 and works.
Don't feed it garbage and it will behave as expected, bigger numbers make longer ON time.

Code: [Select]
`unsigned long waitUntil = 0UL; // because millis() returns UL enum whatFlag { led13state, endOfLine, dataBegun }; byte  Flags = 0;void setup(){  pinMode( 13, OUTPUT );  digitalWrite( 13, bitRead( Flags, led13state ));    Serial.begin( 9600 );  Serial.println( "Blink w/user input. Enter up to 1000 for led-on interval" );  Serial.println();}void loop(){  static byte  c; // c for character buffer//  static byte  endOfLineState = 0;  static unsigned long timeSinceLastSerialRead = 0UL;  static int enter = 0; // to get serial-entered number value.  static int ledMillisOn = 100;  // must be 0-999    // flash led and state changer  if ( waitUntil - millis() >= 10000UL )  // when millis() passes waitUntil the _unsigned_ subtract   {                                       // leaves very large positive result    Flags ^= ( 1 << led13state ); // led13state T/F bit toggle     if (bitRead( Flags, led13state ))  waitUntil = millis() + (unsigned long)(ledMillisOn);     else                              waitUntil = millis() + (unsigned long)(999 - ledMillisOn);     digitalWrite(13, bitRead( Flags, led13state ));    }    // serial input  if (Serial.available())   {    c = Serial.read();//    Serial.print(".");//    Serial.print( c );    timeSinceLastSerialRead = millis();    if ( c >= '0' && c <= '9' )    {      enter *= 10;  // decimal shifting whatever is in enter 1 place up      enter += ( c - '0' ); // ascii 48 is '0'       bitSet(Flags, dataBegun );  // entry is treated as finished      if ( enter >= 100 ) // next digit being able to take the total > 999      {        bitSet(Flags, endOfLine );  // entry is treated as finished      }    }    else if (( c == 13 || c == 10 ) && bitRead( Flags, dataBegun ))     {      bitSet( Flags, endOfLine );  // entry is treated as finished    }    else if (( millis() - timeSinceLastSerialRead >= 500 ) && ! bitRead( Flags, endOfLine ))    {      bitSet( Flags, endOfLine );  // entry is treated as finished    }   }    // serial output  if ( bitRead( Flags, endOfLine ) && bitRead( Flags, dataBegun )) // should be done and have data  {    Serial.print( ">> " );    Serial.print( enter );    Serial.println( " <<" );    ledMillisOn = enter;    enter = 0;    bitClear( Flags, endOfLine );    bitClear( Flags, dataBegun ); // clears bits, endOfLine and dataBegun  }}`