Go Down

Topic: Salida de bucle en control IR remoto de tira led (Read 368 times) previous topic - next topic

Javi25

Jan 04, 2020, 09:38 pm Last Edit: Jan 05, 2020, 11:14 am by Javi25 Reason: Se ha añadido el código completo y enlaces de acuerdo a las normas del foro
Hola,

Muchas gracias de antemano por el tiempo que dediquéis leyendo este post y ayudándome a encontrar la solución :)

Explico en primer lugar el trabajo que estoy realizando y cómo lo estoy programando, y después el problema al que no he encontrado todavía solución.

He encontrado un mando a distancia para controlar leds RGB como el del enlace:

https://www.manomano.es/p/mando-a-distancia-suelto-para-el-controlador-de-tiras-led-modelo-81052-electro-dh-81052-m-8430552140916-7394896

Así que compré una tira led RGB y con un Arduino Nano y un sensor IR VS1838 estoy programando el código para controlar la tira de leds. El sensor IR va conectado al pin digital 5 del arduino nano, y la tira led a los pines digitales 6, 7 y 8 (RGB) y al de alimentación de 5V.

En un curso de introducción a Arduino nos recomendaron utilizar las funciones de interrupción cuando se utilizan controles remotos como este, para dejar "más limpio" el código principal, así que he generado una interrupción en el pin 2 del arduino nano. Básicamente, en el código se definen primero las variables, en el setup se inicializa la recepción IR y se define la función de interrupción, en el loop se lee la señal recibida en el sensor IR y se activa la interrupción, que llama a la función "led". Esta función "led" consiste en un grupo de condicionales IF que encienden un color u otro según el botón del mando pulsado. Cuando son colores fijos o encender o apagar las luces, el programa funciona sin problema.

El problema viene cuando quiero añadir transiciones entre los tres colores RGB y que se repitan cíclicamente hasta que pulse otro botón (son los botones flash, strobe, fade y smooth, por si alguien tiene este tipo de luces led). Aquí he generado 3 bucles "for" para cambiar de rojo a verde, de verde a azul y de azul a rojo de nuevo. Si dejo estos tres bucles, esta transición entre los tres colores solo se ejecuta una vez, pero quiero que esté repitiéndose hasta que pulse otro botón del mando. Para ello, he englobado estos tres bucles "for" dentro de otro bucle "while", y aquí es donde me quedo atascado. Si no pongo ninguna condición (while(1)), el bucle se repite indefinidamente y no se lee ninguna señal nueva procedente del mando a distancia. He intentado poner la función "irrecv.decode" dentro del while e incluso dentro de cada for para que reciba nueva señal del mando y salte la interrupción, pero no me funciona.

Este es el código completo. El problema está en el bucle del botón "Flash":

Code: [Select]


#include "Arduino.h"
#include <IRremote.h>
int receptor = 5;

IRrecv irrecv(receptor);
decode_results codigo;

int ledR = 8;
int ledG = 7;
int ledB = 6;
int intR = 255; // Nivel de intensidad de cada LED RGB (0 (máximo), 255 (mínimo)).
int intG = 255;
int intB = 255;

int intPin0 = 2; // Pin digital 2 para interrupción.

void setup()
{
  Serial.begin(9600); // Inicia comunicación con puerto serie.

  irrecv.enableIRIn();

  pinMode(ledR, OUTPUT);
  pinMode(ledG, OUTPUT);
  pinMode(ledB, OUTPUT);
 
  analogWrite(ledR, intR);
  analogWrite(ledG, intG);
  analogWrite(ledB, intB);

  pinMode(2,OUTPUT);
  digitalWrite(intPin0, HIGH);
 
  attachInterrupt(0, led, FALLING);
}
 
void loop()
{

 if (irrecv.decode(&codigo)){
  digitalWrite(intPin0, LOW);
 
  delay(500);
  irrecv.resume();}


}

void led(){

  digitalWrite(intPin0, HIGH);

      if (codigo.value==0xF7C03F){
        Serial.println("ON");
        intR = 0;
        intG = 0;
        intB = 0;
        analogWrite(ledR, intR);
        analogWrite(ledG, intG);
        analogWrite(ledB, intB);}

      if (codigo.value==0xF740BF){
        Serial.println("OFF");
        intR = 255;
        intG = 255;
        intB = 255;
        analogWrite(ledR, intR);
        analogWrite(ledG, intG);
        analogWrite(ledB, intB);}
       
      if (codigo.value==0xF720DF){
        Serial.println("R");
        intR = 0;
        intG = 255;
        intB = 255;
        analogWrite(ledR, intR);
        analogWrite(ledG, intG);
        analogWrite(ledB, intB);}

      if (codigo.value==0xF7A05F){
        Serial.println("G");
        intR = 255;
        intG = 0;
        intB = 255;
        analogWrite(ledR, intR);
        analogWrite(ledG, intG);
        analogWrite(ledB, intB);}
     
      if (codigo.value==0xF7609F){
        Serial.println("B");
        intR = 255;
        intG = 255;
        intB = 0;
        analogWrite(ledR, intR);
        analogWrite(ledG, intG);
        analogWrite(ledB, intB);}

      if (codigo.value==0xF7E01F){
        Serial.println("W");
        intR = 0;
        intG = 0;
        intB = 0;
        analogWrite(ledR, intR);
        analogWrite(ledG, intG);
        analogWrite(ledB, intB);}

      if (codigo.value==0xF7D02F){
        Serial.println("FLASH");
       
        while (1){
         
        for (int i=0; i<=255; i++){
          analogWrite(ledR, i);
          analogWrite(ledG, 255-i);
          analogWrite(ledB, 255);
          delay(100);}
          Serial.println("Bucle 1");
         
        for (int j=0; j<=255; j++){
          analogWrite(ledG, j);
          analogWrite(ledB, 255-j);
          analogWrite(ledR, 255);
          delay(100);}
          Serial.println("Bucle 2");
         
        for (int k=0; k<=255; k++){
          analogWrite(ledB, k);
          analogWrite(ledR, 255-k);
          analogWrite(ledG, 255);
          delay(100);}
          Serial.println("Bucle 3");
        }

}


¿Dónde o cómo puedo poner dentro de estos bucles que se lea la señal del mando IR y que salga de esta repetición cuando se pulse otro botón?

Muchas gracias por vuestra ayuda!

Saludos,
Javi

surbyte

Hola Javi25, asi como yo he leído tu entrada (como tu la llamas) te pido que leas la entrada de este foro que son las Normas del mismo.
En ellas aprenderás a postear debidamente y saber qué cosas se consideran faltas y como presentar la información para tener mejores y más rápidas respuestas.
Códigos y enlaces se postean usando etiquetas. Ya sabes, espero que los edites.


Tu código adolece el típico problema de delay(), acaso en tu curso no te dijeron que delay() detiene al microcontrolador, al punto que no hace nada?
Asi que no es una buena idea tener loops o for() que incorporen delay() que se multiplican

Tu primer loop de delay(10) consume 256x10= 2560mseg o 2.56 segundos el segundo igual y el tercero multiplica x 10 esa cantidad.
Sencillamente imposible que hagas algo que responda a un comando, no te parece?

La solución esta en la sección Documentación => Indice de temas tutoriales  => millis().
Ve ahi, lee como se usa y emplea millis() y luego modifica tu código para emplearlo sin perder tiempo.

Lo de la interrupción no lo veo porque has puesto un código parcializado.
En las normas se pide que no se pongan códigos parciales porque los que intentamos ayudarte no terminamos de entender que has hecho. Por ejemplo, hablas de interrupciones que en el código mostrado no están presentes.

Asi que lee las normas, lee los tutoriales de millis(), modifica el código con el nuevo criterio y lo publicas y vemos como mejora o consulta lo que no entiendas.

Javi25

Hola surbyte,

Gracias por tu respuesta. Siguiendo tus indicaciones, he leído las normas del foro y he editado el post (veo que os gusta más llamarlo así) con el código completo y enlaces posteados utilizando etiquetas.

He estado mirando la documentación sobre millis() y me parece muy útil, lo revisaré con más detalle para sustituir los delays por millis.

Pero igualmente, ¿no sería necesario incluir alguna función dentro del "while" o de los "for" que compruebe si hay señal recibida en el sensor IR y si la hay que salga del bucle? He intentado introducir "irrecv.decode" en ellos, como en la función loop(), pero no consigo salir del bucle presionando otros botones del mando.

Gracias de nuevo!
Javi


surbyte

#3
Jan 06, 2020, 12:04 am Last Edit: Jan 06, 2020, 01:00 am by surbyte
Quote
he editado el post (veo que os gusta más llamarlo así) con el código completo
Lo llamamos así o yo lo hago asi porque asi lo llamaban cuando llegué al foro, pero si tienes otro nombre como tema, tópico, puedes hacerlo, hablamos español asi que supongo que nos entenderemos.

Si usas interrupciones entonces en una rutina de interrupción no puedes usar esta línea
Code: [Select]
Serial.println("ON");

Terminantemente prohibido porque una interrupción es una rutina VELOZ, entro y salgo lo más rápido posible y Serial.print no lo es. Es todo menos veloz de hecho demora varios mseg.

Así que empieza eliminando todos los Serial.print de tu rutina de interrupción led()

Eso ocurre porque se programa mal y no te ofendas por el comentario. Alguien te ha enseñado que se pueden usar interrupciones para cualquier cosa. La respuesta es que si pero la gran mayoría y yo tmb las usamos cuando corresponde.
En tu caso no corresponde usar interrupciones.
Se puede hacer el programa sin interrupciones, CLARO que sí.
Como? Usando millis()

Voy a modificar tu código basado en esta librería IRremote.h

En ella no hay un solo ejemplo que use interrupciones del modo que tu la usas.
La interrupción la usa la librería para seguir los comandos recibidos, pero de ningún modo para interpretarlos, eso se hace gracias a que

Code: [Select]
f (irrecv.decode(&results)) {
presenta los datos recibidos via results.value

Que se supone que hace ese while(1) que has puesto dentro de la rutina de interrupción para que ejecute indefinidamente esos for?
Eso es lo mismo que escribir "No entendí realmente cómo funciona una interrupción". Pero como nadie nació sabiendo no hay de qué preocuparse.

Ahora te explico. Una vez mas insisto, una interrupción debe ocupar poco tiempo.
Tu además de poner Serial.print que ya de por sí cuelga la interrupción agregas un while(1) que le dice.. ejecuta lo que sigue a continuación hasta que la muerte nos separe!!! Cómo? Si. Así es.

Entonces ni Serial.print, ni while(1) en una interrupción y ya que estamos sacamos todo y lo hacemos de nuevo sin interrupciones.

Empecemos así y dime que tan bien o mal se comporta todo el código.

Code: [Select]
#include "Arduino.h" // usado con platformio sino comentar
#include <IRremote.h>
int receptor = 5;

IRrecv irrecv(receptor);
decode_results codigo;

int ledR = 8;
int ledG = 7;
int ledB = 6;
int intR = 255; // Nivel de intensidad de cada LED RGB (0 (máximo), 255 (mínimo)).
int intG = 255;
int intB = 255;


void setup()
{
  Serial.begin(9600); // Inicia comunicación con puerto serie.
 
  Serial.println("Enabling IRin");
  irrecv.enableIRIn(); // Start the receiver
  Serial.println("Enabled IRin");

  pinMode(ledR, OUTPUT);
  pinMode(ledG, OUTPUT);
  pinMode(ledB, OUTPUT);
 
  analogWrite(ledR, intR);
  analogWrite(ledG, intG);
  analogWrite(ledB, intB);
}
 
void loop()
{
  if (irrecv.decode(&codigo)) {
      Serial.println(codigo.value, HEX);
      irrecv.resume(); // Receive the next value
  }
  if (codigo.value==0xF7C03F){
      Serial.println("ON");
      intR = 0;
      intG = 0;
      intB = 0;
      analogWrite(ledR, intR);
      analogWrite(ledG, intG);
      analogWrite(ledB, intB);
  }

  if (codigo.value==0xF740BF){
      Serial.println("OFF");
      intR = 255;
      intG = 255;
      intB = 255;
      analogWrite(ledR, intR);
      analogWrite(ledG, intG);
      analogWrite(ledB, intB);
  }

  if (codigo.value==0xF720DF){
      Serial.println("R");
      intR = 0;
      intG = 255;
      intB = 255;
      analogWrite(ledR, intR);
      analogWrite(ledG, intG);
      analogWrite(ledB, intB);
  }

  if (codigo.value==0xF7A05F){
      Serial.println("G");
      intR = 255;
      intG = 0;
      intB = 255;
      analogWrite(ledR, intR);
      analogWrite(ledG, intG);
      analogWrite(ledB, intB);
  }

  if (codigo.value==0xF7609F){
      Serial.println("B");
      intR = 255;
      intG = 255;
      intB = 0;
      analogWrite(ledR, intR);
      analogWrite(ledG, intG);
      analogWrite(ledB, intB);
  }

  if (codigo.value==0xF7E01F){
      Serial.println("W");
      intR = 0;
      intG = 0;
      intB = 0;
      analogWrite(ledR, intR);
      analogWrite(ledG, intG);
      analogWrite(ledB, intB);
  }

  if (codigo.value==0xF7D02F){
      Serial.println("FLASH");     
      for (int i=0; i<=255; i++){
        analogWrite(ledR, i);
        analogWrite(ledG, 255-i);
        analogWrite(ledB, 255);
        delay(100);
      }
      Serial.println("Bucle 1");
             
      for (int j=0; j<=255; j++) {
        analogWrite(ledG, j);
        analogWrite(ledB, 255-j);
        analogWrite(ledR, 255);
        delay(100);
      }
      Serial.println("Bucle 2");
           
      for (int k=0; k<=255; k++){
        analogWrite(ledB, k);
        analogWrite(ledR, 255-k);
        analogWrite(ledG, 255);
        delay(100);
      }
      Serial.println("Bucle 3");
  }
}



Javi25

Hola surbyte,

Gracias por la respuesta.

Por supuesto que no me ofendo. Mi formación está totalmente alejada de este mundillo y mi experiencia en él se resume en un curso introductorio de 3 horas hace unos años y unos cuantos programitas sencillos con Arduino basándome en búsquedas en internet y en este foro. Así que obviamente programo mal y no tengo ni idea de cómo funcionan muchas cosas, acudo aquí para aprender y mejorar.

Inicialmente mi código era similar al que me has puesto tú, en el sentido de que todas las funciones "if" dependientes del valor del botón pulsado con el mando a distancia estaban dentro de la función "loop()" (lo de la interrupción lo recordé después y lo modifiqué, aunque veo que ha sido mala idea). Quitaré los "Serial.println", pero de momento me ayudan para conocer qué está funcionando y qué no mientras acabo el programa.

Acabo de probar el código que has escrito. Más o menos el comportamiento es el mismo que ya tenía: a simple vista no soy capaz de ver que la respuesta sea más rápida (aunque creo lo que me dices de que así lo será), y al pulsar el botón "FLASH" la transición entre luces sucede solo una vez, es decir, cada bucle "for" solo se ejecuta una vez, no se repite indefinidamente.

En el monitor serie se lee lo siguiente:

Code: [Select]

F7D02F
FLASH
Bucle 1
Bucle 2
Bucle 3
FFFFFFFF


Por la última línea, entiendo que a la salida de

Code: [Select]
if (codigo.value==0xF7D02F)

codigo.value vale FFFFFFFF, y por eso no repite los bucles "for" de nuevo. Por eso puse el "while", pero no sé qué condición indicarle para que salga cuando se pulse un botón del mando a distancia.

Por otro lado, mientras se ejecuta cada uno de los bucles "for" el programa no responde si se pulsa otro botón del mando. Esto ya me has indicado que se debe al uso del "delay" y que debo cambiarlo por "millis", tengo pendiente profundizar más en este tema.

Gracias,
Javi

surbyte

#5
Jan 07, 2020, 01:40 am Last Edit: Jan 07, 2020, 01:45 am by surbyte
A ver ahora, he modificado todo como para que responda con velocidad usando millis() y máquina de estados

Code: [Select]
#include <IRremote.h>
int receptor = 5;

IRrecv irrecv(receptor);
decode_results codigo;

int ledR = 8;
int ledG = 7;
int ledB = 6;
int intR = 255; // Nivel de intensidad de cada Led RGB (0 (máximo), 255 (mínimo)).
int intG = 255;
int intB = 255;
bool flag = false;
unsigned long tiempo;
int i = 0, j = 0, k = 0;
byte estado = 0;

void setup()
{
  Serial.begin(9600); // Inicia comunicación con puerto serie.
 
  Serial.println("Enabling IRin");
  irrecv.enableIRIn(); // Start the receiver
  Serial.println("Enabled IRin");

  pinMode(ledR, OUTPUT);
  pinMode(ledG, OUTPUT);
  pinMode(ledB, OUTPUT);
 
  analogWrite(ledR, intR);
  analogWrite(ledG, intG);
  analogWrite(ledB, intB);
}
 
void loop()
{
  if (irrecv.decode(&codigo)) {
      flag = false;
      Serial.println(codigo.value, HEX);
      irrecv.resume(); // Receive the next value
  }
  if (codigo.value==0xF7C03F){
      Serial.println("ON");
      intR = 0;
      intG = 0;
      intB = 0;
      analogWrite(ledR, intR);
      analogWrite(ledG, intG);
      analogWrite(ledB, intB);
  }

  if (codigo.value==0xF740BF){
      Serial.println("OFF");
      intR = 255;
      intG = 255;
      intB = 255;
      analogWrite(ledR, intR);
      analogWrite(ledG, intG);
      analogWrite(ledB, intB);
  }

  if (codigo.value==0xF720DF){
      Serial.println("R");
      intR = 0;
      intG = 255;
      intB = 255;
      analogWrite(ledR, intR);
      analogWrite(ledG, intG);
      analogWrite(ledB, intB);
  }

  if (codigo.value==0xF7A05F){
      Serial.println("G");
      intR = 255;
      intG = 0;
      intB = 255;
      analogWrite(ledR, intR);
      analogWrite(ledG, intG);
      analogWrite(ledB, intB);
  }

  if (codigo.value==0xF7609F){
      Serial.println("B");
      intR = 255;
      intG = 255;
      intB = 0;
      analogWrite(ledR, intR);
      analogWrite(ledG, intG);
      analogWrite(ledB, intB);
  }

  if (codigo.value==0xF7E01F){
      Serial.println("W");
      intR = 0;
      intG = 0;
      intB = 0;
      analogWrite(ledR, intR);
      analogWrite(ledG, intG);
      analogWrite(ledB, intB);
  }

  if (codigo.value==0xF7D02F) {
      Serial.println("FLASH");   
      flag = true;
  }
 
  if (flag) {
      switch (estado) {
          case 0: analogWrite(ledR, i);
                  analogWrite(ledG, 255-i);
                  analogWrite(ledB, 255);
                  estado = 1;
                  tiempo = millis();
                  break;
          case 1: if (millis() - tiempo > 100UL) {
                      if (++i > 255) {
                          Serial.println("Bucle 1");
                          estado = 2;
                      }
                  }
                  break;
          case 2: analogWrite(ledG, j);
                  analogWrite(ledB, 255-j);
                  analogWrite(ledR, 255);
                  estado = 3;
                  tiempo = millis();
                  break;
          case 3: if (millis() - tiempo > 100UL) {
                      if (j++ > 255) {
                        Serial.println("Bucle 2");
                        estado = 4;
                      }
                  }
                  break;
          case 4: analogWrite(ledB, k);
                  analogWrite(ledR, 255-k);
                  analogWrite(ledG, 255);
                  estado = 5;
                  tiempo = millis();
                  break;
          case 5: if (millis() - tiempo > 100UL) {
                      if( k++ > 255) {
                          Serial.println("Bucle 3");
                          estado = 0;                        // listo para recomenzar
                          i = 0;
                          j = 0;
                          k = 0;
                      }
                  }
                  break;                 
          default : estado = 0;
                    break;
      }     
  }
}


Esto hace lo mismo que tu primer for() pero sin gastar tiempo entre comillas.

Code: [Select]
          case 0: analogWrite(ledR, i);
                  analogWrite(ledG, 255-i);
                  analogWrite(ledB, 255);
                  estado = 1;
                  tiempo = millis();
                  break;
          case 1: if (millis() - tiempo > 100UL) {
                      if (++i > 255) {
                          Serial.println("Bucle 1");
                          estado = 2;
                      }
                  }
                  break;


Este fragmento de código hace lo mismo que tu for().
El case 0, ejecuta para cada valor que tome i los comandos analogWrite(pin, valor) con valor de 0 a 255.
Como verás, lo siguiente es cambiar la variable estado a 1, con lo que le estoy diciendo que en el próximo loop no entre en ese case sino en el que dice case 1.
Ademas he inicializado tiempo con el valor de millisl().
En el case 1, hay una simple comparación entre el valor de millis() comparado con el que acabo de guardar y no será hasta que su diferencia llegue a 100 mseg o mejo dicho que la supere (si quieres coloca un >= que entonces incrementará el valor de i y volverá a preparar el siguiente estado a 0 para que los leds incrmenten su brillo. Si el valor de i supera 255 entonces ya ha concluido y paso al estado 2 que era tu siguiente for(). Asi se repite con los otros case 2, 3, 4, y 5.

Espero funcione y haga lo que esperas.

Javi25

Hola,

Disculpa que insista con este tema, pero el código no funciona. Cuando pulso el botón FLASH solo se enciende el led Rojo y no varía su intensidad, es decir, parece que el valor de la variable "i" siempre vale 0.

En el monitor serie se lee lo siguiente:

Code: [Select]

Enabling IRin
Enabled IRin
F7D02F
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FFFFFFFF


Saludos,
Javi

surbyte

Esperaba que con la ayuda que te di pudieras al menos buscar la falla por tu cuenta.

Code: [Select]
  if (flag) {
      switch (estado) {
          case 0: //Serial.println("Valor de i:"+String(i));
                  analogWrite(ledR, i);
                  analogWrite(ledG, 255-i);
                  analogWrite(ledB, 255);
                  estado = 1;
                  tiempo = millis();
                  break;
          case 1: if (millis() - tiempo > 100UL) {
                      if (++i > 255) {
                          Serial.println("Bucle 1");
                          estado = 2;
                      }
                      else
                          estado = 0;
                  }
                  break;
          case 2: //Serial.println("Valor de j:"+String(j));
                  analogWrite(ledG, j);
                  analogWrite(ledB, 255-j);
                  analogWrite(ledR, 255);
                  estado = 3;
                  tiempo = millis();
                  break;
          case 3: if (millis() - tiempo > 100UL) {
                      if (j++ > 255) {
                        Serial.println("Bucle 2");
                        estado = 4;
                      }
                      else
                          estado = 2;
                  }
                  break;
          case 4: //Serial.println("Valor de k:"+String(k));
                  analogWrite(ledB, k);
                  analogWrite(ledR, 255-k);
                  analogWrite(ledG, 255);
                  estado = 5;
                  tiempo = millis();
                  break;
          case 5: if (millis() - tiempo > 100UL) {
                      if( k++ > 255) {
                          Serial.println("Bucle 3");
                          estado = 0;                        // listo para recomenzar
                          i = 0;
                          j = 0;
                          k = 0;
                      }
                      else
                          estado = 4;
                  }
                  break;                 
          default : estado = 0;
                    break;
      }     
  }
}


Acá esta funcionando debidamente, corrige desde if(flag) en adelante

Javi25

No, no funciona

Code: [Select]
Enabling IRin
Enabled IRin
F7D02F
FLASH
Valor de i:0
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FFFFFFFF

surbyte

#9
Jan 09, 2020, 11:36 pm Last Edit: Jan 09, 2020, 11:37 pm by surbyte
Pues aca si lo hace, sino quita los comentarios y verás como suben los i, j y k

El programa que vale esta en el post#5, no el anterior.

Javi25

Pues aquí no funciona.

Si no lo entendí mal el código completo está en el post #5, y desde
Code: [Select]
if (flag) { en adelante copié el del post #7.

En mi anterior respuesta ya había quitado los comentarios, y ahí puedes ver que el valor de i no cambia de 0.

Acabo de cargar todo de nuevo y de probarlo, y el valor de i va aumentando conforme yo voy pulsando al botón del mando a distancia. Es decir, no funciona como bucle continuo, si no que espera a que se repita la misma señal en el sensor IR.

Javi25

¿Alguien puede ayudarme con este tema?

Con el último código que me facilitó surbyte (posts #5 y #7) solo consigo que la variable "i" vaya aumentando de valor (de 0 a 255) pulsando el botón "Flash" del mando a distancia.

¿Cómo puedo hacer para que funcione en bucle hasta que pulse otro botón?

Gracias!

surbyte

Si quieres que el mismo comando lo prenda y apague solo haz esto

Code: [Select]
if (codigo.value==0xF7D02F) {
      Serial.println("FLASH");   
      flag = !flag;
  }



y quita el flag = false que esta por ahi.

Javi25

Hola surbyte,

Creo que no he explicado bien el problema con el código que me facilitaste (posts #5 y #7).

Si pulso el botón "FLASH" del mando a distancia, en el monitor serie veo lo siguiente:

Code: [Select]
Enabling IRin
Enabled IRin
F7D02F
FLASH
Valor de i:0
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FLASH
FFFFFFFF


Y esto es lo único que sucede. La tira Led se mantiene en color rojo porque "i" vale 0, pero el valor de "i" no va aumentando, y por tanto el color no cambia de rojo a verde de manera progresiva, ni salta a los estados posteriores (cambio de verde a azul y de azul a rojo, para empezar de nuevo).

¿Se te ocurre alguna solución?

Gracias,
Javi

surbyte

#14
Jan 20, 2020, 04:14 pm Last Edit: Jan 20, 2020, 07:30 pm by surbyte
Bueno a mi no me ocurre eso o mejor dicho no me ocurría. Te puse que salia obtuvo yo cuando lo corrí en mi NANO.
Pero yo no tengo el IR asi que eso lo genero de forma fija.

Crearé una versión donde le envio comandos via puerto serie a ver que esta ocurriendo.

Me sorprende que con la ayuda brindada no encontraras la falla. Era tan simple como al final de tus if poner un codigo.value = 0

Como la variable que comparas no se pone a 0, sigue consultando a cada momento el mismo código del loop una y otra vez.


Code: [Select]

#include <IRremote.h>
int receptor = 5;

IRrecv irrecv(receptor);
decode_results codigo;

int ledR = 8;
int ledG = 7;
int ledB = 6;
int intR = 255; // Nivel de intensidad de cada Led RGB (0 (máximo), 255 (mínimo)).
int intG = 255;
int intB = 255;
bool flag = false;
unsigned long tiempo;
int i = 0, j = 0, k = 0;
byte estado = 0;
String incoming = "";

void setup()
{
  Serial.begin(9600); // Inicia comunicación con puerto serie.
 
  Serial.println("Enabling IRin");
  irrecv.enableIRIn(); // Start the receiver
  Serial.println("Enabled IRin");

  pinMode(ledR, OUTPUT);
  pinMode(ledG, OUTPUT);
  pinMode(ledB, OUTPUT);
 
  analogWrite(ledR, intR);
  analogWrite(ledG, intG);
  analogWrite(ledB, intB);
}
 
void loop()
{
    if (irrecv.decode(&codigo)) {
        flag = false;
        Serial.println(codigo.value, HEX);
        irrecv.resume(); // Receive the next value
    }
/*
    if (Serial.available()> 0) {
        incoming = Serial.readString();
        Serial.println(incoming);
        unsigned long b = strtoul(incoming.c_str(), 0, 16);
        Serial.println(b);
        codigo.value = b;
    }
*/
 
  if (codigo.value==0xF7C03F){
      Serial.println("ON");
      intR = 0;
      intG = 0;
      intB = 0;
      analogWrite(ledR, intR);
      analogWrite(ledG, intG);
      analogWrite(ledB, intB);
  }

  if (codigo.value==0xF740BF){
      Serial.println("OFF");
      intR = 255;
      intG = 255;
      intB = 255;
      analogWrite(ledR, intR);
      analogWrite(ledG, intG);
      analogWrite(ledB, intB);
  }

  if (codigo.value==0xF720DF){
      Serial.println("R");
      intR = 0;
      intG = 255;
      intB = 255;
      analogWrite(ledR, intR);
      analogWrite(ledG, intG);
      analogWrite(ledB, intB);
  }

  if (codigo.value==0xF7A05F){
      Serial.println("G");
      intR = 255;
      intG = 0;
      intB = 255;
      analogWrite(ledR, intR);
      analogWrite(ledG, intG);
      analogWrite(ledB, intB);
  }

  if (codigo.value==0xF7609F){
      Serial.println("B");
      intR = 255;
      intG = 255;
      intB = 0;
      analogWrite(ledR, intR);
      analogWrite(ledG, intG);
      analogWrite(ledB, intB);
  }

  if (codigo.value==0xF7E01F){
      Serial.println("W");
      intR = 0;
      intG = 0;
      intB = 0;
      analogWrite(ledR, intR);
      analogWrite(ledG, intG);
      analogWrite(ledB, intB);
  }

  if (codigo.value==0xF7D02F) {
      flag = !flag;
      Serial.println(flag?"FLASH : flag ON":"FLASH : flag OFF");   
  }
    codigo.value = 0;
   if (flag) {
      switch (estado) {
          case 0: Serial.println("Valor de i:"+String(i));
                  analogWrite(ledR, i);
                  analogWrite(ledG, 255-i);
                  analogWrite(ledB, 255);
                  estado = 1;
                  tiempo = millis();
                  break;
          case 1: if (millis() - tiempo > 100UL) {
                      if (++i > 255) {
                          Serial.println("Bucle 1");
                          estado = 2;
                      }
                      else
                          estado = 0;
                  }
                  break;
          case 2: Serial.println("Valor de j:"+String(j));
                  analogWrite(ledG, j);
                  analogWrite(ledB, 255-j);
                  analogWrite(ledR, 255);
                  estado = 3;
                  tiempo = millis();
                  break;
          case 3: if (millis() - tiempo > 100UL) {
                      if (j++ > 255) {
                        Serial.println("Bucle 2");
                        estado = 4;
                      }
                      else
                          estado = 2;
                  }
                  break;
          case 4: Serial.println("Valor de k:"+String(k));
                  analogWrite(ledB, k);
                  analogWrite(ledR, 255-k);
                  analogWrite(ledG, 255);
                  estado = 5;
                  tiempo = millis();
                  break;
          case 5: if (millis() - tiempo > 100UL) {
                      if( k++ > 255) {
                          Serial.println("Bucle 3");
                          estado = 0;                        // listo para recomenzar
                          i = 0;
                          j = 0;
                          k = 0;
                      }
                      else
                          estado = 4;
                  }
                  break;                 
          default : estado = 0;
                    break;
      }     
  }

}



Go Up