Despertar arduino con control remoto

Hola,

Tengo el siguiente código en el que controlo el estado activado o low power de un arduino con un sensor IR conectado al pin 2 y un control remoto. Pulsando el botón Off entra en modo low power, pero me gustaría que solamente se despierte si pulso el botón On, y que con cualquier otro botón o señal que reciba el IR y que activa la interrupción, vuelva a dormirse. Es decir, el funcionamiento habitual del standby de una televisión por ejemplo.

He estado probando con el siguiente código, basado en otras entradas del foro, donde a través de la variable PowerState intento diferenciar si el estado anterior a recibir la señal era encendido o low power, pero solo funciona a veces:

#include <IRremote.hpp>
#include <LowPower.h>

#define Off 0xFD02EF00
#define On 0xFC03EF00
#define Tecla_1 0xFE01EF00
#define Tecla_2 0xFF00EF00

int IR = 2;

bool PowerOff = false;
bool PowerState = true;

void setup() {
  PowerState = true;

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

  pinMode(IR, INPUT);
  IrReceiver.begin(IR, ENABLE_LED_FEEDBACK);
}

void loop() {
  if (IrReceiver.decode()) {
    if (PowerState) {
      switch (IrReceiver.decodedIRData.decodedRawData) {
        case On:
          PowerState = true;
          PowerOff = false;
        break;

        case Off:
          PowerState = false;
          PowerOff = true;
        break;

        case Tecla_1:
          PowerState = true;
          PowerOff = false;
          digitalWrite(LED_BUILTIN, HIGH);
          // Otras acciones
        break;

        case Tecla_2:
          PowerState = true;
          PowerOff = false;
          // Otras acciones
        break;
      }
    }
    else if (!PowerState && IrReceiver.decodedIRData.decodedRawData == On) { // Se despierta
      PowerState = true;
      PowerOff = false;
    }
    else if (!PowerState && IrReceiver.decodedIRData.decodedRawData != On) { // Vuelve a dormirse
      PowerOff = true;
    }
    delay(200);
    IrReceiver.resume();
  }

  if (PowerOff) {
    PowerState = false;
    delay(200);  // Para evitar detección de nuevos pulsos del C/R
    noInterrupts();
    EIFR = bit(INTF0);  // Limpia interrupciones que pudiesen quedar pendientes
    attachInterrupt(digitalPinToInterrupt(IR), IR_ISR, FALLING);
    interrupts();
    LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);  // *** A dormir! ***
  }
}

void IR_ISR() {
  detachInterrupt(digitalPinToInterrupt(IR));
}

Sin ser muy entendido del tema, creo que cuando funciona es porque la pulsación sobre el botón es larga y da tiempo a despertarse, entrar en el if (IrReceiver.decode()) y reconocer que la variable PowerState está en falso y se ha puslado On. Si la pulsación es muy corta falla. Y sobre todo, deja de funcionar cuando el arduino lleva varias horas dormido. Se recibe la señal, pero no es capaz de identificar que se trata del botón On.

¿Alguien tiene alguna sugerencia de cómo plantear el código?

Muchas gracias por vuestra ayuda.

No es posible porque para detectar un boton requieres de un microcontrolador y no lo tienes porque esta dormido entonces es el huevo o la gallina. Quieres que este dormido y quieres que se despierte detectando un boton específico. Ló unico que puedes hacer es que se despierte porque tocas un boton.

@ap111 Fijate en este código

Ten presente un par de detalles:
El simulador no tiene soporte para el modo sleep, así que está emulado con un lazo while().
Comentando la línea

#define _WOKWI_

lo compilas para la placa real.

El programa responde solo a las teclas Power para dormirlo y 0; 1 y 2 para despertarlo.
Cualquier otra tecla (incluso Power) lo vuelve a dormir si ya estaba dormido, o lo mantiene despierto si así lo está. Por supuesto, en este caso, Power lo manda a dormir.

El código es mío, y a pesar de que desde ya todo lo que aquí se publica es de acceso público, tienes mi autorización explícita para usarlo y modificarlo a tu antojo. :laughing:

Buen truco!!

Muchas gracias. No conocía ese simulador de Arduino, me parece muy buena opción para hacer pruebas aunque no tengas los sensores a disponibles.

El código funciona, aunque tendré que hacerle adaptaciones para que sólo se despierte utilizando una tecla, y con el resto continúe durmiendo. Gracias por cederlo :slight_smile:

Suena como si dijeras no es exactamente lo que quiero, y tengo que trabajar para que haga lo que deseo.
Quitas ls teclas que no usas y listo.
No es la gran modificación.

La verdad espero haberte mal interpretado.

Honestamente, por más que leo mi respuesta anterior no sé dónde puedes encontrar una mala intención en mis palabras. He agradecido a @MaximoEsfuerzo dos veces su aportación, y marcado su respuesta como solución al hilo.

Y sí, voy a tomar como base este código pero necesito hacer algunos cambios, porque el controlo remoto no lo utilizaré únicamente para despertar o enviar a dormir el arduino. Me gustaría que cuando esté despierto el resto de teclas sirvan para hacer otras cosas (de ahí que en mi código inicial escribiera // Otras acciones en los case de Tecla_1 o Tecla_2), pero que estas teclas no despierten al arduino (o en su defecto lo envíen de vuelta a dormir, si ese es el estado en el que se encuentra). Quiero lograr que solo la tecla On despierte el arduino. Imagino que tendré que poner en cada case un condicional tipo if (PowerState) {PowerOff = true}, pero como trabajarlo y comprobarlo me llevará un tiempo, y no quería que pasase más tiempo en dar respuesta y dejar abierto el hilo, por eso puse lo de que necesito adaptarlo. Ni se me ocurrió pensar que pudiera interpretarse como un desprecio a quien me ha dado ayuda.

Espero haber aclarado el malentendido.

Estudiá bien el código.
La idea (que fue planteada por otro usuario) es que

Tené en cuenta que al ser una demostración de como poder hacer uso del c/r para dormir/despertar al micro, no hace mucho más que eso.
Fijate que los botones 0, 1 y 2 solo despiertan al micro pero podrían además hacer otras acciones, solo agrégalas al case que corresponda y si quieres agregar más botones debes agregarlos a switch().
Por otro lado, el "fade" del LED puedes quitarlo, fue parte de la respuesta a una consulta de otro usuario.

Si quieres que solo duerma/despierte con el boton "Power" cambia el código así


void loop() {

  if (irrecv.decode()) {
#ifdef _DEBUG_
    Serial.println(irrecv.decodedIRData.command, HEX);
#endif
// ----- Modificacion -----
    pwrOff = pwrState;
    switch (irrecv.decodedIRData.command){ //decodedRawData) {
      case Boton_Off:
        pwrOff = !pwrOff;
        pwrState = !pwrState;
        break;
      case Boton_0:
        if (pwrOff == false) {
        // acciones que ejecuta este boton
        }
        break;
      case Boton_1:
        if (pwrOff == false) {
        // acciones que ejecuta este otro boton
        }
        break;
      case Boton_2:
        if (pwrOff == false) {
        // acciones que ejecuta este boton
        }
        break;
      default:  // botones que no fueron definidos
#ifdef _DEBUG_
        Serial.print("Tecla no valida. ");
        Serial.println(pwrOff ? "Vuelve a dormir." : "");
#endif
        break;
    }
    irrecv.resume();
  }
// resto del codigo sin cambios

Muchas gracias @MaximoEsfuerzo. Buena idea lo de utilizar el mismo botón para dormir y despertar el arduino

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.