Go Down

Topic: Control de tira led con receptor infrarrojos (Read 292 times) previous topic - next topic

erchiquitin

Oct 07, 2018, 06:58 pm Last Edit: Oct 08, 2018, 10:27 pm by surbyte Reason: Edición de título
Buenas! Soy nuevo en el foro y en el mundo de Arduino. Llevo unos días pillado en un código y he intentado buscar información por YouTube, tutoriales e incluso por este foro y el inglés y nada, aunque supongo que es que no la veo.

Voy a intentar explicarme.

Tengo un Arduino nano conectado a una tira led la cual pruedo controlar led a led. A su vez el Arduino nano está conectado a un receptor de infrarrojos que recibe la señal de un mandito que me venía con el kit de iniciación de arduino.

TIRA LED

Por un lado he conseguido hacer efecto arcoiris girando en la tira led:

Code: [Select]


#include "FastLED.h"

#define PIN 4
#define NUM_LEDS 60

CRGBArray<NUM_LEDS> leds;
uint8_t hue[NUM_LEDS];

void setup() {
  FastLED.addLeds<NEOPIXEL, PIN>(leds, NUM_LEDS);
  for (int i=0; i < NUM_LEDS; i++){
    hue[i] = 255 / NUM_LEDS * i;
  }
}

void loop() {
  for (int i = 0; i < NUM_LEDS; i++){
    leds[i] = CHSV(hue[i]++, 255, 255);
  }

FastLED.show();
    delay(15);
  
}



CODIGO SACADO DE CANAL DE NerdForge

Mi problema es que quiero manejar la tira led a través de infrarrojos. Tengo este código cuyas funciones, si pulso X botón, en orden son:

  • Poner todos los LED en rojo.
  • Apagar los leds.
  • El efecto del código de arriba del cual tengo problemas.
  • Cambiar color hacia arriba.
  • Cambiar color hacia arriba botón pulsado.
  • Cambiar color hacia abajo.
  • Cambiar color hacia abajo botón pulsado.
  • Subir brillo.
  • Subir brillo botón pulsado.
  • Bajar brillo.
  • Bajar brillo botón pulsado.


Code: [Select]


#include "FastLED.h"
#include "IRremote.h"

#define PIN 4
#define NUM_LEDS 60

int k = 0;
int l = 230;
boolean colormas=0;
boolean colormenos=0;
boolean brillomas=0;
boolean brillomenos=0;
boolean rainbow=0;

int receptor = A1;  //receptor infrarrojos
IRrecv irrecv(receptor);
decode_results codigo; //OBJETO CODIGO DE CLASE decode_result, oriundo de IRremote.h

CRGBArray<NUM_LEDS> leds;
uint8_t hue[NUM_LEDS];


void setup() {
  FastLED.addLeds<NEOPIXEL, PIN>(leds, NUM_LEDS);
  for (int i=0; i < NUM_LEDS; i++){
    hue[i] = 255 / NUM_LEDS * i;
  }

  // == INFRARROJOS ==

  Serial.begin(9600); //puerto serie
  irrecv.enableIRIn(); //INICIAR LA RECEPIÓN
  
}

void loop() {

  if(irrecv.decode(&codigo)){
    Serial.println(codigo.value, HEX);

    //ROJO
    if(codigo.value==0xFF30CF){
      colormenos=0;
      colormas=0;
      brillomas=0;
      brillomenos=0;
      
      k=254;
      fill_solid(leds, NUM_LEDS, CHSV(255, 255, l));

    FastLED.show();
    }
    
    //APAGAR
    if(codigo.value==0xFFA25D){
      colormenos=0;
      colormas=0;
      brillomas=0;
      brillomenos=0;
      fill_solid(leds, NUM_LEDS, CHSV(0, 0, 0));

    FastLED.show();
    }

    //RAINBOW
    if(codigo.value==0xFF18E7){
     for (int i = 0; i < NUM_LEDS; i++){
        leds[i] = CHSV(hue[i]++, 255, 255);
     }

      FastLED.show();
      delay(15);      

      }
    

    // ===== CAMIBIAR COLORES ======
    
    //cambiar color +
    if(codigo.value==0xFFC23D){
      colormenos=0;
      colormas=1;
      brillomas=0;
      brillomenos=0;
      
      k=k+5;
      fill_solid(leds, NUM_LEDS, CHSV(k, 255, l));

    FastLED.show();
    }
    
    //cambiar color + Pulsado
    if(codigo.value==0xFFFFFFFF && colormas){
      k=k+5;
      fill_solid(leds, NUM_LEDS, CHSV(k, 255, l));

    FastLED.show();
    }

    //cambiar color -
    if(codigo.value==0xFF02FD){
      colormas=0;
      colormenos=1;
      brillomas=0;
      brillomenos=0;
      
      k=k-5;
      fill_solid(leds, NUM_LEDS, CHSV(k, 255, l));

    FastLED.show();
    }

     //cambiar color - Pulsado
    if(codigo.value==0xFFFFFFFF && colormenos){
      k=k-5;
      fill_solid(leds, NUM_LEDS, CHSV(k, 255, l));
      
    FastLED.show();
    }

    // ===== SUBIR/BAJAR BRILLO =====

     //cambiar brillo +
    if(codigo.value==0xFF906F){
      colormenos=0;
      colormas=0;
      brillomas=1;
      brillomenos=0;
      Serial.println(l);
      if(l<240){
        l=l+10;
        fill_solid(leds, NUM_LEDS, CHSV(k, 255, l));
      }

    FastLED.show();
    }
    
    //cambiar brillo + Pulsado
    if(codigo.value==0xFFFFFFFF && brillomas){
      if(l<240){
        l=l+10;
        fill_solid(leds, NUM_LEDS, CHSV(k, 255, l));
      }

    FastLED.show();
    }

    //cambiar brillo -
    if(codigo.value==0xFFA857){
      colormas=0;
      colormenos=0;
      brillomas=0;
      brillomenos=1;
      
      if(l>20){
        l=l-10;
        fill_solid(leds, NUM_LEDS, CHSV(k, 255, l));
      }

    FastLED.show();
    }

     //cambiar brillo - Pulsado
    if(codigo.value==0xFFFFFFFF && brillomenos){
      if(l>20){
        l=l-10;
        fill_solid(leds, NUM_LEDS, CHSV(k, 255, l));
      }
      
    FastLED.show();
    }

    irrecv.resume();
  }
}



El problema que tengo es que con el código sin mando, el arcoiris se mueve de un led a otro, en cambio con el del mando al no hacer un bucle solo se repite una vez con lo cual solo pone los leds de arcoiris y no van rotando.

Mi primer intento, inocente de mi, fue meter el for dentro de un bucle y me hace el efecto perfecto, pero claro, se queda dentro del bucle y no está atento a recibir señal del infrarrojo.

Mi segundo intento fue poner un while con un booleano de interruptor que cuando detecte que se pulsa otro botón rompa el while, pero no consigo hacer que funcione.

También alguien que me pueda decir si está bien depurado el código o está echo una birria (seguramente sea una birria jajaja).

Saludos y espero puedan ayudarme y que valga para otros que tengan el mismo problema que yo.

Daniel_Arg

Hola. Todo lo que tienes dentro de:

 if(irrecv.decode(&codigo)){
    Serial.println(codigo.value, HEX);
//
//
//
//
    irrecv.resume();
  }

si no me equivoco se ejecuta una sola vez, hasta recibir un nuevo código por el sensor infrarrojo.

Prueba tu código dejando lo anterior mas un delay(200); fuera de la llave y te fijas en el monitor si escribe solo una vez cuando oprimes un botón del mando infrarrojo o imprime el codigo.value continuo cada 200 milisegundos.

Si en el Monitor Serie escribe una sola vez cuando mandas un comando,  entonces todo lo que se deba hacer una sola vez, debe quedar dentro de ese if(irrecv.  y lo que deba repetirse constantemente lo debes sacar fuera pero dentro del loop.

Saludos
Saludos

ArduMyth

Ten en cuenta que el loop es un bucle infinito, verás ejemplos de Arduino donde usan un for para por ejemplo cambiar el color progresivamente de un led o la intensidad pero, ¿Realmente necesitamos un bucle dentro de otro bucle que interrumpa el flujo (que es lo que te pasó)? NO rotundo.

Es tarde, ya mañana te pongo un ejemplo, pero piensa que no necesitas ni delay ni bucles. Un flag (variable boolean) que determine la repetición o timers usanso millis() bastará para conseguir lo que quieres sin interrupciones/bloqueos producidos por delay() o bucles.

Un saludo.

erchiquitin

Hola. Todo lo que tienes dentro de:

 if(irrecv.decode(&codigo)){
    Serial.println(codigo.value, HEX);
//
//
//
//
    irrecv.resume();
  }

si no me equivoco se ejecuta una sola vez, hasta recibir un nuevo código por el sensor infrarrojo.

Prueba tu código dejando lo anterior mas un delay(200); fuera de la llave y te fijas en el monitor si escribe solo una vez cuando oprimes un botón del mando infrarrojo o imprime el codigo.value continuo cada 200 milisegundos.

Si en el Monitor Serie escribe una sola vez cuando mandas un comando,  entonces todo lo que se deba hacer una sola vez, debe quedar dentro de ese if(irrecv.  y lo que deba repetirse constantemente lo debes sacar fuera pero dentro del loop.

Saludos
Saludos
Vale, tenías razón, si pongo un Monitor Serie fuera del if me lo repite siempre. No sabía que lo que hacía arduino era repetir código dentro del loop una y otra vez. (Aunque lo debería haber supuesto ya que se llama loop).

He probado a hacer esto:

Code: [Select]


void loop() {

  if(irrecv.decode(&codigo)){
    Serial.println(codigo.value, HEX);

    // ===== ROJO =====

    if(codigo.value==0xFF30CF){
      rainbow=0;
         
      Serial.println("ROJO");

      k=254;
      fill_solid(leds, NUM_LEDS, CHSV(255, 255, l));

    FastLED.show();
    }

    // ===== FLAG RAINBOW =====

    if(codigo.value==0xFF18E7){
     rainbow = 1;       

      }

  }


    // ===== RAINBOW =====

    if(rainbow){
     for (int i = 0; i < NUM_LEDS; i++){
        leds[i] = CHSV(hue[i]++, 255, l);
     }

      FastLED.show();
      delay(15);       

      }
 
}




El caso es que si pulso el boton de "Rainbow" hace una cosa muy rara, me capta la señal infrarroja porque me muestra los botones en hexadecimal pero tengo un Monitor Serie para que me saque por pantalla la palabra "ROJO" si entra y no me la muestra, con lo cual no entra.

Ten en cuenta que el loop es un bucle infinito, verás ejemplos de Arduino donde usan un for para por ejemplo cambiar el color progresivamente de un led o la intensidad pero, ¿Realmente necesitamos un bucle dentro de otro bucle que interrumpa el flujo (que es lo que te pasó)? NO rotundo.

Es tarde, ya mañana te pongo un ejemplo, pero piensa que no necesitas ni delay ni bucles. Un flag (variable boolean) que determine la repetición o timers usanso millis() bastará para conseguir lo que quieres sin interrupciones/bloqueos producidos por delay() o bucles.

Un saludo.
Tengo muchas ganas de aprender con tu código ArduMyth!

Muchisimas gracias a los dos por responder tan rápido este post!!

ArduMyth

Fijándome en tu código veo que el problema no es de timers, es de flags, aunque igual yo suelo desterrar el uso de delay() salvo que realmente quiera parar todo mi Arduino.
Anoche lo miré por encima y ni tiempo a poner un ejemplo.

Creo entender que lo que quieres es que se repita el ciclo cuando pulses el botón del mando, ya que por lo que veo en el código con IR esas acciones sólo se realizan una vez.

Code: [Select]

[code]
#include "FastLED.h"
#include "IRremote.h"
#define SIZE(x) (sizeof(x) / sizeof(x[0]))

#define PIN 4
#define NUM_LEDS 60

unsigned int k = 0;
unsigned int l = 230;

byte receptor = A1;  
IRrecv irrecv(receptor);
decode_results codigo;

CRGBArray<NUM_LEDS> leds;
uint8_t hue[NUM_LEDS];

struct Opciones {
  bool seleccionado;
};
Opciones Opt[2] = {}; //El índice depende del número de opciones que añadas


void setup() {
  FastLED.addLeds<NEOPIXEL, PIN>(leds, NUM_LEDS);
  for (int i = 0; i < NUM_LEDS; i++) {
    hue[i] = 255 / NUM_LEDS * i;
  }
  Serial.begin(9600);
  irrecv.enableIRIn();
}

void loop() {
  if (irrecv.decode(&codigo)) { //Detectamos botón pulsado
    Serial.println(codigo.value, HEX);
    for(byte i = 0; i < SIZE(Opt); i++){ //Borramos cualquier opción previa
      Opt[i].seleccionado = false;
    }
    
    if(codigo.value == 0xFF30CF){
      Opt[0].seleccionado = true; // Rojo (Guardamos la opción en la global, flag)
    }
    else if(codigo.value == 0xFF18E7){
      Opt[1].seleccionado = true; // Arcoiris (Guardamos la opción en la global, flag)
    }
    // ... y así con cada opción que se desee configurar
    delay(15); //Esto puede ser sustituido con un timer usando millis() especialmente si quisieras hacer animaciones con los leds
  }
  irrecv.resume();
  
  if(Opt[0].seleccionado){  //Rojo está en true
    //aquí el código para rojo
  }
  else if(Opt[1].seleccionado){  //Arcoiris está en true
    //aquí el código para Arcoiris
  }
  // ... y así con cada opción
  // Hasta que no se pulse otro botón se realizará el último seleccionado.

}



La estructura es para ahorrar líneas y evitar escribir un boolean por cada opción, pero es lo mismo.

erchiquitin

Buah, muchisimas gracias ArduMyth, por la depuracion de código, como dices va a quedar con muchas menos lineas.

Mi idea es:
Pulso el botón de rojo, se ponen en rojo todos los leds,
pulso el botón de rainbow, la tira led hace una animación infinita hasta que vuelvo a pulsar el botón rojo que vuelve a poner todos los leds en rojo.

Mi situación ahora mismo es:
Pulso el botón de rojo, se ponen en rojo todos los leds,
pulso el botón de rainbow, la tira led hace una animación infinita,
si pulso el botón rojo no se tornan en rojo ni se cancela la animación de rainbow.
Pero al pulsar el botón del mando, el arduino recoje la señal porque se encienden los leds de estos y en el Monitor Serie me muestra el código Hexadesimal del botón pero no entra dentro de los IF.

Saludos!

ArduMyth

Pon el código qué estás usando pues arriba tienes dos casos y creo que has mezclado cosas. Necesitamos ver qué estás probando.

erchiquitin

Buenas!
Este es el código con el que estoy trabajando.

Code: [Select]


#include "FastLED.h"
#include "IRremote.h"

#define PIN 4
#define NUM_LEDS 60

int k = 0;
int l = 230;
boolean colormas=0;
boolean colormenos=0;
boolean brillomas=0;
boolean brillomenos=0;
boolean rainbow=0;

int receptor = A1;  //receptor infrarrojos
IRrecv irrecv(receptor);
decode_results codigo; //OBJETO CODIGO DE CLASE decode_result, oriundo de IRremote.h

CRGBArray<NUM_LEDS> leds;
uint8_t hue[NUM_LEDS];


void setup() {
  FastLED.addLeds<NEOPIXEL, PIN>(leds, NUM_LEDS);
  for (int i=0; i < NUM_LEDS; i++){
    hue[i] = 255 / NUM_LEDS * i;
  }

  // == INFRARROJOS ==

  Serial.begin(9600); //puerto serie
  irrecv.enableIRIn(); //INICIAR LA RECEPIÓN
 
}

void loop() {

  if(irrecv.decode(&codigo)){
    Serial.println(codigo.value, HEX);

    //ROJO
    if(codigo.value==0xFF30CF){
      colormenos=0;
      colormas=0;
      brillomas=0;
      brillomenos=0;
      rainbow=0;
          Serial.println("ROJO");

      k=254;
      fill_solid(leds, NUM_LEDS, CHSV(255, 255, l));

    FastLED.show();
    }
   
    //APAGAR
    if(codigo.value==0xFFA25D){
      colormenos=0;
      colormas=0;
      brillomas=0;
      brillomenos=0;
      rainbow=0;
      fill_solid(leds, NUM_LEDS, CHSV(0, 0, 0));

    FastLED.show();
    }

    //RAINBOW
    if(codigo.value==0xFF18E7){
     rainbow = 1;       

      }
   

    // ===== CAMIBIAR COLORES ======
   
    //cambiar color +
    if(codigo.value==0xFFC23D){
      colormenos=0;
      colormas=1;
      brillomas=0;
      brillomenos=0;
      rainbow=0;
     
      k=k+5;
      fill_solid(leds, NUM_LEDS, CHSV(k, 255, l));

    FastLED.show();
    }
   
    //cambiar color + FFF
    if(codigo.value==0xFFFFFFFF && colormas){
      k=k+5;
      fill_solid(leds, NUM_LEDS, CHSV(k, 255, l));

    FastLED.show();
    }

    //cambiar color -
    if(codigo.value==0xFF02FD){
      colormas=0;
      colormenos=1;
      brillomas=0;
      brillomenos=0;
      rainbow=0;
     
      k=k-5;
      fill_solid(leds, NUM_LEDS, CHSV(k, 255, l));

    FastLED.show();
    }

     //cambiar color - FFF
    if(codigo.value==0xFFFFFFFF && colormenos){
      k=k-5;
      fill_solid(leds, NUM_LEDS, CHSV(k, 255, l));
     
    FastLED.show();
    }

    // ===== SUBIR/BAJAR BRILLO =====

     //cambiar brillo +
    if(codigo.value==0xFF906F){
      colormenos=0;
      colormas=0;
      brillomas=1;
      brillomenos=0;
      Serial.println(l);
      if(l<240){
        l=l+10;
        fill_solid(leds, NUM_LEDS, CHSV(k, 255, l));
      }

    FastLED.show();
    }
   
    //cambiar brillo + FFF
    if(codigo.value==0xFFFFFFFF && brillomas){
      if(l<240){
        l=l+10;
        fill_solid(leds, NUM_LEDS, CHSV(k, 255, l));
      }

    FastLED.show();
    }

    //cambiar brillo -
    if(codigo.value==0xFFA857){
      colormas=0;
      colormenos=0;
      brillomas=0;
      brillomenos=1;
     
      if(l>20){
        l=l-10;
        fill_solid(leds, NUM_LEDS, CHSV(k, 255, l));
      }

    FastLED.show();
    }

     //cambiar brillo - FFF
    if(codigo.value==0xFFFFFFFF && brillomenos){
      if(l>20){
        l=l-10;
        fill_solid(leds, NUM_LEDS, CHSV(k, 255, l));
      }
     
    FastLED.show();
    }

    irrecv.resume();
  }

    //RAINBOW
    if(rainbow){
     for (int i = 0; i < NUM_LEDS; i++){
        leds[i] = CHSV(hue[i]++, 255, l);
       
       
     }
      if(irrecv.decode(&codigo)){

          if(codigo.value == 0xFF30CF){
            rainbow=0;
            }
         
          }
      FastLED.show();
      delay(15);       

      }
 
}



Dejo un video que muestra lo que hace.

VIDEO

Saludos y gracias.

surbyte

Lo que estas haciendo alimentar una tira led desde un arduino no es adecuado.

Cada led consume 65mA asi que suma 10 leds son 650mA y eso es mas de lo que un UNO debería entregar.

Usen fuentes externas para alimetnar las tiras leds no los Arduinos. Los arduinos CONTROLAN no alimentan salvo sensores de poca corriente..

Tal vez como son pocos no hay problema pero ya ves que el NANO no pudo.
SI no quieres perder un UNO yluego venir al foro a preguntar que las luces estan en ROJO y no parpadean, bueno... ya sabrás por qué?

erchiquitin

Muchisimas gracias surbyte por tu aporte, lo primero que dije antes de hacer ninguna explicación es que soy nuevo en el mundo de arduino. Cualquier aporte por mínimo que sea y tontería que sea, aunque a vosotros os parezca lo más normal del mundo para mi es una lección y algo que me enseñáis, así que muchas gracias.
En próximos días haré que el pobre arduino UNO no alimente la tira led.

Aun sigo pillado en el código, surbyte ¿sabrías la solución?  :smiley-confuse:

surbyte

Solo recuerda esto.. un UNO puede entregar hacia afuera no mas de 350 o 400mA. Algunos lo exigen mas pero no es adecuado.
Como te dije cuento mas de 10 leds en tu video de modo que te pasas de ese valor.

Busca el modo de usar aunque sea un cargador de celular viejo, le cortas los cables, gnd a compartir con Arduino NANO y 5.2V porque entrega algo mas a las tiras leds.
Resto como esta.

Veras que el brillo mejora.

Una fuente de los viejos entrega 700mA y las nuevas van de 1.5 a 2A y mas.

erchiquitin

#11
Oct 09, 2018, 09:59 pm Last Edit: Oct 10, 2018, 02:08 am by surbyte Reason: No repitas lo que se lee arriba
Tenías razón, he cogido un cable usb de un teclado viejo que tenía para tirar, he hecho las conexiones y madre mía como brilla ahora la tira led!

Muchas gracias surbyte.

Eso si, sigo atascado en el mismo sitio del código, pulso el botón y la tira led hace el arcoiris perfectamente, el sensor infrarrojo recoge señal, pero no cambia de color. Tiene que ser una tontería en el código pero no consigo saber qué es.

Saludos.

Go Up