ESP8266 interrupciones y temporizadores con Arduino IDE (NodeMCU)

Si estás buscando aprovechar al máximo tu ESP8266 y NodeMCU, entonces las interrupciones y temporizadores son herramientas clave que debes dominar. En este artículo, te enseñaremos cómo utilizar estas funciones en conjunto con Arduino IDE para sacar el máximo provecho de tu dispositivo. ¡Sigue leyendo para descubrir todo lo que necesitas saber!

En esta guía aprenderá cómo usar interrupciones y temporizadores con ESP8266 NodeMCU usando el IDE de Arduino. Las interrupciones le permiten detectar cambios en el estado de GPIO sin tener que verificar constantemente el valor actual. Con las interrupciones, se activa un evento (se llama a una función) cuando se detecta un cambio.

ESP8266 interrupciones y temporizadores con Arduino IDE (NodeMCU)

Como ejemplo, detectemos movimiento usando un sensor de movimiento PIR: cuando se detecta movimiento, el ESP8266 inicia un temporizador y enciende un LED durante una cantidad predefinida de segundos. Cuando expira el temporizador, el LED se apaga automáticamente.

Para generar una interrupción, llame añadirInterrupción() y pase el pin de interrupción GPIO, ISR (función a llamar) y el modo como argumentos. La función ISR debe ICACHE_RAM_ATTR Atributo declarado. El modo puede CAMBIAR, CRECIENTE o CAER.

attachInterrupt(digitalPinToInterrupt(GPIO), ISR, mode);

Antes de continuar con este tutorial, debes tener instalado el complemento ESP8266 en tu IDE de Arduino. Siga este tutorial para instalar ESP8266 en Arduino IDE si aún no lo ha hecho.

Introducción a las interrupciones ESP8266

Las interrupciones son útiles para provocar operaciones automáticas en programas de microcontroladores y pueden ayudar a resolver problemas de sincronización.

Con las interrupciones no es necesario comprobar constantemente el valor del pin actual. Si se detecta un cambio, se activa un evento: se llama a una función. Esta función se llama Rutina de Servicio de Interrupción (ISR).

Cuando ocurre una interrupción, el procesador deja de ejecutar el programa principal para realizar una tarea y luego regresa al programa principal, como se muestra en la siguiente figura.

ESP8266 interrupciones y temporizadores con Arduino IDE (NodeMCU)

Esto es particularmente útil para activar una acción cuando se detecta movimiento o se presiona una tecla, sin tener que verificar constantemente el estado.

función adjuntarinterrupción()

Para configurar una interrupción en el IDE de Arduino, use el añadirInterrupción() Función que acepta como argumentos: el pin de interrupción GPIO, el nombre de la función a ejecutar y el modo:

attachInterrupt(digitalPinToInterrupt(GPIO), ISR, mode);

pin de interrupción GPIO

El primer argumento es una interrupción GPIO. Deberías usar digitalPinToInterrupt(GPIO) para configurar el GPIO real como pin de interrupción. Por ejemplo, si desea utilizar GPIO 14 como interrupción, utilice:

digitalPinToInterrupt(14)

El ESP8266 admite interrupciones en todos los GPIO excepto GPIO16.

ISR

El segundo argumento añadirInterrupción() Función es el nombre de la función que se llama cada vez que se activa la interrupción: la Rutina de Servicio de Interrupción (ISR).

La función ISR debe ser lo más simple posible para que el procesador pueda volver rápidamente a ejecutar el programa principal.

El mejor enfoque es indicar al código principal que se ha producido la interrupción. Esto se hace usando una variable global y dentro del Cinta() Verifique y borre esta bandera y ejecute el código.

Los ISR deben ICACHE_RAM_ATTR antes de la definición de la función para ejecutar el código de interrupción en la RAM.

Modos de interrupción

El tercer argumento es el modo y hay tres modos diferentes:

  • CAMBIAR: para activar la interrupción cada vez que el pin cambia su valor, por ejemplo de ALTO a BAJO o de BAJO a ALTO;
  • TRAMPA: en caso de que el pin cambie de ALTO a BAJO;
  • CRECIENTE: para activarse cuando el pin cambia de BAJO a ALTO.

Para nuestro ejemplo, estamos usando el modo RISING porque el GPIO al que está conectado cambia de BAJO a ALTO cuando el sensor de movimiento PIR detecta movimiento.

Introducción a los temporizadores ESP8266

ESP8266 interrupciones y temporizadores con Arduino IDE (NodeMCU)

Para este tutorial usaremos temporizadores. Queremos que el LED brille durante un número predeterminado de segundos después de que se detecte movimiento. En lugar de utilizar un cronómetro, Demora() Función que bloquea tu código y no te permite hacer nada más durante una determinada cantidad de segundos. Usamos un cronómetro.

retraso() vs milisegundos()

El Demora() La función acepta un único número int como argumento. Este número representa el tiempo en milisegundos que el programa debe esperar antes de poder pasar a la siguiente línea de código.

delay(time in milliseconds);

Cuando usted llama Retraso(1000) Su programa se detiene en esta línea durante 1 segundo. Demora() es una función de bloqueo. Las funciones de bloqueo impiden que un programa haga cualquier otra cosa hasta que se complete la tarea en cuestión. Si es necesario realizar varias tareas al mismo tiempo, no puede utilizar Demora(). Para la mayoría de los proyectos, debes evitar retrasos y utilizar temporizadores.

Usando una función llamada milisegundos() Puede devolver el número de milisegundos que han pasado desde que se inició el programa por primera vez.

millis();

¿Por qué es útil esta característica? Porque puedes comprobar fácilmente cuánto tiempo ha pasado sin bloquear tu código mediante algunos cálculos matemáticos.

Parpadeo de un LED con millis() (sin demora)

Si no estás familiarizado con milisegundos() función, le recomendamos leer esta sección. Si ya está familiarizado con los temporizadores, puede pasar al proyecto del sensor de movimiento PIR.

El siguiente fragmento de código muestra cómo hacer esto. milisegundos() Función para crear un proyecto de parpadeo. Enciende un LED durante 1000 milisegundos y luego lo vuelve a apagar.

/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com  
*********/

// constants won't change. Used here to set a pin number :
const int ledPin =  26;      // the number of the LED pin

// Variables will change :
int ledState = LOW;             // ledState used to set the LED

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last time LED was updated

// constants won't change :
const 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.

  // check to see if it's time to blink the LED; that is, if the
  // difference between the current time and last time you blinked
  // the LED is bigger than the interval at which you want to
  // blink the LED.
  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);
  }
}

Ver código sin formato

Así es como funciona el código

Echemos un vistazo más de cerca a este boceto de Blink que funciona sin esto. Demora() función (utiliza la milisegundos() función en su lugar).

Básicamente, este código resta el tiempo registrado previamente (anteriorMillis) desde la hora actual (actualMillis). Si el resto es mayor que el intervalo (en este caso 1000 milisegundos), el programa actualiza el anteriorMillis Variable a la hora actual y enciende o apaga el LED.

if (currentMillis - previousMillis >= interval) {
  // save the last time you blinked the LED
  previousMillis = currentMillis;
  (...)

Debido a que este fragmento de código no es bloqueante, cualquier código fuera de esta primera declaración if debería funcionar normalmente.

Ahora debería comprender que tiene tareas adicionales para agregar a su Cinta() La función y su código seguirán haciendo parpadear el LED cada segundo.

Puede cargar este código en su ESP8266 para probarlo. El LED integrado debería parpadear cada segundo.

ESP8266 interrupciones y temporizadores con Arduino IDE (NodeMCU)

ESP8266 NodeMCU con sensor de movimiento PIR

En esta sección, aprenderá cómo usar un sensor de movimiento PIR para detectar movimiento usando interrupciones y temporizadores en su código.

Piezas requeridas

Aquí hay una lista de las piezas necesarias para completar este tutorial:

Puedes utilizar los enlaces anteriores o ir directamente MakerAdvisor.com/tools ¡Para encontrar todas las piezas para tus proyectos al mejor precio!

ESP8266 interrupciones y temporizadores con Arduino IDE (NodeMCU)

Representación esquemática

Monte el sensor de movimiento PIR y un LED en su ESP8266. Conectamos el LED a GPIO 12 (D6) y el PIN de datos del sensor de movimiento PIR GPIO 14 (D5).

ESP8266 interrupciones y temporizadores con Arduino IDE (NodeMCU)

Recomendaciones de literatura: Guía de referencia de asignación de pines ESP8266

Importante: El sensor de movimiento PIR Mini AM312 utilizado en este proyecto funciona a 3,3 V. Sin embargo, si utiliza otro sensor de movimiento PIR como el HC-SR501, funciona a 5 V. Puede modificarlo para que funcione a 3,3 V o simplemente. enciéndalo a través del pin Vin.

La siguiente figura muestra la distribución de pines del sensor de movimiento PIR AM312.

ESP8266 interrupciones y temporizadores con Arduino IDE (NodeMCU)

código

Después de cablear el circuito como se muestra en el esquema, copie el código proporcionado en su IDE de Arduino.

Puede cargar el código tal como está o puede cambiar la cantidad de segundos que el LED permanece encendido después de la detección de movimiento. Solo cambia el TiempoSegundos Variable con el número de segundos deseado.

/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com  
*********/

#define timeSeconds 10

// Set GPIOs for LED and PIR Motion Sensor
const int led = 12;
const int motionSensor = 14;

// Timer: Auxiliary variables
unsigned long now = millis();
unsigned long lastTrigger = 0;
boolean startTimer = false;

// Checks if motion was detected, sets LED HIGH and starts a timer
ICACHE_RAM_ATTR void detectsMovement() {
  Serial.println("MOTION DETECTED!!!");
  digitalWrite(led, HIGH);
  startTimer = true;
  lastTrigger = millis();
}

void setup() {
  // Serial port for debugging purposes
  Serial.begin(115200);
  
  // PIR Motion Sensor mode INPUT_PULLUP
  pinMode(motionSensor, INPUT_PULLUP);
  // Set motionSensor pin as interrupt, assign interrupt function and set RISING mode
  attachInterrupt(digitalPinToInterrupt(motionSensor), detectsMovement, RISING);

  // Set LED to LOW
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);
}

void loop() {
  // Current time
  now = millis();
  // Turn off the LED after the number of seconds defined in the timeSeconds variable
  if(startTimer && (now - lastTrigger > (timeSeconds*1000))) {
    Serial.println("Motion stopped...");
    digitalWrite(led, LOW);
    startTimer = false;
  }
}

Ver código sin formato

Cómo funciona el código

Echemos un vistazo al código.

Comience asignando dos pines GPIO al CONDUJO Y Sensor de movimiento Variables.

const int led = 12;
const int motionSensor = 14;

Luego cree variables que le permitan configurar un temporizador para apagar el LED después de que se detecte movimiento.

unsigned long now = millis();
unsigned long lastTrigger = 0;
boolean startTimer = false;

El Ahora La variable contiene la hora actual. El último disparador La variable contiene el momento en que el sensor PIR detecta movimiento. El iniciar temporizador es una variable booleana que inicia el temporizador cuando se detecta movimiento.

configuración()

En el configuración()Primero inicialice la interfaz serie con una velocidad de 115.200 baudios.

Serial.begin(115200);

Configure el sensor de movimiento PIR como ENTRADA_PULLUP.

pinMode(motionSensor, INPUT_PULLUP);

Para configurar el pin del sensor PIR como una interrupción, use el añadirInterrupción() Funciona como se describió anteriormente.

attachInterrupt(digitalPinToInterrupt(motionSensor), detectsMovement, RISING);

El lápiz que detecta el movimiento es GPIO 14 y la función se llama detecta movimiento() En CRECIENTE Modo.

El LED está encendido PRODUCCIÓN cuyo estado comienza en BAJO.

pinMode(led, OUTPUT);
digitalWrite(led, LOW);

Cinta()

El Cinta() La función se ejecuta constantemente una y otra vez. En cada bucle el Ahora La variable se actualiza con la hora actual.

now = millis();

No pasa nada más en el Cinta(). Sin embargo, si se detecta movimiento, detecta movimiento() La función se llama porque previamente configuramos una interrupción en configuración().

El detecta movimiento() La función imprime un mensaje en el monitor serie, enciende el LED, configura el iniciar temporizador Variable booleana a verdadero y actualiza la último disparador Variable con la hora actual.

ICACHE_RAM_ATTR void detectsMovement() {
  Serial.println("MOTION DETECTED!!!");
  digitalWrite(led, HIGH);
  startTimer = true;
  lastTrigger = millis();
}

Después de este paso el código vuelve a Cinta()Esta vez iniciar temporizador La variable es verdadera. Entonces, cuando haya transcurrido el tiempo especificado en segundos (desde que se detectó movimiento), la siguiente afirmación if es verdadera.

if(startTimer && (now - lastTrigger > (timeSeconds*1000))) {
  Serial.println("Motion stopped…");
  digitalWrite(led, LOW);
  startTimer = false;
}

El mensaje “Movimiento detenido…” se muestra en el monitor serie, el LED se apaga y el iniciar temporizador La variable se establece en «falso».

demostración

Sube el código a tu ESP8266. Asegúrese de haber seleccionado la placa y el puerto COM correctos.

Abra el monitor serie con una velocidad de baudios de 115200.

ESP8266 interrupciones y temporizadores con Arduino IDE (NodeMCU)

Mueva su mano frente al sensor PIR. El LED debería encenderse y el mensaje “¡¡¡MOVIMIENTO DETECTADO!!!«. Después de 10 segundos, el LED debería apagarse.

ESP8266 interrupciones y temporizadores con Arduino IDE (NodeMCU)

Envolver

En resumen, las interrupciones son útiles para detectar un cambio en el estado de GPIO y activar inmediatamente una función. También aprendiste que debes usar temporizadores para escribir código sin bloqueo.

Esperamos que este tutorial te haya resultado útil. Tenemos más tutoriales sobre el manejo de interrupciones con MicroPython y ESP32:

  • MicroPython: Interrupciones con ESP32 y ESP8266
  • ESP32 con sensor de movimiento PIR mediante interrupciones y temporizadores

Obtenga más información sobre la placa ESP8266 con nuestros recursos:

  • Domótica con EPS8266
  • Programación MicroPython con ESP32 y ESP8266
  • Proyectos y tutoriales gratuitos de ESP8266

Gracias por leer.

Error 403 The request cannot be completed because you have exceeded your quota. : quotaExceeded

ESP8266 Interupciones y Temporizadores con Arduino IDE (NodeMCU)

En esta guía, aprenderás cómo utilizar interrupciones y temporizadores con el ESP8266 NodeMCU utilizando Arduino IDE. Las interrupciones te permiten detectar cambios en el estado de las GPIO sin la necesidad de verificar constantemente su valor actual. Con las interrupciones, cuando se detecta un cambio, se desencadena un evento (se llama a una función).

Introducción a las Interrupciones ESP8266

Las interrupciones son útiles para que sucedan cosas automáticamente en programas de microcontroladores y pueden ayudar a resolver problemas de temporización.

Con las interrupciones, no necesitas verificar constantemente el valor actual del pin. Cuando se detecta un cambio, se desencadena un evento: se llama a una función. Esta función se llama rutina de servicio de interrupción (ISR).

Las interrupciones son especialmente útiles para activar una acción cuando se detecta movimiento o cuando se presiona un botón sin la necesidad de verificar constantemente su estado.

Función attachInterrupt()

Para configurar una interrupción en Arduino IDE, utiliza la función attachInterrupt(), que acepta como argumentos: el pin de interrupción de GPIO, el nombre de la función a ejecutar y un modo.

El primer argumento es un GPIO de interrupción. Debes usar digitalPinToInterrupt(GPIO) para configurar el GPIO real como un pin de interrupción. Por ejemplo, si deseas usar GPIO 14 como una interrupción, utiliza:

  1. digitalPinToInterrupt(14)

El segundo argumento de la función attachInterrupt() es el nombre de la función que se llamará cada vez que se active la interrupción: la rutina de servicio de interrupción (ISR).

El tercer argumento es el modo y hay 3 modos diferentes:

  1. CHANGE: para activar la interrupción siempre que el pin cambie de valor, por ejemplo, de ALTO a BAJO o de BAJO a ALTO.
  2. FALLING: para cuando el pin cambia de ALTO a BAJO.
  3. RISING: para activar cuando el pin cambia de BAJO a ALTO.

Para nuestro ejemplo, utilizaremos el modo RISING, porque cuando el sensor de movimiento PIR detecta movimiento, el GPIO al que está conectado pasa de BAJO a ALTO.

Introducción a los Temporizadores ESP8266

Para este tutorial, utilizaremos temporizadores. Queremos que el LED permanezca encendido durante un número predeterminado de segundos después de detectar movimiento. En lugar de utilizar una función delay() que bloquea tu código y no te permite hacer nada más durante un número determinado de segundos, utilizaremos un temporizador.

La función delay() acepta un solo número entero como argumento. Este número representa el tiempo en milisegundos que el programa debe esperar hasta continuar con la siguiente línea de código.

Cuando llamas a delay(1000), tu programa se detiene en esa línea durante 1 segundo. delay() es una función de bloqueo. Las funciones de bloqueo impiden que un programa haga cualquier otra cosa hasta que se complete esa tarea en particular. Si necesitas que múltiples tareas se realicen al mismo tiempo, no puedes usar delay(). Para la mayoría de los proyectos, deberías evitar usar retrasos y utilizar temporizadores en su lugar.

Usando una función llamada millis() puedes devolver el número de milisegundos que han pasado desde que el programa se inició.

Conclusión

En resumen, las interrupciones son útiles para detectar un cambio en el estado de una GPIO y desencadenar instantáneamente una función. También has aprendido que debes usar temporizadores para escribir código no bloqueante.

Esperamos que hayas encontrado útil este tutorial. Tenemos otros tutoriales sobre cómo manejar interrupciones usando MicroPython y el ESP32.

Recursos sobre ESP8266

Aprende más sobre la placa ESP8266 con nuestros recursos:

  1. Automatización del Hogar utilizando ESP8266
  2. Programación de MicroPython con ESP32 y ESP8266
  3. Proyectos y Tutoriales Gratuitos de ESP8266

Gracias por leer.

4 comentarios en «ESP8266 interrupciones y temporizadores con Arduino IDE (NodeMCU)»

Deja un comentario