Arduino: Como Piscar Diversos LEDs em Intervalos Diferentes

O Problema

Ok, um probleminha que tentei resolver hoje. Em um projeto preciso piscar um LED para indicar a situação de uma conexão ao LoRaWAN da The Things Network. Mas quero fazer isso em um intervalo curto pois o circuito funcionará na bateria. Por isso quero ligar o LED 20ms a cada 3 segundos mais ou menos.

Como estou lidando com conexão LoRa, não é viável utilizar a função delay() para esse controle, pois a biblioteca LMIC é bem exigente quanto aos seus temporizadores internos. O uso da função delay() tem o potencial de atrapalhar bastante.

Para resolver isso me utilizei de uma técnica também bastante difundida, que é a de se usar a função millis() para saber quanto tempo passou desde que uma condição ocorreu, e tomar uma ação apenas se a condição for satisfeita.

Daí eu acabei implementando um código que me permite piscar múltiplos LEDs a intervalos diferentes para cada um. Eu posto o código abaixo caso isso seja de ajuda para alguém.

Eu também testei esse código através do simulador Wokwi, caso você queira dar uma olhada antes:

O Código

				
					/**
 * Copyright (c) 2023 - James Owens <jjo(at)arduando.com.br>
 *
 * Arquivo:     012_PiscarLEDsMillis.ino
 * Arquivo:     09/05/2023 15:04:00
 * Versão:
 * Fonte:       
 * Website:     https://arduando.com.br
 *
 * DISCLAIMER:
 * The author is in no way responsible for any problems or damage caused by
 * using this code. Use at your own risk.
 *
 * LICENSE:
 * This code is distributed under the GNU Public License
 * as published by the Free Software Foundation; either version 3
 * of the License, or (at your option) any later version.
 * More details can be found at http://www.gnu.org/licenses/gpl.txt
 */
 
 
typedef struct blinkled {
	uint16_t on;
	uint16_t off;
	uint8_t pin;
	bool status;
    uint32_t millisLED;
} BLINKLED;


BLINKLED initBlink(uint8_t pin, uint32_t on = 500, uint32_t off = 500)
{
	BLINKLED myLED;
	myLED.on = on;
	myLED.off = off;
	myLED.pin = pin;
	pinMode(pin, OUTPUT);
	digitalWrite(pin, LOW);
	myLED.status = LOW;
	myLED.millisLED = millis();
	return myLED;
}

void blinkLED(BLINKLED *myLED)
{
	if (myLED->status == HIGH)
		if ((millis() - myLED->millisLED) > myLED->on)
		{
			digitalWrite(myLED->pin, LOW);
			myLED->status = LOW;
            myLED->millisLED = millis();
		}
	if (myLED->status == LOW)
		if ((millis() - myLED->millisLED) > myLED->off)
		{
			digitalWrite(myLED->pin, HIGH);
			myLED->status = HIGH;
            myLED->millisLED = millis();
		}
}


BLINKLED theLED;
BLINKLED theOtherLED;
BLINKLED theOtherOtherLED;

void setup(void)
{
    Serial.begin(9600);
    while(!Serial);

	theLED = initBlink(LED_BUILTIN, 20, 1980);
    theOtherLED = initBlink(12, 60, 980);
    theOtherOtherLED = initBlink(4, 250, 654);
}



void loop(void)
{
	blinkLED(&theLED);
    blinkLED(&theOtherLED);
    blinkLED(&theOtherOtherLED);
}