Left-hand vs. Right-hand finger tapping experiment

The aim of Brain-Computer Interface (BCI) is to improve the autonomy of people with severe motor disabilities by new communication and control options. It is commonly known that either if you perform a movement, or you think about actually doing this movement, the same area in the brain is activated. Therefore, the point with these people that cannot move but can think about moving their limbs is to use motor-related signals produced by them and create a new communication channel. We understand Lateralized Readiness Potential (LRP) and Event-Related Desynchronization (ERD) as motor-related signals, among others.  

In controls, imagined movements produce motor related signals, but less pronounced in comparison to executed movements. One of the reasons is the duality of the task of imaging a movement but at the same time vetoing the actual movement. Therefore a real movement made by a healthy subject is more like the motor command in disabled persons that an imagined movement. 

My main interest in the following experiment was the examination of stability and refractory behavior of motor related brain signals with increasing speed of execution and the associated bit-rate. For this reason, I examined the cortical signals of executed finger tapping movements in experimental settings with different movement speeds. I started a series of experiments with volunteers performing self-paced finger movements on a two external trigger (buttons) hardwired into the OpenBCI 32bit board.

On-going OpenBCI GUI edited for the finger tapping experiment

The main idea of this OpenBCI GUI Left-hand vs. Right-hand finger tapping experiment version is to present a rhythm and tap to it while using the two external trigger buttons attached into the OpenBCI 32bit board.

// Create variables 
 Button bpm30;
 Button bpm45;
 Button bpm60;
 Button bpm120; 
 boolean RandomButtonPressed = false;
 boolean bpm30ButtonPressed = false;
 boolean bpm45ButtonPressed = false;
 boolean bpm60ButtonPressed = false;
 boolean bpm120ButtonPressed = false;

 // Audio Files
  Minim minim;
  AudioPlayer player30bpm;
  AudioPlayer player45bpm;
  AudioPlayer player60bpm;
  AudioPlayer player120bpm;

// void setup
 bpm30 = new Button (int(x+180), int(y+140), 60, 20, "30 bpm", 10);
 bpm45 = new Button (int(x+180), int(y+165), 60, 20, "45 bpm", 10);
 bpm60 = new Button (int(x+180), int(y+190), 60, 20, "60 bpm", 10);
 bpm120 = new Button (int(x+180), int(y+215), 60, 20, "120 bpm", 10);

  // Load Audio Files
  minim = new Minim(this); // we pass this to Minim so that it can load files from the data directory
  // loadFile will look in all the same places as loadImage does. This means that you can find files that are in the data folder and the sketch folder. You can also pass an absolute path, or a URL.
  player30bpm = minim.loadFile("/data/30BPM.mp3");
  player45bpm = minim.loadFile("/data/45BPM.mp3");
  player60bpm = minim.loadFile("/data/60BPM.mp3");
  player120bpm = minim.loadFile("/data/120BPM.mp3");
GUI_leftright.gif
Figure 1.

Once you have preselected either 30bpm, 45bpm, 60bpm or 120bpm, when you press “Start Experiment” a Dropbox link pops-up.

popup.gif
Figure 2. When you choose between the bpm options and press “Start Experiment”, a Dropbox window pops-up with the audio file selected.

The code used is so easy to implement since the iterations and conditions subjected to whatever BPM option is selected should be pretty straightforward and legit:

if (TestRunning) { 

 if (bpm30ButtonPressed) {
 link("https://www.dropbox.com/s/2f3l4vph5mnbkmc/30BPM.mp3.mp3?dl=0");
 bpm30ButtonPressed = false;
 }

 if (bpm45ButtonPressed) {
 link("https://www.dropbox.com/s/kjwrd6017r9dc31/45BPM.mp3?dl=0");
 bpm45ButtonPressed = false;
 }

 if (bpm60ButtonPressed) {
 link("https://www.dropbox.com/s/egc04c5no4541e5/60BPM.mp3?dl=0");
 bpm60ButtonPressed = false;
 }

 if (bpm120ButtonPressed) {
 link("https://www.dropbox.com/s/sjqsptglnayx675/120BPM.mp3?dl=0");
 bpm120ButtonPressed = false;
 }
 }

 

Improvements

First of all, I would like to say that this is the first draft of this OpenBCI GUI version. So, a lot of improvement needs to be done and implemented. I made a to-do list with all the potential improvements that I could apply to my first draft in order to become my “perfect” version for my proposes.

  • Play the audio files in Processing. I would love to be able to play the audio files in Processing. Although I tried to play them with the Minim function, it seems that I’m not able to upload the audio files. Therefore, I cannot play neither of them when the script is running and I’ve selected one of the bpm options. Here is the error that appears in the OpenBCI GUI console:
==== JavaSound Minim Error ====
==== Couldn't find a sketchPath method on the file loading object provided!
==== File recording will be disabled.

==== JavaSound Minim Error ====
==== Couldn't find a createInput method in the file loading object provided!
==== File loading will be disabled.

==== JavaSound Minim Error ====
==== java.lang.NullPointerException

=== Minim Error ===
=== Couldn't load the file /data/30BPM.mp3

==== JavaSound Minim Error ====
==== java.lang.NullPointerException

=== Minim Error ===
=== Couldn't load the file /data/45BPM.mp3

==== JavaSound Minim Error ====
==== java.lang.NullPointerException

=== Minim Error ===
=== Couldn't load the file /data/60BPM.mp3

==== JavaSound Minim Error ====
==== java.lang.NullPointerException

=== Minim Error ===
=== Couldn't load the file /data/120BPM.mp3
  • Draw the waveforms. To apport a creative way to play the songs, I thought that it would be fancy to draw the waveforms accordingly to the bpm rate. Its based on the example give by Processing located in File > Examples… >  Contributed Libraries > Minim > Basics > PlayAFile. Thus, I created an independent script with Processing and I tried to implement it in my Playground tab with my experiment code, but since I am not able to load and execute the audio files, I cannot run it. What a shame, right?
import ddf.minim.*;

Minim minim;
AudioPlayer player;

void setup() {
 size(512, 200, P3D);
 
 // we pass this to Minim so that it can load files from the data directory
 minim = new Minim(this);
 
 // loadFile will look in all the same places as loadImage does.
 // this means you can find files that are in the data folder and the 
 // sketch folder. you can also pass an absolute path, or a URL.
 player = minim.loadFile("30BPM.mp3");
}

void draw() { 
 background(0);
 stroke(255);
 
 // draw the waveforms
 // the values returned by left.get() and right.get() will be between -1 and 1,
 // so we need to scale them up to see the waveform
 // note that if the file is MONO, left.get() and right.get() will return the same value
 for(int i = 0; i < player.bufferSize() - 1; i++) {
 float x1 = map( i, 0, player.bufferSize(), 0, width );
 float x2 = map( i+1, 0, player.bufferSize(), 0, width );
 line( x1, 50 + player.left.get(i)*50, x2, 50 + player.left.get(i+1)*50 );
 //line( x1, 150 + player.right.get(i)*50, x2, 150 + player.right.get(i+1)*50 );
 }
 
 // draw a line to show where in the song playback is currently located
 float posx = map(player.position(), 0, player.length(), 0, width);
 stroke(60,80,140);
 line(posx, 0, posx, height);
 
 if ( player.isPlaying()) {
 text("Press any key to pause playback.", 10, 20 );
 } else {
 text("Press any key to start playback.", 10, 20 );
 }
}

void keyPressed()
{
 if ( player.isPlaying()) {
 player.pause();
 }
 // if the player is at the end of the file,
 // we have to rewind it before telling it to play again
 else if ( player.position() == player.length()) {
 player.rewind();
 player.play();
 } else {
 player.play();
 }
}
30bpm.gif
Figure 3. The result of the code above.
  • Use Radio Buttons. To implement this kind of buttons, you need to download the “Radio” class from Processing. Likewise, I created an independent script with Radio buttons to select the hand that the user wants to use to perform the experiment and the bpm of the audio files.
class Radio {
 int x, y;
 int size, dotSize;
 color baseGray, dotGray;
 boolean checked = false;
 int me;
 Radio[] others;

 Radio (int xp, int yp, int s, color b, color d, int m, Radio[] o) {
 x = xp;
 y = yp;
 size = s;
 dotSize = size - size/3;;
 baseGray = b;
 dotGray = d;
 others = o;
 me = m;
 }

 // Updates the boolean value press, returns true or false
 boolean press (float mx, float my) {
 if (dist(x, y, mx, my) < size/2) {
 checked = true;
 for (int i=0; i < others.length; i++) {
 if (i!=me) {
 others[i].checked = false;
 }}
 return true;
 } else {
 return false;
 }}

 // Draws the element to the display window
 void display() {
 noStroke();
 fill(baseGray);
 ellipse(x, y, size, size);
 if (checked == true) {
 fill (dotGray);
 ellipse(x, y, dotSize, dotSize);
 }}
}
radiobuttons
Figure 4. Radio Buttons implementation.

However, when I try to import the code to the OpenBCI GUI I simply cannot do it. The buttons are drawn on the main page, not in the Playground tab.

References

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s