Speech Controlled Quadropod
by Adith Jagadish in Circuits > Robots
42800 Views, 509 Favorites, 0 Comments
Speech Controlled Quadropod
This is my first post on Instructables and I am super excited to share my knowledge!
My original robot post is here: Spryo SpoonTail which is just my robot showing some tricks but with a tethered control.
In this Instructable I am going to show you how to make a quadrapod of your own and using speech recognition via bluetooth to control your bot.
Gotta thank Oddbot for introducing me to robotics and helping me on a lot of projects. I am gonna reference his Instructable in certain stages to make this one shorter (with his permission ofcourse!).
Update (24th May 2017): The DAGU quadropod is no longer available in stores. I do not have the CAD files for this design. Kindly use this guide for its speech recognition capabilities with Arduino and not for creating a quadropod itself. Also do note that BitVoicer has gone through updates as well which this Instructable does not reflect. This is an old guide in terms of technological breakthroughs in speech synthesis. If time permits, I will create a new Instructable with other speech software/tools like Alexa, Google Speech API, etc. That being said, feel free to go through the steps to learn what I did for this project and use what you need for your project. Good luck!
Understanding the Project
This project is not simple, in fact if you haven't worked with Arduino and python, this project would be quite challenging, but trust me the end product is completely worth it. Additionally, you will discover how simple and powerful both Arduino and python really are.
It is worth mentioning that the main reason I am making this Instructable is to show that remote control via Bluetooth using speech recognition is quite possible and ain't that hard. Also if you already have a robot of your own or even an RC car you have hacked, you can use this tutorial just for the speech recognition - control part.
Acknowledgements:
Getting Started
Hardware Required:
- Dagu Quadbot Chassis Kit
- Dagu Spider Controller
- Mini USB Cable
- Jumper wires (loads of em)
- Bluetooth Module HC-06
- Batteries (LiPo 7V-30V recommended)
- SRF05 Ultrasonic Sensor (optional)
- Bluetooth USB module (if your PC doesn't come with an inbuilt bluetooth, like in my case)
- LEDs (come on who doesn't like LEDs on their projects, however it is optional)
Software Required:
- Arduino - programming the quadropod
- Python 3.4 - communication
- Eclipse or Geany - python interface
- Bitvoicer ($5) - speech recognition or Google Speech Recognition via python (free but involves more coding)
Skills Recommended:
- Arduino knowledge
- Python language
- Patience (a lot required)
Note:
I am not advertising anything here, I am just linking you the products that I have used for my project, you are free to use tools/software/products of your liking or even make some on your own (think 3D printing).
Chassis Assembly
If you choose to use your own robot like an RC car, teddy bear or even a home automation device, feel free to skip this step.
Remember Oddbot who I mentioned before? He's basically my virtual mentor. What you are going to do now is follow steps 1 to 7 from his Instructable - Playful Puppy Robot or you could use this PDF Manual to assemble to chassis of the quadrapod.
That's it for this step.
Wiring
Lets connect the servos first, they go in like this:
- Front Left Hip servo - pin 46
- Front Right Hip servo - pin 52
- Rear Left Hip servo - pin 28
- Rear Right Hip servo - pin 13
- Front Left Knee servo - pin 47
- Front Right Knee servo - pin 53
- Rear Left Knee servo - pin 29
- Rear Right Knee servo - pin 12
Note: The servos can be connected to which ever pins you find convenient, you just have to change the code to correspond to that changed pin.
Then the HC-06 bluetooth module (figure 4):
- GND - GND
- VCC - +5V
- TXD - RX0 / D0 (Signal)
- RXD - TX0 / D1 (Signal)
Figure 1: Shows the layout of the majestic DAGU Spider Board (note I drew the GND, 5V and Signal regions on the board for those of you who are slightly lazy to go through the manuals which I anyway really really recommend you to do).
Figure 2: Shows the splendid HC 06 Bluetooth module which will be our "RC" for this project. For this specific project, we will only be using the module to receive messages.
Figure 3: Wiring of the HC 06 to an Arduino UNO (in cause you just want to test it with an UNO or similar board for your specific project).
Figure 4: Plugging the HC 06 module to the Spider Board (GND and VCC connections are upto you as long as they are in that same line).
Figure 5: What it should kind of look like with everything plugged it (don't worry about the shinny two 'eyes' in the front part of my bot, its just for show, and the servo on the back is for controlling his tail but the tail broke :( will fix it soon).
Coding
Arduino:
Launch Arduino and open a new sketch. Unfortunately I do not have sufficient time to teach you the basics of Arduino. You can look up some tutorials if you feel like. So this is what we are going to do, once you opened a new sketch: File >> New or Ctrl + N.
Copy Paste the following code (or just download the attached file). I owe Oddbot again for helping me out with the motion part of the code looooong looong back.
The code:
/* Title: Speech Controlled Quadropod Author: Adith Jagadish Boloor Comments: This code is free for you to use, modify or simply stare at when you are really bored. */ #include <Servo.h> // Servo Library // Starting positions of the servos #define FLHcenter 1500 #define FRHcenter 1500 #define RLHcenter 1520 #define RRHcenter 1450 #define FLKcenter 1150 #define FRKcenter 1220 #define RLKcenter 1220 #define RRKcenter 1210 // Here you can change servo pin numbers corresponding // to your specific connections #define FLHpin 46 // Front Left Hip servo pin #define FRHpin 52 // Front Right Hip servo pin #define RLHpin 28 // Rear Left Hip servo pin #define RRHpin 13 // Rear Right Hip servo pin #define FLKpin 47 // Front Left Knee servo pin #define FRKpin 53 // Front Right Knee servo pin #define RLKpin 29 // Rear Left Knee servo pin #define RRKpin 12 // Rear Right Knee servo pin // Buffer for the speech message char INBYTE; // LEDs!!!!! If you choose to use 'em int led1 = 27; int led2 = 11; int led3 = 45; int led4 = 26; // Some constants for the bot's motions, yes you may // play with them to get the best performance int Time = 90; int LShift = 280; int RShift = 280; int Raise = 550; // Define servos Servo FLHservo; Servo FRHservo; Servo RLHservo; Servo RRHservo; Servo FLKservo; Servo FRKservo; Servo RLKservo; Servo RRKservo; void setup() { // Attach servos (digitally) FLHservo.attach(FLHpin); FRHservo.attach(FRHpin); RLHservo.attach(RLHpin); RRHservo.attach(RRHpin); FLKservo.attach(FLKpin); FRKservo.attach(FRKpin); RLKservo.attach(RLKpin); RRKservo.attach(RRKpin); // Attach LEDs (digitally) pinMode(led1, OUTPUT); pinMode(led2, OUTPUT); pinMode(led3, OUTPUT); pinMode(led4, OUTPUT); Serial.begin(9600); // Center servos FLHservo.writeMicroseconds(FLHcenter); FRHservo.writeMicroseconds(FRHcenter); RLHservo.writeMicroseconds(RLHcenter); RRHservo.writeMicroseconds(RRHcenter); FLKservo.writeMicroseconds(FLKcenter+700); FRKservo.writeMicroseconds(FRKcenter+700); RLKservo.writeMicroseconds(RLKcenter+700); RRKservo.writeMicroseconds(RRKcenter+700); delay(500); // Prints out the controls mapped to different letters Serial.println("wasd - movement"); Serial.println("z - sleep"); Serial.println("x - play dead"); Serial.println("i - sit"); Serial.println("u - stand"); Serial.println("q - wake up"); } void loop() { Serial.println("Ready to accept command"); while (!Serial.available()); // stay here so long as COM port is empty INBYTE = Serial.read(); // read next available byte delay(50); if (INBYTE == 'q') // wake up - flashes LEDs if you used them { digitalWrite(led1, LOW); digitalWrite(led2, LOW); digitalWrite(led3, LOW); digitalWrite(led4, LOW); delay(200); digitalWrite(led1, HIGH); digitalWrite(led2, HIGH); digitalWrite(led3, HIGH); digitalWrite(led4, HIGH); delay(200); digitalWrite(led1, LOW); digitalWrite(led2, LOW); digitalWrite(led3, LOW); digitalWrite(led4, LOW); delay(200); digitalWrite(led1, HIGH); digitalWrite(led2, HIGH); digitalWrite(led3, HIGH); digitalWrite(led4, HIGH); delay(200); digitalWrite(led1, LOW); digitalWrite(led2, LOW); digitalWrite(led3, LOW); digitalWrite(led4, LOW); delay(200); digitalWrite(led1, HIGH); digitalWrite(led2, HIGH); digitalWrite(led3, HIGH); digitalWrite(led4, HIGH); delay(200); digitalWrite(led1, LOW); digitalWrite(led2, LOW); digitalWrite(led3, LOW); digitalWrite(led4, LOW); delay(200); digitalWrite(led1, HIGH); digitalWrite(led2, HIGH); digitalWrite(led3, HIGH); digitalWrite(led4, HIGH); } else if (INBYTE == 'z') //Sleeps { FLHservo.writeMicroseconds(FLHcenter); FRHservo.writeMicroseconds(FRHcenter); RLHservo.writeMicroseconds(RLHcenter); RRHservo.writeMicroseconds(RRHcenter); FLKservo.writeMicroseconds(FLKcenter+700); FRKservo.writeMicroseconds(FRKcenter+700); RLKservo.writeMicroseconds(RLKcenter+700); RRKservo.writeMicroseconds(RRKcenter+700); delay(1000); digitalWrite(led1, HIGH); digitalWrite(led2, HIGH); digitalWrite(led3, HIGH); digitalWrite(led4, HIGH); delay(200); digitalWrite(led1, LOW); digitalWrite(led2, LOW); digitalWrite(led3, LOW); digitalWrite(led4, LOW); delay(200); digitalWrite(led1, HIGH); digitalWrite(led2, HIGH); digitalWrite(led3, HIGH); digitalWrite(led4, HIGH); delay(200); digitalWrite(led1, LOW); digitalWrite(led2, LOW); digitalWrite(led3, LOW); digitalWrite(led4, LOW); delay(200); digitalWrite(led1, HIGH); digitalWrite(led2, HIGH); digitalWrite(led3, HIGH); digitalWrite(led4, HIGH); delay(200); digitalWrite(led1, LOW); digitalWrite(led2, LOW); digitalWrite(led3, LOW); digitalWrite(led4, LOW); delay(200); } else if (INBYTE == 'u') // stand Up { // Center servos FLHservo.writeMicroseconds(FLHcenter); FRHservo.writeMicroseconds(FRHcenter); RLHservo.writeMicroseconds(RLHcenter); RRHservo.writeMicroseconds(RRHcenter); FLKservo.writeMicroseconds(FLKcenter); FRKservo.writeMicroseconds(FRKcenter); RLKservo.writeMicroseconds(RLKcenter); RRKservo.writeMicroseconds(RRKcenter); delay(1000); } else if (INBYTE == 'x') // plays dead X { FLHservo.writeMicroseconds(FLHcenter); FRHservo.writeMicroseconds(FRHcenter); RLHservo.writeMicroseconds(RLHcenter); RRHservo.writeMicroseconds(RRHcenter); FLKservo.writeMicroseconds(FLKcenter+700); FRKservo.writeMicroseconds(FRKcenter+700); RLKservo.writeMicroseconds(RLKcenter+700); RRKservo.writeMicroseconds(RRKcenter+700); delay(1000); } else if (INBYTE == 'i') //sits { FLHservo.writeMicroseconds(FLHcenter); FRHservo.writeMicroseconds(FRHcenter); RLHservo.writeMicroseconds(RLHcenter-600); RRHservo.writeMicroseconds(RRHcenter+600); FLKservo.writeMicroseconds(FLKcenter); FRKservo.writeMicroseconds(FRKcenter); RLKservo.writeMicroseconds(RLKcenter+700); RRKservo.writeMicroseconds(RRKcenter+700); } else if (INBYTE == 'h') //shake Hands { FLHservo.writeMicroseconds(FLHcenter-600); FRHservo.writeMicroseconds(FRHcenter); RLHservo.writeMicroseconds(RLHcenter-600); RRHservo.writeMicroseconds(RRHcenter+600); FLKservo.writeMicroseconds(FLKcenter+600); FRKservo.writeMicroseconds(FRKcenter); RLKservo.writeMicroseconds(RLKcenter-700); RRKservo.writeMicroseconds(RRKcenter+700); delay(1000); FLKservo.writeMicroseconds(FLKcenter+300); delay(200); FLKservo.writeMicroseconds(FLKcenter+600); delay(200); FLKservo.writeMicroseconds(FLKcenter+300); delay(200); FLKservo.writeMicroseconds(FLKcenter+600); delay(200); } else if(INBYTE == 'w') // run forward { LShift=300; RShift=300; for(int i=0;i<5;i++) { Run(); } } else if(INBYTE == 'a') // turn left { LShift=-300; RShift=300; for(int i=0;i<3;i++) { Run(); } } else if(INBYTE == 'd') // turn right { LShift=300; RShift=-300; for(int i=0;i<3;i++) { Run(); } } else if(INBYTE == 's') // run back { LShift=-300; RShift=-300; for(int i=0;i<5;i++) { Run(); } } } void Run() { FRKservo.writeMicroseconds(FRKcenter+Raise); // raise front right leg RLKservo.writeMicroseconds(RLKcenter+Raise-10); // raise rear left leg FLHservo.writeMicroseconds(FLHcenter+LShift); // move front left leg backward RRHservo.writeMicroseconds(RRHcenter-RShift); // move rear right leg backward delay(Time/2); FRHservo.writeMicroseconds(FRHcenter+RShift); // move front right leg forward RLHservo.writeMicroseconds(RLHcenter-LShift); // move rear left leg forward delay(Time); FRKservo.writeMicroseconds(FRKcenter); // lower front right leg RLKservo.writeMicroseconds(RLKcenter); // lower rear left leg delay(Time); FLKservo.writeMicroseconds(FLKcenter+Raise); // raise front left leg RRKservo.writeMicroseconds(RRKcenter+Raise); // raise rear right leg FRHservo.writeMicroseconds(FRHcenter-RShift); // move front right leg backward RLHservo.writeMicroseconds(RLHcenter+LShift); // move rear left leg backward delay(Time/2); FLHservo.writeMicroseconds(FLHcenter-LShift); // move front left leg forward RRHservo.writeMicroseconds(RRHcenter+RShift); // move rear right leg forward delay(Time); FLKservo.writeMicroseconds(FLKcenter); // lower front left leg RRKservo.writeMicroseconds(RRKcenter); // lower rear right leg delay(Time); }
Just before you can upload the code, do the following:
Open device manager and look up Ports (COM & LPT). Note the active port for your Arduino. It might say USB Serial Port (COM3) so for me the COM port is 3, THIS MIGHT BE DIFFERENT FOR YOU.
Tools >> Board >> Arduino Mega or Mega 2560 (image 2)
Tools >> Processor >> ATMega 1280 (image 3)
Tools >> Port >> COM3 (3 for my case only!!) (image 4)
Now you can hit the upload button and if all goes smooth, it should upload successfully and the robot should be on its belly with four legs stretched out symmetrically with a steady LED blinking from the HC 06.
If you get this error while uploading:
avrdude: stk500_getsync(): not in sync: resp=0xe0
Just disconnect the HC06 module, upload the code and hook it back on.
Ok I realized something while I was testing and writing this tutorial. You don't need both BitVoicer and Python, you just need either of them. BitVoicer does everything for you and its speech recognition engine is quite powerful but it costs $5 while python's speech recognition uses Google Speech API so it can sometimes give some really weird results and has some more coding, so the choice is yours.
Bluetooth
Okay just before we move on to the speech recognition bit via BitVoicer or Python, lets link the bluetooth of your PC to the HC 06 of your bot. Make sure the bluetooth on your PC works before proceeding because it took me 5 hours to realize that my laptop didn't come with an inbuilt bluetooth and I had to order a module.
Now power up your bot either through USB or the battery pack. OMG when does this tutorial end!!!! Patience! You're almost there.
- Right Click on Bluetooth Devices icon in the tray bar and click add new device.
- Let it search and search and search until HC - 06 pops up
If it doesn't show up after sometime try checking if you can find the device using your mobile phone (every phone except Apple phones should be able to detect it). If you don't you know that there's something wrong with your HC-06 and you need to fix it by checking the connections. - Double click it.
- On the next dialogue box select Enter the device's pairing code and type in 1234. It should then install the HC 06 to your computer.
- Now this part is important open up device manager (Start >> Device Manager)
- Go to Ports (COM & LPT) and note down the COM ports used by the Bluetooth. COM10 and COM21 for my case.
BitVoicer (Option 1)
You can download BitVoicer from here.
First things first, if you are not a American English speaker you might want to change the language/accent that BitVoicer will try to recognize. To do this go to File >> Additional Languages and go on install your preferred language/accent.
Now we are ready to add some commands. For starters we are going to add just two commands namely stand up and sit down. You can edit them or add more commands later. The steps are as follows:
- Create a new Schema by going to File >> New.
- Change the default command data type to char.
- Click Add New Sentence
- Type in "stand up" (no quotes)
- Click Add New Sentence
- Type in "sit down" (again no quotes)
- Now below in Sentence Anagrams, change the data types of both commands to char if its not already char.
- For stand up type the command as u and for sit down type i.
- Your screen should look like Image 5.
- Save your schema in a directory that is convenient for you.
- Now open up preferences by File >> Preferences and fill in the stuff using. The only three things that will be different for you will be the Default Output Folder, Speech Recognition Language and the Port Name.
- Your Port Name will correspond to your COM Port that YOUR Bluetooth uses that you found out in step 6 in Bluetooth. Try the lower number first.
- Hit Save.
- Go to the next step.
Python (Option 2)
First download Python (for this tutorial I am going to use version 3.4) which can be downloaded from https://www.python.org/download/releases/3.4.1/ Why 3.4 and the not the 2.7 version? Well the speech recognition which we are using works only on the 3.4 version of python (ya I know that sucks but hey 3.4 > 2.7 right?)
Install it into C:\Python34 for convenience sake. Next thing you need to do is download and install eclipse which is an interface for writing your code via Python. You can download it from http://www.eclipse.org/downloads/ Install it into C:\eclipse
If you get this error while running it...
A Java Runtime Environment (JRE) or Java Development Kit (JDK) must be available in order to run Eclipse. No Java virtual machine was found after searching the following locations:
C:\eclipse\jre\bin\javaw.exe
javaw.exe in your current PATH
Go to the first answer in http://stackoverflow.com/questions/2030434/eclipse-no-java-jre-jdk-no-virtual-machine
www.stackoverflow.com is the best place to find help for any issues in python
Use this tutorial to install python into eclipse except instead of python 2.6 you should choose python 3.4. Alternatively use this tutorial to install python into Geany if you chose to use Geany which I hear is much nicer than eclipse but I haven't had enough time to migrate to it. There are something called 'libraries' that you will need to access the different functionality of python. Now lets go ahead and install some libraries that we need for this project. For those of you who already know how to install libraries just go ahead install the listed ones and go on to the code.
Libraries Required:
- PyBluez 0.20 - Bluetooth (setup)
- PyAudio 0.2.8 - provides bindings for speech recognition (setup)
- SpeechRecognition 1.1.0 - speech recognition (download)
PyBluez and PyAudio can be installed by downloading the "....win32-py3.4.exe" versions from the link and simply running the executable (setup) file.
SpeechRecognition library is a bit tricky if you're new to python. Open the 'download' link above and click downloads. Download "SpeechRecognition-1.1.0.tar.gz (md5)". Extract all the CONTENTS (not the folder that says SpeechRecognition-1.1.0 but whats in it) of the downloaded folder (via winRAR or any extractor you feel like using) to the python 3.4 directory (C:\Python34). If a dialogue box appears asking whether to replace existing files, click yes to all. Now navigate to C: drive and while holding Shift, right click on the folder that says Python34 and click "Open command window here". Type in "python setup.py install" without quotes and hit Enter. Now you should have all the required libraries installed. Yay!
Open eclipse.
Under the folder PythonTest from the tutorial create a new file called Speech_Controlled_Quadrapod.py similar to how you created the pytest.py file you created in the tutorial. Now paste or download...
The code:
# Title: Speech Controlled Quadrapod # Author: Adith Jagadish # Description: Uses Google's Speech Recognition API and python bluetooth library to control a quadrapod # How to: Say "stand up" to make bot stand up and say "sit down" to make it sit. # Say "stop listening to terminate the program" import bluetooth import speech_recognition as sr port = 1 bd_addr = "xx:xx:xx:xx:xx:xx" sock = bluetooth.BluetoothSocket( bluetooth.RFCOMM ) sock.connect((bd_addr, port)) r = sr.Recognizer() r.pause_threshold = 0.6 r.energy_threshold = 400 MESSAGE = "continue" print("Ready to accept command...\n") while (MESSAGE != "stop listening"): while (MESSAGE == "continue"): try: # use the default microphone as the audio source with sr.Microphone() as source: # listen for the first phrase and extract it into audio data audio = r.listen(source,timeout = None) # recognize speech using Google Speech Recognition print("Me: " + r.recognize(audio)) MESSAGE = str(r.recognize(audio)) except LookupError: # speech is unintelligible MESSAGE = "continue" print("Could not understand audio") if(MESSAGE == "sit down"): sock.send("i") elif(MESSAGE == "stand up"): sock.send("u") elif(MESSAGE == "stop listening"): break; MESSAGE = "continue" sock.close() print("\nProgram terminated.")
The only change you need to do is in the line:
bd_addr = "xx:xx:xx:xx:xx:xx"
Right click on the bluetooth icon on the tray and click on "Show Bluetooth Devices". Right click on HC-06 and click on properties. Go to the Bluetooth tab and copy the Unique identifier number and paste that in the place of xx:xx:xx:xx:xx:xx.
You are good to go on to testing.
Testing and Debugging
Well there's nothing much to say here than what you expect.
Testing:
- Power up the quadropod or your robot.
- Turn on your Bluetooth if you haven't done so already on your computer.
- Make sure your microphone is working.
- Launch BitVoicer or Python which ever you decided to use.
- Run the program.
- Say "stand up" or "sit down" as clearly as you can and see the magic unfold!
- Voila!
Now that you know the basics you can add more lines of code to make your bot do even more cool stuff!
If you weren't lucky enough to get it working in the first go, its okay! It happens to the best of us.
Debugging:
- Try Googling your issue
- Make sure your wiring is correct
- Your code is copied correctly
- If it still doesn't work, post a comment here and I'll try my best to help you out!