Using millis to blink - unequal intervals?

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?

Thanks in advance.

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.

Something like this should work:

#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) {
    if (digitalRead(PIN)) {
      digitalWrite(PIN, LOW);
      nextTime = currentTime + OFF_INTERVAL;
    } else {
      digitalWrite(PIN, HIGH);
      nextTime = currentTime + ON_INTERVAL;
    }
  }
}

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

I've never come across "uint32_t" before

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

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.

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.

Many thanks PaulS and westfw :slight_smile:

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 :blush:)

Cheers Guys

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.

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

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)

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

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.

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?

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

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.

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
  }
}