Hi all,
So I've come to a bit of a pickle... I've got the arduino Due and I'm using almost every pin available on it for a large but simple project. I've come to one major problem. I need to incorporate three separate timed events across the cycle of my main loop.
I need to be running debounce for one, I need to run blink without delay, and I need an output to stay active for 10 minutes after being triggered by a momentary switch input.
The blink without delay is also being called by the onebutton library; single click flash three times, hold flash repeatedly until input X reads low.
I cannot use delay as I need the loop to constantly run, and I cant use a for loop as it will hold everything else up until it's done.
Any ideas, thoughts, suggestions or (and this is my personal favorite) solutions?
eg of existing code
if(digitalRead(button1)==HIGH)
{
digitalWrite(led1,HIGH);
}
else
{
digitalWrite(led1,LOW)
}
if(digitalRead(button2)==HIGH)
{
digitalWrite(led2,HIGH);
}
else
{
digitalWrite(led2,LOW)
}
if(digitalRead(buttonN)==HIGH)
{
digitalWrite(ledN,HIGH);
}
else
{
digitalWrite(ledN,LOW)
}
etc.... all the way through button20, led20
The entirety of the loop is fast enough that all these can be processed and cycled without issue
What I need is, on top of all of this, to have the following three funtinos available
to have a button with debounce trigger a output high for a duration of 10 minutes
To have the onebutton library function on an input
to (WITHOUT DELAY OR "FOR LOOP") have 750 milisec toggle of an led for 3 flashes (6 toggles) as a responce to the short
press, and infinite toggles, until stopped by an independent trigger, for a long press.
unsigned long debounceStart;
unsigned long buttonStart;
unsigned long blinkStart;
// Then later,
debounceStart = millis();
// other code
buttonStart = millis();
// other code
blinkStart = millis();
//Then later
if (millis() - debounceStart >= debounceDuration ) {
// accept the debounced button/key/whatever
}
if (millis() - buttonStart >= buttonDuration ) {
// start another ten minute timer like the others here
}
if (millis() - blinkStart >= blinkDuration ) {
// start another timer like the others to time the blinks themselves.
}
The above are just examples, but the principles are there.
Do these one at a time, making sure each one does it's thing in the way you want it to do. Only after perfecting each one, combine them in the final program. There is only one millis(), but by using separate variables, you can easily time almost any number of events.
//============================================================================
const unsigned long debounceValue = 50UL; //debounce time in milliseconds
const int startSwitch = 2; //note: pressing this switch makes i/p go LOW
unsigned long debounceTime;
boolean lastSwitchState1; //the last read value of switch #1
//boolean lastSwitchState2; //the last read value of switch #2
// etc.
int counter; //equals the number of times the switch is pressed
//============================================================================
void setup()
{
Serial.begin(9600);
pinMode(startSwitch,INPUT_PULLUP);
// other switches here
pinMode(13,OUTPUT);
debounceTime = millis(); //initailize to the current time
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> END OF setup <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
void loop()
{
//================== is it time to check the switches?
if (millis() - debounceTime >= debounceValue)
{
debounceTime = millis(); //re-initialize to the current time
debounceSwitches(); //check the switches
}
//==================
//other sketch/loop code goes here
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> END OF loop() <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// FUNCTIONS
void debounceSwitches() //switches are checked every debounceValue milli seconds
//no minimum switch press time is validated with this code
{
boolean thisState; //re-usable for all the switches
//================== check if this switch has changed state
thisState = digitalRead(startSwitch);
if (thisState != lastSwitchState1)
{
lastSwitchState1 = thisState; //update the switch state
// the switch has changed so do some stuff
// example for the first switch
digitalWrite(13,thisState); //make LED 13 to follow the switch
if(thisState == HIGH) //HIGH condition code
{
}
else //LOW condition code
{
Serial.println(++counter); //example: display the current switch push count
}
}
//==================
//similar code for other switches goes here
}
//>>>>>>>>>>>>>>>>>>>>>>> END OF debounceSwitches() <<<<<<<<<<<<<<<<<<<<<<<<<<
You are using the DUE so I think the best answer to your question is the "Scheduler" library. I wont go into much detail and re write your code but you can run several things almost simultaneously (I don't think this is exactly simultaneously seeing as this is a micro controller still but with a 85 MHz clock it's the best you are going to get)
With Scheduler you can build separate loops() and delay(); of one loop executes the next and then yield(); of that loop executes the next and it all works out pretty cleanly.
I quickly mocked up some example code to show this working on an LCD display. You can see the numbers start to get off at a rate of about 1/1000 clock cycles. Which could be a big deal but probably not.