1

I'm new to Arduino. For my first project, I want to make aviation strobe lights. My challenge is to use ONE Arduino to blink both sets of lights. My issue is, I DON'T want them to be synchronized. I saved a sketch of the blink example from the Arduino IDE software after editing it to do what I want. But, the LED's are synchronized. One LED strobes twice, while the other strobes once as I want them to. However, they begin their loops together currently and stay synchronized, which isn't what I want.

So my question is: What is the code I need to write to make each LED blink unsynchronized from the other without having to use 2 Arduino units?

Code:

int led = 11;
int led2 = 12;

void setup() {
  pinMode(led, OUTPUT);
  pinMode(led2, OUTPUT);
}

void loop() {
  digitalWrite(led, HIGH);
  delay(50);
  digitalWrite(led, LOW);
  delay(1000);
  digitalWrite(led2,  HIGH);
  delay(50)
  digitalWrite(led2, LOW);
  delay(100) ;
  digitalWrite(led2,  HIGH);
  delay(50)
  digitalWrite(led2, LOW);
  delay(1000);
}
3
  • Could you post your current code?
    – Gerben
    Sep 7 '16 at 7:59
  • That code is only for one led. You said you got things working for two LEDs.
    – Gerben
    Sep 7 '16 at 19:17
  • OK, I fixed it to reflect what I've got. Sep 7 '16 at 20:39
3

The Arduino Blink example uses delay() to pause the Arduino in a specific state, so that for a specific amount of milliseconds the device will keep the blinkPin HIGH or LOW.

Instead of using a delay(), you should use millis(). The main advantage of millis() over delay() is that it does not interrupt the code. When you call a delay() the whole code pauses, nothing can be done during those milliseconds. But millis() doesn't work that way. You also don't call it the same way as delay().

What millis() does is that it stores a timer value into an unsigned long. At a later point in time you can substract a new millis() from your previously stored millis in the unsigned long. The result is a difference in time between each millis() in milliseconds.

Now, instead of using only one unsigned long, we use two different ones: one for each LED. Now you can log a time interval, independently, for each LED. Furthermore, if you apply the logic of millis() for keeping the LEDs on or off, you don't have to interrupt the code with delay() functions. This means, that regardless of each LEDs state (HIGH or LOW), the timer keeps running, keeps logging and thus can control both LEDs simultaneously.

To give you a bit more information on millis(), below are some references that will get you started in how to implement. If you have more questions, just comment on this answer :)

2
  • 1
    Using the millis function call is generally always better than delay. However it is more complex to use the millis functions as the developer needs to understand a different variable type (unsigned long) as well as consider what happens when the millis function wraps around (however infrequent). I think, in this case, using delays for the time base and counters that do not over flow for any variable type makes for an easy to explain and simple to implement answer to the question.
    – st2000
    Sep 7 '16 at 11:39
  • Although more complex, it allows for much more functionality on a device. Simply more than one thing can be done without completely disrupting the code. I never use delay() anymore, except when it is the only way to process some stuff (for example with a WiFi chip or Serial communications where short delays are sometimes needed to simplify the code). Anyway, millis() is amazing and delay() is not, haha.
    – Len
    Sep 7 '16 at 11:52
0

You need to implement a pair of LFSRs, one for each LED. This will give a result that eventually repeats, but with registers of differing lengths and the correct polynomials it won't repeat quickly enough for it to matter.

2
  • But then OP would have to implement finite filed arithmetic for polynomials on an adruino for implementing an LFSR.
    – qwerty10
    Sep 7 '16 at 12:06
  • The article gives a couple of sample implementations in C that strictly use bit operations. It's not as complex as it sounds. Sep 7 '16 at 14:46
0

It is not possible to escape the fact that both LEDs will be driven from a common clock. However, it is possible to arrive at a convincing solution where the LEDs appear to be unsynchronized. What is necessary is a rather fast event loop and rather large numbers which are not quite multiples of one another. As an example consider a loop with a delay of 10ms and two counter which will count up to 100 and 51 respectively. Each time the counters reach their goal their respective LED is toggled and the counter is reset to zero. One LED will appear to turn on off on with a period of about 2 second. The other LED will turn on off on with a period of about 1 second. However, over time,the second LED will start to trail the first. Giving the appearance that they are not synchronized.

You can use any numbers you wish. Edger suggested in the comments to use golden ratio numbers 144 and 89.

If you want to emulate the short burst of strobe lights you need to alter the suggested design (which provides a 50% duty cycle) to something that provides, say, a 10% duty cycle.

Let's adapt your code from above. Add 2 counters one each for LED1 and LED2. Define numbers for the period of LED1 and for LED2. Also define a number for the length of time the LEDs will be on for. Notice that we only need one 10ms call to the delay method. All counters are incremented each time we enter the loop method. Since our delay is 10ms we enter the loop method 100 times a second. Inside the loop method we keep track and cap the counters at their predefined limits. When we get close to those limits we turn on the appropriate LED. When we hit the limit we turn off the appropriate LED and clear that LED's counter.

// What is the period of led 1 in 10s of milliseconds.
#define LED1_PERIOD_10MS 144
// What is the period of led 2 in 10s of milliseconds.
#define LED2_PERIOD_10MS 89
// How long to keep the LED on in 10s of milliseconds.
#define LED_ON_TIME_10MS 10

int led = 11;
int led2 = 12;
unsigned int count_led1;
unsigned int count_led2;

void setup() {
  pinMode(led, OUTPUT);
  pinMode(led2, OUTPUT);

  count_led1 = 0;
  count_led2 = 0;
}

void loop() {
  count_led1++;
  if(count_led1 == LED1_PERIOD_10MS - LED_ON_TIME_10MS)
  {
    digitalWrite(led, HIGH);
  }

  if(count_led1 > LED1_PERIOD_10MS)
  {
    count_led1 = 0;
    digitalWrite(led, LOW);
  }

  count_led2++;
  if(count_led2 == LED2_PERIOD_10MS - LED_ON_TIME_10MS)
  {
    digitalWrite(led2, HIGH);
  }

  if(count_led2 > LED2_PERIOD_10MS)
  {
    count_led2 = 0;
    digitalWrite(led2, LOW);
  }

  // Delay 10ms.
  delay(10);
}

I have only proof read the above code. If you find any problems make a comment below and I will make the corrections.

9
  • So, how would I write the code to achieve the counter reset? Basically, what I've got is: Sep 7 '16 at 4:05
  • This answers your question. However, it's worth noting LEDs lack the ability to simulate incandescent light bulbs as they have little thermal inertia. In order to simulate this you might consider programmable LED and slowly bringing up the down the brightness. You can also use a normal LED and the Arduino's PWM feature to control the brightness.
    – st2000
    Sep 7 '16 at 4:05
  • The code isn't difficult. In your Arduino loop method increment each number and test one for, say, greater than 100 & the other for, say, greater than 51. If the test is true toggle the pin connected to the respective LED and zero out that counter. Then you need to call a delay, say, 10ms. The loop method will be called over and over again as this is part of the Arduino design.
    – st2000
    Sep 7 '16 at 4:09
  • Oh, Ok.looks like it's gonna be a bit of tinkering to get the desired result. No problem, as it helps me learn. Sep 7 '16 at 4:43
  • 1
    Instead of 100 and 51, which is almost a factor 2, I would probably try something close to the golden ratio, like 144 and 89. The golden ratio being in some sense the “most irrational number”, it should provide a feeling of completely unrelated frequencies, instead of the “slowly drifting synchronization” you would get with 100/51. Sep 7 '16 at 10:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.