Voice controlled Lego merry-go-round
Build a model using lego and a motorDrive the motor at various speed using an arduino board as variable frequency drive
Send commands to the arduino board using your voice, through
a Processing sketch on your computer and bluetooth
That's it, and it works
Description
hardware
A Lego motor - old motor from Lego technics - DC current - 4.5V
Arduino - Uno in our case
Bluetooth board - ref
Transistor
Diode
Breadboard and jumper cables
Arduino code :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
char val; // variable to receive data from the serial port | |
#include <SoftwareSerial.h> | |
int x = 0; | |
int motor = 9; | |
int bluetoothTx = 2; // TX-O pin of bluetooth mate, Arduino D2 | |
int bluetoothRx = 3; // RX-I pin of bluetooth mate, Arduino D3 | |
SoftwareSerial bluetooth(bluetoothRx, bluetoothTx); | |
int ledpin = 13; // Arduino LED pin 13 (on-board LED) | |
void setup() { | |
pinMode(ledpin, OUTPUT); // pin 13 (on-board LED) as OUTPUT | |
pinMode(motor, OUTPUT); | |
Serial.begin(9600); // Begin the serial monitor at 9600bps | |
bluetooth.begin(115200); // The Bluetooth Mate defaults to 115200bps | |
bluetooth.print("$"); // Print three times individually | |
bluetooth.print("$"); | |
bluetooth.print("$"); // Enter command mode | |
delay(100); // Short delay, wait for the Mate to send back CMD | |
bluetooth.println("U,9600,N"); // Temporarily Change the baudrate to 9600, no parity | |
//bluetooth.println("S~6"); | |
// 115200 can be too fast at times for NewSoftSerial to relay the data reliably | |
bluetooth.begin(9600); // Start bluetooth serial at 9600 | |
// Serial.begin(9600); // start serial communication at 9600bps | |
Serial.println("connected"); | |
digitalWrite(ledpin, HIGH); // turn ON the LED | |
} | |
void loop() | |
{ | |
if(bluetooth.available()) // If the bluetooth sent any characters | |
{ | |
// Send any characters the bluetooth prints to the serial monitor | |
val = bluetooth.read(); // read it and store it in 'val' | |
Serial.print(val); | |
} | |
if( val == 'H' ) // if 'H' was received | |
{ | |
digitalWrite(ledpin, HIGH); // turn ON the LED | |
x = min(x+20,255); | |
} | |
if( val == 'L' ) // if 'L' was received | |
{ | |
digitalWrite(ledpin, LOW); // otherwise turn it OFF | |
x = max(x-20,0); | |
} | |
//scaling signal : tackling the 0 value first, | |
if(x<10){ | |
analogWrite(motor,0); | |
} | |
else | |
{ | |
// then if not zero, scales the signal to the band that creates motion to the motor only | |
analogWrite(motor, map(x,0,255,140,255)); // set motor speed | |
} | |
//send the actual speed value (0 to 255) over serial and bluetooth | |
Serial.println(x); | |
bluetooth.println(x); | |
val =0; | |
delay(100); // wait 100ms for next reading | |
if(Serial.available()) // If stuff was typed in the serial monitor | |
{ | |
// Send any characters the Serial monitor prints to the bluetooth | |
bluetooth.print((char)Serial.read()); | |
} | |
// and loop forever and ever! | |
} |
Processing code :
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Sketch listens to the mic input, analyses the spectrum and tests if the max amplitude is higher or lower than a reference | |
//draws the max amplitude as a line | |
// establishes a BT connection to a device (list of ports shown first in console) | |
// then sends a command H if sound is pitched higher than reference, L is lower | |
// on the receivers side, uses a sketch on arduino to listen to BT and determine an action (sets speed of a motor for eg....) | |
import processing.sound.*; | |
import processing.serial.*; | |
Serial port; | |
boolean connected; | |
FFT fft; | |
AudioIn in; | |
int bands = 512; | |
String val; | |
float[] spectrum = new float[bands]; | |
int maxi = 0 ; | |
float maxamp = 0; | |
float average =0; | |
float sumspectrum = 0; | |
int treshold = 30; | |
String[] lports ; | |
void setup() { | |
size(1000, 660); | |
//fullScreen(); | |
background(255); | |
//displays list of ports | |
lports = Serial.list(); | |
//println(lports); | |
// connects to selected port - first port displayed is number 0 | |
try { | |
port = new Serial(this, Serial.list()[4], 9600); | |
connected = true; | |
} | |
catch(Exception e) { | |
connected = false; | |
} | |
// Create an Input stream which is routed into the Amplitude analyzer | |
fft = new FFT(this, bands); | |
in = new AudioIn(this, 0); | |
// start the Audio Input | |
in.start(); | |
// patch the AudioIn | |
fft.input(in); | |
} | |
void draw() { | |
background(255); | |
strokeWeight(1); | |
stroke(60); | |
//draw a vertical line in the center - shows the treshold for sound processing | |
line(width/2,height, width/2, 0); | |
//displays list of ports if not connected | |
if(!connected) { | |
textSize(10); | |
fill(100); | |
text("Not connected : select port below",20,9); | |
for (int p = 0; p < lports.length;p++) { | |
text(p+" : " + lports[p],20,20+p*11); | |
} | |
} else | |
{ | |
textSize(10); | |
fill(100); | |
text("Connected to bluetooth Arduino",20,9); | |
} | |
//Starts fft analysis | |
fft.analyze(spectrum); | |
for(int i = 0; i <treshold * 2; i++){ | |
// The result of the FFT is normalized | |
if(spectrum[i] > maxamp){ | |
maxamp = spectrum[i]; | |
maxi = i; | |
} | |
//draw the spectrum on the screen | |
line(0.5*i*width/treshold,height/2 + spectrum[i]*height*3,0.5*i*width/treshold, height/2 - spectrum[i]*height*3); | |
//computes the average frequency of the spectrum - will be used to drive the arduino motor | |
average+=i*spectrum[i]; | |
sumspectrum+=spectrum[i]; | |
} | |
average = average / sumspectrum; | |
maxi = int(average); | |
//draws the average freauency | |
strokeWeight(10); | |
stroke(200); | |
line(0.5*maxi*width/treshold,height/2 +maxamp*height*5, 0.5*maxi*width/treshold, height/2 - maxamp*height*5); | |
//retains only sounds with a clear main freauency to interact with the motor | |
if(maxamp>0.04) { | |
//displays the frequency | |
stroke(255,0,0); | |
strokeWeight(5); | |
line(0.5*maxi*width/treshold,height/2 +maxamp*height*3,0.5*maxi*width/treshold, height/2 - maxamp*height*3); | |
println(maxi+" "+maxamp); | |
//determine if the frequency is higher or lower than the treshold and sends command over COM port if available | |
if(maxi>treshold) { | |
if(connected){ port.write('H');} | |
//write text sent to bluetooth port | |
textSize(20); | |
fill(200); | |
text(maxi + " H",width*3/4,30); | |
} else { | |
if(connected){port.write('L');} | |
//write text sent to bluetooth port | |
textSize(20); | |
fill(200); | |
text(maxi + " L",width/4,30); | |
} | |
} | |
maxi=0; | |
maxamp = 0; | |
average =0; | |
sumspectrum = 0; | |
//read value returned by the bluetooth serial link - actual motor speed | |
if(connected) { | |
while (port.available() > 0) { | |
val = port.readStringUntil('\n'); // read it and store it in val | |
//int intVal = Integer.parseInt(val.trim()); | |
//println(val); | |
} | |
} | |
// displays the actual value | |
textSize(12); | |
fill(200); | |
String txt = "actual speed:"+val+"/255"; | |
text(txt,width/2.5,30); | |
//adds a delay to the loop to prevent over processing sounds and sending too many commands | |
delay(50); | |
} |
Comments
Post a Comment