INTERACTION DESIGN STUDIO
Alis Blog Processing and EEG

PROCESSING, ARDUINO AND EEG PART 3

MAKING THINGS SPIN




In this Arduino project, we are going to use EEG Data to control the speed of a DC motor by using PWM and go over how to build a circuit to use a motor that is too big for the Arduino to handle.

To start with, we are going to build a circuit that will enable us to control the speed of a DC motor by using a potentiometer and Arduino. Then step by step we are going to move to the Processing environment and use EEG Data to control the speed of the motor.

Arduino analogRead from Potentiometer

The first step is reading the value of potentiometer (0-1023) through analog pin (A0) and display the value in the Serial Monitor.

Here is the Arduino code for the sketch

void setup() {
   Serial.begin(9600);
}
void loop() {
   // analogRead from pin 0
   int sensorValue = analogRead(A0);
   // print the read value
   Serial.println(sensorValue);
   delay(1); 
}

 

the image of the circuit

Arduino and Potentiometer Sketch 06a

and the Fritzing file

Arduino and Potentiometer Fritzing File Sketch 06a

 

Arduino analogWrite and PWM

The second step is reading the value of potentiometer (0-1023) through analog pin (A0) and display the value by adjusting the brightness of a LED  (9) through PWM.

Here is the Arduino code for the sketch:

int led = 9;
void setup() {
  Serial.begin(9600);
  pinMode(led,OUTPUT);
}
void loop(){
  // analogRead from pin 0
  int sensorValue = analogRead(0);
  // print the read value
  Serial.println(sensorValue);
  // map the sensor value from 0-1023 to 0-255
  sensorValue = map(sensorValue, 0, 1023, 0, 255);
  // send the value to the LED on pin 9
  analogWrite(led,sensorValue);
  delay(1);  
}

 

the image of the circuit

Arduino and Potentiometer Sketch 06b

and the Fritzing file

Arduino and Potentiometer Fritzing File Sketch 06b

Arduino DC Motor Control

As we can easily transform the circuit above and replace the LED with a small motor, this is not the safest way and should be avoided. The pins can handle only 40ma each safely (max), and if you’re trying to run a motor from a pin, you’re trying to pull a bigger current,  so you may damage a pin soon if you don’t stop!

For this reason, we are going to build another circuit and use H-Bridge to control the DC motor using the value we get from the potentiometer.

An H bridge is an electronic circuit that enables a voltage to be applied across a load in either direction. These circuits are often used in robotics and other applications to allow DC motors to run forward and backward.[1]

Most DC-to-AC converters (power inverters), most AC/AC converters, the DC-to-DC push-pull converter, most motor controllers, and many other kinds of power electronics use H bridges. In particular, a bipolar stepper motor is almost invariably driven by a motor controller containing two H bridges.

H Bridge

If you simply want to turn a motor on and off, and don’t need to reverse it, for example, if you’re controlling a fan, try the tutorial on controlling high current loads with transistors.

To build the circuit, we will follow the instructions found at Lets Make Robots website written by Guilherme “guibot” Martins. In the first sketch, we are not going to use the potentiometer but only run predefined functions, yet again we are leaving the potentiometer in its place as we will use it in the following sketch when we will control the speed of a DC motor using PMW.

We will need:
– An Arduino
– Breadboard (x2)
– L293D Chipset
– DC Motor (x2)
– 9V Battery
– 0.1mF 20V Electrolytic Capacitor (x3)
– 0.1uF Ceramic Capacitor (x4)
– Jump Wires

A better version of the circuit above with capacitors included would look like:

H Bridge with Capacitors

 

Here is the image file,

Arduino H Bridge Sketch 06c

Fritzing file

Arduino H Bridge Fritzing File Sketch 06c

and the Arduino code of the circuit:

// ————————————————————————— Motors
int motor_left[] = {2, 3};
int motor_right[] = {7, 8};
// ————————————————————————— Setup
void setup() {
   Serial.begin(9600);
   // Setup motors
   int i;
   for(i = 0; i < 2; i++){
      pinMode(motor_left[i], OUTPUT);
      pinMode(motor_right[i], OUTPUT);
   }
}

// ————————————————————————— Loop
void loop() {
   drive_forward();
   delay(1000);
   motor_stop();
   Serial.println('1');

   drive_backward();
   delay(1000);
   motor_stop();
   Serial.println('2');

   turn_left();
   delay(1000);
   motor_stop();
   Serial.println('3');

   turn_right();
   delay(1000);
   motor_stop();
   Serial.println('4');
}

// ————————————————————————— Drive
void motor_stop(){
 digitalWrite(motor_left[0], LOW);
 digitalWrite(motor_left[1], LOW); 
 digitalWrite(motor_right[0], LOW);
 digitalWrite(motor_right[1], LOW);
 delay(25);
}
void drive_forward(){
 digitalWrite(motor_left[0], HIGH);
 digitalWrite(motor_left[1], LOW);
 digitalWrite(motor_right[0], HIGH);
 digitalWrite(motor_right[1], LOW);
}
void drive_backward(){
 digitalWrite(motor_left[0], LOW);
 digitalWrite(motor_left[1], HIGH);
 digitalWrite(motor_right[0], LOW);
 digitalWrite(motor_right[1], HIGH);
}
void turn_left(){
 digitalWrite(motor_left[0], LOW);
 digitalWrite(motor_left[1], HIGH);
 digitalWrite(motor_right[0], HIGH);
 digitalWrite(motor_right[1], LOW);
}
void turn_right(){ 
  digitalWrite(motor_left[0], HIGH);
  digitalWrite(motor_left[1], LOW);
  digitalWrite(motor_right[0], LOW);
  digitalWrite(motor_right[1], HIGH);
}

 

Arduino DC Motor Control with PMW

We will modify the previous sketch and use the information coming from the potentiometer to control the speed of the DC Motor. To do this simple modification, we connect the first leg of the H-Bridge to the pin 9 on the Arduino Board. Then based on our readings from the Potentiometer (A0) we adjust the speed of the DC Motor.

Here is the image file,

Arduino H Bridge with PWM Sketch 06d

Fritzing file

Arduino H Bridge with PWS Fritzing File Sketch 06d

and the Arduino code of the circuit:

/*
 Developed by Alis Design, February 2015
 Revisited November 2017
 www.alis.design
 
 based on the sketch developed by
 Guilherme “guibot” Martins
 Control your motors with L293D
 Sep, 2008
 http://letsmakerobots.com/node/2074
 
*/


// Use this code to test your motor with the Arduino board:

// —————————————————————————  Motors
int motor_left[] = {2, 3};
int motor_right[] = {7, 8};
int motor_speed = 9; 

// ————————————————————————— Setup
void setup() {
  Serial.begin(9600);

  // Setup motors
  int i;
  for(i = 0; i < 2; i++){
    pinMode(motor_left[i], OUTPUT);
    pinMode(motor_right[i], OUTPUT);
  }
  pinMode(motor_speed, OUTPUT);
  pinMode(A0, INPUT);

}

// ————————————————————————— Loop
void loop() {
  // analogRead from pin 0
  int sensorValue = analogRead(A0);
  // print the read value
  Serial.println(sensorValue);
  sensorValue = map(sensorValue, 0, 1023, 0, 255);
  analogWrite(motor_speed, sensorValue);

  drive_forward();
}

// ————————————————————————— Drive

void motor_stop(){
  digitalWrite(motor_left[0], LOW);
  digitalWrite(motor_left[1], LOW);

  digitalWrite(motor_right[0], LOW);
  digitalWrite(motor_right[1], LOW);
  delay(25);
}

void drive_forward(){
  digitalWrite(motor_left[0], HIGH);
  digitalWrite(motor_left[1], LOW);

  digitalWrite(motor_right[0], HIGH);
  digitalWrite(motor_right[1], LOW);
}

void drive_backward(){
  digitalWrite(motor_left[0], LOW);
  digitalWrite(motor_left[1], HIGH);

  digitalWrite(motor_right[0], LOW);
  digitalWrite(motor_right[1], HIGH);
}

void turn_left(){
  digitalWrite(motor_left[0], LOW);
  digitalWrite(motor_left[1], HIGH);

  digitalWrite(motor_right[0], HIGH);
  digitalWrite(motor_right[1], LOW);
}

void turn_right(){
  digitalWrite(motor_left[0], HIGH);
  digitalWrite(motor_left[1], LOW);

  digitalWrite(motor_right[0], LOW);
  digitalWrite(motor_right[1], HIGH);
}

 

Processing and PWM

Step by step, we are proceeding to connect the EEG Headset to the DC motor.

Here is the Processing code to use the same setup and control the speed of the DC motor by using the value read from Potentiometer. For this to work, we again need the Firmata uploaded to Arduino board.

/*
 Developed by Alis Design, February 2015
 Revisited November 2017
 www.alis.design
 
 based on the sketch developed by
 Guilherme “guibot” Martins
 Control your motors with L293D
 Sep, 2008
 http://letsmakerobots.com/node/2074
 
*/


//================================= arduino

import processing.serial.*;
import cc.arduino.*;
Arduino arduino;
int pot = 0;
int motor_left[] = {2, 3};
int motor_right[] = {7, 8};
int motor_speed = 9; 

//================================= font

PFont f;

//================================= init

void setup() {
  size(500, 500);

  // initialize the font object
  f = createFont("Arial", 16, true); // Arial, 16 point, anti-aliasing on

  // prints out the available serial ports.
  println(Arduino.list());

  arduino = new Arduino(this, Arduino.list()[2], 57600);

  // Setup motors
  int i;
  for (i = 0; i < 2; i++) {
    arduino.pinMode(motor_left[i], Arduino.OUTPUT);
    arduino.pinMode(motor_right[i], Arduino.OUTPUT);
  }
  arduino.pinMode(motor_speed, Arduino.OUTPUT);
  arduino.pinMode(pot, Arduino.INPUT);
}

void clearBackground() {
  background(40);
}


// ————————————————————————— Loop
void draw() {
  clearBackground();
  // analogRead from pin 0
  float sensorValue = arduino.analogRead(pot);
  // print the read value
  sensorValue = map(sensorValue, 0, 1023, 0, 255);
  arduino.analogWrite(motor_speed, int(sensorValue));

  textFont(f, 80);                    //  Specify font to be used
  fill(0);                            //  Specify font color 
  text(sensorValue, width/2, 100);    //  Display Text
  textAlign(CENTER);

  drive_forward();
}

// ————————————————————————— Drive

void motor_stop() {
  arduino.digitalWrite(motor_left[0], Arduino.LOW);
  arduino.digitalWrite(motor_left[1], Arduino.LOW);

  arduino.digitalWrite(motor_right[0], Arduino.LOW);
  arduino.digitalWrite(motor_right[1], Arduino.LOW);
  delay(25);
}

void drive_forward() {
  arduino.digitalWrite(motor_left[0], Arduino.HIGH);
  arduino.digitalWrite(motor_left[1], Arduino.LOW);

  arduino.digitalWrite(motor_right[0], Arduino.HIGH);
  arduino.digitalWrite(motor_right[1], Arduino.LOW);
}

void drive_backward() {
  arduino.digitalWrite(motor_left[0], Arduino.LOW);
  arduino.digitalWrite(motor_left[1], Arduino.HIGH);

  arduino.digitalWrite(motor_right[0], Arduino.LOW);
  arduino.digitalWrite(motor_right[1], Arduino.HIGH);
}

void turn_left() {
  arduino.digitalWrite(motor_left[0], Arduino.LOW);
  arduino.digitalWrite(motor_left[1], Arduino.HIGH);

  arduino.digitalWrite(motor_right[0], Arduino.HIGH);
  arduino.digitalWrite(motor_right[1], Arduino.LOW);
}

void turn_right() {
  arduino.digitalWrite(motor_left[0], Arduino.HIGH);
  arduino.digitalWrite(motor_left[1], Arduino.LOW);

  arduino.digitalWrite(motor_right[0], Arduino.LOW);
  arduino.digitalWrite(motor_right[1], Arduino.HIGH);
}

 

EEG, Processing and PWM

We are going to end this post with a wrap-up sketch and use the methods that we have seen above in a single Processing file. Our intention is to control the speed of the DC motor based on the attention value derived from the EEG Headset.

Here is the Processing code. Feel free to play with the values to have happy accidents :)

/*
 Developed by Alis Design, February 2015
 Revisited November 2017
 www.alis.design
 
 based on the sketch developed by
 Guilherme “guibot” Martins
 Control your motors with L293D
 Sep, 2008
 http://letsmakerobots.com/node/2074
 
 based on the library developed by
 Andreas Borg
 http://crea.tion.to/
*/


//================================= neurosky

import neurosky.*;
import org.json.*;
ThinkGearSocket neuroSocket;
int attention, meditation, delta, theta, low_alpha, high_alpha, low_beta, high_beta, low_gamma, mid_gamma, sig, blinkStrength;

//================================= arduino

import processing.serial.*;
import cc.arduino.*;
Arduino arduino;
int pot = 0;
int motor_left[] = {2, 3};
int motor_right[] = {7, 8};
int motor_speed = 9; 

//================================= font

PFont f;

//================================= init

void setup() {
  size(500, 500);
  
  // initialize the font object
  f = createFont("Arial", 16, true); // Arial, 16 point, anti-aliasing on

  // prints out the available serial ports.
  println(Arduino.list());

  // Modify this line, by changing the "0" to the index of the serial
  // port corresponding to your Arduino board (as it appears in the list
  // printed by the line above).
  // Alternatively, use the name of the serial port corresponding to your
  // Arduino (in double-quotes), as in the following line.
  // arduino = new Arduino(this, "/dev/tty.usbmodem621", 57600);
  // Set the Arduino digital pins as outputs.
  arduino = new Arduino(this, Arduino.list()[2], 57600);

  // Setup motors
  int i;
  for(i = 0; i < 2; i++){
    arduino.pinMode(motor_left[i], Arduino.OUTPUT);
    arduino.pinMode(motor_right[i], Arduino.OUTPUT);
  }
  arduino.pinMode(motor_speed, Arduino.OUTPUT);
  arduino.pinMode(pot, Arduino.INPUT);
  
  // initialize the headset
  ThinkGearSocket neuroSocket = new ThinkGearSocket(this);
  try {
    neuroSocket.start();
  } 
  catch (Exception e) {
    println("Is ThinkGear running??");
  }

}

void clearBackground() {
  background(40);
}


//================================= loop
void draw() {
  clearBackground();
  textFont(f, 180);                      //  Specify font to be used
  fill(255);                             //  Specify font color 
  text(attention, width/2, height/2);    //  Display Text
  textAlign(CENTER);
  
  arduino.analogWrite(motor_speed, int(attention*2.55));
  drive_forward();

}

//================================= drive

void motor_stop(){
  arduino.digitalWrite(motor_left[0], Arduino.LOW);
  arduino.digitalWrite(motor_left[1], Arduino.LOW);

  arduino.digitalWrite(motor_right[0], Arduino.LOW);
  arduino.digitalWrite(motor_right[1], Arduino.LOW);
  delay(25);
}

void drive_forward(){
  arduino.digitalWrite(motor_left[0], Arduino.HIGH);
  arduino.digitalWrite(motor_left[1], Arduino.LOW);

  arduino.digitalWrite(motor_right[0], Arduino.HIGH);
  arduino.digitalWrite(motor_right[1], Arduino.LOW);
}

void drive_backward(){
  arduino.digitalWrite(motor_left[0], Arduino.LOW);
  arduino.digitalWrite(motor_left[1], Arduino.HIGH);

  arduino.digitalWrite(motor_right[0], Arduino.LOW);
  arduino.digitalWrite(motor_right[1], Arduino.HIGH);
}

void turn_left(){
  arduino.digitalWrite(motor_left[0], Arduino.LOW);
  arduino.digitalWrite(motor_left[1], Arduino.HIGH);

  arduino.digitalWrite(motor_right[0], Arduino.HIGH);
  arduino.digitalWrite(motor_right[1], Arduino.LOW);
}

void turn_right(){
  arduino.digitalWrite(motor_left[0], Arduino.HIGH);
  arduino.digitalWrite(motor_left[1], Arduino.LOW);

  arduino.digitalWrite(motor_right[0], Arduino.LOW);
  arduino.digitalWrite(motor_right[1], Arduino.HIGH);
}

//================================= neurosky functions

void poorSignalEvent(int sigLevel) {
  sig=sigLevel;
}

void attentionEvent(int attentionLevel) {
  attention = attentionLevel;
}

void meditationEvent(int meditationLevel) {
  meditation = meditationLevel;
}

void blinkEvent(int blinkStrengthLevel) {
  blinkStrength = blinkStrengthLevel;
}

void eegEvent(int deltaLevel, int thetaLevel, int low_alphaLevel, int high_alphaLevel, int low_betaLevel, int high_betaLevel, int low_gammaLevel, int mid_gammaLevel) {
  delta = deltaLevel;
  theta = thetaLevel;
  low_alpha = low_alphaLevel;
  high_alpha = high_alphaLevel;
  low_beta = low_betaLevel;
  high_beta = high_betaLevel;
  low_gamma = low_gammaLevel;
  mid_gamma = mid_gammaLevel;
}

void rawEvent(int[] rawArray) {
}  

void stop() {
  neuroSocket.stop();
  super.stop();
}