¿Cómo puedo controlar las cosas sin usar el retraso?

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?

¿No hay un área separada de Arduino? Me resulta extraño ver cosas relacionadas con la programación en el área de ingeniería eléctrica (aparte de la pregunta sobre un LED que es)
@GeorgeBirbilis Esta pregunta tiene casi tres años, mucho antes de que hubiera un intercambio de pila de Arduino.
Lo de @pipe es que vine aquí por la misma pregunta en Arduino stackexchange y había un comentario allí de que también se había copiado aquí o algo así

Respuestas (2)

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 Timer1dispara, 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.