tornamesas en acción

publicado el 2018-09-15

parte del proyecto: tortilla-stories


¡muchos avances desde la entrada anterior! por un lado eso está súper bien, pero por otro trataré de no abrumarme reportando todo lo que hice.

básicamente en esta semana ya quedó el circuito de control de los motores, una implementación limpia de dicho circuito, y una versión estable de las tornamesas funcionales (y la semana incluyó el hacer los prototipos)

rata panchis con un cable en las patas que viene de un microcontrolador

semana electrónica y tangible

foto filtrada de mel vista de atrás, en la mesa se pueden ver tres cajas con discos en su techo; dos de ellas tienen tortillas con dibujos

mel ensayando con las tornamesas

más adelante compartiré un archivo completo con la documentación para replicar todos los componentes del sistema; por el momento quiero organizarlo mejor, y muero por compartir estas fotos y videos aunque sean fragmentos.

videos

con estos videos quiero mostrar un poco de los avances en acción antes de pasar a las fotos. el audio que se desencadena todavía no está presente por logística de grabación, pero en el siguiente ensayo ya lo tendremos con audio también.

tres tornamesas, tortillas de papel

esta primera grabación muestra una prueba con la primera versión de las tornamesas, desde el punto de vista de la cámara del lector. cuando las tortillas de papel son detectadas después de activar la perilla, las tornamesas empiezan a girar. y cuando la perilla se mueve de regreso, se detienen.

tres tornamesas, tortillas de maíz

este video muestra el mismo procedimiento de arriba, pero ahora utilizando tortillas de maíz. al inicio del video se puede notar un poco cómo el lector no detecta la primera tortilla. el desempeño puede mejorarse ajustando con más calma los tamaños de las ventanas de detección, el umbral de iluminación, y el rango de áreas válidas.

tres tornamesas v2, tortillas de maíz, punto de vista externo

aquí vemos algunas tomas de las tornamesas más recientes en acción. el procedimiento de detección no se puede distinguir pero sigue sucediendo: las tornamesas giran solo cuando el código de la tortilla se ha detectado.

circuitos

además de probar cómo controlar los motores de pasos, parte del proceso de la semana fue limpiar los circuitos para que pudieran ser relativamente robustos y fáciles de conectar y desconectar.

el resultado hasta ahora consiste en cada tornamesa teniendo un pequeño circuito que se conecta con un cable arcoiris a un “área central” donde está conectado el arduino.

foto de una maraña de cables que vienen de un arduino y hacia una protoboard, y de ahí hacia tres motores

primero estuve probando con el circuito l293d (puente h), eventualmente cambié al uln2003

diagrama electrónico dibujado a mano

diagrama ilustrado del circuito para cada tornamesa, con el fin de solo recibir señales de poder y control. al final el décimo pin sí fue utilizado y el resistor se colocó del otro lado del cable arcoiris

foto de un conector

el conector en físico

foto de una serie de cables conectados a una protoboard, y de ahí a un arduino

el otro lado de los cables arcoiris, la central que se conecta al arduino

construcción

hice varias pruebas con cartón y cortadora láser, para alinear y ensamblar los componentes que cada tornamesa tendría: su motor, un potenciómetro, y un led.

ya que las pruebas fueron exitosas, pasé a hacer el diseño que les daría más robustez en forma de caja.

tornamesas versión 1, con un cartón blanco de empaque

foto de una pieza circular con hoyo en medio, y una pieza cuadrada con varios agujeros

piezas iniciales para probar las tornamesas: una superficie para colocar los componentes electrónicos, y la pieza circular para apoyar la tortilla

foto de dos piezas circulares con hoyo en medio, una clara y otra cosa, y una pieza cuadrada con varios agujeros y bordes redondeados

después de mejorar el tamaño de los agujeros, hice otra versión. el círculo oscuro es de un cartón más grueso para dar soporte a la otra pieza

foto de la pieza cuadrada con bordes redondeados, con partes de los componentes electrónicos saliendo a través de los agujeros

aquí vemos la parte de enfrente con el motor atornillado y el potenciómetro y led en posición

foto de la vista trasera pieza cuadrada con bordes redondeados, con los componentes electrónicos expuestos

aquí vemos la parte de atrás con el motor atornillado y el potenciómetro y led en posición

foto de la tornamesa completa, la pieza circular ensamblada en el eje del motor y tapando los tornillos que se veían en las imágenes anteriores

el aspecto de la tornamesa ya con las dos tapas circulares colocadas

foto de las tres tornamesas ensambladas, en proceso de conectarse al arduino

la apariencia de las tres tornamesas ya armadas, con el cableado en proceso

tornamesa versión 2, con cajas de cartón de pizza

aquí faltan más fotos del proceso, pero ya con las medidas tomadas en la versión inicial, aquí pasé a trasladarlas a una versión de caja para que pudieran sostenerse solas.

foto de un par de manos ensamblando las paredes de las cajas

ensamblando las cajas

tres cajas apiladas; sus paredes tienen arcos como si fueran edificios. son de cartón y se ven fragmentos de las ilustraciones que estaban originalmente en las cajas

aspecto final de las cajas de las tornamesas

tornamesa vista por debajo (caja vista por dentro), se ven varios cables y un motor

por debajo, cada tornamesa tiene sus componentes electrónicos y conectores

programación

el código del lector hecho en processing quedó casi igual, solo hubo que agregarle la tercera tornamesa y ajustar el archivo de configuración para alinear las áreas de lectura. además le agregué el envió del comando para activar o desactivar un motor específico ya que se confirmó su cambió de estado (y se envió por osc)

en la tierra del arduino, hice varias pruebas de control de los motores de pasos, pues la documentación que encontraba o el orden de los cables no me cuadraba.

al final el programa es un remix del ejemplo de analogreadserial y del control básico de la biblioteca de stepper, en conjunto con mi pequeño protocolo de comunicación.

cabe hacer el comentario que no se puede hacer un arreglo de variables de tipo Stepper (?).

dejo el código aquí abajo porque es relativamente pequeño y por referencia de los pines utilizados en el arduino due que estoy utilizando (por ser el que tengo, probablemente podría usar uno “menor”).

insisto en que organizaré el archivo de todos los componentes del sistema para compartirlos completos :)


/*
   código de control de tornamesas
   implementado en un arduino due
*/

#include <Stepper.h>
#define NUM_STEPS 10
#define MOTOR_SPEED 60
const int stepsPerRevolution = 512;  

Stepper motor2 = Stepper(stepsPerRevolution, 22, 24, 26, 28);
Stepper motor1 = Stepper(stepsPerRevolution, 30, 32, 34, 36);
Stepper motor0 = Stepper(stepsPerRevolution, 38, 40, 42, 44);

#define NUM_TORNAMESAS 3
#define TIMER_DELAY 50
#define THRESHOLD_POT 800
#define TH_TIMEOUT 100

// protocolo
#define C_ENCIENDE 0x20
#define C_MOTORON 0x30
#define C_MOTOROFF 0x40
#define C_ACTIVA 0x50
#define C_APAGA 0x60

bool estado [NUM_TORNAMESAS]; // estado de cada tornamesa
bool estadoMotor [NUM_TORNAMESAS]; // estado de cada motor 
int timer[NUM_TORNAMESAS];
int led[NUM_TORNAMESAS];
int an[NUM_TORNAMESAS];
unsigned long timeout[NUM_TORNAMESAS];


// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(115200);

  led[0] = 46;
  led[1] = 48;
  led[2] = 50;

  an[0] = A0;
  an[1] = A1;
  an[2] = A2;

  motor0.setSpeed(MOTOR_SPEED);
  motor1.setSpeed(MOTOR_SPEED);
  motor2.setSpeed(MOTOR_SPEED);


  for(int i=0; i<NUM_TORNAMESAS; i++){
	  pinMode(led[i],OUTPUT);
	  timeout[i] = millis();
	  enciende(i);
  }


}

// the loop routine runs over and over again forever:
void loop() {

  int sensorValue = 0;

  for(int i=0; i<NUM_TORNAMESAS; i++){
	  if(timer[i] > 0){
		timer[i]--;
	  }
	  else{
		digitalWrite(led[i],LOW);	
	  }

	  sensorValue = analogRead(an[i]);

          // si está apagado y el sensor supera el threshold
	  // activa
          if(!estado[i] && 
	     sensorValue >= THRESHOLD_POT && 
	     esTimeout(i)){
            estado[i] = true;
            activa(i);
          }
          // si está encendido y el sensor está por debajo
	  // apaga
          else if(estado[i] &&
	          sensorValue < THRESHOLD_POT && 
		  esTimeout(i)){
            estado[i] = false;
	    apaga(i);
          }

  }

  int cuentaMotores = 0;
  if(estadoMotor[0]){
    motor0.step(NUM_STEPS);
    cuentaMotores++;
  }
  if(estadoMotor[1]){
    motor1.step(NUM_STEPS);
    cuentaMotores++;
  }
  if(estadoMotor[2]){
    motor2.step(NUM_STEPS);
    cuentaMotores++;
  }

  recibeMensajes();

  if(cuentaMotores < 1){
    delay(10);        // delay in between reads for stability
  }
}

boolean esTimeout(int i){
	if(millis()-timeout[i] > TH_TIMEOUT){
		timeout[i] = millis();
		return true;
	}
	return false;
}

//void serialEvent(){
void recibeMensajes(){
  char ch, cod, i;
  while(Serial.available()>0){
	ch = (char)Serial.read();
	cod = ch & 0xF0;
	i = ch & 0x0F;

	switch(cod){
		case C_ENCIENDE:
		  enciende(i);
		break;
		case C_MOTORON:
		  motorOn(i);
		break;
		case C_MOTOROFF:
		  motorOff(i);
		break;
	}
  }
}

void enciende(int i){
  timer[i] = TIMER_DELAY;
  digitalWrite(led[i],HIGH);
}

void motorOn(int i){
	estadoMotor[i] = true;
}

void motorOff(int i){
	estadoMotor[i] = false;

}

void activa(int i){
  Serial.write(C_ACTIVA + i);
}

void apaga(int i){
  Serial.write(C_APAGA + i);
}