Luces RGB

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?

Si eso llego a entenderlo, el problema es a la hora de implementar otro modo como el del cambio de color aleatoriamente o un parpadeo. Ando perdido en como implementar algo de eso.

Tal como esta hecho el código ahora, un parpadeo podrias hacerlo como algo que cambia de 0 a 255 en cada paso, asi que implementa una nueva fila con LETRA asociada, y usa un paso 255 para que salte de Brillo total o apagado.

Cambio de color aleatorio requiere algo como random() entre 3 opciones o 4 RGB y blanco.
Si ese fuera el caso, de nuevo, elige una letra nueva ('M') que será tu opcion de aleatoriedad y harías algo asi
debes agregar
{'M', 0, 0, 0, 0}, // Aleatorio A..F
{'N', 0, 0, 0, 0}, // Aleatorio G..L

for (size_t i = 0; i < (sizeof(ARRAY_VALORES) / NUMERO_CAMPOS); i++) {
            byte datos;
            switch (datos_serial) {
                      case 'M': datos = random(0,5)+'A'; // o sea que random dará valores aleatorios entre 0 y 2, que debemos sumar
                                               // a los grupos A.. F
                                   break;
                      case 'N': datos = random(0,5)+'G'; // o sea que random dará valores aleatorios entre 0 y 2, que debemos sumar
                                               // a los grupos G..L
                                   break;
                      default:  datos = datos_serial;
                         
            }
            if (ARRAY_VALORES[i][INDICE_LETRA] == datos) { // Buscamos la tecla pulsada

De nuevo, es algo que implemento al pasar, pruébalo a ver si funciona.

Antes de nada, pido disculpas porque lo he hecho un poco con prisas. Creo que la mejor solución es poder mandar "comandos" básicos que configure el LED como queramos. Y así no tenemos que volver a tocar el programa del Ardunino para nada.

Aquí está el programa:

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

byte valorR = 0;
byte valorG = 0;
byte valorB = 0;
byte limiteR = 0;
byte limiteG = 0;
byte limiteB = 0;

enum estado_lectura_t {
    ESTADO_LEE_R,
    ESTADO_LEE_G,
    ESTADO_LEE_B,
    ESTADO_LEE_PASO,
    ESTADO_LEE_PARPADEO,
    ESTADO_LEE_PARPADEO_APAGADO,
    ESTADO_LEE_PARPADEO_ENCENDIDO,
    ESTADO_REPOSO
};
estado_lectura_t estadoLectura = ESTADO_REPOSO;

enum estado_parpadeo_t {
    ESTADO_PARPADEO_INACTIVO,
    ESTADO_PARPADEO_ENCENDIDO,
    ESTADO_PARPADEO_APAGADO
};
estado_parpadeo_t estadoParpadeo = ESTADO_PARPADEO_INACTIVO;

unsigned long tiempoParpadeoEncendido = 0;
unsigned long tiempoParpadeoApagado = 0;
unsigned long momentoCambioParpadeo = 0;
unsigned int valorLeido = 0;
byte digitosLeidos = 0;
int paso = 0;
int valorReferencia = VALOR_MAXIMO;
unsigned long momentoCambio = 0;

void finValor() {
    switch (estadoLectura) {
        case ESTADO_LEE_R :
                valorR = limiteR = (valorLeido > VALOR_MAXIMO) ? VALOR_MAXIMO : valorLeido;
            break;
        case ESTADO_LEE_G :
                valorG = limiteG = (valorLeido > VALOR_MAXIMO) ? VALOR_MAXIMO : valorLeido;
            break;
        case ESTADO_LEE_B :
                valorB = limiteB = (valorLeido > VALOR_MAXIMO) ? VALOR_MAXIMO : valorLeido;
            break;
        case ESTADO_LEE_PARPADEO :
        case ESTADO_LEE_PARPADEO_APAGADO :
                tiempoParpadeoApagado = valorLeido * 10; // valorLeido se consideran como centésimas de segundo
        case ESTADO_LEE_PARPADEO_ENCENDIDO :
                if (estadoLectura != ESTADO_LEE_PARPADEO_APAGADO) {
                    tiempoParpadeoEncendido = valorLeido * 10; // valorLeido se consideran como centésimas de segundo
                }
                if ( (tiempoParpadeoEncendido == 0) || (tiempoParpadeoApagado == 0) ) {
                    estadoParpadeo = ESTADO_PARPADEO_INACTIVO;
                }
                else if (estadoParpadeo == ESTADO_PARPADEO_INACTIVO) {
                    momentoCambioParpadeo = millis();
                    estadoParpadeo = ESTADO_PARPADEO_ENCENDIDO;
                }
            break;
        case ESTADO_LEE_PASO :
                paso = (valorLeido > (VALOR_MAXIMO - VALOR_MINIMO)) ? (VALOR_MAXIMO - VALOR_MINIMO) : valorLeido;
                valorReferencia = VALOR_MAXIMO;
            break;
        case ESTADO_REPOSO : // No se hace nada
            break;
    }
    digitosLeidos = 0;
    valorLeido = 0;
    estadoLectura = ESTADO_REPOSO;
}

void setValor(byte valor) {
    valorLeido = (valorLeido * 10 + (valor - '0')) % 1000;
    digitosLeidos++;
    if (digitosLeidos >= 3) {
        finValor();
    }
}

void setEstado(estado_lectura_t nuevoEstado) {
    finValor();
    estadoLectura = nuevoEstado;
}

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

void loop() {
    if (Serial.available() > 0) {
        byte datoSerie = Serial.read();
        Serial.write(datoSerie);        // Comentar esta línea si no se quiere "eco"
        switch (datoSerie) {
            case 'R' :
            case 'r' :
                setEstado(ESTADO_LEE_R);
                break;
            case 'G' :
            case 'g' :
                setEstado(ESTADO_LEE_G);
                break;
            case 'B' :
            case 'b' :
                setEstado(ESTADO_LEE_B);
                break;
            case 'V' :
            case 'v' :
                setEstado(ESTADO_LEE_PASO);
                break;
            case 'P' :
            case 'p' :
                setEstado(ESTADO_LEE_PARPADEO);
                break;
            case 'A' :
            case 'a' :
                setEstado(ESTADO_LEE_PARPADEO_APAGADO);
                break;
            case 'E' :
            case 'e' :
                setEstado(ESTADO_LEE_PARPADEO_ENCENDIDO);
                break;
            default :
                if ( (datoSerie >= '0') && (datoSerie <= '9') ) {
                    setValor(datoSerie);
                }
                else {
                    finValor();
                }
        }
    }
    if ( (millis() - momentoCambio) >= TIEMPO_CAMBIO ) {
        momentoCambio = millis(); // Guardamos el instante en el que se ha hecho el cambio
        valorR = map(valorReferencia, 0, 255, 0, limiteR);
        valorG = map(valorReferencia, 0, 255, 0, limiteG);
        valorB = map(valorReferencia, 0, 255, 0, limiteB);
        if (estadoParpadeo == ESTADO_PARPADEO_APAGADO) {
            analogWrite(PIN_R, LOW);
            analogWrite(PIN_G, LOW);
            analogWrite(PIN_B, LOW);
        }
        else {
            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;
    }

    if ( (estadoParpadeo == ESTADO_PARPADEO_APAGADO) && ( (millis() - momentoCambioParpadeo) >= tiempoParpadeoApagado ) ) {
        estadoParpadeo = ESTADO_PARPADEO_ENCENDIDO;
        momentoCambioParpadeo = millis();
        analogWrite(PIN_R, valorR);
        analogWrite(PIN_G, valorG);
        analogWrite(PIN_B, valorB);
    }
    else if ( (estadoParpadeo == ESTADO_PARPADEO_ENCENDIDO) && ( (millis() - momentoCambioParpadeo) >= tiempoParpadeoEncendido ) ) {
        estadoParpadeo = ESTADO_PARPADEO_APAGADO;
        momentoCambioParpadeo = millis();
        analogWrite(PIN_R, LOW);
        analogWrite(PIN_G, LOW);
        analogWrite(PIN_B, LOW);
    }
}

Y aquí están las instrucciones.

Al Arduino se le manda por el puerto serie un comando formado por una letra (da igual si es mayúscula o minúscula) y hasta tres dígitos que configuran su valor. No se "realiza la acción" hasta que lleguen los tres dígitos o llegue otro carácter que no sea un dígito del 0 al 9 (no importa si ese otro carácter es un comando válido o no).

Los comandos son:
R establece el valor del rojo (de 0 a 255)
G establece el valor del verde (de 0 a 255)
B establece el valor del azul (de 0 a 255)
V establece la velocidad con que varía de intensidad continuamente (de 0 a 255). El 0 lo desactiva y deja el LED al máximo preestablecido.
P establece en centésimas de segundo el tiempo que está encendido y apagado durante el parpadeo (de 0 a 999). El 0 desactiva el parpadeo y se queda fijo.
E establece en centésimas de segundo el tiempo que está encendido durante el parpadeo (de 0 a 999). El 0 desactiva el parpadeo y se queda fijo.
A establece en centésimas de segundo el tiempo que está apagado durante el parpadeo (de 0 a 999). El 0 desactiva el parpadeo y se queda fijo.

Si el valor supera el máximo permitido, se evalúa como el máximo. Los comandos diferentes son "acumulativos" es decir, si le decimos que se ponga rojo, establecemos una velocidad de cambio y le decimos que parpadee, se pondrá rojo, cambiará de brillo y parpadeará.

Se puede probar con el monitor del IDE de Arduino. Tiene "eco" para que se vea lo que le estamos enviando. Si no se quiere que tenga "eco" basta con comentar la línea indicada en el programa.

Ejemplo, si queremos que se ponga verde le mandamos:
G255

Si ahora queremos que pase de verde a celeste bastaría con encender el azul:
B255

Si ahora queremos que se ponga rojo, habría que apagar el verde y el azul, y encender el rojo. Como ya he comentado, si después del comando no se completan los tres dígitos porque se manda otro comando u otro carácter que no reconoce, tomará el valor 0 o lo el de los dígitos que hubieran. Así que para apagar el verde y el azul y encender el rojo no hace falta mandar G000B000R255, basta con mandar:
GBR255

Para que ahora parpadee a un hercio, podemos decirle que lo haga con un tiempo de medio segundo (medio segundo encendido, medio segundo apagado) y como lo que se le dice son centésimas de segundo, hay que mandar es 50 centésimas. Si no vamos a mandar seguidamente otro comando, lo que tendremos que mandar el 50 con tres dígitos (050)
P050

Si ahora queremos que esté encendido segundo y medio en lugar de medio segundo, podemos cambiar sólo el tiempo que está encendido mandando:
E150

Si queremos apagar el parpadeo nos basta con poner a cero cualquier parámetro del parpadeo P000, E000 o A000 pararían el parpadeo y dejarían el LED todo el tiempo encendido.

El parpadeo y el cambio de velocidad son compatibles entre sí y pueden estar activos a la vez. Ejemplo:
RGB255V2E50A003

Sólo me he preocupado de completar con ceros a la izquierda el último comando ya que como no hay otro que lo termine es imprescindible que tenga tres dígitos. También se puede "completar" mandando un carácter "no válido" como puede ser el retorno de carro, o un punto, o una X. Esto haría lo mismo:
RGB255V2E50A3;

Así que si se quiere apagar, bastaría con mandar:
RGB;

Pero eso no para el parpadeo ni el cambio de intensidad. Así que si estaban activos antes de apagar, seguirán activos si se enciende (probar a mandar B255). Para "apagarlo todo" habría que mandar:
RGBVP;

Ahora si se manda B255 se encenderá fijo el azul.

Bueno, espero que se entiendan mis explicaciones y que esto le sirva a OrnyTorrynKo.

Nuevamente muchisima gracias a ambos.

El código de surbyte no tengo muy claro como implementarlo y de todas las formas que he probado al mandar "M" se que el led apagado.

Para el codigo de IgnoranteAbsoluto voy a modificar la app completamente para poder probarlo pero tengo la duda si en este código viene lo de las luces tenues y lo de los colores aleatorios o lo has quitado y has puesto el parpadeo? ya que me interesaria mas lo de las luces tenues y los colores aleatorios.
Y otra pregunta que te qeria hacer es si este código o el anterior que realizaste se puede adaptar a anillos rgb que funcionan con la libreria neopixel de Adafruit.

IgnoranteAbsoluto he modificado la app y tu código funciona a la perfeccion.

Ya me he dado cuenta de que si esta incluido lo de las luces tenues jejeje. Muchas gracias!

Intentaré incluir lo de el cambio de color aleatorio a ver que tal se me da.

Agregaste OrnyTorrynKo lo que te indiqué? Seguramente no.. ni te tomaste el tiempo.

Claro que si IgnoranteAbsoluto te va a resolver cada opción jajaja ni vale la pena considerar lo que te digo.

Asi que lo dejo ahi.

Surbyte como dije antes en el comentario anterior intente implementarlo, lo probé incluso antes que el codigo de IgnoranteAbsoluto, pero no me terminaba de quedar claro como incluirlo en el codigo, por lo que me daba fallos y ya probé el otro codigo

OrnyTorrynKo, como ya dije, lo hice con prisas. Para probar el concepto y ver si funcionaba. Así que no implementé lo de los colores aleatorios. Habrá que esperar a que tenga un hueco y me pueda sentar a implementarlo.

Lo de los neopixel tiene una complicación y un posible problema. La complicación es que ya no se trata de uno, sino de varios LEDs y supongo que querrás manejar cada uno por separado (¿O quieres que todos tengan el mismo comportamiento a la vez?). Para ello lo más práctico sería rediseñar y modificar el programa para que fuera orientado a objetos. Definir una clase que controle un neopixel y crear un array de objetos de esa clase. Por otro lado habría que ingeniar algún sistema para "direccionar" un determinado neopixel para poder aplicar los "comandos" sólo a él, o a un conjunto de ellos.

Otro problema es que si son muchos neopixel los tiempos no pueden ser muy cortos, ya que "tratar" todos los neopixel lleva su tiempo. Y el transmitir el cambio de sólo uno de ellos supone tener que transmitir de nuevo la información de todos ellos, y eso lleva su tiempo.

Otra cosa que hay que tener en cuenta es que por cada neopixel se va a necesitar cierta cantidad de memoria para gestionarlos, así que no pueden ser muchos porque te podrías quedar sin memoria. Y por otro lado ten en cuenta también que consumen bastante corriente y si son muchos tendrás que alimentarlos "externamente". ¿Cuántos neopixel estás pensando manejar?

IgnoranteAbsoluto, no te preocupes por no implementarlo, solo tenia la duda y bastante me estas ayudando jeje.

Por otro lado, volviendo al tema, en un principio me conformo con que todos los pixel trabajen de la misma forma, no es necesario que cada uno tenga un comportamiento distinto. En principio tenia pensado un anillo de 8 leds y para controlarlo seria el Arduino Nano, ya que quiero que me ocupe el menos sitio posible.
¿Que opinas o que me recomendarias?

Si son solo ocho no creo que sea problemático. Ya tendrás noticias mías con una posible implementación para los neopilxels.

Perfecto, muchas gracias compañero!

Aquí está la versión para el LED RGB con la opción de color aleatorio y, ya de paso, apagar todo con un sólo carácter. Para la próxima voy a ver qué se puede hacer con los neopixel.

Los nuevos comandos son:
X establece un color aleatorio y cada cuánto tiempo se ha de cambiar aleatoriamente en centésimas de segundo (de 0 a 999). Si el tiempo es 0 para los cambios si había tiempo establecido, si no había tiempo establecido entonces cambia de color sólo una vez.
Z apaga el LED y desactiva todas las opciones (parpadeo, aleatoriedad y cambio intensidad).

Ejemplo para apagarlo todo:
Z

Ahora, para que cambie aleatoriamente de color una sola vez:
X;

El ; es para no tener que poner X000. Para Z no hace falta porque no necesita ningún valor.

Para que cambie de color cada segundo:
X100

Para que pare de cambiar y mantenga el último:
X;

Y por supuesto, funcionan todos los anteriores comandos.

Al final el programita se me ha convertido en un pequeño ejemplo de "multitarea" y de pequeñas "máquinas de estado".

Adjunto el programa porque ya se ha hecho mayorcito y no cabe como "code".

luces_RGB.ino (9.44 KB)

Perfecto compañero, en cuanto tenga un rato modificaré la app para incluirle esto último y te comentaré los resultados.

Estuve investigando sobre los neopixel y intentaré hacer algunas pruebas con el codigo, aunque lo veo complicado jejeje

Aquí está la versión para neopixel. Con el "pequeño defecto" de que los gestiona todos por igual y no individualmente (tal vez la próxima versión). Hay dos constantes a tener en cuenta en el código: PIN_NEOPIXEL que indica en qué pin está conectado los neopixel, que en mi caso lo he conectado al pin 3. Y la constante TOTAL_CANTIDAD_NEOPIXEL que indica cuantos neopixel son los que tiene la tira o los que se quiere controlar, yo lo he usado 8.

Como en las pruebas he visto que los neopixel iluminan mucho así que, para no deslumbra demasiado, le he añadido un nuevo comando (i):

I establece la intensidad del LED (de 0 a 255). Si se establece 0 "se apaga" el control de la intensidad y es como si se hubiera establecido a 255 (el máximo).

Ejemplo, ponerlo azul y la intensidad a 10:
B255I10;

Si ahora queremos poner la intensidad al máximo podemos usar I000, I; o I255

El resto de comandos anteriores continúan funcionando igual. Ver este comentario y este otro.

Recuerdo que los comandos no diferencia entre mayúsculas y minúsculas. Y también recomiendo terminar siempre con algún carácter que no se a un comando como el ; (punto y coma) o un retorno de carro.

Adjunto el programa.

foro_neopixel.ino (10.6 KB)

Me parece una gran propuesta la que has realizado con todo este código y estoy totalmente agradecido por la ayuda que me has dado y las cositas que he aprendido.

En cuanto disponga del anillo led probaré el código aunque sin duda alguna se que funcionará.

Estaremos en contacto compañero y estaremos en contacto, un saludo!

Al final creo que se me ha ido un poco de las manos. He encapsulado el código en clases y ahora se pueden controlar los neopixel todos juntos, uno a uno o varios a la vez. Para ello he implementado nuevos comandos que permiten la selección. Todos los comandos anteriores funcionan igual (sobre los LEDs seleccionados). Al empezar están todos seleccionados con lo que los comandos que no son de selección afectan a todos.

El código está configurado para conectar 16 neopixel en el pin 3. Si se quiere cambiar se han de modificar las líneas:

const int PIN_NEOPIXEL = 3;              // Pin al que están conectado los neopixel
const int CANTIDAD_TOTAL_NEOPIXEL = 16;  // Cantidad total de neopixel

Cuidado, se necesitan al menos 28 bytes por neopixel para controlarlos. Así que si se conectan muchos tal vez el Arduino se quede sin memoria.

Para saber cuales son los comandos anteriores ver los tres anteriores post:
https://forum.arduino.cc/index.php?topic=485147.msg3319112#msg3319112
https://forum.arduino.cc/index.php?topic=485147.msg3321914#msg3321914
https://forum.arduino.cc/index.php?topic=485147.msg3322652#msg3322652

Los nuevos comandos son:

N establece un único LED a manejar (de 0 a CANTIDAD_TOTAL_NEOPIXEL - 1) si el valor es mayor o igual que CANTIDAD_TOTAL_NEOPIXEL calcula el resto de dividir el valor establecido por CANTIDAD_TOTAL_NEOPIXEL.
D establece desde qué LED se va a manejar en conjunto (admite los mismos valores que el comando 'N'). Si 'D' es mayor que 'H' entonces se selecciona desde 'H' hasta el final y desde el principio hasta 'D'.
H establece hasta qué LED se va a manejar en conjunto (admite los mismos valores que el comando 'N'). Si 'D' es mayor que 'H' entonces se selecciona desde 'H' hasta el final y desde el principio hasta 'D'.
< inicia un comentario (para terminarlo se usa '>').
> finaliza un comentario comenzado por '<'.
T seleccionar todos los LEDs a la vez.
+ activa el seleccionado por el comando 'N' o por un '+' o '-' anterior y selecciona el siguiente sin activarlo. Del último se pasa al primero.
- desactiva el seleccionado por el comando 'N' o por un '+' o '-' y selecciona el siguiente sin activarlo. Del último se pasa al primero.
C invierte la selección de LEDs.
O inverte el parpadeo.
Z apagar y desactivar toda configuración de los LEDs seleccionados.

Ejemplo de seleccionar todos (T), inicializarlos (ponerlos todo a cero) con Z, ponerlos azul (B) y establecer la intensidad (i) a 10 para que no deslumbren mucho. Usamos el punto y coma porque la intensidad sólo necesita dos dígitos y no hay más comandos.
TZB255i10;

Siguiendo con el ejemplo anterior, los hacemos parpadear todos (con ejemplo de comentario):
TZB255i10;P50;

Siguiendo con el ejemplo anterior, Seleccionamos del 4 al 7 e invertimos el parpadeo (o minúscula para que no se confunda con el cero. Sirve igualmente en mayúsculas):
D4H7o

Continuando lo anterior, selecciono el segundo LED, le quito el azul y lo pongo rojo:
N1BR255

Continúo desactivando la selección del segundo LED y "pasando" al tercero con el menos (-), selecciono el tercero y "paso" al cuarto con el más (+), deselecciono el cuarto y paso al quinto (-), deselecciono el quinto y paso al sexto (-), selecciono el sexto y paso al septimo (+), y ya no selecciono nada más. A los dos seleccionados (tercero y septimo) le digo que cambie de color aleatoriamente (X) cada 10 centésimas de segundo:
-+--+X10;

Ahora invierto la selección (C) y les digo que varíen de intensidad con "velocidad" 2:
CV5;

La intensidad la hemos limitado anteriormente a 10. Ahora la vamos a limitar a 100 (salvo los que están aleatorios que no están seleccionados).
i100

Por último invertimos la selección y paramos los aleatorios:
CX;

Un ejemplo "completo" de comandos para una matriz de neopixel de 4x4 (las letras están en minúsculas para no confundir con los números):
tzi10n0+++-+-+-+-+++-+b255p50n0++---------++on2pn4pn3x40n5+---+-----+r255v5;

Que mostraría algo tal que así:

ejemplo.gif

Advierto que lo he hecho un poco "a las prisas" porque no he tenido mucho tiempo disponible. Entiendo que para muchos neófitos en la programación orientada a objeto les va a resultar difícilmente comprensible el código. Y para los ya curtidos también puede que les parezca enrevesado. Aún así, si alguien tiene alguna duda y se atreve a preguntar ruego lo hagan por aquí, por si le puede servir de ayuda a otros.

Adjunto el programa.

foro_neopixel_individual.ino (25.7 KB)

ejemplo.gif

Perfecto IgnoranteAbsoluto, en cuanto tenga un poco de tiempo libre reconfiguraré la app adaptada al nuevo código y te comento los resultados.

Un saludo compañero.