This is a tiny, minimalist version of a popular biped robot design. I used tiny hobby servos, a very small lipo battery, a SHARP distance sensor and an ATtiny85 (previous version used an ESP8266 module).
Two legs, four servos, ATtiny85 for brains
This is a tiny, minimalist version of a popular biped robot design. I used tiny hobby servos, a very small lipo battery, a SHARP distance sensor and an ATtiny85 (previous version used an ESP8266 module).
All that was left was writing the code, and testing it. And making some corrections, and testing them. And fine-tuning some parameter, and testing. And then a little bit of testing.
All this time I was programming the robot using my programming clip. Unfortunately, it became a bit loose, so I had to hold it in place with my hand while programming, so it was a little inconvenient. Because of the placement of the chip, I also had to remove at least one leg every time I wanted to program it, and I had to disconnect the servos, as they take too much power and make the computer shut down the USB port. In the end, it was a lot of reprogramming, and I wish I had broken out the programming interface in some more convenient way. Oh well.
During testing, I also connected a piezo speaker to the last unused pin, and bit-banged beeps on it (it's not a timer pin, so couldn't do PWM, I guess something to consider for the next version). That helped in debugging a lot, since I could place different beeps in different places in the program, and I would know where the robot was. Since they were primitively bit-banged, the robot also paused while beeping, which let me see better the different phases of its movement.
At some point I decided to get rid of the old feed, and made new ones, out of an expired public transportation card. I also painted the new feet with liquid rubber, to give them a better grip.
You can also see on this photo, that I went back to the old battery. It fits in the hat, and it has a much better C value. I decided to not include the battery charger module in the robot this time -- you have to disconnect the battery for charging.
Finally, a video of the robot doing its thing. It checks the distance at every step, at the moment when the body is horizontal. I used the fact that with each step it's looking in a different direction, and I made it choose the direction of the turn based on that. Oh, I also sped up the final version of the code. Unfortunately, I had to remove the beeping code to make it all fit in 1kB for the challenge.
AVR Memory Usage ---------------- Device: attiny85 Program: 1006 bytes (12.3% Full) (.text + .data + .bootloader) Data: 19 bytes (3.7% Full) (.data + .bss + .noinit)The walking code turned out to be much larger than I expected -- even though it's mostly just calling a single function with three 16-bit integer parameters. I guess I could scale them down to bytes to save some space...
For the first time µBob has a working distance sensor on board (you might recall I tried to give it a distance sensor earlier, but it didn't work). So let's make use of it.
The sensor I'm using is a SHARP GP2Y0A60SZLF on a breakout board from Pololu. It's an analog sensor, which is good, because I can use only a single pin for it. All I have to do is get the ADC to work. A bit of googling for examples, and a little bit of cross-checking with the datasheet, and I had the basic procedure:
ADCSRA = 1<<ADEN | 1<<ADPS2 | 1<<ADPS1 | 0<<ADPS0; // Pre-scaler 64.
ADMUX = 0<<ADLAR | 0<<REFS1 | 0<<REFS0 | pin & 0x03;
ADCSRA |= 1<<ADSC;
while (ADCSRA & (1<<ADSC)) {
// Pass.
}
return ADCH << 8 | ADCL;
However, that didn't work. I spent half a day trying to figure out why it would keep returning the same number all the time, changing only on reset. Everything was exactly the same as in the datasheet, the examples, even the Arduino cores that I checked. What did I miss? After asking around a bit on IRC and robotics forums, someone pointed out to me that the order in which you read ADCH and ADCL is important -- there is a latch there, that makes sure the values won't change in the middle of your reading. Sure enough, I had the order wrong. The fix is very simple -- I can defer to the compiler to do the right thing by just doing:
return ADC;
That's it. Suddenly I started getting changing values, as expected. However, the changes still weren't in any way correlated with the voltage on the pin... Back to the drawing board. Four re-readings of the datasheet later I just tried the same program on a different chip, and it worked fine. Turns out the ATtiny85 that I have soldered to a breakout board some 2 years ago and used since for all sorts of uncanny experiments must have gotten the ADC broken somehow -- possibly by applying higher voltage than it should get.
In any case, the next step is checking the range of the sensor. I don't have any way to display the readings from the robot (and I want to check the readings in the robot, not on a separate circuit, because the voltages would be different), so I wrote a simple program that basically moves a servo depending on the value read from the sensor. Since I know the servo's range, I can guess what the reading was.
That worked pretty well, now I just need to fine-tune the walking algorithm to make the robot go straight, add some animations for turning and going backwards, and make a simple state machine switching between those animations depending on the sensor readings. Should fit in the ~400 bytes of program space I have left.
Today I'm continuing the work on resurrecting µBob. I decided to use a Pololu SHARP distance sensor (because it can work with 3V), and using a bit of hot glue I attached the pins to it, so that I can plug it in easily:
On the robot side, I used stacking headers to give some distance from the PCB:
Next, to make sure it will walk in this configuration, a quick test:
Then I worked on the body frame. I decided to use paperclips this time. Turns out you can solder them, so I bent them and soldered them into the holes in the PCB:
A little bit of hot glue, and the hat is back on:
Finally, I also transplanted the old mustache.
I really wanted to enter one of my robots into the 1kB contest, but unfortunately the inverse kinematics calculations result in quite some bit of code. I tried to use some pretty neat algorithms to get around that (see https://hackaday.io/project/6050-tote/log/50664-cordic), but in the end there is just too much happening on thet 8-bit microcontroller. Switching to a 32-bit microcontroller would probably helped, but then there is the size of all the HAL libraries and such -- it would probably come down to about the same, or worse. So I looked at the shelf on which my robots are standing, and saw µBob. It has hard-coded gait, so there should be no problem with calculations. However, it used an ESP8266, and that's again a lot of code in the SDK/Lua/MicroPython.
The robot also got quite beaten up on the last few conferences and maker fairs it has visited. The distance sensor never worked, the wires got loose, the battery inside shifted and changed its center of gravity, the feet lost some of the fingers, and the power switch is in a place that is really awkward to reach. So I decided to recycle the parts and make a new robot.
Time to re-build this robot again, with a little bit more of proper construction. I started with the PCB, because you have to wait for them so long. So I made this:The two big empty spaces are for attaching the servos. There is also room for a power switch and a battery connector, and a footprint for an ATtiny85. I got two pins free, so I've broken them out into some extra headers.Once the PCBs arrived, I quickly assembled one, and started to program the attiny. That took whole day, because for some reason the programming would fail at various stages with very strange results. Lowering the clock speed of the programmer, adding some jumpers and additional options would help sometimes and then break again later. In the end it turned out that the wires that I soldered to my programming clip came off, and weren't giving a good connection.
Next, I needed some code to drive the servos. Unfortunately, I couldn't use the code from #Mechatronic Ears, because this time I needed to drive 3 servos at once (actually 4, but two of them share a common signal). So I looked around and found a servo library for the ATtiny85. It was too big for my purposes, but I used the ideas from it to write my own, that's about 512 bytes (and probably can be further optimized).
Once I had that, I disassembled the poor µBob, and removed its legs:
Then I attached the servos to the new PCB, with a programmed ATtiny85 and a smaller battery (from those small quadcopters):The current status: the legs are just moving back and forth for now (testing the servos). Next, I will need some simple codo to make it move into poses, and then maybe I will attach a distance sensor and add some code for reading the ADC.So the PCBs arrived, and I assembled and tested one of the servo breakout boards. It's quite small, here's the comparison with a coin:
All the servo sockets (for those small, 3.3V servos) are on the back side:
There is also a voltage regulator there, and a couple of pullup resistors, and that's pretty much it. All pins except for the power are 1.27mm, to save space.
I finally found the motivation today to replace the distance sensor on µBob. That involved de-soldering the ESP-12 module, replacing the sensor, bending the legs just right, replacing the power switch with a smaller one, and re-soldering the ESP-12. I also made a small change in the software, to make it start walking immediately after being powered on -- this way I can show it off at various conferences and talks without having to connect to WiFi to issue the commands.
I also tested the new sensor (after moving the battery out of the way), but it seems that it's not working properly. The previous one was always high, this one is always low. Using a cellphone camera I can see that the light in the sensor is actually shining properly, so I suppose it's something wrong with my wiring -- either the connections are wrong, or the PCB that I etched has some gap or short. Either way, no sensors for this version of µBob.
I other news, while Micropython for the ESP8266 is still very experimental and not suitable yet to control this robot, there is some very nice support for ESP8266 in the Arduino IDE now, and the have ported the Servo library. They claim it can support up to 12 servos with a single timer, and up to 24 with the second one used. Which makes me wonder how I would connect them all when the best module so far, ESP-12, has only 10 usable GPIO pins (well, 11 if I use some trick to have GPIO15 held down at boot). There are some rumors about an ESP-12D module, which has 2 additional usable GPIO pins due to using a dual-channel flash chip, instead of quad-channel one, but nobody seems to have those in stock. In any case, that would let me build an ESP-based quadruped robot, so took some time already to design a servo breakout board for it:
It's one inch by one inch, has room for a dozen of those ultra-micro servos, a voltage regulator, and free analog pin, which could maybe be used for some sensor... If I can't find an ESP-12D, an ESP-12 will also work, sans 2 servos. But I can still build a quadruped like #Katka, a mammalian robot with just eight of the servos.
I have a lot of bad luck with this project. Or maybe I'm just sloppy. Anyways, I uploaded the nodemcu firmware, uploaded the uBob code, and decided it's time to test the servos -- to do that, I need to run it from a battery. So I got out my battery, and tried to connect it, but the connector wouldn't want to fit... So I forced it. And when I saw the blue smoke, I realized I connected it backwards...
The module fried, along with the power switch. Probably also the distance sensor.
I quickly desoldered the fried module and switch, and soldered new ones (ugh, my stash is running out). Uploaded firmware, uploaded code, connected battery, connected servos, ran it:
It works! Of course I switched two of the pins, but that's a small correction in the software. But does the distance sensor work? A quick test says "no". It always returns 1. And I don't know if it's a bad connection, bad wiring, or if I fried it too. I also don't have enough motivation now to desolder everything and solder a new sensor, so I'm putting it off to some later date. Maybe by that time I can use Micropython!
As I mentioned previously, I'm remaking µBob's brains. It's still going to be an ESP8266, but this time it's the ESP-12 module, and it's properly mounted on a printed circuit board that I have etched myself! Also, a distance sensor. But first, the board:
As you can see, the quality is abysmal. After several failed attempts at transferring the toner from the printed page to the board properly, I finally decided to call it "good enough", fix the most glaring problems with acrylic paint and etch the thing. Surprisingly, the drilling went well and I only broke one drill bit. Then I covered all the traces with solder, and fixed the broken traces with small pieces of wire. Soldered all the parts, and here it is:
You can see the module, the distance sensor, and one of the two SMD capacitors I had to add for it. On the other side:
You see the four servo sockets, the power switch, and a bunch of headers for power and debugging. Then I went over the board with an ohm-meter. And I'm glad I did! after removing a couple of short circuits that would have fried my programmer, I decided I'm ready to risk, and actually connected the thing to my computer:
Seems like at least some connections work, because I was able to flash Micropython to it, and get a REPL prompt on the serial console. I'm afraid to check if the servo connections and the distance sensor work...
Also, I will have to upload NodeMCU firmware to it for now, as the Micropython one doesn't support PWM yet, and I'm not sure I'm up to bit-banging it by brute force.
The PCB I made for µBob last time didn't work out so well, so I set out to make another one. This time with the ESP-12 module, as the ESP-03 I used before got broken in transport (I soldered some parts, including the power switch, directly to the module, and when there was some force applied on them during transport, they stripped the traces on the module).
I also got inspired by the Bob jr. robot and decided to make it a proper autonomous robot -- with a distance sensor! I'm going to use one of those teeny little digital Sharp sensors, this one should detect stuff between 2 and 10cm, which sounds about right for this size of a robot.
So I have my PCB designed, and now I'm struggling with transferring the toner from a print onto the board. The latest attempt is almost acceptable, if not for several places where the toner didn't transfer for some reason:
So I was presenting my robots on this year's PyCon.us, and this little guy didn't survive the flight over the Big Pond. It looks like the ESP8266 board is fried. When I get home, I will rebuild it properly, on a printed circuit board and with some nice distance sensors, and, most importantly, a voltage regulator.
First, you will need a PCB. There is a Fritzing file in the repository, which you can use to generate the gerbers and order it, and here is an OSHPark order you can use: https://oshpark.com/shared_projects/qjZ6fhAS
Once the PCBs arrive, you have to cut all the excess pieces, and polish the resulting irregularities. Depending on the servos you have, you might also need to file the PCB a bit to make them fit well. My servos fit exactly right, with some force, but you never know.
Assemble the PCB -- solder the switch, the power socket, the servo sockets, the chip. Make sure to put two of the servo sockets on one side, and two on the other side -- so that you don't have to move wires through the PCB.
[this comment has been deleted]
Please take your blatant and useless advertising somewhere else. Kindly delete this comment, or I will report it.
Very awesome project you have here, Radomir. I am going to try this out as well... One question, you mention that you can only use 3 PWM pins at a time, is this simply a limitation of the ESP chip or did your module only have 3 PWM pins broke out? Also, did you happen to make a schematic? Thanks!
Thank you.
The limit of 3 servos is due to the NodeMCU firmware that I'm using, which only allows you to have 1 PWM timer with 3 channels at most. So you can have one frequency and 3 different duty cycles on any 3 pins. I don't know if the limitation is arbitrary, or due to the underlying SDK that they used, or maybe hardware. I suppose in the worst case I could bit-bang PWM using the alarms, but fortunately I didn't have to.
I still have a few pins available, and I plan to attach a distance sensor there, when it finally arrives. Then it can have a little more interesting behavior than "Onward!".
I posted the schematic as a new project log. Let me know if you have any questions.
Awesome i love Bipeds, interesting to see new ways of programming them, would be cool if the hat can add some festure