Recently I needed to write an Arduino program to turn on/off multiple LEDs at different frequencies while still allowing other code to run. To solve this, I used the built-in interrupt timer to check when each LED should be turned on/off. Each LED can be turned on with a frequency up to 500 Hz. I thought other people might find the code useful so I'm posting it here. Let me know if you have any questions or suggestions.
Thanks!
-Chris
// Chris Torrence, Jan 2019
// License: CC BY
//
// Reference: https://learn.adafruit.com/multi-tasking-the-arduino-part-2/timers
//
int playFrequencyDelay[12] = {0};
// Freq is the frequency of blinking in blinks per second
// pin = 2 to 13
void playFrequency(float freq, int pin)
{
float freq1 = freq;
if (freq1 > 500) freq1 = 500;
if (pin >= 2 && pin <= 13)
{
if (freq1 > 0) {
pinMode(pin, OUTPUT);
playFrequencyDelay[pin - 2] = (int) (500/freq1 + 0.5);
} else {
playFrequencyDelay[pin - 2] = 0;
}
}
}
// pin = 2 to 13
void stopPlayFrequency(int pin)
{
if (pin >= 2 && pin <= 13)
{
playFrequencyDelay[pin - 2] = 0;
digitalWrite(pin, LOW);
}
}
// Used by hd_PlayFrequency
// Interrupt is called once a millisecond
SIGNAL(TIMER0_COMPA_vect)
{
unsigned long t = millis();
for (int pin = 2; pin <= 13; pin++)
{
// See if our current time is a multiple of the desired LED period
if (playFrequencyDelay[pin - 2] != 0 && (t % playFrequencyDelay[pin - 2]) == 0)
{
digitalWrite(pin, 1 - digitalRead(pin));
}
}
}
void setup() {
// Use Timer0 (millis) for playFrequency
OCR0A = 0xAF;
TIMSK0 |= _BV(OCIE0A);
// Let's test the code
playFrequency(0.5,13);
playFrequency(1,12);
playFrequency(2,11);
playFrequency(5,10);
playFrequency(10,9);
delay(10000);
stopPlayFrequency(13);
stopPlayFrequency(12);
stopPlayFrequency(11);
stopPlayFrequency(10);
stopPlayFrequency(9);
}
void loop() {
}