 # Help with a multifunction millis() program

I have a question - what I’d like to do is trigger a relay and LED’s based on a timer count (int timer) [see below]

the complicated part for me is I need the relay to be on and off for different times - like blink an LED on and off but “on” longer than “off”, let’s say for example at timer = 60 seconds , LED will blink long, off short, on long, then LED = false; wait for next time.

I’ve tried using an array to contain the times and then trigger a function, I couldn’t get it to work without bugs, so if I can have an array = { 1, 10, 20, 30, 60}; and at those times blink an LED, I’ve found myself at a roadblock and though I’ve found good examples and learned cool stuff like how to use poynters, I haven’t figured this out - driving me crazy.

I couldn’t seem to get this to work, I’m sure there’s got to be a better way:

``````for( i = 0, i <= sizeof(array[]), i++){
If ( timer == array[i]){ //run LED sequence here;
}
``````

I’m always looking to improve my programming so all advice is greatly appreciated

``````void loop() {
// Main start

start = true;
}

if (start == true){
sequence = true;
start = false;
timer = 0;
}

if (sequence == true){
while (timer < 180)
{
ms = millis();

if(ms - prevms >= oneSEC ){
prevms = ms;
timer++;
Serial.println(timer); // for checking time on serial monitor

}

if (timer == 1){
longON();
}
``````

Show us a good schematic of your circuit.
Show us a good image of your ‘actual’ wiring.

Use CTRL T to format your code then copy the ‘complete sketch’ and paste it here between code tags.

-I’m using the arduino uno for developing this project, final project will likely be using the pro mini
-happy to share a schematic once I complete the project, right now it’s just a prototype or in other words a simple LED and one button, I’m using pin 4 for the button and pin 12 for the LED
-the relay is 5v, triggered the same way as an LED - when HIGH it’s on otherwise it’s LOW

• I have a ton of code written and none of them quite work which is why I’m here.
``````void onLONG() {
ms = millis();
if (ms - prevms1 >= ledON) {
HORN = true;
digitalWrite(hornPin, LED);
prevms1 = ms;
}
if (ms - prevms2 >= ledOFF) {
HORN = false;
digitalWrite(hornPin, LED);
prevms2 = ms;
}
``````

Here’s one that is a proof of concept, but not quite there:

``````//

//BTN's

int start3BTN = 4;

//Boolean Vars

bool start = false;
bool sequence = false;
bool warning = false;
bool leds1 = false;

//int's

int timer = 0;
int count = 0;

unsigned long ms = 0;
unsigned long prevms = 0;
unsigned long oneSEC = 1000UL;

const uint8_t         pinLED      = 12;   // Arduino Uno

const unsigned long     dtON_DELAY  = 600UL;
const unsigned long     dtOFF_DELAY = 125UL;

const uint8_t           LED_OFF     = LOW;
const uint8_t           LED_ON      = HIGH;

uint8_t                 stateLED    = LED_OFF;
unsigned long           dtTrigger;

bool hasTimeArrived(const unsigned long& dtTrigger)
{
return (((long)(millis() - dtTrigger)) >= 0);
}

{
stateLED = ((stateLED == LED_ON) ? LED_OFF : LED_ON);
digitalWrite(pinLED, stateLED);

return ((stateLED == LED_ON) ? dtON_DELAY : dtOFF_DELAY);
}

void setup()
{

pinMode(4, INPUT);

dtTrigger = millis();

pinMode(pinLED, OUTPUT);
}

void loop()
{

{
start = true;
}

if (start == true) {
sequence = true;
start = false;
}

if (sequence == true)
{
while (timer < 180)
{
ms = millis();
if (ms - prevms >= oneSEC )
{
prevms = ms;
timer++;
}
if (timer == 1) {
warning = true;
}
if (warning = true) {
leds1 = true;
warning = false;
if (leds1 = true) {
LED();
}
}
}

}

}

void LED()
{

if ( hasTimeArrived(dtTrigger) )
{
}

}
``````

How did you get this far without testing as you wrote the code?
Paul

OOPS

Here is the BlinkWithoutDelay example blinking S-O-S using an array for the timing.

File → Examples → 02.Digital → BlinkWithoutDelay

``````// constants won't change. Used here to set a pin number:
const int ledPin =  LED_BUILTIN;// the number of the LED pin
const int buzzerPin =  10;

// Variables will change:
int ledState = HIGH;             // ledState used to set the LED

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last time LED was updated

#define s    100      // Morse code short
#define l    (3 * s)  // long
#define g    s        // gap between dots and dashes
#define mg   (3 * s)  // medium gap between letters
#define lg   (7 * s)  // long gap between words

// constants won't change:
const long interval[] = { s,g,s,g,s,mg,l,g,l,g,l,mg,s,g,s,g,s,lg }; // S-O-S

void setup() {
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
pinMode(buzzerPin, OUTPUT);
}

void loop() {
static int state = 0;

// here is where you'd put code that needs to be running all the time.

// check to see if it's time to blink the LED; that is, if the difference
// between the current time and last time you blinked the LED is bigger than
// the interval at which you want to blink the LED.
unsigned long currentMillis = millis();

if (currentMillis - previousMillis >= interval[state]) {
// save the last time you blinked the LED
previousMillis = currentMillis;

// if the LED is off turn it on and vice-versa:
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}

// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
digitalWrite(buzzerPin, !ledState);

state = ( state +1 ) % ( sizeof( interval ) / sizeof( interval ) );
}
}
``````
1 Like

You can save half the space of that interval array by just automatically doing a short gap after every entry, and adjusting the medium and long gaps to take that into account.

Also, whenever you #define an expression, enclose it in parentheses so there’s no chance of an order of operations problem. Like: #define l (3 * s). Remember that #define is a text substitution not a variable, so if you use it around operators that have higher precedence that what’s used in the expression it can cause unexpected behavior without parentheses around it.

``````#include "blinker.h"

// So everyone wants newbies to write blink without delay. This is good
// because delay() is bad. Well, here's the simple way to do it..

// Allocate a global blinker object.

void setup() {

// Fire it up.
}

void loop() {

// blinker is an idler. Calling idle() once in loop lets ALL idlers run.
idle();
}
``````

That will deal with the relay/blinking You will need to grab LC_baseTools from the library manager to compile it.

Good luck!

-jim lee

1 Like

I used an Arduino Nano 33 IoT with 256kB of Flash and 32kB of RAM to blink an LED and a buzzer. No need to save any memory. You are right about the define. I will change that to show good programming.

1 Like

Thank you Klaus! This is very very helpful

This is also very interesting Jim, definitely going to check this out as well, thank you!

How is start3BTN wired?

if ( == true){ }

I usually wire them like this:
SIK Experiment Guide for Arduino - V3.2 - learn.sparkfun.com.

Here are a couple methods that you may like to use on your blinker.

``````aBLinker.setPeriod(float ms);
``````

You can set the total(period) and pulse-on time, on the fly, with these two.

-jim lee

This example in
in my How to write Timers and Delays in Arduino
covers sequences of on/off

Great info and example @drmpf

So I got one part of what I want to occur… sometimes, I had it mostly working maybe 75% of the time which is alot better than 0% of the time lol

my current problem is some of the time the LED blinks more than it’s supposed to and the intervals aren’t correct - any ideas on how to fix this? The code and variables are at the bottom if you want to test it out, I setup an external led on pin 12 for testing

``````Serial.println(interval[state]); // delay time
Serial.println(trig); // trigger value, this is set at 5 then subtracts 1 each time the delay is reached

``````

250
4
450
3
250
2
450
1
250
4
250
4
250
4
450
3
250
2
450
1
250
0

the interval state should start with 450 then go to 250 based on the array, and they should alternate - they’re repeating sometimes. Also trig should be 5 then trig-- each time through the loop until trig == 0 ( if(trig > 0)) appears it doesn’t stop when trig == 1 then sets trig = 4, so that I’m confused about

here’s the loop for this part

``````void SEQUENCE() {

static int state = 0;
unsigned long currentMillis = millis();

// start
if (currentMillis - prms >= second) {
prms = currentMillis;
timer++;

//  Serial.println(timer);
}
// main timer keeps track of time left

//start time functions
if (timer == 1) {
trig = 5;
state = 0;
runTrig = true;
}

if (runTrig == true && trig > 0) {
if (currentMillis - previousMillis >= interval[state]) {
// save the last time you blinked the LED
trig--;
state++;

// if the LED is off turn it on and vice-versa:
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}

// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);

Serial.println(interval[state]);
Serial.println(trig);
previousMillis = currentMillis;
}
}
else {
digitalWrite(ledPin, false);
runTrig = false;
}
}

``````

Variables needed to test this code

``````// constants
const int ledPin =  12;// the number of the LED pin

// Variables will change:
int ledState = LOW;  // ledState used to set the LED
int lastSTATE = LOW;

int btnSTATE = LOW;
bool start;
bool sequence;
bool runTrig;

//int vars
int timer;
int trig;

unsigned long previousMillis = 0;        // timer memory
unsigned long prms = 0;                 //trigger time memory

#define s    450     // long delay
#define g    250        // short delay
#define second 1000 // one second

// constants won't change:
const long interval[] = { s, g, s, g, s, g, s, g, s, g };
``````

Not exactly sure what trig is doing, but try this code.
If you have two separate things happening, put them in separate tasks

``````// install SafeString V4.0.3 from Arduino library manager for millisDelay
#include "millisDelay.h"
// constants
const int ledPin =  13;// the number of the LED pin

// Variables will change:
bool ledStateON = false;  // ledState used to set the LED
int lastSTATE = LOW;

int btnSTATE = LOW;
bool start;
bool sequence;
bool runTrig;

//int vars
int timer;
int trig;

unsigned long previousMillis = 0;        // timer memory
unsigned long prms = 0;                 //trigger time memory

#define s    450     // long delay
#define g    250        // short delay
#define second 1000 // one second

// constants won't change:
const unsigned long interval[] = { s, g, s, g, s, g, s, g, s, g };
size_t intervalSize = sizeof(interval) / sizeof(unsigned long); // number of elements in interval
size_t intervalIdx = intervalSize; // will not run yet
millisDelay intervalTimer;
millisDelay mainTimer;

void setLed(bool ledStateON) {
if (ledStateON) {
digitalWrite(ledPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
}
}

void setup() {
pinMode(ledPin, OUTPUT);
ledStateON = false;
setLed(ledStateON);
mainTimer.start(10000); // run seq every 10sec
Serial.begin(9600);
for (int i = 10; i > 0; i--) {
Serial.print(' '); Serial.print(i);
delay(500);
}
Serial.println();
}

if (intervalIdx >= intervalSize) {
return;
}
if (intervalTimer.justFinished()) {
// toggle led and do next interval
// if the LED is off turn it on and vice-versa:
ledStateON = !ledStateON;
setLed(ledStateON);
// do next interval
intervalIdx++;
if (intervalIdx >= intervalSize) {
ledStateON = false;
setLed(ledStateON);
return;
} else {
Serial.print(" intervalIdx:"); Serial.print(intervalIdx);
intervalTimer.start(interval[intervalIdx]);
Serial.print(" time:"); Serial.println(interval[intervalIdx]);
}
}
}

// check if we should start led sequence
void checkMainTimer() {
if (mainTimer.justFinished()) {
Serial.println(F("start seq"));
mainTimer.repeat();
intervalIdx = 0;
intervalTimer.start(interval[intervalIdx]);
ledStateON = true;
setLed(ledStateON);
}
}

void loop() {
checkMainTimer();
blinkSequence(); // does nothing if interval idx >= intervalSize
}
``````

The delay time and number of blinks works really well using your library, starting to get familiar and optimistic this can do what I’m hoping for Thank you!

Hey All, thanks for all the ideas, I’ve just come up with a simplified version that works for delaying blinks at different intervals, I’m using an array and if/else to change from  to , seems to work quite well with less code, hope this helps anyone who’s looking to do this and maybe helps everyone create something might be a convenient way to use several delays because you can just write say 10 different ones in the array, then switch them for your conditions - maybe you want regular blink but then like a strobe effect, this is basically what my program is going to be except it will just include a couple of different blink types, run for a specific period of time and be activated by a momentary button

thanks again for everyone’s help!

``````//unsigned
uint32_t currentMillis = 0;
uint32_t prevMillis = 0;

//definitions
#define a 450 //define time LED is off for
#define b 50 //define time LED is on for

// array for delay times
const uint32_t delayShift [] = {a, b}; // array for switching delay times
uint32_t index = 0; //array index

//ints
int ledpin = 13; // set pin for LED

//bools
bool LED; // for writing LED on or off

void setup() {
// setup code here, to run once:

pinMode(ledpin, OUTPUT);

}

void loop() {
//  main code here, to run repeatedly:

currentMillis = millis();

if (currentMillis - prevMillis >= delayShift[index] ) {
LED = !LED;
digitalWrite(ledpin, LED);
if (index == 0) {
index = 1;
}
else {
index = 0;
}
prevMillis = currentMillis;

}
}

``````