Arduino + MATLAB = Pizarra mágica

En este tutorial vamos a aprender a crear una pizarra mágica con Arduino y MATLAB, mediante comunicación por puerto serie entre ambos.

Arduino + MATLAB = Pizarra mágica

¡Hola! En este tutorial, como habréis visto en el título, vamos a aprender a crear una pizarra mágica con Arduino y MATLAB, mediante comunicación por puerto serie entre ambos.

Podríamos decir, que este tutorial es parecido a uno que ya hicimos en Geeky Theory sobre la representación en tiempo real de un voltaje ofrecido por un potenciómetro. Podéis verlo aquí: MATLAB + Arduino: Serial Port Communication

Si fuiste a nuestro taller en el IEEE Developer Days, en la Universidad Miguel Hernández de Elche, pudiste ver y probar lo que vamos a mostraros en este artículo.

matlabarduinogeekytheory

Si no sabéis lo que es una pizarra mágica o telesketch, os lo cuento: una pizarra mágica es eso con lo que jugábamos cuando éramos pequeños, que tenía dos ruedecitas y que servía para dibujar. Cuando acababas, lo borrabas y comenzabas de nuevo.

Ese mismo juguete, vamos a crearlo y montarlo tan sólo con un Arduino y un par de potenciómetros.

Vamos a ver cómo va a funcionar nuestro proyecto: con Arduino, leeremos el valor de dos potenciómetros, que nos darán un valor de X y otro de Y. Tras leer estos datos (recuerdo que tendremos un resultado entre 0 y 1023), los mandaremos por el puerto serie a MATLAB y, desde ahí, los recogeremos y los iremos graficando en una ventana.

El aspecto de nuestra ventana, será el que veréis en la siguiente imagen. Aunque yo he dibujado la palabra "GEEKY", podréis hacer lo que queráis.

arduino matlab

Antes de nada, creo que es importante saber cómo va a ser el montaje de nuestro proyecto para comprender mejor su funcionamiento, así que, montadlo tal y como se ve en la siguiente imagen. Es muy sencillo. Como ya he dicho antes, sólo se necesitan un par de potenciómetros:

schematic_bb

Pasamos ahora a ver el código de Arduino:

1º. Declaramos las variables necesarias para leer los datos e inicializamos la comunicación por puerto serie:

int potenciometroX_pin=0; //Pin analógico 0 int valor_potenciometroX=0; //Aquí guardo el valor que lea del potenciómetro X int potenciometroY_pin=1; //Pin analógico 1 int valor_potenciometroY=0; //Aquí guardo el valor que lea del potenciómetro Y void setup(){ Serial.begin(9600); //Inicializo la comunicación puerto serie }

2º. En la función loop leemos los valores de cada potenciómetro y los mandamos por el puerto serie:

void loop(){ valor_potenciometroX=analogRead(potenciometroX_pin); Serial.println(valor_potenciometroX); valor_potenciometroY=analogRead(potenciometroY_pin); Serial.println(valor_potenciometroY); delay(100); }

Una vez hayamos escrito este código, lo cargaremos en nuestra placa Arduino:

Selection_025

Ahora, ya podemos pasar a la parte de programación en MATLAB: 1º. Creamos un nuevo sketch y lo guardamos como "telesketch.m". 2º. Comenzamos a programar. Este código cierra las ventanas que teníamos abiertas en MATLAB e inicializa los vectores para ir guardando datos durante la ejecución:

close all; %Cierro lo que tenía abierto clc; %Limpio la Command Window x=zeros(1, 100000); %Vector donde se guardarán los datos X y=zeros(1, 100000); %Vector donde se guardarán los datos Y

3º. Inicializo el puerto serial que utilizaré: No es el mismo código para Windows que para Linux, o sistemas UNIX, así que os cuento cómo se hará para ambas opciones: Windows: tendréis que fijaros en el COM que estáis utilizando. Sustituid la 'X' del código por el número de puerto.

delete(instrfind({'Port'},{'COMX'})); puerto_serial=serial('COMX');

Linux: MATLAB no reconoce los puertos /dev/ttyACM*, así que tendremos que hacer un enlace simbólico a otro puerto, que si reconocerá. Abrimos una nueva terminal y escribimos:

sudo ln -s /dev/ttyACM0 /dev/ttyUSB0

Con este nuevo enlace, ya podremos escribir el código:

delete(instrfind({'Port'},{'/dev/ttyUSB0'})); puerto_serial=serial('/dev/ttyUSB0'); %Creo una variable llamada puerto_serial

4º. Definimos el BaudRate de la comunicación, abrimos el puerto, e inicializamos un contador de muestras:

puerto_serial.BaudRate=9600; warning('off','MATLAB:serial:fscanf:unsuccessfulRead'); %Abro el puerto serial fopen(puerto_serial); %Declaro el contador de muestras contador_muestras=1;

5º. Creamos una ventana y configuramos el título y los ejes:

%Creo una ventana para la gráfica figure('Name','Telesketch - GEEKY THEORY') %Título de la ventana title('Matlab + Arduino - Telesketch'); %Título de la gráfica xlabel('X'); %Nombre del eje X ylabel('Y'); %Nombre del eje Y grid off; %Quitamos la rejilla hold on; ylim([0 5.0]); %Leemos valores de 0 a 5 Voltios en ambos ejes xlim([0 5.0]); lHandle = line(nan, nan); %Lo utilizaré para una representación en tiempo real más eficiente

Podéis ver la documentación sobre la función line aquí.

Esta función la voy a utilizar porque es mucho más eficiente que la función plot para llevar a cabo este proyecto. Hay que tener en cuenta que vamos a graficar muchos valores y, tenemos que hacerlo muy rápidamente. Con el comando plot, cuando pasan unos segundos, hay un cierto retardo en la representación gráfica, dejando de ser a tiempo real. Esto no nos conviene y, por esto vamos a utilizar el código del punto 6.

6º. Mediante un bucle while-true, tomaremos los datos y los representaremos punto a punto:

while true valor_potenciometro_X=fscanf(puerto_serial,'%d')'; valor_potenciometro_Y=fscanf(puerto_serial,'%d')'; x(contador_muestras)=(valor_potenciometro_X(1))*5/1024; y(contador_muestras)=(valor_potenciometro_Y(1))*5/1024; X = get(lHandle, 'XData'); Y = get(lHandle, 'YData'); x = [X x(contador_muestras)]; y = [Y y(contador_muestras)]; set(lHandle, 'XData', x, 'YData', y); %DRAWNOW es muy importante para la representación en tiempo real drawnow contador_muestras=contador_muestras+1; end

7º. Cierro el puerto serie y elimino los datos guardados: Aunque este código nunca se va a ejecutar, puesto que está después de un while-true, es conveniente saber cómo se finalizaría la comunicación entre Arduino y MATLAB.

fclose(puerto_serial); delete(puerto_serial); clear all;

Como es una representación infinita, es importante que sepáis que la ejecución se para con CTRL+C. Ya hemos acabado la programación. Si ejecutamos el código de Arduino con el Serial Monitor, veremos algo parecido a esto:

Selection_026

Estos son los datos que estamos mandando a MATLAB por el puerto serie. Veamos un resultado en vídeo:

github

Sin más, damos por finalizado el tutorial. Nos vemos en el próximo. ¡Saludos!