Skip to content

Ejercicio 4 * Lámpara RGB

s/c edited this page Mar 27, 2023 · 34 revisions

Lámpara

Interacciones sensibles para jugar con luz.

Estoy diseñando mi lámpara.

Ideas de interacción

Bocetos Inspo: Andel. (1990). Art into life : russian constructivism, 1914-1932.

El diseño de esta lámpara se centra en dos cosas: el [A] recorrido por el espectro RGB, y el [B] gesto sensible que lo permite.
Para determinar los gestos hice exploraciones con paletas de pingpong, con movimientos tipo tabla ouija, girando anillos... al final decidí que apuntar a algo y girar/rotar cubos eran gestos sencillos e intuitivos que a la vez dan una sensación de juego. Durante el proceso de prototipado nació una 3ra idea, mirar/dirección, que correlaciona la orientación (N-S-E-O) con el espectro de la luz.

Sobre los cambios de luz, me di cuenta que era más fácil comprender el recorrido por el espectro de modo R-Y-G-C-B-M, es decir, incorporando el cian, magenta y amarillo como puntos medios. De hecho, pensar en 6 variables de color me llevó a considerar el cubo (6 lados) como mecanismo de interacción, y a armar el código considerando esas 6 etapas.


Prototipos (sin magia ni código, pero igual prototipos)

1 - Apunta y Antorcha Un cono, que en su extremo más estrecho tiene el led RGB. La luz nace de él. El cono es sensible a las señales infrarrojas. Cada vez que se orienta hacia un emisor particular, el led adapta ese color. Entonces las transiciones se dan "recogiendo" luz. Para apagar la "antorcha" se sopla el cono.
Apunta y Antorcha
Consideraciones:

  • Los emisores de color deben estar suficientemente espaciados entre sí para evitar transiciones accidentales. (Pero no tan lejos como para que de pereza explorar el color).
  • El cono debe ser rígido para poder soportar todos los sensores. Es más como un megáfono.
  • Este imitaría -maso- como funcionan los TV's. Un sólo receptor (el TV) puede responder a muchas distintas señales (los botones del control). El TV siempre está pendiente de recibir, es decir, el Arduino estaría escaneando siempre posibles señales; y los puntos donde se "recoge" el color siempre están emitiendo.
Captura de pantalla 2023-03-25 a la(s) 7 26 08 p m Captura de pantalla 2023-03-25 a la(s) 7 26 08 p m

2 - Cubo
El cubo es un objeto muy agradable de sostener. Hay varias cosas a tener en cuenta. Cada cara del cubo ofrece una de las 6 variables de color (R-Y-G-C-B-M). Existen infinitas maneras de sostener y mover un cubo. Entonces hay que limitar los gestos posibles del cubo para determinar cómo recorrer el espectro. Para comenzar voy a trabajar sólo en que reaccione a la orientación de las diferentes caras. Igual anoto posibles recorridos de luz que se me ocurren:
[1] Que al dejar caer sobre la cara siguiente, se navegue hasta ese color lentamente. Si uno quiere hacer varias transiciones, se van "apilando" los cambios.
[2] Si se tira, se gira o se agita (en general, si se mueve con más ímpetu), se activan transiciones de color predeterminadas (sólo cálidos, fríos, etc.).
No sé muy bien cómo prender y apagar la lámpara. Por ahora la concibo como un ente que siempre emite luz. (Y si el que la compre sólo acepta que con esta lámpara se va a encartar porque una vez encendida no hay vuelta atrás?) Una opción es que por inactividad de movimiento se apague. Eso me agrada.

Magic

3 - Orientar la luz / en el horizonte
El campo magnético de la tierra le permite a ciertos sensores interpretar la dirección hacia la cual se está apuntando. Eso me agrada porque mientras hacía pruebas con el cono, pensé que se parece también a un telescopio. Y que el gesto de apuntar el cono y que salga luz de él, pintando amebas coloridas en el techo y en las paredes es muy bonito.

Entonces algo que quiero probar es que mientras la persona gire en círculos (recorriendo N-E-S-W), vaya recorriendo el espectro R-Y-G-C-B-M (que también es como un círculo). Guiándome por el campo magnético de la tierra puedo determinar la dirección de la persona en el mundo, y en el círculo imaginario para recorrer la luz. Como una lámpara que reacciona a la dirección.
Algo bello de este input es que el campo magnético de la tierra se va transformando con el tiempo, afectando la lectura de los sensores y por ende generando outputs diferentes a lo largo del año. Según chatgpt: "The Earth's magnetic field has both a static component (known as the declination angle) and a time-varying component (known as magnetic field variation). The declination angle varies based on the geographic location of the sensor, while magnetic field variation varies over time and can be affected by various factors such as solar activity and changes in the Earth's core.".
Explore


Captura de pantalla 2023-03-26 a la(s) 2 03 44 a m


**Otras exploraciones**
Estos son algunos de los efectos de luz que me parecieron más interesantes:
luces 1 luces 2

Componentes

LEDS
Estoy utilizando leds de 4 pines, de ánodo común. Un código sencillito para manejarlos, cortesía de chatgpt.
Nota: en este setup la conexión se hace al ground, pero en mi caso la hice a 5V.

setup-rgb



Sensor de gestos GY-PAJ7620
Prometía mucho pero no logra hacer lecturas, salvo Transmission error! o PAJ7620 I2C error - halting. Este sensor tiene un datasheet increíble, y según la documentación, puede reconocer 9 gestos:

  • move up
  • move down
  • move left
  • move right
  • circle clockwise
  • circle anti-clockwise (counter-clockwise / widdershins)
  • forwards / towards
  • backards / away
  • wave
switch (gesture) {
      case GES_RIGHT_FLAG:
        Serial.println(F("Right"));          
        break;
      case GES_LEFT_FLAG: 
        Serial.println(F("Left"));         
        break;
      case GES_UP_FLAG:
        Serial.println(F("Up"));        
        break;
      case GES_DOWN_FLAG:
        Serial.println(F("Down"));         
        break;
      case GES_FORWARD_FLAG:
        Serial.println(F("Forward"));
        break;
      case GES_BACKWARD_FLAG:     
        Serial.println(F("Backward"));
        break;
      case GES_CLOCKWISE_FLAG:     
        Serial.println(F("Clockwise"));
        break;
      case GES_COUNT_CLOCKWISE_FLAG:     
        Serial.println(F("Counterclockwise"));
        break;
      case GES_WAVE_FLAG:     
        Serial.println(F("Wave"));
        break;
      default:
        break;
    }

Si pudiera hacerlo funcionar sería la salvación. Sobretodo porque el gesto del círculo (counter-clockwise) me encanta. Curiosamente este sensor funciona a 115200 baudios, no con los 9600 normales. No logro que saque ninguna lectura. Poca documentación y tiempo entonces cambiaré de sensor. Todo el código que estudié se encuentra en esta carpeta.

setup-rgb
ERROR



**Sensores infrarrojos **
Conseguí una variedad de sensores y emisores IR.

Este fragmento de código me permite leer los códigos específicos que emite un control, y funciona bastante bien:

#include <IRremote.h>

IRrecv receptor(3);


void setup() {
  receptor.enableIRIn();
  Serial.begin(9600);
}

void loop() {
  //IR.decode(); // retorna true si se detecta luz infraroja
  if (receptor.decode()){
    Serial.println(receptor.decodedIRData.decodedRawData, HEX);
    delay(10);
    receptor.resume();
    }
}



Acelerómetro MPU-9255
Este acelerómetro es GENIAL porque, me acabo de enterar, tiene un magnetómetro incorporado. Y busqué por todos lados magnetómetros y no conseguía. Este sensor cuenta con acelerómetro y giroscopio de 6 ejes, por lo cual puede medir la rotación en x, y, & z. El mangnetómetro permite medir la dirección del campo magnético terrestre, en un rango de ±4800uT (microteslas), tanto en dirección positiva como negativa. Esto es muy cool porque el campo magnético de la tierra, sobre su superficie, varía entre 30 y 60 uT; así que el sensor puede sensarlo con facilidad. Una posible desventaja de un rango tan alto es que hace al dispositivo muy sensible a otros imanes.

setup-rgb

Este sensor tiene un datasheet gigantesco. Como dato curioso, los ejes del magnetómetro y del acelerómetro de este sensor no están alienados entre sí:

EstimateOrientationUsingInertialSensorFusionAndMPU9250Example_02-1

Las lecturas funcionan bastante bien y responden al movimiento intuitivamente. Con este código básico se puede saber hacia dónde se está mirando:

#include <MPU9250_asukiaaa.h>
MPU9250_asukiaaa mySensor;
float mDirection;
uint16_t mX, mY, mZ;

void setup() {
  Serial.begin(115200);
  Wire.begin();
  mySensor.setWire(&Wire);
  mySensor.beginMag();
}

void loop() {
  mySensor.magUpdate();
  mX = mySensor.magX();
  mY = mySensor.magY();
  mZ = mySensor.magZ();
  mDirection = mySensor.magHorizDirection();
  Serial.println(mDirection);
}

Pero la calibración es muy necesaria. Sin calibrar, los rangos van de 170 a 160 y de -10 a -180, o otros valores así raros. Este código para calibrar funciona de maravillas y me permite tener lecturas estables en un rango de -180º a 180º. La división del círculo, en 6 rangos correspondientes a los colores del espectro (R-Y-G-C-B-M) se da de la siguiente manera:
Captura de pantalla 2023-03-26 a la(s) 12 17 16 p m

Y con el siguiente fragmento de código se definen las áreas del espectro:

  String direction;
  if (mDirection >= -180 && mDirection < -120) {
    direction = "Rojo";
  } else if (mDirection >= -120 && mDirection < -60) {
    direction = "Amarillo";
  } else if (mDirection >= -60 && mDirection < 0) {
    direction = "Verde";
  } else if (mDirection >= 0 && mDirection < 60) {
    direction = "Cian";
  } else if (mDirection >= 60 && mDirection < 120) {
    direction = "Azul";
  } else if (mDirection >= 120 && mDirection < 180) {
    direction = "Magenta";
  } 

Y adicionando la escritura al led, se logra este resultado:

See the light


Mejorando la interacción

En el código inicial no se recorre el espectro con fluidez. Simplemente se convocan 6 colores predeterminados:

  String direction;
  if (mDirection >= -180 && mDirection < -120) {
    direction = "Rojo";
    // Red
    analogWrite(redPin, 255);
    analogWrite(greenPin, 0);
    analogWrite(bluePin, 0);
    
  } else if (mDirection >= -120 && mDirection < -60) {
    direction = "Amarillo";
    // Yellow
    analogWrite(redPin, 255);
    analogWrite(greenPin, 255);
    analogWrite(bluePin, 0);

  } else if (mDirection >= -60 && mDirection < 0) {
    direction = "Verde";
    // Green
    analogWrite(redPin, 0);
    analogWrite(greenPin, 255);
    analogWrite(bluePin, 0);
  
  } else if (mDirection >= 0 && mDirection < 60) {
    direction = "Cian";
    // Cyan
    analogWrite(redPin, 0);
    analogWrite(greenPin, 255);
    analogWrite(bluePin, 255);
    
  } else if (mDirection >= 60 && mDirection < 120) {
    direction = "Azul";
    //Blue
    analogWrite(redPin, 0);
    analogWrite(greenPin, 0);
    analogWrite(bluePin, 255);
    
  } else if (mDirection >= 120 && mDirection < 180) {
    direction = "Magenta";
    // Magenta
    analogWrite(redPin, 255);
    analogWrite(greenPin, 0);
    analogWrite(bluePin, 255);
  } 

En clase trabajamos el siguiente código para hacer transiciones fluidas:

unsigned int rgbColor[3];
// set up an array with 3 unsigned integers (0..255) 
// to store the current RGB color
void loop() {
  // start the array with red
  rgbColor[0] = 255;
  rgbColor[1] = 0;
  rgbColor[2] = 0;

  // choose the colors to increment and decrement (0, 1 or 2)
  for (int decColor = 0; decColor < 3; decColor += 1) {
    int incColor;
    if (decColor == 2) { //cuando ya llego a azul
      incColor = 0; // volver a rojo
    } else {
      incColor = decColor + 1; //sino rotar entre el siguiente color
    }

    // crossfade the two colors
    for (int i = 0; i < 255; i += 1) {
      rgbColor[decColor] -= 1;
      rgbColor[incColor] += 1;
      // set the LED color with the current color
      analogWrite(redPin, rgbColor[0]);
      analogWrite(greenPin, rgbColor[1]);
      analogWrite(bluePin, rgbColor[2]);
      delay(5); //con un solo milisegundo se muere , el for lo hace tan rápido que sólo se ve blanco
    }
  }

Además me hace falta saber cómo se apaga la lámpara. Aprovechando que el dispositivo ya tiene un acelerómetro incorporado, voy a usar esas lecturas para que el dispositivo lea si está quieto y si está apuntando hacia abajo. Así, si el cono se coloca sobre una mesa, se apaga, y siempre que esté en movimiento va a poder generar luz.


Construir el dispositivo

El cono requiere de un soporte rígido para adherir los componentes a él y de una fuente de energía independiente (para no limitar el movimiento con cables).


Links útiles consultados