
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
and the Fritzing file
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
and the Fritzing file
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.
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:
Here is the image file,
Fritzing file
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,
Fritzing file
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(); }