Siempre he odiado que no pudieras hacer otras cosas mientras usabas la delay();
función. Sin embargo, quiero hacer parpadear un LED o hacer lo que sea mientras uso la serie, pero ¿cómo funciona esto? ¿Cómo hago esto sin usar la función de retraso?
Las interrupciones son una forma común de hacer las cosas mientras sucede otra cosa. En el siguiente ejemplo, el LED parpadea sin utilizar delay()
. Cada vez que se Timer1
dispara, se llama a la rutina de servicio de interrupción (ISR) isrBlinker()
. Enciende/apaga el LED.
Para mostrar que otras cosas pueden suceder simultáneamente, loop()
escribe repetidamente foo/bar en el puerto serie independientemente del parpadeo del LED.
#include "TimerOne.h"
int led = 13;
void isrBlinker()
{
static bool on = false;
digitalWrite( led, on ? HIGH : LOW );
on = !on;
}
void setup() {
Serial.begin(9600);
Serial.flush();
Serial.println("Serial initialized");
pinMode(led, OUTPUT);
// initialize the ISR blinker
Timer1.initialize(1000000);
Timer1.attachInterrupt( isrBlinker );
}
void loop() {
Serial.println("foo");
delay(1000);
Serial.println("bar");
delay(1000);
}
Esta es una demostración muy simple. Los ISR pueden ser mucho más complejos y pueden activarse mediante temporizadores y eventos externos (pines). Muchas de las bibliotecas comunes se implementan mediante ISR.
Aquí hay un ejemplo en Arduino:
const int ledPin = 13; // the number of the LED pin
int ledState = LOW; // ledState used to set the LED
long previousMillis = 0; // will store last time LED was updated
// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 1000; // interval at which to blink (milliseconds)
void setup() {
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
}
void loop()
{
// here is where you'd put code that needs to be running all the time.
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
}
}
Esto registra cuándo tendrá que cambiar y espera hasta que sea ese momento.
Por supuesto, esta función ( millis();
) se restablecerá después de unos 50 días cuando sea demasiado grande para almacenarla, pero si no la mantiene activada durante más de 40 días, debería estar bien. Puede evitar esto averiguando qué tan grande puede ser este valor y hacer una declaración if para cuando se acerque a la parte superior para detenerse durante un minuto más o menos. Tendría problemas para sumar milisegundos cuando llega tan alto, pero no sé cómo resolverlo, pero esto funcionará para un proyecto pequeño.
Jorge Birbilis
tubo
Jorge Birbilis