I’ve always wanted to make a walking robot. I wanted to make something fairly rapidly and cheaply that I could try to get walking.
And so, 24 hours of hardware and software hacking later:
He’s waving only by a short amount because otherwise he falls over 🙂 Took a day and half to do, so overall I’m pretty pleased with it. It uses 17 MG996R servos, and a Chinese rtrobot 32 servo controller board.
Reverse Engineering Servo board
The controller board amazingly provides INCOMPLETE instructions. The result is that anyone trying to use this board will find that it just does not work because the board completely ignores the commands that are supposed to work.
I downloaded the example software that they provide, which does work. I ran the software through strace like:
$ strace ./ServoController 2>&1 | tee dump.txt
Searching in dump.txt for ttyACM0 reveals the hidden initialization protocol. They do:
open("/dev/ttyACM0", O_RDWR|O_NOCTTY|O_NONBLOCK) = 9 write(9, "~RT", 3) = 3 read(9, "RT", 2) = 2 read(9, "\27", 1) = 1 ioctl(9, TCSBRK, 1) = 0 write(9, "~OL", 3) = 3 write(9, "#1P1539\r\n", 9) = 9
(The TCSBRK ioctl basically just blocks until nothing is left to be sent). Translating this into python we get:
#!/usr/bin/python import serial from time import sleep ser = serial.Serial('/dev/ttyACM0', 9600) ser.write('~RT') print(repr(ser.read(3))) ser.write('~OL') ser.flush() ser.write("#1P2000\r\n") # move motor 1 to 2000 sleep(1) ser.write("#1P1000\r\n") # move motor 1 to 1000 print("done")
(Looking at the strace more, running it over multiple runs, sometimes it writes “~OL” and sometimes “OL”. I don’t know why. But it didn’t seem to make a difference. That’s the capital letter O btw.)
I wanted to have a crude sensor measurement of which way up it is. After all, how can it stand up if it doesn’t know where up is? On other projects, I’ve used an accelerometer+gyro+magnetometer, and fused the data with a kalman filter or similar. But honestly it’s a huge amount of work to get right, especially if you want to calibrate them (the magnetometer in particular). So I wanted to skip all that.
Two possible ideas:
- There’s a really quick hack that I’ve used before – simply place the robot underneath a ceiling light, and use a photosensitive diode to detect the light (See my Self Balancing Robot). Thus its resistance is at its lowest when it’s upright 🙂 (More specifically, make a voltage divider with it and then measure the voltage with an Arduino). It’s extremely crude, but the nice thing about it is that it’s dead cheap, and insensitive to vibrational noise, and surprisingly sensitive still. It’s also as fast as your ADC.
- Use an Android phone.
I want to move quickly on this project, so I decided to give the second way a go. Before dealing with vibration etc, I first wanted to know whether it could work, and what the latency would be if I just transmitted the Android fused orientation data across wifi (UDP) to my router, then to my laptop, which then talks via USB to the serial board which then finally moves the servo.
So, I transmitted the data and used the phone tilt to control the two of the servos on the arm, then recorded with the same phone’s camera at the same time. The result is:
I used a video editor (OpenShot) to load up the video, then measured the time between when the camera moved and when the arm moved. I took 6 such measurements, and found 6 or 7 frames each time – so between 200ms and 233ms.
That is.. exactly what TowerKing says is the latency of the servo itself (Under 0.2s). Which means that I’m unable to measure any latency due to the network setup. That’s really promising!
I do wonder if 200ms is going to be low enough latency though (more expensive hobby servos go down to 100ms), but it should be enough. I did previously do quite extensive experimental tests on latency on the stabilization of a PID controlled quadcopter in my own simulator, where 200ms delay was found to be controllable, but not ideal. 50ms was far more ideal. But I have no idea how that lesson will transfer to robot stabilization.
But it is good enough for this quick and dirty project. This was done in about 0.5 days, bringing the total so far up to 2 full days of work.
Cost and Time Breakdown so far
|Metal skeleton||$99 USD|
|17x MG996R servo motors||$49 USD|
|RT Robot 32ch Servo control board||$25 USD|
|Delivery from China||$40 USD|
|USB Cable||$2 USD|
|Android Phone||(used own phone)|
For tools, I used nothing more than some screwdrivers and needle-nosed pliers, and a bench power supply. Around $120 in total. I could have gotten 17x MG995 servos for a total of $45, but I wanted the metal gears that the MG996R provide.
|Mechanical build||1 day|
|Reverse engineering servo board||0.5 days|
|Hooking up to Android phone + writing some visualization code||0.5 days|
|Blogging about it 🙂||0.5 days|
Future Plans – Q Learning
My plan is to hang him loosely upright by a piece of string, and then make a neural network in tensor flow to control him to try to get him to stand full upright, but not having to deal with recovering from a collapsed lying-down position.
Specifically, I want to get him to balance upright using Q learning. One thing I’m worried about is the sheer amount of time required to physically do each tests. When you have a scenario where each test takes a long time compared to the compute power, this just screams out for Bayesian learning. So… Bayesian Q-parameter estimation? Is there such a thing? A 10 second google search doesn’t find anything. Or Bayesian policy network tuning? I need to have a think about it 🙂