Usando um Delay
Esta é a forma usada no exemplo Blink do Arduino:
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
}
Simples, direto, mas fica difícil fazer outras coisas ao mesmo tempo.A Solução por Hardware
Pulsar um sinal é trabalho para PWM!
O ATmega328 possui tês timers, cada um com dois canais de PWM, vamos usar aqui o Timer1. A programação é um pouco complicada, pois o timer pode trabalhar de diversas formas.
No código abaixo vamos usar um divisor de 1024 para o clock do Arduino (16MHz), o que significa que vamos contar passos de 1024/16000 milissegundos. O PMW é configurado para inverter o sinal de saída a cada 7812 passos (7812*1024/16000 = 500ms).
void setup() {
pinMode(9, OUTPUT);
TCCR1A = _BV(COM1A0);
TCCR1B = _BV(WGM12)|_BV(CS12)|_BV(CS10);
OCR1A = 7812;
}
void loop() {
delay(100); // nada para fazer
}
Parece mágica, não é? A desvantagem é que a seleção de pinos é limitada, neste caso não dá para usar o LED da placa e precisei colocar o LED na saída digital 9.Usando Tempos
Para não ficarmos com o Arduino parado no delay, podemos testar no loop() se está na hora de mudar o LED:
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
static bool aceso = false;
static unsigned long pisca = 0;
if (millis() > pisca) {
digitalWrite(LED_BUILTIN, aceso? LOW : HIGH);
aceso = !aceso;
pisca = millis() + 500L;
}
delay (50); // faz outras coisas
}
Obs: variáveis static em uma função mantém o valor de uma chamada para outra.Embora este método libere o microcontrolador para fazer outras coisas, a piscada do LED fica sensível à duração destas outras coisas (experimente aumentar o delay(50) para delay(300)).
Usando Interrupção de Tempo
Este é o meu método preferido... Usando interrupção o processamento corre normalmente a maior parte do tempo. Vamos usar de novo o timer1, mas neste caso vou usar a biblioteca TimerOne (que você pode instalar direto da IDE do Arduino).
#includevoid setup() { pinMode(LED_BUILTIN, OUTPUT); Timer1.initialize(500000L); Timer1.attachInterrupt(piscaLED); } void loop() { delay(100); // nada para fazer } void piscaLED(void) { static bool aceso = false; digitalWrite(LED_BUILTIN, aceso? LOW : HIGH); aceso = !aceso; }
A desvantagem (tem que ter, não é?) é que o código fica um pouco mais complicado (a biblioteca TimerOne escondeu a maior parte). À medida que se coloca mais coisas na interrupção é preciso tomar cuidado com a concorrência no acesso a variáveis e não deixar a interrupção demorada demais.

Nenhum comentário:
Postar um comentário