Skip to main content

MID Taller de Productos

0 · 0 ·
Table of Contents
Repositorio de encargos del ramo de Taller de Productos. Aquí aprendimos nuevamente a utilizar arduino y metodologías para realizar proyectos buenos, en donde siempre el enfoque fue el de presentar algo rentable u útil.

Profesores: Carolina Pino - Francisca Meza —– Ayudante: Cristóbal Ogrodnik Bert



Encargo 01 - Concepto verbo #

CONCEPTO #

Verbos
Richard Serra, verbs

El proceso de realización del encargo de crear algo en base al concepto del verbo “levantar” de Richard Serra en el Parque Quinta Normal involucró varias etapas y reflexiones creativas. A continuación, describiré el proceso detalladamente:

Observación inicial: Al llegar al Parque Quinta Normal, noté que había mucho ruido y la gente hablaba en tono elevado. Esta experiencia me llevó a seleccionar el verbo “levantar” debido a su conexión con la elevación del tono de voz y la presencia destacada del ruido en el entorno.

Reflexión y asociación de ideas: Al regresar al parque después de grabar, noté que la atmósfera había cambiado drásticamente. Ya no había mucha gente, sino numerosas parejas disfrutando del parque y compartiendo amor. Aquí surgió una conexión entre el verbo “levantar” y el concepto del amor, ya que las parejas se levantan mutuamente el ánimo en momentos difíciles y brindan apoyo fundamental.

Idea conceptual: Considerando la dependencia de la cercanía en el amor y la necesidad de comunicación a larga distancia, se me ocurrió la idea de crear un prototipo con electrónica. Este consistiría en una lámpara que, al ser tocada, encendería la luz correspondiente en la lámpara de la pareja, incluso si estuviera al otro lado del mundo. La conexión inalámbrica a través de Wi-Fi permitiría esta interacción.

Significado de los colores: Para representar diferentes emociones y estados de ánimo, decidí asignar colores a las distintas intensidades de presión sobre la lámpara. Si se presiona con fuerza, la luz sería roja, simbolizando la felicidad. Una presión moderada activaría una luz amarilla, que representaría un estado de ánimo normal. Por último, una presión suave se traduciría en una luz azul, simbolizando la tristeza, ya que en esos momentos uno a menudo carece de energía para realizar actividades.

Desarrollo técnico: Aunque inicialmente planeé utilizar la plataforma Arduino Cloud IoT para lograr la conexión inalámbrica a través de Wi-Fi, lamentablemente no pude hacerla funcionar. En su lugar, opté por desarrollar un prototipo más básico que funcionara de forma presencial y estuviera conectado a pilas doble A para encender las luces de manera sencilla.

En resumen, el proceso de creación de este encargo implicó una observación inicial, una reflexión sobre la conexión entre el verbo “levantar” y las experiencias vividas en el parque, la generación de una idea conceptual que involucrara electrónica y la asociación de colores con diferentes intensidades de presión. Aunque no se pudo realizar la conexión inalámbrica planificada debido a dificultades técnicas, el prototipo final fue diseñado para permitir que las parejas se comuniquen a través de la luz y transmitan diferentes estados de ánimo, basándose en la idea original de “levantar” el ánimo en el amor.






Encargo 02 - Drawdio #

DRAWDIO #

Drawdio
Drawdio, Jay Silver, MIT Media Lab

El Drawdio es un pseudo instrumento musical diseñado originalmente por Jay Silver en el MIT Media Lab. Utiliza un circuito integrado 555 Timer IC y componentes adicionales para generar sonidos a través de un lápiz conductor y una superficie conductora, como papel. Los componentes y materiales utilizados fueron:

Circuito

  • Electrónica
    • 1 x 555 Timer IC (circuito integrado)
    • 1 x PNP Transistor
    • 1 x Resistor de 270 KΩ
    • 1 x Resistor de 10 KΩ
    • 1 x Resistor de 10 MΩ
    • 1 x Resistor de 10 Ω
    • 1 x Condensador 0.1 μF
    • 1 x Condensador 100μF
    • 1x Condensador cerámico 570 pF
    • 1 x Parlante pequeño de 8 ohms
    • 2 x Pilas AAA

El proceso fue un tanto tedioso ya que el diagrama que pasaron estaba malo, pero fue solucionado con otro encontrado en internet (créditos al Juan-k) y funcionó de maravilla.

#

Posterior a eso, se le dio vuelta al concepto del Drawdio y del verbo “almacenar” y se creó una especie de caja de seguridad, en donde al intentarla abrir suena.






Encargo 03 - Drawdio 2 remix #

DRAWDIO 2 - EL REMIX #

El encargo consistió en la combinación de dos elementos: el Drawdio y el Arduino. El Drawdio es un pseudo instrumento musical diseñado originalmente por Jay Silver en el MIT Media Lab, mientras que Arduino es una plataforma de prototipado electrónico de código abierto.

El Drawdio utiliza un circuito integrado 555 Timer IC y componentes adicionales para generar sonidos a través de un lápiz conductor y una superficie conductora, como papel. El Arduino, por otro lado, es una placa programable que permite controlar dispositivos electrónicos.

En este proyecto, se decidió integrar el Drawdio con el Arduino para realizar modificaciones en el sonido generado por el Drawdio. Para lograr esto, se utilizó un potenciómetro conectado al Arduino para controlar el volumen del sonido. Además, se añadió una funcionalidad adicional de controlar un LED RGB en base al valor del potenciómetro.

#

El código modificado permitió ajustar el color del LED RGB en función del valor del potenciómetro. Cuando el valor del potenciómetro era bajo, el LED mostraba un color azul intenso. A medida que el valor del potenciómetro aumentaba, el LED cambiaba a verde y, finalmente, a rojo cuando el valor del potenciómetro era máximo.

Además, se modificó el sonido generado por el Drawdio utilizando el Arduino. En lugar de utilizar el circuito del 555 Timer IC, se generó el tono directamente desde el Arduino, controlando la frecuencia del tono en base al valor del potenciómetro. De esta manera, el sonido del Drawdio se modificaba de forma progresiva, siendo más suave cuando el valor del potenciómetro era bajo y más fuerte a medida que el valor del potenciómetro aumentaba.

#

En resumen, el proyecto logró integrar el Drawdio y el Arduino, permitiendo controlar el color del LED RGB y modificar el sonido del Drawdio en base al valor del potenciómetro. Esto proporcionó una experiencia interactiva y personalizable para explorar la música generada por el Drawdio. Abajo se encuentra la descarga del código Arduino utilizado.

    
      
const int RED_PIN = 9;
const int GREEN_PIN = 10;
const int BLUE_PIN = 11;
const int POT_PIN = A0; // Pin del potenciómetro
const int SPEAKER_PIN = 3; // Pin de salida del parlante

const int DISPLAY_TIME = 200;  // used in mainColors() to determine the 
// length of time each color is displayed.

void setup() {
  pinMode(RED_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(BLUE_PIN, OUTPUT);
  pinMode(SPEAKER_PIN, OUTPUT);

  Serial.begin(9600);
}

void loop() {
  int potValue = analogRead(POT_PIN);

  // Controlar el color del LED RGB
  if (potValue < 341) {
    analogWrite(RED_PIN, 0);
    analogWrite(GREEN_PIN, 0);
    analogWrite(BLUE_PIN, 255);
  } else if ((potValue > 342) and (potValue < 682)) {
    analogWrite(RED_PIN, 0);
    analogWrite(GREEN_PIN, 255);
    analogWrite(BLUE_PIN, 0);
  } else if (potValue > 682) {
    analogWrite(RED_PIN, 255);
    analogWrite(GREEN_PIN, 0);
    analogWrite(BLUE_PIN, 0);
  }

  // Controlar el sonido del Drawdio modificando la frecuencia del tono
  int frequency = map(potValue, 0, 1023, 100, 10000);
  tone(SPEAKER_PIN, frequency);

  Serial.println(potValue);

  delay(10);
}


    
  
Descargar






Encargo 04 - Sensor de color #

Cubo infinito de leds vibrador #

Verbos
Cubo infinito de leds vibrador

Este encargo comenzó con la realización de 3 tareas del libro de ejercicios de electrónica.

#

Verbos
Mapa risomático

Luego se formaron parejas y fui con Catalina Plencovich, en donde se nos asignó el sensor de color. Decidimos realizar un cubo de leds infinito con espejos y un parlante hackeado que, al vibrar, generase patrones en base al color dado. Aunque no se pudo lograr eso último, uno puede tocar el vibrador y así sentir el color que se está viendo.

Se tuvo la intención de hacer patrones con la vibración, es decir, que cada color tuviese su patrón asociado. No se consiguió.

-

Este fue el resultado final de la parte 1, ya que de momento queda que forme los patrones.

    
      

// Definición de los pines
const int pinR = 9;
const int pinB = 10;
const int pinG = 11;

const int s0 = 4;
const int s1 = 5;
const int s2 = 6;
const int s3 = 7;
const int out = 8;

const int speakerPin = 3;  // Pin digital utilizado para el parlante
int frequency = 0;  // Variable para almacenar la frecuencia actual

void setup()
{
  Serial.begin(9600);
  pinMode(s0, OUTPUT);
  pinMode(s1, OUTPUT);
  pinMode(s2, OUTPUT);
  pinMode(s3, OUTPUT);
  pinMode(out, INPUT);

    // Configuración de los pines como salidas
  pinMode(pinR, OUTPUT);
  pinMode(pinB, OUTPUT);
  pinMode(pinG, OUTPUT);

  digitalWrite(s0, HIGH);
  digitalWrite(s1, HIGH);

   pinMode(speakerPin, OUTPUT);
}

void loop()
{
  int R = getRojo();
  delay(200);
  int V = getVerde();
  delay(200);
  int A = getAzul();
  delay(200);

  Serial.print("Int R " + String(R));
  Serial.print("  --   Int V " + String(V));
  Serial.println("  --   Int A " + String(A));

  if (R > V && V > A && R >20 && V > 8) {
    Serial.print(" EL COLOR ES CELESTE");
      // Encender el color azul
  digitalWrite(pinR, HIGH);
  digitalWrite(pinB, LOW);
  digitalWrite(pinG, HIGH);
  frequency = 10;  // Actualizar la frecuencia solo si es diferente de cero
      tone(speakerPin, frequency);  // Generar el tono en el parlante con la nueva frecuencia ingresada
  }
  if (R > V && V < A && R > 13 && V <= 16) {
    Serial.print(" EL COLOR ES VERDE CLARO");
       // Encender el color rojo
  digitalWrite(pinR, HIGH);
  digitalWrite(pinB, HIGH);
  digitalWrite(pinG, LOW);
   frequency = 50;  // Actualizar la frecuencia solo si es diferente de cero
      tone(speakerPin, frequency);  // Generar el tono en el parlante con la nueva frecuencia ingresada
     
  }
  else if (R < V && V > A && R >= 5 && V <= 11) {
    Serial.print(" EL COLOR ES ROSADO");
  }
  if (R < V && V > A && R > 7 && V <= 29) {
    Serial.print(" EL COLOR ES ROJO");
     // Encender el color verde
  digitalWrite(pinR, LOW);
  digitalWrite(pinB, HIGH);
  digitalWrite(pinG, HIGH);
   frequency = 90;  // Actualizar la frecuencia solo si es diferente de cero
      tone(speakerPin, frequency);  // Generar el tono en el parlante con la nueva frecuencia ingresada
 
  }
  else
  {
    Serial.print(" EL COLOR NO HA SIDO REGISTRADO");
  }
  Serial.print(" ");

 
}

int getRojo()
{
  //leer color rojo
  digitalWrite(s2, LOW);
  digitalWrite(s3, LOW);
  int ROJO = pulseIn(out, LOW);
  return ROJO;
}

int getAzul()
{
  //leer color azul
  digitalWrite(s2, LOW);
  digitalWrite(s3, HIGH);
  int AZUL = pulseIn(out, LOW);
  return AZUL;
}

int getVerde()
{
  //leer color verde
  digitalWrite(s2, HIGH);
  digitalWrite(s3, HIGH);
  int VERDE = pulseIn(out, LOW);
  return VERDE;
}


    
  
Descargar






Encargo 05 - Reloj de arena digital #

Reloj del tiempo #

Portada
Relojes del tiempo

En este nuevo proyecto, tuve nuevamente el placer de trabajar junto a Catalina Plencovich, formando un gran equipo. Se nos encomendó la tarea de crear un reloj de arena digital que simulara el movimiento y caída de la arena utilizando LEDs. Decidimos ser creativos y, además de cumplir con el encargo, creamos una interesante combinación de relojes de arena: uno digital, uno de arena real y otro con agua.

Aunque el proyecto no estuvo exento de desafíos, supimos enfrentar y superar diversas problemáticas para llevarlo a buen puerto. Entre las más destacadas, encontramos la típica situación de que el Arduino no funcionara a pesar de tener todo correctamente conectado, la presencia de una pequeña roca en el reloj de arena real y la formación de burbujas en el reloj de agua.

Los elementos electrónicos fundamentales fueron:

  • Arduino Uno
  • Giroscopio Mpu6050
  • 2 matrices leds 8x8

Para lograr la funcionalidad deseada, utilizamos varias bibliotecas en nuestro código. Una de ellas fue para el manejo del acelerómetro, permitiendo determinar la orientación del triángulo en el reloj de arena. Además, empleamos una librería llamada “LedControl” para controlar la matriz de LEDs, permitiéndonos implementar efectos visuales con el encendido y apagado de cada led por separado y crear una visualización por multiplexación, creando así la ilusión de movimiento y dinamismo.

Para ejecutar este código, se necesitan las bibliotecas “MPU6050_tockn.h” y “LedControl.h” instaladas.

    
      


// Fotorresistencia
const int fotorresistenciaPin = 0; // Usamos '0' para representar el pin analógico A0

int valorMapeado = 1;

#include "Arduino.h"
#include 
#include "LedControl.h"
#include "Delay.h"

#define  MATRIX_A  1
#define MATRIX_B  0

MPU6050 mpu6050(Wire);

// valores entregados: 260/330/400
#define ACC_THRESHOLD_LOW -25
#define ACC_THRESHOLD_HIGH 25

// Matriz
#define PIN_DATAIN 11   // DIN
#define PIN_CLK 13      // CLK
#define PIN_LOAD 10     // CS

// Acelerómetro
#define PIN_X  mpu6050.getAngleX()
#define PIN_Y  mpu6050.getAngleY()

// Rotary Encoder
#define PIN_ENC_1 3
#define PIN_ENC_2 2
#define PIN_ENC_BUTTON 7

#define PIN_BUZZER 14

// This takes into account how the matrixes are mounted
#define ROTATION_OFFSET 90

// in milliseconds
#define DEBOUNCE_THRESHOLD 500

#define DELAY_FRAME 50   //Velocidad de caída

#define DEBUG_OUTPUT 1

#define MODE_HOURGLASS 0
#define MODE_SETMINUTES 1
#define MODE_SETHOURS 2

byte delayHours = 0;
byte delayMinutes = 1;
int mode = MODE_HOURGLASS;
int gravity;
LedControl lc = LedControl(PIN_DATAIN, PIN_CLK, PIN_LOAD, valorMapeado);
NonBlockDelay d;
int resetCounter = 0;
bool alarmWentOff = false;


/**
 * Get delay between particle drops (in seconds)
 */
long getDelayDrop() {
  // since we have exactly 60 particles we don't have to multiply by 60 and then divide by the number of particles again :)
  return delayMinutes + delayHours * 60;
}


#if DEBUG_OUTPUT
void printmatrix() {
  Serial.println(" 0123-4567 ");
  for (int y = 0; y<8; y++) {
    if (y == 4) {
      Serial.println("|----|----|");
    }
    Serial.print(y);
    for (int x = 0; x<8; x++) {
      if (x == 4) {
        Serial.print("|");
      }
      Serial.print(lc.getXY(0,x,y) ? "X" :" ");
    }
    Serial.println("|");
  }
  Serial.println("-----------");
}
#endif



coord getDown(int x, int y) {
  coord xy;
  xy.x = x-1;
  xy.y = y+1;
  return xy;
}
coord getLeft(int x, int y) {
  coord xy;
  xy.x = x-1;
  xy.y = y;
  return xy;
}
coord getRight(int x, int y) {
  coord xy;
  xy.x = x;
  xy.y = y+1;
  return xy;
}



bool canGoLeft(int addr, int x, int y) {
  if (x == 0) return false; // not available
  return !lc.getXY(addr, getLeft(x, y)); // you can go there if this is empty
}
bool canGoRight(int addr, int x, int y) {
  if (y == 7) return false; // not available
  return !lc.getXY(addr, getRight(x, y)); // you can go there if this is empty
}
bool canGoDown(int addr, int x, int y) {
  if (y == 7) return false; // not available
  if (x == 0) return false; // not available
  if (!canGoLeft(addr, x, y)) return false;
  if (!canGoRight(addr, x, y)) return false;
  return !lc.getXY(addr, getDown(x, y)); // you can go there if this is empty
}



void goDown(int addr, int x, int y) {
  lc.setXY(addr, x, y, false);
  lc.setXY(addr, getDown(x,y), true);
}
void goLeft(int addr, int x, int y) {
  lc.setXY(addr, x, y, false);
  lc.setXY(addr, getLeft(x,y), true);
}
void goRight(int addr, int x, int y) {
  lc.setXY(addr, x, y, false);
  lc.setXY(addr, getRight(x,y), true);
}


int countParticles(int addr) {
  int c = 0;
  for (byte y=0; y<8; y++) {
    for (byte x=0; x<8; x++) {
      if (lc.getXY(addr, x, y)) {
        c++;
      }
    }
  }
  return c;
}


bool moveParticle(int addr, int x, int y) {
  if (!lc.getXY(addr,x,y)) {
    return false;
  }

  bool can_GoLeft = canGoLeft(addr, x, y);
  bool can_GoRight = canGoRight(addr, x, y);

  if (!can_GoLeft && !can_GoRight) {
    return false; // we're stuck
  }

  bool can_GoDown = canGoDown(addr, x, y);

  if (can_GoDown) {
    goDown(addr, x, y);
  } else if (can_GoLeft&& !can_GoRight) {
    goLeft(addr, x, y);
  } else if (can_GoRight && !can_GoLeft) {
    goRight(addr, x, y);
  } else if (random(2) == 1) { // we can go left and right, but not down
    goLeft(addr, x, y);
  } else {
    goRight(addr, x, y);
  }
  return true;
}



void fill(int addr, int maxcount) {
  int n = 8;
  byte x,y;
  int count = 0;
  for (byte slice = 0; slice < 2*n-1; ++slice) {
    byte z = slice ACC_THRESHOLD_HIGH) { return 0;  }
  if (y > ACC_THRESHOLD_HIGH) { return 270; }
  if (x < ACC_THRESHOLD_LOW)  { return 180; }
}


int getTopMatrix() {
  return (getGravity() == 90) ? MATRIX_A : MATRIX_B;
}
int getBottomMatrix() {
  return (getGravity() != 90) ? MATRIX_A : MATRIX_B;
}



void resetTime() {
  for (byte i=0; i<2; i++) {
    lc.clearDisplay(i);
  }
  fill(getTopMatrix(), 60);
  d.Delay(getDelayDrop() * 1000);
}



/**
 * Traverse matrix and check if particles need to be moved
 */
bool updateMatrix() {
  int n = 8;
  bool somethingMoved = false;
  byte x,y;
  bool direction;
  for (byte slice = 0; slice < 2*n-1; ++slice) {
    direction = (random(2) == 1); // randomize if we scan from left to right or from right to left, so the grain doesn't always fall the same direction
    byte z = slice ACC_THRESHOLD_HIGH || z < ACC_THRESHOLD_LOW) {
    resetCounter++;
    Serial.println(resetCounter);
  } else {
    resetCounter = 0;
  }
  if (resetCounter > 20) {
    Serial.println("RESET!");
    resetTime();
    resetCounter = 0;
  }
}



void displayLetter(char letter, int matrix) {
  // Serial.print("Letter: ");
  // Serial.println(letter);
  lc.clearDisplay(matrix);
  lc.setXY(matrix, 1,4, true);
  lc.setXY(matrix, 2,3, true);
  lc.setXY(matrix, 3,2, true);
  lc.setXY(matrix, 4,1, true);

  lc.setXY(matrix, 3,6, true);
  lc.setXY(matrix, 4,5, true);
  lc.setXY(matrix, 5,4, true);
  lc.setXY(matrix, 6,3, true);

  if (letter == 'M') {
    lc.setXY(matrix, 4,2, true);
    lc.setXY(matrix, 4,3, true);
    lc.setXY(matrix, 5,3, true);
  }
  if (letter == 'H') {
    lc.setXY(matrix, 3,3, true);
    lc.setXY(matrix, 4,4, true);
  }
}



void renderSetMinutes() {
  fill(getTopMatrix(), delayMinutes);
  displayLetter('M', getBottomMatrix());
}
void renderSetHours() {
  fill(getTopMatrix(), delayHours);
  displayLetter('H', getBottomMatrix());
}




void knobClockwise() {
  Serial.println("Clockwise");
  if (mode == MODE_SETHOURS) {
    delayHours = constrain(delayHours+1, 0, 64);
    renderSetHours();
  } else if(mode == MODE_SETMINUTES) {
    delayMinutes = constrain(delayMinutes+1, 0, 64);
    renderSetMinutes();
  }
  Serial.print("Delay: ");
  Serial.println(getDelayDrop());
}
void knobCounterClockwise() {
  Serial.println("Counterclockwise");
  if (mode == MODE_SETHOURS) {
    delayHours = constrain(delayHours-1, 0, 64);
    renderSetHours();
  } else if (mode == MODE_SETMINUTES) {
    delayMinutes = constrain(delayMinutes-1, 0, 64);
    renderSetMinutes();
  }
  Serial.print("Delay: ");
  Serial.println(getDelayDrop());
}



volatile int lastEncoded = 0;
volatile long encoderValue = 0;
long lastencoderValue = 0;
long lastValue = 0;
void updateEncoder() {
  int MSB = digitalRead(PIN_ENC_1); //MSB = most significant bit
  int LSB = digitalRead(PIN_ENC_2); //LSB = least significant bit

  int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value

  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue--;
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue++;

  // Serial.print("Value: ");
  // Serial.println(encoderValue);
  if ((encoderValue % 4) == 0) {
    int value = encoderValue / 4;
    if (value > lastValue) knobClockwise();
    if (value < lastValue) knobCounterClockwise();
    lastValue = value;
  }
  lastEncoded = encoded; //store this value for next time
}



/**
 * Button callback (incl. software debouncer)
 * This switches between the modes (normal, set minutes, set hours)
 */
volatile unsigned long lastButtonPushMillis;
void buttonPush() {
  if((long)(millis() - lastButtonPushMillis) >= DEBOUNCE_THRESHOLD) {
    mode = (mode+1) % 3;
    Serial.print("Switched mode to: ");
    Serial.println(mode);
    lastButtonPushMillis = millis();

    if (mode == MODE_SETMINUTES) {
      lc.backup(); // we only need to back when switching from MODE_HOURGLASS->MODE_SETMINUTES
      renderSetMinutes();
    }
    if (mode == MODE_SETHOURS) {
      renderSetHours();
    }
    if (mode == MODE_HOURGLASS) {
      lc.clearDisplay(0);
      lc.clearDisplay(1);
      lc.restore();
      resetTime();
    }
  }
}



/**
 * Setup
 */
void setup() {

Serial.begin(9600);


mpu6050.calcGyroOffsets(true);
 // Serial.begin(9600);
mpu6050.begin();
  
  // while (!Serial) {
  //   ; // wait for serial port to connect. Needed for native USB
  // }

  // setup rotary encoder
  pinMode(PIN_ENC_1, INPUT);
  pinMode(PIN_ENC_2, INPUT);
  pinMode(PIN_ENC_BUTTON, INPUT);
  digitalWrite(PIN_ENC_1, HIGH); //turn pullup resistor on
  digitalWrite(PIN_ENC_2, HIGH); //turn pullup resistor on
  digitalWrite(PIN_ENC_BUTTON, HIGH); //turn pullup resistor on
  attachInterrupt(digitalPinToInterrupt(PIN_ENC_1), updateEncoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(PIN_ENC_2), updateEncoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(PIN_ENC_BUTTON), buttonPush, RISING);

  // Serial.println(digitalPinToInterrupt(PIN_ENC_1));
  // Serial.println(digitalPinToInterrupt(PIN_ENC_2));
  // Serial.println(digitalPinToInterrupt(PIN_ENC_BUTTON));

  randomSeed(analogRead(A0));

  // init displays
  for (byte i=0; i<2; i++) {
    lc.shutdown(i,false);
    lc.setIntensity(i,0);
  }

  resetTime();
}



/**
 * Main loop
 */
void loop() {

int valorFotorresistencia = analogRead(fotorresistenciaPin);

  // Mapear el valor de la fotorresistencia al rango 1-13
  int valorMapeado = map(valorFotorresistencia, 0, 1023, 13, 1);



  mpu6050.update();
  Serial.println("angleX : ");
  Serial.println(mpu6050.getAngleX());
  Serial.println("\tangleY : ");
  Serial.println(mpu6050.getAngleY());
 
  delay(DELAY_FRAME);
  

  // update the driver's rotation setting. For the rest of the code we pretend "down" is still 0,0 and "up" is 7,7
  gravity = getGravity();
  lc.setRotation((ROTATION_OFFSET + gravity) % 360);

  // handle special modes
  if (mode == MODE_SETMINUTES) {
    renderSetMinutes(); return;
  } else if (mode == MODE_SETHOURS) {
    renderSetHours(); return;
  }

  // resetCheck(); // reset now happens when pushing a button
  bool moved = updateMatrix();
  bool dropped = dropParticle();

  // alarm when everything is in the bottom part
  if (!moved && !dropped && !alarmWentOff && (countParticles(getTopMatrix()) == 0)) {
    alarmWentOff = true;
    alarm();
  }
  // reset alarm flag next time a particle was dropped
  if (dropped) {
    alarmWentOff = false;
  }
}



    
  
Descargar






Encargo 06 - MidTerm #

ADVOLUTION: Espejo emocional viajero #

El presente exámen de Diseño describe un prototipo de interacción emocional que combina tecnologías de reconocimiento facial en tiempo real con Arduino y Python para crear una experiencia única y personalizada.

Portada
Equipo Advolution en prototipo

AdVolution (MIDTERM T.Producto)

El objetivo principal del prototipo es generar emociones específicas a partir del reconocimiento facial y proporcionar una respuesta visual a través de luces LED y una matriz de LEDs 8x8 que simula un reloj de arena digital. La idea es implementar esta interacción emocional en espacios relacionados con viajes o agencias de viajes, donde dependiendo de la emoción del usuario, se le ofrecerá un destino con una oferta de tiempo limitado.

Componentes:

  • Dispositivo de Captura de Imágenes: Se utiliza una cámara web conectada a una computadora para capturar imágenes faciales en tiempo real. Se emplea la biblioteca mediapipe de Python para la detección y seguimiento facial.

  • Procesamiento de Imágenes y Reconocimiento Emocional: La librería DeepFace de Python se utiliza para analizar las imágenes capturadas y extraer la emoción dominante del usuario en tiempo real.

  • Interacción con Arduino: Se establece una conexión serial entre la computadora y un Arduino, el cual controla un LED RGB y una matriz de LEDs 8x8.

  • Respuesta Visual del Prototipo:

    • LED RGB: El LED RGB cambia de color según la emoción detectada: azul para tristeza, rojo para enojo, verde para felicidad y morado para sorpresa.

    • Matriz de LEDs 8x8: Representa un reloj de arena digital, donde la parte superior se llena de forma aleatoria cuando se detecta una emoción, y luego “cae” hacia la parte inferior.

  • Interfaz de Usuario: En el futuro, se puede implementar una interfaz de usuario en una pantalla LED o una pantalla para proporcionar información adicional sobre el destino sugerido basado en la emoción del usuario.

Funcionamiento del Prototipo:

  1. El prototipo comienza capturando imágenes faciales en tiempo real mediante la cámara web.

  2. La biblioteca mediapipe procesa las imágenes y detecta la cara del usuario, mientras la librería DeepFace analiza la imagen y extrae la emoción dominante del usuario.

  3. El resultado de la emoción se utiliza para cambiar el color del LED RGB y activar la matriz de LEDs 8x8.

  4. El LED RGB se ilumina con el color correspondiente a la emoción detectada. La matriz de LEDs 8x8 se llena de forma aleatoria en la parte superior, simulando un reloj de arena.

  5. Luego, los LEDs de la matriz “caen” hacia la parte inferior, creando un efecto visual interesante.

  6. Si el usuario muestra otra emoción, el proceso se repite y el prototipo responde en consecuencia.

  7. El prototipo puede ofrecer un destino basado en la emoción detectada, lo que crea una experiencia interactiva y personalizada para el usuario.

Proyecciones futuras

El prototipo se puede implementar en espacios relacionados con viajes o agencias de viajes, como aeropuertos, estaciones de tren o agencias de turismo. La interacción emocional permitirá ofrecer destinos turísticos adecuados para el estado de ánimo del usuario, lo que crea una experiencia única y atractiva. Además, el uso de pantallas LED o pantallas como interfaz de usuario proporcionará información detallada sobre el destino sugerido y ofertas especiales de tiempo limitado, lo que aumentará el atractivo del prototipo para los usuarios.

#

En conclusión, prototipo de interacción emocional con destino aleatorio representa una experiencia innovadora y única para los usuarios en espacios relacionados con viajes. La combinación de tecnologías de reconocimiento facial en tiempo real con Arduino y Python permite una respuesta visual dinámica y personalizada, lo que mejora la interacción del usuario y crea un ambiente emocionante. La implementación futura del prototipo en espacios turísticos y agencias de viajes tiene el potencial de atraer y cautivar a los usuarios, al tiempo que ofrece destinos sugeridos y ofertas especiales en función de sus emociones.

Código Python:

    
      


# Importamos las librerias
from deepface import DeepFace
import cv2
import mediapipe as mp

import serial
import time

# Declaramos la deteccion de rostros
detros = mp.solutions.face_detection
rostros = detros.FaceDetection(min_detection_confidence= 0.8, model_selection=0)
# Dibujo
dibujorostro = mp.solutions.drawing_utils

# Realizamos VideoCaptura
cap = cv2.VideoCapture(1)

espera = 0.03

# Arduino
def enviar_numero_a_arduino(numero):
    arduino.write(str(numero).encode())
    #print(f"Enviando número: {numero}")
    time.sleep(2)

arduino = serial.Serial("COM5", 9600)
time.sleep(2)



# Empezamos
while True:
    # Leemos los fotogramas
    ret, frame = cap.read()
    # Leemos imagen
    #img =cv2.imread("img.png")
    #img = cv2.resize(img, (0, 0), None, 0.18, 0.18)
    #ani, ali, c = img.shape

    # Correccion de color
    rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)


    # Procesamos
    resrostros = rostros.process(rgb)

    # Deteccion
    if resrostros.detections is not None:
        # Registramos
        for rostro in resrostros.detections:
            # Extraemos informacion de ubicacion
            al, an, c = frame.shape
            box = rostro.location_data.relative_bounding_box
            xi, yi, w, h = int(box.xmin * an), int(box.ymin * al), int(box.width * an), int(box.height * al)
            xf, yf = xi + w, yi + h

            # Dibujamos
            cv2.rectangle(frame, (xi, yi), (xf, yf), (255, 255, 0), 1)
            #frame[10:ani + 10, 10:ali+10] = img

            # Informacion
            #info = DeepFace.analyze(rgb, actions=['age', 'gender', 'race', 'emotion'], enforce_detection= False)
            info = DeepFace.analyze(rgb, actions=['emotion'], enforce_detection= False)

            # Edad
            #edad = info['age']

            # Emociones
            emociones = info['dominant_emotion']

            # Race
            #race = info['dominant_race']

            # Genero
            #gen = info['gender']
            #print(str(gen) + " de " + str(edad) + " años de edad, con estado de animo " + str(emociones) + " de etnia " + str(race))

            # Traducimos
  
                # Emociones
            if emociones == 'angry':
                numero = 1
                time.sleep(espera)
            if emociones == 'disgust':
                numero = 1
                time.sleep(espera)
            if emociones == 'fear':
                numero = 3
                time.sleep(espera)
            if emociones == 'happy':
                numero = 2
                time.sleep(espera)
            if emociones == 'sad':
                numero = 3
                time.sleep(espera)
            if emociones == 'surprise':
                numero = 5
                time.sleep(espera)
            if emociones == 'neutral':
                numero = 1
                time.sleep(espera)
                    
            enviar_numero_a_arduino(numero)

            # Mostramos info
            #cv2.putText(frame, str(gen), (65, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)
            #cv2.putText(frame, str(edad), (75, 90), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)
            #cv2.putText(frame, str(emociones), (75, 135), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)
            #cv2.putText(frame, str(race), (75, 180), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)

    # Mostramos los fotogramas
    #cv2.imshow(" Deteccion de Edad ", frame)

    # Leemos el teclado
    t = cv2.waitKey(5)
    if t == 27:
        break

cv2.destroyAllWindows()
cap.release()



    
  
Descargar

Código Arduino: #
    
      

#include "Arduino.h"
#include "LedControl.h"
#include "Delay.h"


///////////////////////////////////////////////                       MATRICES                       /////////////////////////////////////////////// 

#define  MATRIX_A  1
#define  MATRIX_B  0

// Values are 260/330/400
#define ACC_THRESHOLD_LOW 300
#define ACC_THRESHOLD_HIGH 360

// Matrix
#define PIN_DATAIN 5   // DIN
#define PIN_CLK 4      // CLK
#define PIN_LOAD 6     // CS

// Esto tiene en cuenta cómo se montan las matrices.
#define ROTATION_OFFSET 90

// in milliseconds
#define DEBOUNCE_THRESHOLD 500

#define DELAY_FRAME 100        //Velocidad de caida de particulas, original 100. A mayor numero, más lento.

#define DEBUG_OUTPUT 1

#define MODE_HOURGLASS 0
#define MODE_SETMINUTES 1
#define MODE_SETHOURS 2

byte delayHours = 0;
byte delayMinutes = 1;
int mode = MODE_HOURGLASS;
int gravity;
LedControl lc = LedControl(PIN_DATAIN, PIN_CLK, PIN_LOAD, 8);
NonBlockDelay d;
int resetCounter = 0;
bool alarmWentOff = false;


///////////////////////////////////////////////                       LED RGB                       /////////////////////////////////////////////// 

int LEDROJO = 9;		// pin 9 a anodo LED rojo
int LEDVERDE = 10;		// pin 10 a anodo LED verde
int LEDAZUL = 11;		// pin 11 a anodo LED azul

int numero = 8;

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////                     CÓDIGO                       /////////////////////////////////////////////// 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


/**
 * Obtener retraso entre caídas de partículas (en segundos)
 */
long getDelayDrop() {
  // como tenemos exactamente 60 partículas, no tenemos que multiplicar por 60 y luego dividir por el número de partículas nuevamente
  return delayMinutes + delayHours * 60;
}


#if DEBUG_OUTPUT
void printmatrix() {
  Serial.println(" 0123-4567 ");
  for (int y = 0; y<8; y++) {
    if (y == 4) {
      Serial.println("|----|----|");
    }
    Serial.print(y);
    for (int x = 0; x<8; x++) {
      if (x == 4) {
        Serial.print("|");
      }
      Serial.print(lc.getXY(0,x,y) ? "X" :" ");
    }
    Serial.println("|");
  }
  Serial.println("-----------");
}
#endif



coord getDown(int x, int y) {
  coord xy;
  xy.x = x-1;
  xy.y = y+1;
  return xy;
}
coord getLeft(int x, int y) {
  coord xy;
  xy.x = x-1;
  xy.y = y;
  return xy;
}
coord getRight(int x, int y) {
  coord xy;
  xy.x = x;
  xy.y = y+1;
  return xy;
}


bool canGoLeft(int addr, int x, int y) {
  if (x == 0) return false; // not available
  return !lc.getXY(addr, getLeft(x, y));              // you can go there if this is empty
}
bool canGoRight(int addr, int x, int y) {
  if (y == 7) return false; // not available
  return !lc.getXY(addr, getRight(x, y));             // you can go there if this is empty
}
bool canGoDown(int addr, int x, int y) {
  if (y == 7) return false; // not available
  if (x == 0) return false; // not available
  if (!canGoLeft(addr, x, y)) return false;
  if (!canGoRight(addr, x, y)) return false;
  return !lc.getXY(addr, getDown(x, y));              // you can go there if this is empty
}



void goDown(int addr, int x, int y) {
  lc.setXY(addr, x, y, false);
  lc.setXY(addr, getDown(x,y), true);
}
void goLeft(int addr, int x, int y) {
  lc.setXY(addr, x, y, false);
  lc.setXY(addr, getLeft(x,y), true);
}
void goRight(int addr, int x, int y) {
  lc.setXY(addr, x, y, false);
  lc.setXY(addr, getRight(x,y), true);
}


int countParticles(int addr) {
  int c = 0;
  for (byte y=0; y<8; y++) {
    for (byte x=0; x<8; x++) {
      if (lc.getXY(addr, x, y)) {
        c++;
      }
    }
  }
  return c;
}


bool moveParticle(int addr, int x, int y) {
  if (!lc.getXY(addr,x,y)) {
    return false;
  }

  bool can_GoLeft = canGoLeft(addr, x, y);
  bool can_GoRight = canGoRight(addr, x, y);

  if (!can_GoLeft && !can_GoRight) {
    return false; // we're stuck
  }

  bool can_GoDown = canGoDown(addr, x, y);

  if (can_GoDown) {
    goDown(addr, x, y);
  } else if (can_GoLeft&& !can_GoRight) {
    goLeft(addr, x, y);
  } else if (can_GoRight && !can_GoLeft) {
    goRight(addr, x, y);
  } else if (random(2) == 1) {                  // Podemos ir a izquierda y derecha, pero no abajo
    goLeft(addr, x, y);
  } else {
    goRight(addr, x, y);
  }
  return true;
}


void fill(int addr, int maxcount, bool fromTop = false) {
  int n = 8;
  byte x, y;
  int count = 0;
  for (byte slice = 0; slice < 2 * n - 1; ++slice) {
    byte z = slice < n ? 0 : slice - n + 1;
    for (byte j = z; j <= slice - z; ++j) {
      y = fromTop ? j : 7 - j;
      x = slice - j;
      lc.setXY(addr, x, y, (++count <= maxcount));
    }
  }
}




/**
 * Detectar la orientación usando el acelerómetro
 *
 *     | up | right | left | down |
 * --------------------------------
 * 400 |    |       | y    | x    |
 * 330 | y  | x     | x    | y    |
 * 260 | x  | y     |      |      |
 */
int getGravity() {
/*  
  int x = analogRead(PIN_X);
  int y = analogRead(PIN_Y);
  if (y < ACC_THRESHOLD_LOW)  { return 0;   }
  if (x > ACC_THRESHOLD_HIGH) { return 90;  }
  if (y > ACC_THRESHOLD_HIGH) { return 180; }
  if (x < ACC_THRESHOLD_LOW)  { return 270; }
*/  
  int x = 180;       // Agregado
  int y = 180;       // Agregado
  return x;          // Agregado
  return y;          // Agregado
}


int getTopMatrix() {
  return (getGravity() == 90) ? MATRIX_A : MATRIX_B;
}
int getBottomMatrix() {
  return (getGravity() != 90) ? MATRIX_A : MATRIX_B;
}


//                                                                                                            // Para ver cuantos granos iniciales de arriba parten                                   **********************

/*
//int totalParticles = random(65);  // Generar un número aleatorio entre 0 y 64
  int totalParticles = 4;

*/


void resetTime() {
  for (byte i = 0; i < 2; i++) {
    lc.clearDisplay(i);
  }

  //int totalParticles = random(62);  // Generar un número aleatorio entre 0 y 64
  int totalParticles = 4;

  int particlesMatrixA = totalParticles;
  int particlesMatrixB = 64 - totalParticles;

  // Llenar ambas matrices desde la parte superior
  fill(getTopMatrix(), particlesMatrixA, true);
  fill(getBottomMatrix(), particlesMatrixB, true);

  d.Delay(getDelayDrop() * 1000);
}






/**
 * Atraviese la matriz y compruebe si es necesario mover las partículas
 */
bool updateMatrix() {
  int n = 8;
  bool somethingMoved = false;
  byte x,y;
  bool direction;
  for (byte slice = 0; slice < 2*n-1; ++slice) {
    direction = (random(2) == 1); // RANDOM de izq o der de granito al no haber centro
    byte z = slice ACC_THRESHOLD_HIGH || z < ACC_THRESHOLD_LOW) {
    resetCounter++;
    Serial.println(resetCounter);
  } else {
    resetCounter = 0;
  }
  if (resetCounter > 20) {
    Serial.println("RESET!");
    resetTime();
    resetCounter = 0;
  }
}

void displayLetter(char letter, int matrix) {
  // Serial.print("Letter: ");
  // Serial.println(letter);
  lc.clearDisplay(matrix);
  lc.setXY(matrix, 1,4, true);
  lc.setXY(matrix, 2,3, true);
  lc.setXY(matrix, 3,2, true);
  lc.setXY(matrix, 4,1, true);

  lc.setXY(matrix, 3,6, true);
  lc.setXY(matrix, 4,5, true);
  lc.setXY(matrix, 5,4, true);
  lc.setXY(matrix, 6,3, true);

  if (letter == 'M') {
    lc.setXY(matrix, 4,2, true);
    lc.setXY(matrix, 4,3, true);
    lc.setXY(matrix, 5,3, true);
  }
  if (letter == 'H') {
    lc.setXY(matrix, 3,3, true);
    lc.setXY(matrix, 4,4, true);
  }
}



void renderSetMinutes() {
  fill(getTopMatrix(), delayMinutes);
  displayLetter('M', getBottomMatrix());
}
void renderSetHours() {
  fill(getTopMatrix(), delayHours);
  displayLetter('H', getBottomMatrix());
}




void knobClockwise() {
  Serial.println("Clockwise");
  if (mode == MODE_SETHOURS) {
    delayHours = constrain(delayHours+1, 0, 64);
    renderSetHours();
  } else if(mode == MODE_SETMINUTES) {
    delayMinutes = constrain(delayMinutes+1, 0, 64);
    renderSetMinutes();
  }
  Serial.print("Delay: ");
  Serial.println(getDelayDrop());
}
void knobCounterClockwise() {
  Serial.println("Counterclockwise");
  if (mode == MODE_SETHOURS) {
    delayHours = constrain(delayHours-1, 0, 64);
    renderSetHours();
  } else if (mode == MODE_SETMINUTES) {
    delayMinutes = constrain(delayMinutes-1, 0, 64);
    renderSetMinutes();
  }
  Serial.print("Delay: ");
  Serial.println(getDelayDrop());
}



volatile int lastEncoded = 0;
volatile long encoderValue = 0;
long lastencoderValue = 0;
long lastValue = 0;
void updateEncoder() {
  
/*  
  int MSB = digitalRead(PIN_ENC_1); //MSB = most significant bit
  int LSB = digitalRead(PIN_ENC_2); //LSB = least significant bit
*/
  int MSB = 0; //MSB = most significant bit      //Agregado
  int LSB = 0; //LSB = least significant bit     //Agregado
  

  int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value

  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue--;
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue++;

  // Serial.print("Value: ");
  // Serial.println(encoderValue);
  if ((encoderValue % 4) == 0) {
    int value = encoderValue / 4;
    if (value > lastValue) knobClockwise();
    if (value < lastValue) knobCounterClockwise();
    lastValue = value;
  }
  lastEncoded = encoded; //store this value for next time
}



/**
 * Button callback (incl. software debouncer)
 * Esto cambia entre los modos (normal, establecer minutos, establecer horas)
 */
volatile unsigned long lastButtonPushMillis;
void buttonPush() {
  
  if((long)(millis() - lastButtonPushMillis) >= DEBOUNCE_THRESHOLD) {
    mode = (mode+1) % 3;
    Serial.print("Modo cambiado a: ");
    Serial.println(mode);
    lastButtonPushMillis = millis();

    if (mode == MODE_SETMINUTES) {
      lc.backup(); // we only need to back when switching from MODE_HOURGLASS->MODE_SETMINUTES
      renderSetMinutes();
    }
    
    if (mode == MODE_SETHOURS) {
      renderSetHours();
    }
    
    if (mode == MODE_HOURGLASS) {
      lc.clearDisplay(0);
      lc.clearDisplay(1);
      lc.restore();
      resetTime();
    }
    
  }
}

///////////////////////////////////////////////                       SETUP                       ///////////////////////////////////////////////

void setup() {

  Serial.begin(9600);

  pinMode(LEDROJO, OUTPUT);	// todos los pines como salida del led RGB
  pinMode(LEDVERDE, OUTPUT);
  pinMode(LEDAZUL, OUTPUT);


  randomSeed(analogRead(A0));

  // init displays
  for (byte i=0; i<2; i++) {
    lc.shutdown(i,false);
    lc.setIntensity(i,0);     //Controla la intensidad de brillo en las particulas
  }
  resetTime();
}




///////////////////////////////////////////////                       LOOP                       ///////////////////////////////////////////////

void loop() {





//////////////////////////                      MATRICES                       ////////////////////////////////

  delay(DELAY_FRAME);

  // actualizar la configuración de rotación del controlador. Para el resto del código pretendemos que "abajo" sigue siendo 0,0 y "arriba" es 7,7
  gravity = getGravity();
  lc.setRotation((ROTATION_OFFSET + gravity) % 180);

  // manejar modos especiales
  if (mode == MODE_SETMINUTES) {
    renderSetMinutes(); return;
  } else if (mode == MODE_SETHOURS) {
    renderSetHours(); return;
  }

  // resetCheck();                   // el reinicio ahora ocurre al presionar un botón
  bool moved = updateMatrix();
  bool dropped = dropParticle();

  // alarma cuando todo está en la parte inferior
  if (!moved && !dropped && !alarmWentOff && (countParticles(getTopMatrix()) == 0)) {
    alarmWentOff = true;
    resetTime();            //Agregado
  }
  // reset alarm flag next time a particle was dropped
  if (dropped) {
    alarmWentOff = false;
  }

//////////////////////////////                      Colores led rgb                       ///////////////////////////////// 
///*
  // Esperamos a recibir un número desde Python
  //while (!Serial.available()) {
  //  delay(10);
  //}

  // Leemos el número enviado desde Python
  if (Serial.available()>0){

    numero = Serial.parseInt();

    delay(100);

  
  

  // Si el número es mayor o igual a 5, encendemos el LED
  if (numero == 1) {
    analogWrite(LEDROJO, 255);
    analogWrite(LEDVERDE, 0);
    analogWrite(LEDAZUL, 0);
    //delay(2000);
  }
  else if (numero == 2){
    analogWrite(LEDROJO, 0);
    analogWrite(LEDVERDE, 255);
    analogWrite(LEDAZUL, 0);
    //delay(2000);
  }
  else if (numero == 3) {
    analogWrite(LEDROJO, 0);
    analogWrite(LEDVERDE, 0);
    analogWrite(LEDAZUL, 255);
    //delay(2000);
  }

  else if (numero == 4)  {           // Cian
    analogWrite(LEDROJO, 0);
    analogWrite(LEDVERDE, 255);
    analogWrite(LEDAZUL, 255);
    //delay(2000);
  }

  else if (numero == 5)  {           // Morado
    analogWrite(LEDROJO, 255);
    analogWrite(LEDVERDE, 0);
    analogWrite(LEDAZUL, 255);
    //delay(2000);
  }

  else if (numero == 6)  {           // Amarillo
    analogWrite(LEDROJO, 255);
    analogWrite(LEDVERDE, 40);
    analogWrite(LEDAZUL, 10);
    //delay(2000);
  }

  else if (numero == 7)  {           // Blanco
    analogWrite(LEDROJO, 255);
    analogWrite(LEDVERDE, 255);
    analogWrite(LEDAZUL, 255);
    //delay(2000);
  }

  else if (numero == 8)  {           // Naranjo
    analogWrite(LEDROJO, 255);
    analogWrite(LEDVERDE, 10);
    analogWrite(LEDAZUL, 0);
    //delay(2000);
  }

  else if (numero == 9)  {           // Rosa
    analogWrite(LEDROJO, 255);
    analogWrite(LEDVERDE, 10);
    analogWrite(LEDAZUL, 10);
    //delay(2000);
  }
/*
  else if (numero >= 10) {           //  APAGADO
    analogWrite(LEDROJO, 0);
    analogWrite(LEDVERDE, 0);
    analogWrite(LEDAZUL, 0);
    //delay(2000);
  }
*/  

  // Esperamos un poco para evitar recibir datos repetidos
  //delay(100);

  }


  
}




    
  
Descargar






Encargo 07 - Avance FinalTerm #

Publigramas #

Idea publigramas






Encargo 08 - Testeo #

Testeo Publigrama #

publigramas testeo






Encargo 09 - FinalTerm #

Publigrama | La publicidad del futuro #

Portada
Holograma

El presente exámen de Diseño describe un proyecto de publicidad interactiva que combina tecnologías de visualización 3D con hologramas y electrónica que permite esta interactividad a través de “botones de luz”.

#

PUBLIGRAMA Presentación final

Fabricación:

Soldadura y corte fierros

Corte láser MDF

Electrónica y programación:

Proyección publicidad interactiva en hologramas

Código Python: #
    
      



import serial
import time
import cv2
import threading

def enviar_numero_a_arduino(numero):
    arduino.write(str(numero).encode())
    time.sleep(2)

def reproducir_video(ruta_video):
    cap = cv2.VideoCapture(ruta_video)

    # Verificar si se puede abrir el video
    if not cap.isOpened():
        print("Error al abrir el video.")
        return

    # Obtener dimensiones de la ventana de video
    window_name = "Reproduciendo video"
    cv2.namedWindow(window_name, cv2.WND_PROP_FULLSCREEN)
    cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)

    while True:
        ret, frame = cap.read()

        if not ret:
            # Fin del video, salir de la reproducción
            break

        # Mostrar el fotograma en pantalla completa
        cv2.imshow(window_name, frame)

        # Esperar 30 ms y verificar si se presionó la tecla 'q' para salir
        if cv2.waitKey(30) & 0xFF == ord('q'):
            break
        if valor_anterior != valor:
            break

    # Cerrar ventana al finalizar la reproducción
    cv2.destroyAllWindows()

# Función para reproducir el video en un hilo separado
def reproducir_video_thread(ruta_video):
    thread = threading.Thread(target=reproducir_video, args=(ruta_video,))
    thread.start()
    return thread

# Configurar comunicación con Arduino
arduino = serial.Serial("COM5", 9600)
time.sleep(2)

# Rutas de los videos
ruta_rojo = r'D:\Baul\Ale_UAI_Cosas\2023\2do semestre\Taller_prod_Caaro_pino_fran\E07_publicida\Final\Videos\2vid_rojo.mp4'
ruta_verde = r'D:\Baul\Ale_UAI_Cosas\2023\2do semestre\Taller_prod_Caaro_pino_fran\E07_publicida\Final\Videos\2vid_verde.mp4'
ruta_azul = r'D:\Baul\Ale_UAI_Cosas\2023\2do semestre\Taller_prod_Caaro_pino_fran\E07_publicida\Final\Videos\2vid_azul.mp4'
ruta_amarilla = r'D:\Baul\Ale_UAI_Cosas\2023\2do semestre\Taller_prod_Caaro_pino_fran\E07_publicida\Final\Videos\2vid_amarillo.mp4'
ruta_morada = r'D:\Baul\Ale_UAI_Cosas\2023\2do semestre\Taller_prod_Caaro_pino_fran\E07_publicida\Final\Videos\2vid_morado.mp4'
ruta_cian = r'D:\Baul\Ale_UAI_Cosas\2023\2do semestre\Taller_prod_Caaro_pino_fran\E07_publicida\Final\Videos\2vid_cian.mp4'
ruta_blanco = r'D:\Baul\Ale_UAI_Cosas\2023\2do semestre\Taller_prod_Caaro_pino_fran\E07_publicida\Final\Videos\2vid_blanco.mp4'

# Inicializar el valor anterior
valor_anterior = None
video_thread = None

while True:
    valor = arduino.readline().decode('utf-8').strip()
    print(valor)

    # Interrumpir el video en curso si se recibe un nuevo valor
    if video_thread is not None and video_thread.is_alive():
        video_thread.join()  # Esperar a que el hilo de reproducción termine
        cv2.destroyAllWindows()

    if valor == valor_anterior:
        # Si el valor es igual al valor anterior, reproducir el video actual nuevamente
        if valor == '1':
            video_thread = reproducir_video_thread(ruta_rojo)
        elif valor == '2':
            video_thread = reproducir_video_thread(ruta_verde)
        elif valor == '3':
            video_thread = reproducir_video_thread(ruta_azul)
        elif valor == '4':
            video_thread = reproducir_video_thread(ruta_amarilla)
        elif valor == '5':
            video_thread = reproducir_video_thread(ruta_morada)
        elif valor == '6':
            video_thread = reproducir_video_thread(ruta_cian)
        elif valor == '7':
            video_thread = reproducir_video_thread(ruta_blanco)
    else:
        # Si el valor es diferente al valor anterior, actualizar el valor anterior y reproducir el video correspondiente
        valor_anterior = valor
        if valor == '1':
            video_thread = reproducir_video_thread(ruta_rojo)
        elif valor == '2':
            video_thread = reproducir_video_thread(ruta_verde)
        elif valor == '3':
            video_thread = reproducir_video_thread(ruta_azul)
        elif valor == '4':
            video_thread = reproducir_video_thread(ruta_amarilla)
        elif valor == '5':
            video_thread = reproducir_video_thread(ruta_morada)
        elif valor == '6':
            video_thread = reproducir_video_thread(ruta_cian)
        elif valor == '7':
            video_thread = reproducir_video_thread(ruta_blanco)






    
  
Descargar

Código Arduino: #
    
      

#include "Arduino.h"


int espera = 100;
int aumento = 10;

int num_inicial = 50;
int num_final = 52;

///////////////////////////////////////////////                       SENSORES                      /////////////////////////////////////////////// 

int sens_1 = 9;    
int sens_2 = 10;    
int sens_3 = 11;
//int sens_4 = 10;  
//int sens_5 = 9; 
//int sens_6 = 8;     


///////////////////////////////////////////////                       LED RGB                       /////////////////////////////////////////////// 

int l_rojo = 2;   
int l_verde = 3;    
int l_azul = 4;
int l_amarillo = 5; 
//int l_morado = A0;  // ROJO
//int l_cian = A1; // VERDE
//int l_rgb = A2; // AZUL   



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////                     CÓDIGO                       /////////////////////////////////////////////// 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



///////////////////////////////////////////////                       SETUP                       ///////////////////////////////////////////////

void setup() {

  Serial.begin(9600);

  pinMode(sens_1, INPUT);
  pinMode(sens_2, INPUT);
  pinMode(sens_3, INPUT);
  //pinMode(sens_4, INPUT);
  //pinMode(sens_5, INPUT);
  //pinMode(sens_6, INPUT);

  pinMode(l_rojo, OUTPUT);
  pinMode(l_verde, OUTPUT);
  pinMode(l_azul, OUTPUT);
  //pinMode(l_amarillo, OUTPUT);
  //pinMode(l_morado, OUTPUT);
  //pinMode(l_cian, OUTPUT);
  //pinMode(l_rgb, OUTPUT);



  digitalWrite(l_rojo , HIGH);
  digitalWrite(l_verde , HIGH);
  digitalWrite(l_azul , HIGH);




}

  void loop() {



///////////////////////////////////////////////                       LOOP                       ///////////////////////////////////////////////



//////////////////////////////                      SENSORES                       /////////////////////////////////

//////////     ROJO     /////////
 if ((digitalRead(sens_1) == HIGH) & (digitalRead(sens_2)== LOW) & ((digitalRead(sens_3)== LOW))) {
      // Enviar el mensaje "sensor activado" por el puerto serial
      num_final = 1;
      
      if (num_inicial != num_final){
        Serial.println("1");
        num_inicial = 1;
      }

      
      delay(espera);
 }

//////////     VERDE     /////////
 else if ((digitalRead(sens_2) == HIGH) & (digitalRead(sens_1)== LOW) & ((digitalRead(sens_3)== LOW))) {
      // Enviar el mensaje "sensor activado" por el puerto serial
      num_final = 2;
      
      if (num_inicial != num_final){
        Serial.println("2");
        num_inicial = 2;
      }
      
      delay(espera);
 }

//////////     AZUL     /////////
 else if ((digitalRead(sens_3) == HIGH) & (digitalRead(sens_1)== LOW) & ((digitalRead(sens_2)== LOW))) {
      // Enviar el mensaje "sensor activado" por el puerto serial
      num_final = 3;
      
      if (num_inicial != num_final){
        Serial.println("3");
        num_inicial = 3;
      }

      
      delay(espera);
 }

//////////     AMARILLO     /////////
 else if ((digitalRead(sens_1) == HIGH) & (digitalRead(sens_2)== HIGH) & ((digitalRead(sens_3)== LOW))) {
      // Enviar el mensaje "sensor activado" por el puerto serial
      num_final = 4;
      
      if (num_inicial != num_final){
        Serial.println("4");
        num_inicial = 4;
      }

      
      delay(1500);
 }

//////////     MORADO     /////////
 else if ((digitalRead(sens_1) == HIGH) & (digitalRead(sens_3)== HIGH) & ((digitalRead(sens_2)== LOW))) {
      // Enviar el mensaje "sensor activado" por el puerto serial
      num_final = 5;
      
      if (num_inicial != num_final){
        Serial.println("5");
        num_inicial = 5;
      }

      
      delay(1500);
 }

//////////     CIAN     /////////
 else if ((digitalRead(sens_2) == HIGH) & (digitalRead(sens_3)== HIGH) & ((digitalRead(sens_1)== LOW))) {
      // Enviar el mensaje "sensor activado" por el puerto serial
      num_final = 6;
      
      if (num_inicial != num_final){
        Serial.println("6");
        num_inicial = 6;
      }

      
      delay(1500);
 }

 else if ((digitalRead(sens_2) == HIGH) & (digitalRead(sens_3)== HIGH) & ((digitalRead(sens_1)== HIGH))) {
      // Enviar el mensaje "sensor activado" por el puerto serial
      num_final = 7;
      
      if (num_inicial != num_final){
        Serial.println("7");
        num_inicial = 7;
      }

      
      delay(espera);
 }
/*
 else if ((digitalRead(sens_4) == HIGH)) {
      // Enviar el mensaje "sensor activado" por el puerto serial
      Serial.println("7");
      /*
      digitalWrite(l_rojo , LOW);
      digitalWrite(l_verde , LOW);
      digitalWrite(l_azul , LOW);
      digitalWrite(l_amarillo,LOW);
      analogWrite(l_morado,0);
      analogWrite(l_cian,0);
      analogWrite(l_rgb,0);
      */
      delay(espera+aumento);
 }

/*


}

/*
//////////////////////////////                      Colores led rgb                       ///////////////////////////////// 
///*
  // Esperamos a recibir un número desde Python
  //while (!Serial.available()) {
  //  delay(10);
  //}

  // Leemos el número enviado desde Python
  if (Serial.available()>0){

    numero = Serial.parseInt();

    delay(100);


  // Si el número es mayor o igual a 5, encendemos el LED
  if (numero == 1) {
    //analogWrite(LEDROJO, 255);
    //delay(2000);
  }
  else if (numero == 2){
    //analogWrite(LEDROJO, 0);
    
    //delay(2000);
  }
  else if (numero == 3) {
    //analogWrite(LEDROJO, 0);
    //delay(2000);
  }
  delay(espera);
  }
}

*/




    
  
Descargar






Reseñas series #

ENSAYOS SERIES #

The Billion dollar code

Olafur Eliasson: El diseño del Arte




There are no articles to list here yet.