Archive for May 2009

h1

Audiencia al embajador de Processing

15 May 2009

Una de las posibilidades más atractivas que posee Arduino es poder comunicarse con otros programas, y si estos son libres, mejor que mejor. El IDE de Arduino está basado en el de Processing, un lenguaje y entorno de programación en código abierto basado a su vez en Java, utilizado por artistas y diseñadores gráficos.

Aprovechando el divisor de tensión, ddt, con LDR de la entrada anterior, queremos que al acercar o alejar la mano del circuito, un círculo cambie su tamaño y su color. En este vídeo podemos ver lo que queremos.

Para conseguir nuestro objetivo necesitaremos dos programas: uno para Arduino, que deberá leer los valores del ddt y escribirlos en el puerto USB o serie virtual, y otro para Processing que deberá leer dichos valores y operar en consecuencia.

El programa de Arduino es muy sencillo. Aquí tenemos su listado:


int ldrPin=3;
void setup(){
Serial.begin(9600);
}
void loop(){
int val=analogRead(ldrPin);
Serial.print(val,BYTE);
delay(75);
}

Veamos sus líneas principales, de las cuales, las dos primeras ya las hemos visto anteriormente:

  • Serial.begin(9600): configura la velocidad de transmisión del puerto; en este caso 9600 baudios.
  • analogRead(ldrPin): lee el valor del ddt conectado al pin 3. Dicho valor, comprendido entre 0 y 255, se almacena, en la variable val.
  • Serial.print(val. BYTE): envía el valor de la variable val al puerto en formato byte.

El programa para Processing es algo más complicado y lo vamos a analizar por partes. Aquí tenemos sus primeras líneas:


import processing.serial.*;
String portname = "/dev/ttyUSB0";
Serial port;
int valorUSB;
int valorMin=62;
int valorMax=240;

  • import processing.serial.*: carga la librería necesaria para la comunicación con el puerto serie.
  • String portname = «/dev/ttyUSB0»: se asigna a la variable portname el nombre del puerto al que está conectado nuestro Arduino. Este nombre lo podemos ver marcado desde la barra de menú Tools==>Serial port en el IDE de Arduino. En mi máquina ese nombre es ttyUSB0, muy familiar para quienes trabajamos libremente con GNU/Linux.
  • Serial port: crea un objeto denominado port de la clase Serial.
  • valorUSB, valorMin, valorMax: variables para almacenar los valores presente en el puerto, mínimo y máximo respectivamente. Los dos últimos dependerán de la luz ambiental que tengamos por lo que habrá que ajustarlos como se detalla más delante.

La función setup() se ejecuta al arrancar el programa y en ella se incluyen las características que se desean.


void setup() {
size(300, 300);
stroke(255);
smooth();
port = new Serial(this, portname, 9600);
}

  • size(300, 300): define la dimensión de la ventana, en nuestro caso de 300×300 píxeles.
  • stroke(255): proporciona el color del borde del círculo. El  valor 255 se corresponde con el blanco.
  • smooth(): suaviza el borde del círculo mejorando su aspecto visual.
  • port=new Serial(this, portname, 9600): se asigna a port un nuevo objeto denominado Serial. La opción this hace referencia al propio objeto. De este modo se abre el puerto al que está conectado la placa a una velocidad de 9600 bps.

La función draw() se ejecutará continuamente como un bucle infinito:


void draw() {
background(0);
int valorColor= 255*(valorUSB-valorMin)/(valorMax-valorMin);
fill(valorColor,255-valorColor,255);
int radio = height*(valorUSB -valorMin)/(valorMax-valorMin);
ellipse(width/2,height/2,radio,radio);
if (port.available() > 0) {
valorUSB = port.read();
}
println(valorUSB);
}

  • backgroun(0): define el color de fondo de la ventana. El valor 0 se corresponde con el negro.
  • valorColor: esta variable permitirá cambiar el color del círculo. La fórmula ajusta los valores desde 0 a 255.
  • fill(): establece el color de relleno del círculo. Dicho color viene definido por defecto en términos RGB. Al dejar el tercer parámetro fijo a 255, las variaciones se corresponden con distintos tonos desde el azul al rosa, como se aprecia en el vídeo. Se puede cambiar el orden de estos tres prámetros para obtener otros colores.
  • radio: valor del radio. La fórmula permite que varía desde 0 hasta el alto de la ventana.
  • ellipse(): dibuja una elipse en la ventana. En nuestro caso será un circulo puesto que los dos últimos parámetros son iguales al valor de radio. Los dos primeros, width/2 y height/2 proporcionan las coordenadas de su centro, que se correponden en esye caso con el centro de la ventana. Las constantes width y height se corresponden con los valores, en píxeles del ancho y alto de la ventana, respectivamente, en nuestro caso 300 y 300, definidos en size().
  • if(port.available()>0): si el dato está disponible…
  • valorUSB=port.read(): … lee su valor y lo almacena en la variable valorUSB.
  • println(valorUSB): muestra en el IDE el valor leído. Esto nos permitirá obtener las asignaciones a la variables valorMin y valorMax.

El programa funciona, descárguelo desde este enlace y compruébelo. Alguna vez se me ha bloqueado el puerto y he tenido que reiniciar el ordenador. También he observado que si ela prueba se hace en un ambiente donde la luz varía constantemente, sobre todo si esa luz proviene de fluorescentes, las variaciones de tamaño y color son demasiado bruscas.

h1

Su majestad ve mi mano

6 May 2009

En la anterior entrada vimos como crear sencillas melodías con las ocho notas musicales básicas. En este caso vamos a intentar que el rey Arduino de Ivrea «vea» nuestra mano y toque una nota diferente en función de lo cerca o alejada que se encuentre de su majestad.

Para ello vamos a utilizar un circuito muy sencillo y bien conocido por los estudiantes de electricidad o electrónica: el divisor de tensión, ddt. Se trata de dos o más resistencias conectadas en serie. En la figura de la izquierda se muestra este circuito en su versión más sencilla. Fácilmente se puede demostrar que la tensión en bornes de R2, Vout es:

Ecuación de salidaPara nuestro ejercicio conectaremos Vin a 5 V,  Vout a uno de los puertos analógicos de entrada, tomaremos una resistencia de 1 kΩ para R1 y sustituiremos R2 por un fotoresistor o ldr, un componente cuyo valor resistivo varía con la intensidad luminosa de modo que a mayor luz menor resistencia. De este modo al acercar o alejar nuestra mano, la sombra hará que varíe su resistencia y por lo tanto Vout.

Antes de realizar el programa principal necesitaremos conocer de qué orden es la variación mencionada, variación que dependerá, obviamente de la luz ambiental de donde nos encontremos. Para ello probaremos el siguiente programa.

int ldrPin = 3;
int valor = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
valor = analogRead(ldrPin);
Serial.println(valor);
delay(250);
}

Según se puede deducir, se tomará el pin 3 para conectar al punto Vout del ddt y se declara la variable «valor» para almacenar su lectura. Esto último se consigue con el comando analogRead(ldrPin), el cual proporciona valores en función de la tensión presente en el pin 3, valores que estarán comprendidos entre 0, para 0 V, y 1.023, para 5 V. Para poder visualizarlos, primero hay que configurar la transmisión serie con Serial.begin(9600), donde 9600 es el valor en baudios típico, y a continuación imprimirlos en el Serial Monitor con Serial.println(valor). Hay que recordar que una vez arrancado el programa, para ver los valores hay que hacer clic en el icono Serial Monitor para activarlo. En este video puede verse la captura de pantalla mostrando valores cada 0,25 s, tiempo regulado por el comando delay(250).

En mi caso observo al alejar y acercar la mano unos valores respectivos que van desde el 642 al 790. Estos valores puedo oírlos con el siguiente programa al que denomino LdrAudible.
int ldrPin = 3;
int zumbadorPin = 11;
int valor = 0;
void setup() {
pinMode(zumbadorPin, OUTPUT);
}
void loop() {
valor = analogRead(ldrPin);
digitalWrite(zumbadorPin, HIGH);
delayMicroseconds(valor);
digitalWrite(zumbadorPin, LOW);
delayMicroseconds(valor);
}

Para ello se conecta el zumbador en el pin 11 y se declara como salida. El programa principal consiste en leer los valores visualizados anteriormente y mandar niveles altos y bajos con retardos en microsegundos de los mismos.

El programa que pretendíamos lo llamo LdrNotas, en el que se declaran las siguientes constantes y variables

int ldrPin = 3;
int zumbadorPin = 11;
int valor = 0;
int tiempo=300;
int valormin=742;
int valormax=790;
int intervalo=(valormax - valormin)/8;

Observe que, como vamos a disponer de 8 notas, la constante «intervalo» nos servirá para proporcionar a cada una de ellas un rango similar de valores. Esto se consigue mediante la función if y los else if anidados como puede verse en el siguiente listado incompleto.

void loop() {
valor = analogRead(ldrPin);
if (valor <= valormin){
tocarNota('c', tiempo);
Serial.println("Do");
}else if (valor >=valormin && valor <= valormin + intervalo){
tocarNota('d', tiempo);
Serial.println("Re");
}else if (valor > valormin + intervalo && valor <=valormin + 2*intervalo){
tocarNota('e', tiempo);
Serial.println("Mi");
............................................................
delay(200);
}

De este modo conseguimos que cada 200 ms toque una nota que dependa de lo cerca o lejos que pongamos la mano de la fotoresistencia. Los comandos del tipo Serial.println(«nota») permitirán mostrar por el monitor la nota que está sonado en cada momento. Se recuerda de nuevo que para poder verlas hay que hacer clic en el icono Serial Monitor para activarlo. El programa completo puede descargarse desde este enlace. En el mismo observará la función tocarNota(), que lleva asociada la función tocarTono(), que ya fueron explicadas anteriormente. Y no diremos más. Veamos finalmente como su majestad toca al ver mi mano.