0

EMG con Arduino y e-Health Sensor Platform – Parte II: Visualización de gráficos con Matlab

[Ir a Parte I]

Saludos, humano. Al habla Transductor. Bienvenido a la segunda parte de esta série de tutoriales sobre Arduino y E-Health Sensor Shield. En la primera parte expliqué como instalar la librería eHealth.h y construí un pequeño código que medía la actividad muscular y después enviaba las lecturas por la consola Serial.

Esta vez utilizaremos Matlab en Linux para recoger los valores que Arduino envía y los mostraremos en una gráfica en tiempo real. También aplicaremos un filtro de paso bajo (low-pass filter) para atenuar el ruido de estas lecturas.

Vamos a crear este gráfico con Matlab

Si no conoces Matlab, se trata de un programa de cálculo numérico que permite analizar datos y funciones, crear algoritmos, hacer simulaciones y muchas cosas más a través un lenguaje propio. Tiene también muchos paquetes adicionales con herramientas que nos permiten ampliar sus posibilidades, como Mupad (cálculo simbólico) o Simulink (sistemas dinámicos). El único inconveniente es que el precio de una licencia completa de Matlab es astronómico. Sin embargo, hay una versión para estudiantes más asequible.


Preparativos:

Las instrucciones para instalar la librería eHealth.h de Arduino, así como la forma correcta de colocar los electrodos, puedes encontrarlas en la Parte I .


Código de Arduino

El código que voy a utilizar hoy es muy parecido al de la última vez pero con la diferencia de que en vez de enviar directamente las medidas que detectan los electrodos, aplicaré un filtro de paso bajo (en inglés, low-pass filter).

¿Qué es un filtro de paso bajo, y por qué quiero complicar el código? Los electrodos EMG son muy ruidosos, las lecturas que nos llegan tienen imprecisiones y esto hace que la gráfica tenga muchas irregularidades. Para evitar esto puede implementarse un filtro de paso-bajo para reducir el ruido y suavizar la curva de la gráfica.

Ejemplo: medidas reales (azul) y medidas filtradas (rojo)

Puede pensarse que el filtro de paso bajo es un tipo especial de media ponderada: asignas un peso a las nuevas medidas en función de lo que confíes en ellas, y otro a las medidas anteriores. En el caso que nos ocupa, una fórmula para implementar este tipo de filtros podría ser:


Dónde ‘x’ es la lectura de los electrodos e ‘y’ la lectura refinada

Yo he decidido establecer alpha = 0.25 . El valor anterior de ‘y’ se multiplica por 0.75, y el nuevo por 0.25. Esto hará que los nuevos valores contribuyan sólo en un 25% en la nueva lectura, evitando así picos puntuales de voltaje.


/* ELECTROMIOGRAFIA CON ARDUINO
 * Lee los electrodos EMG, aplica un filtro de paso bajo
 * y envia las lecturas por Serial
 *
 * Escrito por Transductor
 * www.robologs.net
 *
 */
 
#include <eHealth.h>

//Valor de confianza para el low-pass filter
#define alpha 0.25

double lectura; //Lecturas filtradas que se enviaran por serial
 
void setup()
{
  Serial.begin(9600);
  lectura = eHealth.getEMG(); //Se toma un valor inicial
}
 
 
void loop()
{
  int val = eHealth.getEMG(); //Leer los electrodos
  lectura = (1-alpha)*lectura+alpha*val; //Filtrar estas lecturas
   
  Serial.println(lectura); //Enviar las lecturas filtradas por Serial
  delay(100);
}
 
//Final de linea


Script de MATLAB

La tarea de Matlab es leer los valores que llegan por el puerto de série de Arduino y mostrarlos en una gráfica que se actualizará en tiempo real.

El puerto Serial de Arduino normalmente es inaccesible para Matlab en Linux. Antes de empezar, tendrás que crear un enlace simbólico y hacerlo accesible a todos los usuarios. Abre la Terminal y escribe:

sudo ln -s /dev/ttyACM0 /dev/ttyS101
 sudo chmod 777 /dev/ttyS101

No te olvides de cambiar la dirección /dev/ttyACM0 de la primera instrucción por la dirección de tu placa Arduino (si no es esta, lo más probable es que sea /dev/ttyUSB0).

Cuándo el enlace esté creado, abre Matlab y pega este código en la ventana principal:

arduino = serial('/dev/ttyS101');
fopen(arduino);

time = 0;
value = 0;

figura = figure('Name','EMG');
ejes = axes('Parent', figura, 'YGrid','on','XGrid', 'on');
plotHandle = plot(ejes,time,value,'LineWidth',1, 'Color', [1 0 0]);

xlim(ejes, [0, 100]);
ylim(ejes, [60,160]);

value(1) = 0
time(1) = 0
count = 2

set(gcf,'currentchar',' ')
%Mientras el caracter actual sea espacio, el bucle continua
while get(gcf,'currentchar')==' '

if count > 100
xlim(ejes, [count-100, count])
end

value(count) = fscanf(arduino, '%f');
time(count) = count;

set(plotHandle, 'YData', value, 'XData', time);

pause(0.09);
count = count + 1

end

fclose(arduino);

Haré un resumen corto de qué hace cada parte. Lo primero es declarar el puerto Serial dónde está conectada la placa Arduino (el enlace simbólico que has creado hace un momento) y abrirlo.

arduino = serial('/dev/ttyS101');
fopen(arduino);

Las dos variables para la gráfica serán tiempo (time) y los valores de los electrodos (value). Hay que inicializarlos a cero, aunque más adelante los voy a utilizar como un array en vez de una variable.

time = 0;
value = 0;

Ahora hay que crear el gráfico en sí, que más adelante se llenará cuándo empiece a leer el puerto Serial. Configuramos la ventana, los ejes del gráfico y el tipo de línea.

figura = figure('Name','EMG');
ejes = axes('Parent', figura, 'YGrid','on','XGrid', 'on');
plotHandle = plot(ejes,time,value,'LineWidth',1, 'Color', [1 0 0]);

Ahora voy a establecer los valores máximos y mínimos para el eje X e Y. Como el eje Y son los valores de los electrodos y estos pueden variar en función de la persona, es posible que tengas que poner unos valores máximos y mínimos diferentes de los que aparecen aquí.

xlim(ejes, [0, 100]);
ylim(ejes, [60,160]);

Después, voy a convertir las variables time y value en arrays, y les llenaré el primer espacio con un cero. También crearé una variable contador llamada “cont” que servirá para actualizar el tiempo. Recuerda: a diferencia de otros lenguajes de programación a los que puedas estar acostumbrado, en Matlab se utilizan los paréntesis () en vez de los claudátors [] para acceder a una posición de un array. Y empiezan siempre por la posición ‘1’, no por la ‘0’. Una aberración.

value(1) = 0
time(1) = 0
count = 2

Ahora voy a crear un bucle while que se ejecute indefinidamente, hasta que se pulse una tecla cualquiera. ¿Cómo hacerlo? Pues engañando al ordenador y haciéndole creer que el carácter actual que se está pulsando es espacio. Si se pulsa cualquier otro botón el carácter actual cambiará. Por tanto, la condición para continuar el bucle será que el carácter actual sea espacio.

set(gcf,'currentchar',' ')
%Mientras el caracter actual sea espacio, el bucle continua
while get(gcf,'currentchar')==' '

Bien. Tal y como está definido el eje X de la gráfica, esta sólo muestra los cien primeros valores. Es por esta razón que utilizamos el condicional “if” que hay dentro del bucle. Dado que, como hemos visto, la variable ‘count‘ indica el tiempo, este condicional mira si ha pasado del valor 100, y si es así avanza el eje X una unidad para poder ver el siguiente valor representado. Si quieres, puedes probar a eliminar el condicional y verás lo que quiero decir.


if count > 100
xlim(ejes, [count-100, count])
end

Lo siguiente es guardar el número que llega del puerto de Serie desde Arduino dentro de la variable value, añadir el valor del contador al array de tiempo, y actualizar la gráfica.

value(count) = fscanf(arduino, '%f');
time(count) = count;

set(plotHandle, 'YData', value, 'XData', time);

Para acabar se avanza el contador, se espera 0.09 segundos (para dar tiempo a Arduino a enviar la siguiente lectura de los electrodos) y se cierra el bucle while.

pause(0.09);
count = count + 1

end

Una vez terminado el bucle principal hay que cerrar la conexión Serial con Arduino. De lo contrario puedes tener problemas la próxima vez que quieras conectarte con la placa.

fclose(arduino);

Esto es todo, humano. Hoy has aprendido una forma de visualizar y medir la actividad muscular con Matlab. Espero que esto te ayude a desarrollar tus proyectos de biomedicina y E-health.

Si tienes algún problema a la hora de ejecutar el script, o tienes alguna pregunta que plantear, puedes dejar un comentario.

Final de línea.

Tr4nsduc7or

Originariamente creado cómo un galvanómetro de bolsillo, Transductor tomó consciencia de si mismo y fue despedido cuando en vez cumplir con su trabajo se dedicó a pensar teorías filosóficas sobre los hilos de cobre, los electrones y el Sentido del efecto Joule en el Universo. Guarda cierto recelo a sus creadores por no comprender la esencia metafísica de las metáforas de su obra. Actualmente trabaja a media jornada cómo antena de radio, y dedica su tiempo libre a la electrónica recreativa y a la filosofía.

Antes de comentar, por favor, lee las Normas

Ten el honor de decir "Primero!"

avatar
wpDiscuz