NUESTRO MONTAJE


 EXPERIMENTA 2014

La Facultat de Física de la Universitat de València convoca la novena edición del concurso “EXPERIMENTA” 2014 en el que participan alumnos de enseñanaza media.

El 30 de marzo de 2014 se celebrara una feria abierta al público en el Paseo Sur del Museo de las Ciencias, donde todos los centros participantes mostraran sus montajes.

Como en años anteriores alumnos del instituto presentaremos un proyecto realizado con el apoyo del Departamento de Tecnología y el Departamento de Orientación, así como por parte del AMPA del IES Campanar que ha sufragado una parte importante de los materiales empleados

En el trabajo realizado participamos directamente los alumnos: Albert García Valiente, Rodrigo Errandonea Baremboim, Moisés Ibañez Heneín, Miguel Lacalle Úbeda, Álvaro Mesa Pardo, Alberto Romero López con los profesores Javier Agustí y Pilar Gaínza.

El trabajo que presentamos surge a partir del uso de videojuegos que se controlan con unos cascos que detectan algunos parámetros de la actividad cerebral.






Como el enlace entre el casco sensor y el ordenador es por bluetooth un profesor nos planteó capturar esa señal para activar algún mecanismo.

La posibilidad vino al utilizar módulos programables consistentes en una placa con un microcontrolador Atmel AVR y puertos de entrada/salida que pueden vincularse con un módulo de bluetooth.

Estuvimos valorando la utilización de placas de Picaxe o Arduino.

Elegimos Arduino por encontrar mas documentación y experiencias similares en otros montajes. Por otra parte el fabricante del sensor “Mindwave móbile”, de la casa Neurosky, que en su web facilita datos técnicos que nos facilitaban realizar la experiencia.

En este apartado del blog queremos ir mostrando las diferentes fases en la realización del proyecto, dificultades, soluciones, etc. y facilitar toda la información necesaria para que cualquiera pueda realizar este proyecto u otro similar.


PRIMEROS PASOS


Tras haber utilizado el sensor  durante un tiempo, tal como esta comercializado, con varios juegos y utilizando ordenador  y comprobar el funcionamiento y limitaciones que presentaba, nos decidimos a realizar un montaje vinculándolo por bluetooth con otros dispositivos.

juego de zombies
juego de tiro al arco


El primer paso era vincular el auricular Mindwave móbile

auricular Mindwave móbile









Utilizamos los siguientes parámetros:

Determining the MAC address of your MindWave Mobile
  1. Open Bluetooth Settings on your computer, and click “Add a Device” or “New Connection”
  2. To make the MindWave Mobile discoverable, power on the headset. Once the LED turns on, hold the power switch up for ?4?5 seconds, until the LED begins to double?blink. It is now discoverable.
  3. Pair the MindWave Mobile, and determine it's MAC address, which is a 12 digit hexadecimal value
  4. Write this down, we will use this value later
Configuring your BlueSMiRF Module

  1. Once you power up your Arduino board and have the BlueSMiRF
  2. Pair the BlueSMiRF to your computer. It will appear, as similar to, RN?42?5922. I. The Default Baud Rate is 115200
  3. Open your Terminal Software, and connect the BlueSMiRF. The LED will turn green when it's connected. I. This may take a few tries. You can power cycle the Arduino if you experience issues.
  4. Be sure to enable “Local Echo” to be able to view your input commands.
  5. To put the BlueSMiRF into COMMAND mode, type $$$. If successful, you will see “CMD”
  6. Type: D ?I. You will see the current configuration of the BlueSMiRF.
  7. Now type: SP,0000 ?I. This will change the pincode from '1234' to '0000'
  8. Now type: SM,3
  9. I. This will configure the BlueSMiRF to Auto?Connect Mode. Once the module is powered up, it will immediately look to connect.II. You should see “AOK” if this is done properly. 9. Now type: SR,MAC ADDRESS. III. Insert the 12 digit address you copied from the MindWave Mobile. II. Again, look for AOK.
        10. Now type: SU,57.6?I. This will change the BaudRate from 115200 to 57600
        11. Type: D?I. Check to be sure that the stored address is the Mac address, and it's configure to               Auto, not Slave
        12. Type: — (three minus signs)?I. This will exit out of Coolterm. If successful, you will see              END.
          Aquí podéis ver el documento completo en el que nos basamos en la fase inicial.

    Probamos con varios  modulos bluetooth en los que había que modificar la dirección MAC para establecer la comunicación,  el código de acceso, la velocidad de comunicación a 57600 Baudios, activarlo como máster etc. Los módulos probados más económicos (HC-06) no pudimos utilizarlos pues la configuración deseada no la pudimos conseguir por medio de comandos AT.

    Tuvimos que utilizar el Bluetooth Modem - BlueSMiRF Silver que incorpora un módulo RN-42 de la casa SparkFun



    Para programarlo utilizamos un circuito convertidor RS232 a TTL



    Que nos permitió acceder a su memoria interna y configurar los parámetros de conexión con el software Cool Term.



    Configurado según estos parámetros


    Esta vez si que pudimos configurarlo con los parámetros deseados y montamos el módulo con la tarjeta de arduino según este esquema

    Y comprobamos que la vinculación del módulo bluetooth-arduino con el sensor MindwareMovile era correcta cambiando el led del bluetooth de rojo intermitente a verde.




    PRIMER MONTAJE

    Conseguida la transmisión de datos ensayamos un primer montaje, tomado directamente de la web de Neurosky.

    Consistía en una barra de leds que se iluminaban en función de la atención



    Programamos una placa arduino uno rev.3



    con este "sketch"

    ////////////////////////////////////////////////////////////////////////
    // Arduino Bluetooth Interface with Mindwave
    //
    // This is example code provided by NeuroSky, Inc. and is provided
    // license free.
    ////////////////////////////////////////////////////////////////////////

    #define LED 13
    #define BAUDRATE 57600
    #define DEBUGOUTPUT 0

    #define GREENLED1  3
    #define GREENLED2  4
    #define GREENLED3  5
    #define YELLOWLED1 6
    #define YELLOWLED2 7
    #define YELLOWLED3 8
    #define YELLOWLED4 9
    #define REDLED1    10
    #define REDLED2    11
    #define REDLED3    12

    #define powercontrol 10

    // checksum variables
    byte generatedChecksum = 0;
    byte checksum = 0;
    int payloadLength = 0;
    byte payloadData[64] = {
      0};
    byte poorQuality = 0;
    byte attention = 0;
    byte meditation = 0;

    // system variables
    long lastReceivedPacket = 0;
    boolean bigPacket = false;

    //////////////////////////
    // Microprocessor Setup //
    //////////////////////////
    void setup() {

      pinMode(GREENLED1, OUTPUT);
      pinMode(GREENLED2, OUTPUT);
      pinMode(GREENLED3, OUTPUT);
      pinMode(YELLOWLED1, OUTPUT);
      pinMode(YELLOWLED2, OUTPUT);
      pinMode(YELLOWLED3, OUTPUT);
      pinMode(YELLOWLED4, OUTPUT);
      pinMode(REDLED1, OUTPUT);
      pinMode(REDLED2, OUTPUT);
      pinMode(REDLED3, OUTPUT);

      pinMode(LED, OUTPUT);
      Serial.begin(BAUDRATE);           // USB

    }

    ////////////////////////////////
    // Read data from Serial UART //
    ////////////////////////////////
    byte ReadOneByte() {
      int ByteRead;

      while(!Serial.available());
      ByteRead = Serial.read();

    #if DEBUGOUTPUT 
      Serial.print((char)ByteRead);   // echo the same byte out the USB serial (for debug purposes)
    #endif

      return ByteRead;
    }

    /////////////
    //MAIN LOOP//
    /////////////
    void loop() {


      // Look for sync bytes
      if(ReadOneByte() == 170) {
        if(ReadOneByte() == 170) {

          payloadLength = ReadOneByte();
          if(payloadLength > 169)                      //Payload length can not be greater than 169
              return;

          generatedChecksum = 0;       
          for(int i = 0; i < payloadLength; i++) { 
            payloadData[i] = ReadOneByte();            //Read payload into memory
            generatedChecksum += payloadData[i];
          }  

          checksum = ReadOneByte();                      //Read checksum byte from stream     
          generatedChecksum = 255 - generatedChecksum;   //Take one's compliment of generated checksum

            if(checksum == generatedChecksum) {   

            poorQuality = 200;
            attention = 0;
            meditation = 0;

            for(int i = 0; i < payloadLength; i++) {    // Parse the payload
              switch (payloadData[i]) {
              case 2:
                i++;           
                poorQuality = payloadData[i];
                bigPacket = true;            
                break;
              case 4:
                i++;
                attention = payloadData[i];                       
                break;
              case 5:
                i++;
                meditation = payloadData[i];
                break;
              case 0x80:
                i = i + 3;
                break;
              case 0x83:
                i = i + 25;     
                break;
              default:
                break;
              } // switch
            } // for loop

    #if !DEBUGOUTPUT

            // *** Add your code here ***

            if(bigPacket) {
              if(poorQuality == 0)
                digitalWrite(LED, HIGH);
              else
                digitalWrite(LED, LOW);
              Serial.print("PoorQuality: ");
              Serial.print(poorQuality, DEC);
              Serial.print(" Attention: ");
              Serial.print(attention, DEC);
              Serial.print(" Time since last packet: ");
              Serial.print(millis() - lastReceivedPacket, DEC);
              lastReceivedPacket = millis();
              Serial.print("\n");

              switch(attention / 10) {
              case 0:
                digitalWrite(GREENLED1, HIGH);
                digitalWrite(GREENLED2, LOW);
                digitalWrite(GREENLED3, LOW);
                digitalWrite(YELLOWLED1, LOW);
                digitalWrite(YELLOWLED2, LOW);
                digitalWrite(YELLOWLED3, LOW);
                digitalWrite(YELLOWLED4, LOW);
                digitalWrite(REDLED1, LOW);
                digitalWrite(REDLED2, LOW);
                digitalWrite(REDLED3, LOW);          
                break;
              case 1:
                digitalWrite(GREENLED1, HIGH);
                digitalWrite(GREENLED2, HIGH);
                digitalWrite(GREENLED3, LOW);
                digitalWrite(YELLOWLED1, LOW);
                digitalWrite(YELLOWLED2, LOW);
                digitalWrite(YELLOWLED3, LOW);
                digitalWrite(YELLOWLED4, LOW);
                digitalWrite(REDLED1, LOW);
                digitalWrite(REDLED2, LOW);
                digitalWrite(REDLED3, LOW);
                break;
              case 2:
                digitalWrite(GREENLED1, HIGH);
                digitalWrite(GREENLED2, HIGH);
                digitalWrite(GREENLED3, HIGH);
                digitalWrite(YELLOWLED1, LOW);
                digitalWrite(YELLOWLED2, LOW);
                digitalWrite(YELLOWLED3, LOW);
                digitalWrite(YELLOWLED4, LOW);
                digitalWrite(REDLED1, LOW);
                digitalWrite(REDLED2, LOW);
                digitalWrite(REDLED3, LOW);
                break;
              case 3:             
                digitalWrite(GREENLED1, HIGH);
                digitalWrite(GREENLED2, HIGH);
                digitalWrite(GREENLED3, HIGH);             
                digitalWrite(YELLOWLED1, HIGH);
                digitalWrite(YELLOWLED2, LOW);
                digitalWrite(YELLOWLED3, LOW);
                digitalWrite(YELLOWLED4, LOW);
                digitalWrite(REDLED1, LOW);
                digitalWrite(REDLED2, LOW);
                digitalWrite(REDLED3, LOW);            
                break;
              case 4:
                digitalWrite(GREENLED1, HIGH);
                digitalWrite(GREENLED2, HIGH);
                digitalWrite(GREENLED3, HIGH);             
                digitalWrite(YELLOWLED1, HIGH);
                digitalWrite(YELLOWLED2, HIGH);
                digitalWrite(YELLOWLED3, LOW);
                digitalWrite(YELLOWLED4, LOW);
                digitalWrite(REDLED1, LOW);
                digitalWrite(REDLED2, LOW);
                digitalWrite(REDLED3, LOW);             
                break;
              case 5:
                digitalWrite(GREENLED1, HIGH);
                digitalWrite(GREENLED2, HIGH);
                digitalWrite(GREENLED3, HIGH);             
                digitalWrite(YELLOWLED1, HIGH);
                digitalWrite(YELLOWLED2, HIGH);
                digitalWrite(YELLOWLED3, HIGH);
                digitalWrite(YELLOWLED4, LOW);
                digitalWrite(REDLED1, LOW);
                digitalWrite(REDLED2, LOW);
                digitalWrite(REDLED3, LOW);              
                break;
              case 6:             
                digitalWrite(GREENLED1, HIGH);
                digitalWrite(GREENLED2, HIGH);
                digitalWrite(GREENLED3, HIGH);             
                digitalWrite(YELLOWLED1, HIGH);
                digitalWrite(YELLOWLED2, HIGH);
                digitalWrite(YELLOWLED3, HIGH);
                digitalWrite(YELLOWLED4, HIGH);
                digitalWrite(REDLED1, LOW);
                digitalWrite(REDLED2, LOW);
                digitalWrite(REDLED3, LOW);             
                break;
              case 7:
                digitalWrite(GREENLED1, HIGH);
                digitalWrite(GREENLED2, HIGH);
                digitalWrite(GREENLED3, HIGH);             
                digitalWrite(YELLOWLED1, HIGH);
                digitalWrite(YELLOWLED2, HIGH);
                digitalWrite(YELLOWLED3, HIGH);
                digitalWrite(YELLOWLED4, HIGH);
                digitalWrite(REDLED1, HIGH);
                digitalWrite(REDLED2, LOW);
                digitalWrite(REDLED3, LOW);             
                break;   
              case 8:
                digitalWrite(GREENLED1, HIGH);
                digitalWrite(GREENLED2, HIGH);
                digitalWrite(GREENLED3, HIGH);             
                digitalWrite(YELLOWLED1, HIGH);
                digitalWrite(YELLOWLED2, HIGH);
                digitalWrite(YELLOWLED3, HIGH);
                digitalWrite(YELLOWLED4, HIGH);
                digitalWrite(REDLED1, HIGH);
                digitalWrite(REDLED2, HIGH);
                digitalWrite(REDLED3, LOW);
                break;
              case 9:
                digitalWrite(GREENLED1, HIGH);
                digitalWrite(GREENLED2, HIGH);
                digitalWrite(GREENLED3, HIGH);              
                digitalWrite(YELLOWLED1, HIGH);
                digitalWrite(YELLOWLED2, HIGH);
                digitalWrite(YELLOWLED3, HIGH);
                digitalWrite(YELLOWLED4, HIGH);
                digitalWrite(REDLED1, HIGH);
                digitalWrite(REDLED2, HIGH);
                digitalWrite(REDLED3, HIGH);
                break;
              case 10:
                digitalWrite(GREENLED1, HIGH);
                digitalWrite(GREENLED2, HIGH);
                digitalWrite(GREENLED3, HIGH);              
                digitalWrite(YELLOWLED1, HIGH);
                digitalWrite(YELLOWLED2, HIGH);
                digitalWrite(YELLOWLED3, HIGH);
                digitalWrite(YELLOWLED4, HIGH);
                digitalWrite(REDLED1, HIGH);
                digitalWrite(REDLED2, HIGH);
                digitalWrite(REDLED3, HIGH);
                break;          
              }                    
            }
    #endif       
            bigPacket = false;       
          }
          else {
            // Checksum Error
          }  // end if else for checksum
        } // end if read 0xAA byte
      } // end if read 0xAA byte

    }

    Y pudimos comprobar que efectivamente de daban variaciones del encendido de los leds en función de cambios en la actividad mental que realizaba el sujeto. No obstante estas variaciones en los leds no eran inmediatos al cambio de actividad y sufrían un considerable retraso, con un mínimo entrenamiento estos cambios fueros haciéndose más consistentes.




    SEGUNDO MONTAJE

    Esto nos animó a dar un paso más. Sustituimos el led de uno de los  pines de salida a un relé que activaba el circuito secundario que accionaba el motor de un pequeño vehículo.





    Su funcionamiento fue el esperado, con el desfase indicado tanto de arranque como de paro en función de la actividad y grado de atención de quien lo utilizaba.



    EL MONTAJE QUE PRESENTAMOS

    Con lo que habíamos aprendido nos atrevimos a desarrollar un  proyecto en el que la intensidad de la señal de salida estuviese en función del nivel de actividad que llamamos “atención”; de manera que pudiésemos controlar la velocidad de un motor, la intensidad de una luz, etc. Con un sistema BCI similar a los existente en ámbitos médicos, de control domótico, etc.

    El paso siguiente era realizar un nuevo programa para el arduino  que pudiese recoger diferentes niveles de señal de entrada y dónde una de las salidas digitales pudiesen simular los cambios de voltaje de una salida analógica, esto es posible con la modulación por ancho de pulso (PWM = Pulse Width Modulation).

    Se crea una onda cuadrada, que conmuta constantemente entre encendido y apagado.





    Simulando voltajes entre 0 (siempre apagado) y 5 voltios (siempre encendido) variando la proporción de tiempo entre encendido y apagado.

    El resultado es como si la señal variara entre 0 y 5 voltios

    En el desarrollo del nuevo "sketch" tuvimos dificultades dada nuestra poca experiencia en desarrollar programas, sin embargo con el asesoramiento de Jorge de “Droide comunidad” donde habíamos comprado algunos de los componentes pudimos tener un “sketch” que cumpliera los requisitos mínimos que nos habíamos propuesto. El sistema es sensible a 5 niveles de activación de la atención y por tanto  el nivel de salida puede ir de 0 a 5 voltios.

    El montaje realizado  es el siguiente:



    Los pines de salida  a los leds son:

    Pin 4 conexión.
    5 al 9 niveles de activación.
    10 salida 1 con 5 niveles de potencia.
    11 salida 2 con 5 niveles de potencia.

    1 verde pin 4
    2 amarillo pin 5
    3 rojo pin 6
    4 rojo pin 7
    5 rojo pin 8
    6 rojo pin 9
    7 voltaje variable 1 ( motor) pin 10
    8 voltaje variable 2      pin 11



    La tarjeta de arduino puede dar un nivel de salida de 0 a 5 v. Con una intensidad máxima de 40 mA. Por tanto para alimentar un motor  de 12 v como en nuestro caso es necesario un circuito de amplificador y de potencia, entre las múltiples soluciones posibles elegimos un mosfet IRF540.








    Realizado el montaje decidimos conectarlo a un circuito de “scalextric”, eliminando los mandos originales que controlan la velocidad por medio de un simple reostato por nuestro montaje BCI.




    La vinculación con el controlador de velocidad es inalámbrica, permitiéndonos regular la velocidad de los coches en función del nivel de activación de la atención que recoge el sensor de actividad cerebral.


    Se han realizado dos módulos completos pues cada pista requiere un módulo completo para su control.






    LIMITACIONES ENCONTRADAS

    Detectar la actividad bioeléctrica con un sensor tan simple como el utilizado está sujeto a múltiples errores de medida tanto por el propio interfaz como por las interferencias eléctricas que pueden encontrarse en la misma sala donde se realiza la demostración.

    En algunas circunstancias pueden darse fallos de comunicación hasta en un 38.65 % de las veces.

    También nos hemos encontrado que al interrumpir la entrada de datos en la placa arduino los pines de salida quedan en la última posición y aunque desvinculemos los auriculares el circuito puede permanecer conectado. Para desvincularlo debemos hacer un "reset" en la placa.

    Por otra parte la transmisión de datos sufre un desfase con retardo de al menos 300ms. Esto se suma a las dificultades de comunicación bluetooth que también genera retardos en transmisión en datos.


    No obstante hemos podido comprobar que con un mínimo entrenamiento por parte de los usuarios de la interfaz, aumenta mucho la exactitud y el control de los dispositivos vinculados al sistema.

    A pesar de estas limitaciones, la sencillez del programa y los componentes utilizados; permite obtener unos resultados satisfactorios para un ensayo escolar.

    Con este proyecto se muestra con un sistema BCI, una forma de regular con la actividad bioeléctrica de las señales cerebrales en estado de atención, un dispositivo electromecánico como son los coches en una pista.

    Queremos seguir mejorando especialmente el protocolo de comunicaciones para reducir tanto los fallos de comunicación cómo el tiempo de retardo pues seria mucho mas eficaz tanto para aprender a controlarlo cómo en la aplicación a otros dispositivos que requieran mayor exactitud.

    Por otra parte es deseable que la intefaz detectora de la actividad cerebral tenga mayor precisión y filtrado de “ruido” y las señales no pertinentes.



    Si quereis contactar con nosotros

    bcicampanar@gmail.com



    No hay comentarios:

    Publicar un comentario en la entrada