Luces RGB

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.

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.

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:

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.

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

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.

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:

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);
    }
}

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.

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);
  }
}

Muchas gracias copañeros, lo probaré lo antes qe pueda y os comento :wink:

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.

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.

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

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!!

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

OrnyTorrynKo:
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".

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

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

No tengo claro si lo afirmas o lo preguntas. Pero supongo que se trata de una pregunta.

Si quieres que pueda hacer parpadeos o cambiar de colores aleatoriamente, lo primero es tener claro qué es lo que quieres que haga. Luego ver cómo lo podría hacer y qué necesitaría para ello. Después ver cómo implementarlo, si adaptando lo que ya hay, añadiendo cosas nuevas o rehaciendo todo desde cero.

Para empezar, para el parpadeo habría que especificar cuánto tiempo quieres que esté encendido y cuanto apagado y si quieres que todos los parpadeos duren lo mismo o que cada uno tenga unos tiempos diferentes.

Y en cuanto a cambiar de color aleatoriamente ¿cuándo? cada vez que reciba una instrucción (letra) o automáticamente pasado cierto tiempo.

Lo de cambiar de color aleatoriamente cuando se recibe, por ejemplo, una 'U' es relativamente sencillo de implementar, ya que sólo has de cambiar las variables limiteR, limiteG y limiteB con valores aleatorios si te llega el carácter 'U'. Cada "TIEMPO_CAMBIO" milisegundos se actualizan los valores en el LED. Lo que si mantendrá si estaba "fijo" o "tenue".

Por cierto, no le he comentado, pero puedes añadir más letras y combinaciones de colores al array. El cálculo del límite del bucle se realiza "automáticamente".

Ya vi el problema del código, le envias la orden y solo lo hace una vez.
Contaba conque una J recibida permaneciera en el loop hasta que se digite otra cosa pero en mis pruebas, luego de la J muestra un 0x00
asi que se detiene
POr eso solo avanzó a 5 de luminosidad y no siguió

Lo del parpadeo seria por ejemplo 1s encendido y 1s apagado, seria igual que lo de las luces tenues, cuando le llegue una letra haga ese parpadeo con color rojo, por ejemplo.

Y respecto al cambio de color, como has dicho, cuando le llegue "U" cambie a otro color aleatorio cada unos 5 segundos, o por ejemplo cada vez que haga el aumento y decremento de iluminación cambie de color cada vez que llegue a 0, no se si esto ultimo se podrá hacer, supongo que si pero me faltan conocimientos aun xD

Llevo toda la tarde intentando implementar en el código el cambio aleatorio de colores pero no termino de comprander algunas partes de los array y no soy capaz de terminar de programarlo

Una matriz como la que uso IgnoranteAbsoluto permite manipular todas tus opciones de manera simple y rápida.

// 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
};

Primero si miras, con detenimiento, la matriz repite ordenadamente cada una de tus opciones, mas algunas que agregó justamente para darte mas opciones.
Tienes una matriz de bytes, con muchas filas y solo 5 columnas.
Las columnas tienen un primer valor que es tu comando anterior. El que ingresabas por Serial.
Luego los valores RGB y por ultimo un valor de paso usado para el incremento/decremento.

La variable que contiene todo la llamó ARRAY_VALORES[fila][columna]
si pones diferentes valores en fila y columna, recuperas los datos almacenados en cada uno de las posiciones de la matriz.

De ese modo
ARRAY_VALORES[0][0] devuelve 'A'
ARRAY_VALORES[0][1] devuelve 0
ARRAY_VALORES[0][2] devuelve 0
ARRAY_VALORES[0][3] devuelve 255
ARRAY_VALORES[0][4] devuelve 0

Dime si ahora se ve mejor esto?