Introduction: BUCKi - Brain Computer Interface Controlled Arduino Car

Hey Kiwis!

You might remember us from our previous project KIVI ( https://www.instructables.com/id/KIVI/ ).This time we bring to you something even more interesting. Presenting, BuCKi, an Emotiv Epoc+ BCI (Brain Computer Interface) controlled Arduino car.

We use the Emotiv's Inertial Sensor to control the cursor, the Facial Sensors to emulate a mouse left click, and Processing to create an interface for the user to pass commands onto the Arduino car. The Processing interface consists of five buttons, each is linked to a specific command such as forward, left, brake etc. When the user clicks on any one of the buttons, that instruction is sent through the Bluetooth Module to the Arduino which then controls the motors accordingly.

We noticed the lack of BCI related projects and tutorials and decided to share some of our experiences with this unconventional device!

Step 1: WHAT WE NEED:

To build this Leap Motion Controlled Arduino Car, you will need:

  • 1x Emotiv Epoc+ BCI
    (Here)
  • 1x Arduino Uno (or an Arduino Mega)

https://goo.gl/QyCNa1

  • 1x USB to UART TTL Serial Cable

https://goo.gl/AuPN6E

  • 1x HC - 05 Bluetooth Module

https://goo.gl/DX1WvL

  • 1x L293D Motor Driver IC (Dual H-Bridge Motor Controller)

https://goo.gl/GWu9T6

  • 2x DC Carbon Brush Motors

https://goo.gl/voJQDJ

  • 1x RC Car Chassis

https://goo.gl/jqEGmg

  • 2x 9V Batteries

https://goo.gl/y48Ukg

  • 2x Battery Caps

https://goo.gl/Q84mGj

  • Many Male to Male Jumper Wire

https://goo.gl/xLnKXy

Step 2: OTHER IMPORTANT TOOLS:

Step 3: WHAT TO LOOK AHEAD TO:

This is a snippet of what to look forward to in this Instructable!

Step 4: THE CODE:

The code is implemented in two parts:

Processing:

//CONTROL INTERFACE

import processing.serial.*;
Serial myPort;

int rectx, recty;   //Declaring coordinates for the buttons
int rect1x, rect1y;
int rect2x, rect2y;
int rect3x, rect3y;
int rect4x, rect4y;

int rectsize = 90;   //All the buttons will have height and width of 90 pixels

color rectColor = 0; //We will implement change in color for good UX
color rect1color =0;
color rect2color =0;
color rect3color =0;
color rect4color =0;

boolean rectover  = false;// To check whether cursor is over a button
boolean rect1over = false;
boolean rect2over = false;
boolean rect3over = false;
boolean rect4over = false;

void setup()
{
  size(800, 600);
  rectColor = color(0);
  rectx = width/2 - rectsize/2;         //Setting the buttons
  recty = height/2 - rectsize/2;
  rect1x = width/2 - 10 - 3*rectsize/2;
  rect1y = height/2 -rectsize/2;
  rect2x =width/2 +10 +rectsize/2;
  rect2y = height/2 -rectsize/2;
  rect3x = width/2  -rectsize/2;
  rect3y = height/2 + 10+ rectsize/2;
  rect4x = width/2 - rectsize/2;
  rect4y = height/2 -10 -3*rectsize/2;
  
  myPort = new Serial(this, Serial.list()[0], 9600);
}

void draw()
{
  update(mouseX, mouseY);
  background (255);
  stroke(0);
  fill(rectColor);
  rect(rectx, recty, rectsize, rectsize);//Creating the buttons
  fill(rect1color);
  rect(rect1x, rect1y, rectsize, rectsize);
    fill(rect2color);
  rect(rect2x, rect2y, rectsize, rectsize);
    fill(rect3color);
  rect(rect3x, rect3y, rectsize, rectsize);
    fill(rect4color);
  rect(rect4x, rect4y, rectsize, rectsize); 
}

void update(int x, int y) //Gives which button the cursor is on
{
  if(overRect(rectx, recty, rectsize, rectsize)){
  rectover  = true;
  rect1over = false; 
  rect2over = false;
  rect3over = false;
  rect4over = false;
}
else if(overRect(rect1x, rect1y, rectsize, rectsize))
{
  rectover  = false;
  rect1over = true;
  rect2over = false;
  rect3over = false;
  rect4over = false;
}
else if(overRect(rect2x, rect2y, rectsize, rectsize))
{
  rectover  = false;
  rect1over = false;
  rect2over = true;
  rect3over = false;
  rect4over = false;
}
else if(overRect(rect3x, rect3y, rectsize, rectsize))
{
  rectover  = false;
  rect1over = false;
  rect2over = false;
  rect3over = true;
  rect4over = false;
}
else if(overRect(rect4x, rect4y, rectsize, rectsize))
{
  rectover  = false;
  rect1over = false;
  rect2over = false;
  rect3over = false;
  rect4over = true;
}
}

void mousePressed(){
  if (rectover){ 
  rectColor =255;
  myPort.write(str(5));
}
else if(rect1over){
  rect1color =255;
  myPort.write(str(4));
}
else if(rect2over){
  rect2color =255;
  myPort.write(str(6));
}
else if(rect3over){
  rect3color =255;
  myPort.write(str(2));
}
else if(rect4over){
  rect4color =255;
  myPort.write(str(8));
}
}

void mouseReleased()
{
  if(rectover)
  {rectColor   =0;
  }
  else if(rect1over)
  {rect1color =0;
  }
  else if(rect1over)
  {rect1color =0;
  }
  else if(rect2over)
  {rect2color =0;
  }
  else if(rect3over)
  {rect3color =0;
  }
  else if(rect4over)
  {rect4color =0;
  }
}



boolean overRect(int x, int y, int width, int height)  {
  if (mouseX >= x && mouseX <= x+width && 
      mouseY >= y && mouseY <= y+height) {
    return true;
  } else {
    return false;
  }
}


Arduino:

#include <SoftwareSerial.h>

SoftwareSerial Genotronex(10, 11);

int x=0;
void setup()

{

pinMode(6, OUTPUT);
pinMode(9, OUTPUT);
pinMode(3 ,OUTPUT);
pinMode(5 ,OUTPUT);
Genotronex.begin(9600);
}
void forward()
{
  digitalWrite(3, LOW);
  digitalWrite(5, HIGH);
  digitalWrite(9, HIGH);
  digitalWrite(6, LOW);
}
void backward()
{
  digitalWrite(3, HIGH);
  digitalWrite(5, LOW);
  digitalWrite(9, LOW);
  digitalWrite(6, HIGH);
}
void brake()
{
  digitalWrite(3, LOW);
  digitalWrite(5, LOW);
  digitalWrite(9, LOW);
  digitalWrite(6, LOW);
}
void left()
{
  digitalWrite(3, LOW);
  digitalWrite(5, HIGH);
  digitalWrite(9, LOW);
  digitalWrite(6, LOW);
}
void right()
{
  digitalWrite(3, LOW);
  digitalWrite(5, LOW);
  digitalWrite(9, HIGH);
  digitalWrite(6, LOW);
}

void loop()

{
  while(Genotronex.available()>0)
{
  
 x= Genotronex.parseInt();
 if(x==8){
 Genotronex.print("FORWARD");
 forward();
}
  else if(x==2){
  Genotronex.println("BACKWARD");
  backward();
}
  else if(x==5){
   Genotronex.println("BRAKE");
   brake();
}
  else if(x==4){
   Genotronex.println("LEFT");
   left();
}
  else if(x==6){
   Genotronex.println("RIGHT");
   right();
}

}

}

Step 5: THE CIRCUIT:

Step 6: CONSTRUCTION:

  1. While making the connections, ensure that the jumper wires being used are not faulty. This can be tested by administering the Continuity Test with a Multimeter.
  2. To ensure continuous, even supply throughout the length of the breadboard, short the two halves of the upper and lower power rails with the help of a jumper wire. To do this, insert the jumper wire between the fifth and sixths columns of the first row in the upper power rail and repeat the same with the lower.
  3. The Bluetooth Module used here is utilized in the Slave Mode. In case your module needs to be re-configured, use the appropriate AT Commands to do so.
  4. A 9V battery can be used to power the Arduino, however, only a 5V supply must be given to the Bluetooth Module.
  5. Take care to not interchange the connections made to the TX and RX pins of the Bluetooth Module.
  6. In case the motors rotate in opposite directions, reverse the connections made to the terminals of any one of the motors.
  7. An additional battery can be made use of in order to increase the rpm of the wheels.

Step 7: GETTING SET UP:

Follow these steps to get you hack set up:

  1. Firstly, salinate the sensor buds. We found the optimal amount to be seven drops of the salinated solution.
  2. Put the headset on and make sure it touches the scalp of the user.
  3. Check the Emotiv software to make sure the sensors are positioned correctly (It's okay if couple fail to configure).
  4. In the 'Facial Expression' section, train the BCI on your neutral expression.
  5. Open the Emotiv Xavier EmoKey software and set up the Rule and Condition for the Rule to Occur (refer to the picture).
  6. Open the Inertial Sensor section and enable the Mouse Emulator.
  7. Open the Processing Sketch and press the play button.
  8. Make sure that the processing play is in focus.
  9. Have Fun!! :)

Step 8: TESTS TESTS TESTS...

1. While testing, make sure to test the motor functioning first

2. Before moving onto wireless, test the code with the USB UART cable. (Always better to know which part is malfunctioning, if one is).

3. If the readings seem to be inconsistent, try salinating the Sensor Buds again.

Step 9: PRESENTING BUCKi:

CORE PROJECT TEAM MEMBERS:

  • PRABHAV BHATNAGAR
  • NITYA BASKAR
  • AARYAN DEHLOO
  • YUGVIR PARHAR

SPECIAL MENTION TO:

  • ANSHUMAN PANDEY (for lending us his brain)
  • ROHAN POONIWALA (for the same)
  • RAGHAV GUPTA (for his expertise)
  • AKANKSHA KHANNA (camera work)
Remote Control Contest 2017

Participated in the
Remote Control Contest 2017

Arduino Contest 2017

Participated in the
Arduino Contest 2017