Go Down

Topic: Luces RGB (Read 2360 times) previous topic - next topic

OrnyTorrynKo

Buenas, quiero hacer un programa por el cual, a traves de una app que he creado, sea capaz de encender el led con el color deseado. Para encenderlo del color que quiera de forma fija no tengo problema, el problema surge cuando en otro modo hago que el led haga aumentar y disminuir su intensidad. Quiero que entre en un bucle y cambie su intensidad hasta que yo desde la app le diga qe haga otra cosa, tengo el problema de que no me sale del bucle cuando por ejemplo selecciono a que se ponga a luz fija.
Code: [Select]
int luminosidad = 0;
char datos_serial=0;
//char enviar_dato ;

int G = 9;
int B = 10;
int R = 11;

void setup()
   {
       Serial.begin(9600);
       pinMode(R, OUTPUT);
       pinMode(G, OUTPUT);
       pinMode(B, OUTPUT);
   }

//   void Color(int R, int G, int B)
//    {     
//        analogWrite(9 , R) ;   // Red    - Rojo
//        analogWrite(10, G) ;   // Green - Verde
//        analogWrite(11, B) ;   // Blue - Azul
//    }

    void loop(){
       if (Serial.available()>0){
            char datos_serial =Serial.read();


             /////LUCES FIJAS/////
             //Rojo fijo
             if(datos_serial == 'C')
             {
              analogWrite(R,255);
              analogWrite(G,0);
              analogWrite(B,0);
             }
 
             //Azul fijo
             if(datos_serial == 'A')
             {
              analogWrite(R,0);
              analogWrite(G,0);
              analogWrite(B,255);
             }
 
              //Verde fijo
             if(datos_serial == 'B')
             {
              analogWrite(R,0);
              analogWrite(G,255);
              analogWrite(B,0);
             }
 
             //Celeste fijo
             if(datos_serial == 'F')
             {
              analogWrite(R,0);
              analogWrite(G,255);
              analogWrite(B,255);
             }

             //Rosa fijo
             if(datos_serial == 'E')
             {
              analogWrite(R,255);
              analogWrite(G,0);
              analogWrite(B,255);
             }

             //Amarillo fijo
             if(datos_serial == 'D')
             {
              analogWrite(R,255);
              analogWrite(G,255);
              analogWrite(B,0);
             }


             /////LUCES TENUES/////
             //Rojo tenue
             if(datos_serial == 'J')
             {
             for (luminosidad = 0;
             luminosidad <= 255;
             luminosidad=luminosidad+5)
             {
             analogWrite(R, luminosidad); // ilumina el led con el valor asignado a luminosidad (entre 0 y 255)
             delay(30);}
             for (luminosidad = 255; //for hace decrecer la luminocidad de 5 en 5
             luminosidad >=0;
             luminosidad=luminosidad-5)
             {
             analogWrite(R, luminosidad);
             delay(30);
             }
             //}
             }
 
             //Azul tenue
             if(datos_serial == 'H'){
             for (luminosidad = 0;
             luminosidad <= 255;
             luminosidad=luminosidad+5)
             {
             analogWrite(B, luminosidad);
             analogWrite(R, 0);
             analogWrite(G, 0);
             delay(30);}
             for (luminosidad = 255;
             luminosidad >=0;
             luminosidad=luminosidad-5)
             {
             analogWrite(B, luminosidad);
             analogWrite(R, 0);
             analogWrite(G, 0);
             delay(30);
             }     
             }
             
 
              //Verde fijo
             if(datos_serial == 'B')
             {
              analogWrite(R,0);
              analogWrite(G,255);
              analogWrite(B,0);
             }
 
             //Celeste fijo
             if(datos_serial == 'F')
             {
              analogWrite(R,0);
              analogWrite(G,255);
              analogWrite(B,255);
             }

             //Rosa fijo
             if(datos_serial == 'E')
             {
              analogWrite(R,255);
              analogWrite(G,0);
              analogWrite(B,255);
             }

             //Amarillo fijo
             if(datos_serial == 'D')
             {
              analogWrite(R,255);
              analogWrite(G,255);
              analogWrite(B,0);
             }
        }
   }



La app esta creada  en appinventor y lo que hago es enviar una letra cada vez que pulso el boton para cada color.


Naruto128

lo que debes hacer es codificar tu codigo de comunicacion, por ejemplo para encender le envias la letra E, y el 1.  y para apagar E,0.  para cambiar el brillo, le mandas la letra B, el valor de intencidad 255-0. entonces asi puedes hacer mas cosas.

para eso debes prepar al arduino que va a recivir dos byte, el primero dice de que se trata la funcion a hacer, el otro el parametro que va a cambiar .

algo asi:

OrnyTorrynKo

La cosa es que no quiero darle yo la intensidad del led sino que automáticamente se que aumentando y disminuyendo la intensidad continuamente hasta que yo no decida cambiar de modo, nose si me explico, como unas luces de navidad que se qedan subiendo y bajando la luz.

surbyte

En tu código tienes comandos que van de A a J, como se compatibiliza con lo que acabas de afirmar?

OrnyTorrynKo

Como puedes ver en el codigo, cuando recibe la J entra en un bucle en el cual aumenta y reduce la intensidad. El problema aparece cuando quiero salir de ese bucle porqe quiero cambiar de color, por ejemplo.

IgnoranteAbsoluto

Hola OrnyTorrynKo. No he podido evitarlo, pero me he tomado la libertad de rehacer tu código. He de confesar que lo he hecho un poco a las carreras. No lo he comentado mucho y es probable que buena parte del código te suene a chino. Pero si quieres lo puedes usar para tomar ideas.

La idea principal, es hacer una única parte del código común a todos los colores (tanto fijos como "tenues") y simplemente configurar las letras y colores en un array bidimensional. Se puede meter todo e un único array porque el tipo de los cinco campos es el mismo (en este caso byte).

El primer campo es la letra que quieres que active el color. Los otros tres corresponden a los valores R, G y B que definen el color (admite valores de 0 a 255, incluido valores intermedio).  Y el último campo es "el paso" con que quieres que varíe la intensidad del color (cero hace que permanezca fijo, un valor bajo hace que cambie lentamente y un valor alto hace que cambie más rápidamente).

He configurado unas cuantas letras y valores. Las de la A a la F coincide (si no me he equivocado) con los colores "fijos" que tú tenías. En cambio el resto los he puesto diferente (copy+paste + cambio de paso).

Y todo hecho con la máxima de no usar delay().

Espero que haga lo que querías y te sirva:

Code: [Select]

const int PIN_G = 9;
const int PIN_B = 10;
const int PIN_R = 11;

const unsigned long TIEMPO_CAMBIO = 30; // Milisegundos que pasa entre cambio de valor. Se puede lograr más o menos velocidad cambiando el paso
const byte VALOR_MINIMO = 2;            // Se puede probar con 0, pero como se apaga del todo hace un efecto que no me gusta mucho
const byte VALOR_MAXIMO = 255;          // No aconsejo cambiarlo

const size_t NUMERO_CAMPOS = 5;

// El problema de usar un array es que consume RAM. Otra solución es usar PROGMEM: https://www.arduino.cc/en/Reference/PROGMEM
const byte ARRAY_VALORES[][NUMERO_CAMPOS] = {
    //      R    G    B  paso (se puede lograr más o menos velocidad cambiando el paso) (paso == 0 no cambia nunca el LED)
    {'A',   0,   0, 255,   0}, // Azul fijo
    {'B',   0, 255,   0,   0}, // Verde fijo
    {'C', 255,   0,   0,   0}, // Rojo fijo
    {'D', 255, 255,   0,   0}, // Amarillo fijo
    {'E', 255,   0, 255,   0}, // Rosa fijo
    {'F',   0, 255, 255,   0}, // Celeste fijo

    {'G',   0,   0, 255,   5}, // Azul tenue
    {'H',   0, 255,   0,   5}, // Verde tenue
    {'I', 255,   0,   0,   5}, // Rojo tenue
    {'J', 255, 255,   0,   5}, // Amarillo tenue
    {'K', 255,   0, 255,   5}, // Rosa tenue
    {'L',   0, 255, 255,   5}, // Celeste tenue

    {'V', 255, 255, 255,   0}, // Blanco fijo
    {'W', 255, 255, 255,   5}, // Blanco tenue

    {'X', 140, 255,  55,   0}, // fijo
    {'Y', 140, 255,  55,   3}, // tenue

    {'Z',   0,   0,   0,   0}  // Apagado
};

const size_t INDICE_LETRA = 0;
const size_t INDICE_R     = 1;
const size_t INDICE_G     = 2;
const size_t INDICE_B     = 3;
const size_t INDICE_PASO  = 4;

byte valorR = 0;
byte valorG = 0;
byte valorB = 0;

byte limiteR = 0;
byte limiteG = 0;
byte limiteB = 0;

int paso = 0;
int valorReferencia = 0;

unsigned long momentoCambio = 0; // Guarda el instante en que hizo el último cambio para esperar que pase TIEMPO_CAMBIO

void setup() {
    Serial.begin(9600);
    pinMode(PIN_R, OUTPUT);
    pinMode(PIN_G, OUTPUT);
    pinMode(PIN_B, OUTPUT);
}

void loop() {
    if (Serial.available() > 0) {
        byte datos_serial = Serial.read();
        for (size_t i = 0; i < (sizeof(ARRAY_VALORES) / NUMERO_CAMPOS); i++) {
            if (ARRAY_VALORES[i][INDICE_LETRA] == datos_serial) { // Buscamos la tecla pulsada
                momentoCambio = millis() - TIEMPO_CAMBIO;  // Forzamos a que haga "el cambio", así no tenemos que asignar los valores a los pines aquí
                // Asignamos el "valor de inicio"
                valorR = limiteR = ARRAY_VALORES[i][INDICE_R];  // a = b = 5; // Hace que a y b valgan 5
                valorG = limiteG = ARRAY_VALORES[i][INDICE_G];
                valorB = limiteB = ARRAY_VALORES[i][INDICE_B];
                paso = ARRAY_VALORES[i][INDICE_PASO];
                valorReferencia = VALOR_MAXIMO;
                break;
            }
        }
    }
    if ( (millis() - momentoCambio) >= TIEMPO_CAMBIO ) {
        momentoCambio = millis(); // Guardamos el instante en el que se ha hecho el cambio
        analogWrite(PIN_R, valorR);
        analogWrite(PIN_G, valorG);
        analogWrite(PIN_B, valorB);
        if ( ( (valorReferencia + paso) > VALOR_MAXIMO ) || ((valorReferencia + paso) < VALOR_MINIMO) ) {
            // Como se sale de los límites con en el próximo paso, lo cambiamos de sentido
            paso = -paso;
        }
        valorReferencia += paso;
        // Calculamos los valores para el próximo "cambio". No lo hacemos antes porque la primera vez lo "forzamos" y queremos que tome el "valor de inicio"
        valorR = map(valorReferencia, 0, 255, 0, limiteR);
        valorG = map(valorReferencia, 0, 255, 0, limiteG);
        valorB = map(valorReferencia, 0, 255, 0, limiteB);
    }
}


surbyte

Bueno no he visto que hizo IgnoranteAbsoluto que seguramente esta bien pero esta es mi versión
Modificación leve de tu código para que hagas lo que quieres.

Code: [Select]
int luminosidad     = 0;
char datos_serial   = 0;
//char enviar_dato ;

int G = 9;
int B = 10;
int R = 11;

#define ASCENDENTE  true
#define DESCENDENTE false
bool lumDIR = ASCENDENTE;

void setup()
   {
       Serial.begin(9600);
       pinMode(R, OUTPUT);
       pinMode(G, OUTPUT);
       pinMode(B, OUTPUT);
   }

//   void Color(int R, int G, int B)
//    {     
//        analogWrite(9 , R) ;   // Red    - Rojo
//        analogWrite(10, G) ;   // Green - Verde
//        analogWrite(11, B) ;   // Blue - Azul
//    }

void loop(){
  if (Serial.available()>0){
      char datos_serial = Serial.read();
      lumDIR = ASCENDENTE;
  }

  /////LUCES FIJAS/////
  //Rojo fijo
  if(datos_serial == 'C'){
    analogWrite(R,255);
    analogWrite(G,0);
    analogWrite(B,0);
  }

  //Azul fijo
  if (datos_serial == 'A')  {
      analogWrite(R,0);
      analogWrite(G,0);
      analogWrite(B,255);
  }

  //Verde fijo
  if (datos_serial == 'B') {
      analogWrite(R,0);
      analogWrite(G,255);
      analogWrite(B,0);
  }

  //Celeste fijo
  if (datos_serial == 'F') {
      analogWrite(R,0);
      analogWrite(G,255);
      analogWrite(B,255);
  }

  //Rosa fijo
  if (datos_serial == 'E') {
      analogWrite(R,255);
      analogWrite(G,0);
      analogWrite(B,255);
  }

  //Amarillo fijo
  if (datos_serial == 'D')  {
      analogWrite(R,255);
      analogWrite(G,255);
      analogWrite(B,0);
  }


  /////LUCES TENUES/////
  //Rojo tenue
  if (datos_serial == 'J') {
           analogWrite(R, luminosidad); // ilumina el led con el valor asignado a luminosidad (entre 0 y 255)
           delay(30);
           if (lumDIR) {
               luminosidad = luminosidad + 5;
               if (luminosidad > 255)
                   lumDIR = DESCENDENTE;
           }
           else {
               luminosidad = luminosidad -5;
               if (lumDIR <= 0)
                   lumDIR = ASCENDENTE;
           }
  }

  //Azul tenue
  if (datos_serial == 'H'){
      analogWrite(B, luminosidad);
      analogWrite(R, 0);
      analogWrite(G, 0);
      delay(30);
      if (lumDIR) {
         luminosidad = luminosidad + 5;
         if (luminosidad > 255)
             lumDIR = DESCENDENTE;
      }
      else {
         luminosidad = luminosidad -5;
         if (lumDIR <= 0)
             lumDIR = ASCENDENTE;
      }
  }

  //Verde fijo
  if (datos_serial == 'B') {
      analogWrite(R,0);
      analogWrite(G,255);
      analogWrite(B,0);
  }

  //Celeste fijo
  if (datos_serial == 'F') {
      analogWrite(R,0);
      analogWrite(G,255);
      analogWrite(B,255);
  }

  //Rosa fijo
  if (datos_serial == 'E') {
      analogWrite(R,255);
      analogWrite(G,0);
      analogWrite(B,255);
  }

  //Amarillo fijo
  if (datos_serial == 'D') {
      analogWrite(R,255);
      analogWrite(G,255);
      analogWrite(B,0);
  }
}



OrnyTorrynKo

Muchas gracias copañeros, lo probaré lo antes qe pueda y os comento ;)

OrnyTorrynKo

He probado ambos códigos y el de surbyte presenta algunos problemas a la hora de recibir el carácter, cosa que he modificado pero no hace exactamente la idea que tenia en mente, aunque te agradezco enormemente el aporte.

El de IgnoranteAbsoluto es exactamente lo que buscaba hacer, me va perfecto, pero tengo varias dudas que te quería preguntar. Enviad los caracteres "X" e "Y" para luz fija y tenue, respectivamente, para que lo usas exactamente? ya enviando directamente los demás caracteres funciona a la perfección.

surbyte

No me excuso, no lo probé esta, basado en el tuyo. Asi que debería funcionar. con algun ajuste.
Solo modifiqué el tuyo para que no tuviera esa gran demora por los dos for 0 a 255 para subir y bajar la luminosidad de la luz.

OrnyTorrynKo

Lo unico era un corchete mal posicionado jeje aunque de tu forma cambiaba el brillo cada vez que le daba a la app no de forma continua

surbyte

Que raro!!
Supuestamente como datos_serial no cambia y se mantiene, en cada ciclo vuelve a entrar en ese if y va incrementando del mismo modo que lo hacias tu.
Cuando supera a 255 cambia de sentido y comienza a devanecerse a 5 por vez.
Con algun toque debería funcionar!!

OrnyTorrynKo

Sisi tenia buena pinta, pero probé el otro codigo y va exactamente como quiero, asi que lo he aprovechado, aunque no lo entiendo del todo para hacerle modificaciones jeje

IgnoranteAbsoluto

tengo varias dudas que te quería preguntar. Enviad los caracteres "X" e "Y" para luz fija y tenue, respectivamente, para que lo usas exactamente?
X e Y son un ejemplo de que no sólo va con "colores básicos" en donde los parámetros R, G y B son 0 o 255, sino que también funciona con colores "intermedios".

OrnyTorrynKo

Entendido, como podria insertar otro "modo" para que por ejemplo haga lo de la intensidad, haga un parpadeo, o que cambie de colores aleatoriamente

Go Up