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);
- }
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
- }
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
- }
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).
- #include <timerone .h="">
- void 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;
- }
- </timerone>
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