Pages: [1]   Go Down
 Author Topic: Using millis to blink - unequal intervals?  (Read 1262 times) 0 Members and 1 Guest are viewing this topic.
Gloucestershire, UK
Offline
Full Member
Karma: 1
Posts: 107
Outta Steam
 « on: December 11, 2011, 05:21:39 pm » Bigger Smaller Reset

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?

 Logged

Seattle, WA USA
Offline
Brattain Member
Karma: 601
Posts: 48543
Seattle, WA USA
 « Reply #1 on: December 11, 2011, 05:26:49 pm » Bigger Smaller Reset

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.
 Logged

0
Offline
Sr. Member
Karma: 0
Posts: 360
Arduino rocks
 « Reply #2 on: December 11, 2011, 05:28:35 pm » Bigger Smaller Reset

Something like this should work:

Code:
#define PIN 13
#define ON_INTERVAL 100
#define OFF_INTERVAL 1000
uint32_t nextTime;

void setup() {
pinMode(PIN, OUTPUT);
}

void loop() {
uint32_t currentTime = millis();
if (currentTime > nextTime) {
digitalWrite(PIN, LOW);
nextTime = currentTime + OFF_INTERVAL;
} else {
digitalWrite(PIN, HIGH);
nextTime = currentTime + ON_INTERVAL;
}
}
}

 Logged

Gloucestershire, UK
Offline
Full Member
Karma: 1
Posts: 107
Outta Steam
 « Reply #3 on: December 11, 2011, 05:40:47 pm » Bigger Smaller Reset

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!!
 Logged

Seattle, WA USA
Offline
Brattain Member
Karma: 601
Posts: 48543
Seattle, WA USA
 « Reply #4 on: December 11, 2011, 07:02:58 pm » Bigger Smaller Reset

Quote
I've never come across "uint32_t" before
u = unsigned
int = integer
32 = number of bits
So, it's an unsigned long.
 Logged

SF Bay Area (USA)
Offline
Tesla Member
Karma: 124
Posts: 6647
Strongly opinionated, but not official!
 « Reply #5 on: December 11, 2011, 09:41:27 pm » Bigger Smaller Reset

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.
 Logged

Pittsburgh, PA, USA
Offline
Karma: 95
Posts: 4761
I learn a bit every time I visit the forum.
 « Reply #6 on: December 12, 2011, 01:34:50 am » Bigger Smaller Reset

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.

 Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Gloucestershire, UK
Offline
Full Member
Karma: 1
Posts: 107
Outta Steam
 « Reply #7 on: December 12, 2011, 08:02:56 am » Bigger Smaller Reset

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
 Logged

Seattle, WA USA
Offline
Brattain Member
Karma: 601
Posts: 48543
Seattle, WA USA
 « Reply #8 on: December 12, 2011, 08:09:31 am » Bigger Smaller Reset

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.
 Logged

Gloucestershire, UK
Offline
Full Member
Karma: 1
Posts: 107
Outta Steam
 « Reply #9 on: December 12, 2011, 10:53:02 am » Bigger Smaller Reset

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
 Logged

0
Offline
Sr. Member
Karma: 0
Posts: 360
Arduino rocks
 « Reply #10 on: December 12, 2011, 11:11:24 am » Bigger Smaller Reset

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)
 Logged

Offline
Newbie
Karma: 0
Posts: 7
Swim
 « Reply #11 on: December 18, 2011, 01:36:01 pm » Bigger Smaller Reset

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
 Logged

Seattle, WA USA
Offline
Brattain Member
Karma: 601
Posts: 48543
Seattle, WA USA
 « Reply #12 on: December 18, 2011, 02:18:56 pm » Bigger Smaller Reset

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?
 Logged

Offline
Edison Member
Karma: 64
Posts: 2464
Now, More Than Ever
 « Reply #13 on: December 18, 2011, 02:23:16 pm » Bigger Smaller Reset

http://arduino.cc/forum/index.php/topic,83626.0.html
 Logged

"Hello, I must be going..."
"You gotta fight -- for your right -- to party!"
"Who is like unto the beast? who is able to make war with him?"

Pittsburgh, PA, USA
Offline
Karma: 95
Posts: 4761
I learn a bit every time I visit the forum.
 « Reply #14 on: December 19, 2011, 12:13:58 am » Bigger Smaller Reset

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:
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);
}

// serial input
if (Serial.available())
{
//    Serial.print(".");
//    Serial.print( c );
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
}
}
 Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

 Pages: [1]   Go Up