Hello, I want to make navigation lights to my drone. I make it work using delay, but the delay function stop all other code running. So I need to make this happen without using delay.
Wanted function:
LED 1: blink twice (100ms on, 200ms of, while LED 2 is off.
Delay time 1000ms between LED 1 and LED2.
LED 2: blink once while LED 1 have blinked two times.
I`m new to programming and have tried to make it happen using counter, if/and operators and handling the sequence with +- millis time. But I do not get it to work.
Can someone give me some pointers? or share some code?
This is the code that I have modified without success:
My problem is, I need somehow to stop LED 1 stop blinking while LED 2 start to blink. What is the best strategy? Maybe this is done before in a example?
If you think about it each of the 2 LEDs simply have their own flash pattern implemented as separate BWoD "timers"
I am not clear exactly what the blink pattern should be for LED1 in relation to LED1 but here is my best guess
//1. LED 1: blink twice (100ms on, 200ms of, while LED 2 is off.
//2. Delay time 1000ms between LED 1 and LED2.
//3. LED 2: blink once while LED 1 have blinked two times.
unsigned long currentTime;
unsigned long blink1StartTime;
unsigned long blink2StartTime;
const unsigned long blink1Periods[] = {100, 200, 100, 200, 1000};
const byte blink1States[] = {LOW, HIGH, LOW, HIGH, HIGH};
const unsigned long blink2Periods[] = {300, 300, 1000};
const byte blink2States[] = {HIGH, LOW, HIGH};
byte blink1Index = 0;
byte blink2Index = 0;
const byte led1Pin = 3;
const byte led2Pin = 5;
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(led1Pin, OUTPUT);
pinMode(led2Pin, OUTPUT);
digitalWrite(led1Pin, HIGH);
digitalWrite(led2Pin, HIGH);
}
void loop()
{
currentTime = millis();
blink1();
blink2();
}
void blink1()
{
if (currentTime - blink1StartTime > blink1Periods[blink1Index])
{
digitalWrite(led1Pin, blink1States[blink1Index]);
blink1StartTime = currentTime;
blink1Index++;
if (blink1Index == sizeof(blink1States))
{
blink1Index = 0;
}
}
}
void blink2()
{
if (currentTime - blink2StartTime > blink2Periods[blink2Index])
{
digitalWrite(led2Pin, blink1States[blink2Index]);
blink2StartTime = currentTime;
blink2Index++;
if (blink2Index == sizeof(blink2States))
{
blink2Index = 0;
}
}
}
The code uses arrays to hold the required periods and associated states which may look complicated but it makes it easier to change because the program is driven by that data so to change the blink patters and timing the program does not have to be changed
Note that I have assumed that outputting LOW turns on an LED, which is what I normally do, but if your system needs HIGH to turn on an LED then invert the states in the arrays to suit
Hello, after some hours of testing, it seems like the intervalls drift. I think this may a result of the controller processing time, i.e. the time between blinkstate1 and blinkstate2. (I use 72MHz STM32 bluepill).
In the start, the intervall between LED1 and LED2 is fine. After 30 minutes, I can clearly see that they aproach each other and drift away again, as a sine function.
With independent timing of the two LEDs there is always a danger of them drifting, not least because the processor is doing other things behind then scenes that might cause a problem
One small improvement would be to write the update to the next blink differently, like this
Doing it this way avoids using currentTime to calculate the time that the period starts by calculating it based on the previous start time plus the previous interval
Another approach would be to build a table holding the state of both LEDs showing when either of them change state and the time at which they entered the new state
I never really made sense of your original description
//1. LED 1: blink twice (100ms on, 200ms of, while LED 2 is off.
//2. Delay time 1000ms between LED 1 and LED2.
//3. LED 2: blink once while LED 1 have blinked two times.
Number 1 I understand, but is there then a 1000 mS delay before LED 2 blinks once and the pattern repeats or some other requirement ? How long is LED 2 turned on when it blinks. I assume that LED 1 is never on when LED 2 is on. Is that right ?
Please post your code as it is now as it will give some clues as to what you want to do
An alternative approach that is guaranteed to keep the LEDs in step as long as you set the data up correctly
const byte ON = LOW; //change to suit target system
const byte OFF = HIGH;
struct dataFormat
{
unsigned long period; //period for this stage
byte led1State; //led 1 stage for this stage
byte led2State; //led 2 state for this stage
};
dataFormat ledData[] =
{
{500, ON, OFF}, //led 1 on/led 2 off for 500
{500, OFF, OFF}, //led 1 off for 500, led 2 off for 500
{500, ON, ON}, //led 1 on for 500, led 2 on for 500
{500, OFF, ON}, //led 1 off 500, led 2 on for 500
{1000, OFF, OFF}, //both off for 1000
{100, ON, ON}, //both on for 100
{1000, OFF, OFF} //both off for 1000
};
const byte NUMBER_OF_STAGES = sizeof(ledData) / sizeof(ledData[0]);
byte stage = 0;
const byte led1Pin = 3;
const byte led2Pin = 5;
unsigned long stageStart;
unsigned long currentTime;
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(led1Pin, OUTPUT);
pinMode(led2Pin, OUTPUT);
digitalWrite(led1Pin, ledData[stage].led1State);
digitalWrite(led2Pin, ledData[stage].led2State);
stageStart = millis();
}
void loop()
{
currentTime = millis();
if (currentTime - stageStart >= ledData[stage].period)
{
stageStart = stageStart + ledData[stage].period;
stage++;
stage = stage % NUMBER_OF_STAGES; //wrap around after all stages
digitalWrite(led1Pin, ledData[stage].led1State);
digitalWrite(led2Pin, ledData[stage].led2State);
}
}