¿Alguien me podría explicar este código?

Hola, me gustaría que alguien me explicara este código. Se trata de un proyecto para controlar un LED RGB mediante mando a distancia. Quiero usarlo como base para hacer algo parecido, pero hay cosas un par de cosas que no consigo entender. Hasta ahora nunca había trabajado con el comando byte y aunque alguna vez he usado char, siempre me cuesta mucho usarlo correctamente. Este es el código en cuestión.

#include <irremote .h=".h">
 
int RECV_PIN = 8;
int R_PIN = 9;
int G_PIN = 6;
int B_PIN = 10;
 
#define ON                0XFFE01F
#define OFF               0xFF609F
#define BRIGHTNESS_UP     0xFFA05F
#define BRIGHTNESS_DOWN   0xFF20DF
#define FLASH             0xFFF00F
#define STROBE            0xFFE817
#define FADE              0xFFD827
#define SMOOTH            0xFFC837
 
#define RED               0xFF906F
#define GREEN             0XFF10EF
#define BLUE              0xFF50AF
#define WHITE             0xFFD02F
 
#define ORANGE            0xFFB04F
#define YELLOW_DARK       0xFFA857
#define YELLOW_MEDIUM     0xFF9867
#define YELLOW_LIGHT      0xFF8877
 
#define GREEN_LIGHT       0XFF30CF
#define GREEN_BLUE1       0XFF28D7
#define GREEN_BLUE2       0XFF18E7
#define GREEN_BLUE3       0XFF08F7
 
#define BLUE_RED          0XFF708F
#define PURPLE_DARK       0XFF6897
#define PURPLE_LIGHT      0XFF58A7
#define PINK              0XFF48B7
 
#define INCREMENTO 10
 
unsigned long rgb = 0;
byte r,g,b;
 
IRrecv irrecv(RECV_PIN);
 
decode_results results;
 
 
void setup()
{
  irrecv.enableIRIn(); // Inicializamos el receptor
  Serial.begin(9600);
  pinMode(R_PIN, OUTPUT);   
  pinMode(G_PIN, OUTPUT);   
  pinMode(B_PIN, OUTPUT);   
}
 
 
void variar (byte* color, char valor) {
    if (valor > 0) {
        if ( *color + valor <= 255) {
            *color += valor;
        } else {
            *color = 255;
        }
    } else { 
        if (*color + valor >= 0) {
            *color += valor;
        } else {
            *color = 0;
        }
  }
}
 
void RGB(unsigned long valor) {
   r = valor >> 16; 
   g = (valor >> 8) & 0xFF; 
   b = valor & 0xFF; 
}
 
void loop() {
  if (irrecv.decode(&results)) {
    if ( results.value != 0xFFFFFFFF) {
      switch (results.value) {
           case BRIGHTNESS_UP : 
               variar (&r, INCREMENTO);
               variar (&g, INCREMENTO);
               variar (&b, INCREMENTO);
               break; 
           case BRIGHTNESS_DOWN : 
               variar (&r, -INCREMENTO);
               variar (&g, -INCREMENTO);
               variar (&b, -INCREMENTO);
               break; 
           case OFF :
               r = g = b = 0;
               break;    
           case RED           : RGB(0x00FF0000); break;
           case GREEN         : RGB(0x0000FF00); break;
           case BLUE          : RGB(0x000000FF); break;
           case WHITE         : RGB(0x00FFFFFF); break;
           case ORANGE        : RGB(0x00FF7F00); break;
           case YELLOW_DARK   : RGB(0x00FFAA00); break;
           case YELLOW_MEDIUM : RGB(0x00FFD400); break;
           case YELLOW_LIGHT  : RGB(0x00FFFF00); break;
           case GREEN_LIGHT   : RGB(0x0000FFAA); break;
           case GREEN_BLUE1   : RGB(0x0000FFFF); break;
           case GREEN_BLUE2   : RGB(0x0000AAFF); break;
           case GREEN_BLUE3   : RGB(0x000055FF); break;
           case BLUE_RED      : RGB(0x00000080); break;
           case PURPLE_DARK   : RGB(0x003F0080); break;
           case PURPLE_LIGHT  : RGB(0x007A00BF); break;
           case PINK          : RGB(0x00FF00FF); break;
      }
      Serial.println(results.value, HEX);
      Serial.println(r,DEC);
      Serial.println(g, DEC);
      Serial.println(b, DEC);
      analogWrite(R_PIN,r);
      analogWrite(G_PIN,g);
      analogWrite(B_PIN,b);
    }
    irrecv.resume(); // Receive the next value
  }
}

Concretamente, la parte que no entiendo es la siguiente:

void variar (byte* color, char valor) {
    if (valor > 0) {
        if ( *color + valor <= 255) {
            *color += valor;
        } else {
            *color = 255;
        }
    } else { 
        if (*color + valor >= 0) {
            *color += valor;
        } else {
            *color = 0;
        }
  }
}

Intuyo que sirve para limitar el valor de la variable rgb, pero por mucho que intento comprender como funciona, no consigo entenderlo. Por otra parte está esta función, que creo que sirve para ajustar los valores de salida de cada pin RGB en función al valor obtenido en el proceso anterior. El problema es que no consigo entender la sintaxis.

void RGB(unsigned long valor) {
   r = valor >> 16; 
   g = (valor >> 8) & 0xFF; 
   b = valor & 0xFF;

Si alguien pudiera explicarme cómo funcionan estas dos partes línea por línea le estaría muy agradecido.

La primera parte hace exactamente lo que has dicho, valor parece ser un número positivo o negativo, y los límites serían 0 y 255

La segunda parte el comando >> es una rotación y &FF SE llama máscara binaria, elimina la parte alta del longitud y se queda con el último byte

Parece que valor en binario sería: rrrrrrrrggggggggbbbbbbbb y los separa cada uno en una variable

byte es lo mismo que unsigned char
porque unsigned char son 8 bits o 0-255 al igual que byte

Hola Zegius,

Aqui te dejo un enlace con el proyecto en espanol. Saludos.

-p

Arduino RGB LED Manejado por Control Remoto

Hola Palliser, de ahí es precisamente de donde lo he sacado :stuck_out_tongue_closed_eyes:
El código sé para que sirve, pero no entiendo cómo funcionan las dos partes que he puesto en el anterior post. De todas formas se agadecé la intención.

GO_zalo:
La primera parte hace exactamente lo que has dicho, valor parece ser un número positivo o negativo, y los límites serían 0 y 255

La segunda parte el comando >> es una rotación y &FF SE llama máscara binaria, elimina la parte alta del longitud y se queda con el último byte

Parece que valor en binario sería: rrrrrrrrggggggggbbbbbbbb y los separa cada uno en una variable

Gracias por la respuesta, ahora sé para qué sirve, pero sigo sin entender cómo funciona. Algo hemos avanzado!! jejeje

surbyte:
byte es lo mismo que unsigned char
porque unsigned char son 8 bits o 0-255 al igual que byte

Y hay alguna razón para usar uno en lugar de otro? Creo que tengo mucho que aprender todavía.

Zegius:

void RGB(unsigned long valor) {

r = valor >> 16;
  g = (valor >> 8) & 0xFF;
  b = valor & 0xFF;




Si alguien pudiera explicarme cómo funcionan estas dos partes línea por línea le estaría muy agradecido.

La segunda parte del codigo contiene la funcion RGB que extrae del color del pixel (valor) los valores de rojo, verde y azul que luego son imprimidos por el puerto serial y enviados a los pines 9, 6 y 10 respectivamente del Arduino. Observa que si bien valor tiene 32 bits, solo se manipulan los 24 menos significativos (rgb). Los 8 bist faltantes (mas significativos) son lo que se llama transparencia o alfa y no se tocan.

-p

Palliser:
La segunda parte del codigo contiene la funcion RGB que extrae del color del pixel (valor) los valores de rojo, verde y azul que luego son imprimidos por el puerto serial y enviados a los pines 9, 6 y 10 respectivamente del Arduino. Observa que si bien valor tiene 32 bits, solo se manipulan los 24 menos significativos (rgb). Los 8 bist faltantes (mas significativos) son lo que se llama transparencia o alfa y no se tocan.

-p

Y como podría modificar estos valores? Estoy tratando de crear una función automática para que al presionar el botón auto, se ajuste la luz a los valores del sensor, pero no consigo hacerlo porque no sé como funciona esa parte del código. Entiendo que "r" es igual al valor, pero que pasa con ">>16"? Eso que hace? Como le doy a los valores r,g y b un valor numérico decimal para poder manipularlos mediante operaciones matemáticas simples? Hasta ahora, para modificar la potencia del rgb lo estaba haciendo así.

#define sensor A0
#define R_PIN  9
#define G_PIN  10
#define B_PIN   6

int valorSen; //Recoge el valor del sensor
int valorLed; //Recoge el valor del sensor una vez escalado a 0 - 255
float incremento; //porcentaje de luz a sumar o restar al conjunto

void setup() {
  pinMode(R_PIN, OUTPUT);
  pinMode(G_PIN, OUTPUT);
  pinMode(B_PIN, OUTPUT);
  Serial.begin(9600);
}

void loop(){
    valorSen = analogRead(sensor);                //Lee el sensor     
    valorLed = map(valorSen,400,900,0,255);      //Mapea los valores
      if (valorLed < 0){                        //evita sobrepasar el limite de 0-255
        valorLed = 0;
      }
      if (valorLed > 255){
        valorLed = 255;
      }
     incremento = map(valorLed,0,255,0,100);   //Convierte el valor obtenido en un porcentaje
     incremento = incremento/100;              //Convierte el porcentaje en un numero decimal
       if (valorLed > 0){
        colorAuto(255,255,255);       
       }
       else{
         colorAuto(0,0,0);
       }
  }

void colorAuto(int rojo, int verde, int azul){
  
  rojo = rojo*incremento;       //Ajusta cada canal de manera porcentual en función 
  verde = verde*incremento;  //de la cantidad de luz recibida por el sensor
  azul = azul*incremento;
  
  analogWrite(R_PIN, rojo);
  analogWrite(G_PIN, verde);
  analogWrite(B_PIN, azul);
}

Hay alguna manera de integrar ambos códigos modificando la función void RGB?

   r = valor >> 16; 
   g = (valor >> 8) & 0xFF; 
   b = valor & 0xFF;

16 desplaza los bits 16 lugares a derecha
como veras valor esta definido como unsigned long o sea 32 bits
supon x un momento que tienes
b1000 0000 0000 0000 0000 0000 0000 0000
te lo escribo con un espacio para que se vean los medios bytes o nibbles.
bien si valor valiera eso y aplicas >> 16 desplazas los bits 16 lugares
es como arrastrar los 8 primeros bits a la derecha
o sea que queda
b0000 0000 0000 0000 1000 0000 0000 0000

Ahora vamos a tu problema.
porque no usas la rutina lego que tienes R, G y B y ahi incrementas?

Muchas gracias surbyte, ahora si que me ha quedado claro. Voy a intentar hacerlo como dices a ver si me funciona.

Y entendiste esto?

  g = (valor >> 8) & 0xFF; 
   b = valor & 0xFF;

A grandes rasgos creo que he entendido el concepto, aunque aún no tengo muy claro como funciona exactamente 0xFF. De momento sigo trabajando sobre el código y ya he conseguido reducir la luz en función de los valores tomados por la fotoresistencia. Actualmente mi nivel de programación es bastante bajo y no sé si será muy recomendable profundizar más sobre lenguaje hexadecimal, aunque ya he estado leyendo algo sobre el tema para ir aclarando conceptos. Cuando haya avanzado un poco más con el código lo subiré a ver qué se puede mejorar, porque seguro que lo complico más de lo necesario.

Esas son máscaras. Se usan para descartar cosas y quedarme con lo que quiero.

g = (valor >> 8) & 0xFF;

aca lo que hace el código es quedarse con los 8 bits mas altos.
Porqué?
valor >> 8 desplaza los bits 8 lugares a la derecha.
a ese resultado le sigue una operación con una mascara de justamente 8 bits xq 0xFF = 0b11111111
Para entender toda la operación recordemos que valor es de 32 bits
supongamos **1001 0001 0111 1010 **1001 0001 0111 1010 => 32 bits

8 0000 0000 1001 0001 0111 1010 1001 0001 desplazo 8 lugares
& 0xFF & 0000 0000 0000 0000 1111 1111 1111 1111


0000 0000 0000 0000 0111 1010 1001 0001 resultado

Ahora sí! Lo has explicado perfectamente surbyte. Muchísimas gracias.