I was just reading over some of my previous posts, when I suddenly realised:
They are really boring.
Useful - I hope - to those of you who are interested in building humanoid robots, but probably not that exciting to read.
There were two reasons I decided to create this blog. Firstly, I wanted to have what I have just now decided should be called a "blogbook". This is a collection of my notes on the project of writing software for my humanoid robot, so that I can refer back to it when I forget something, or at least a space where I can get my thoughts to sit down and stay in one place. Making it avaliable online adds the important contribution of allowing other people to read about my mistakes, and how not to make them.
The second reason for starting this blog is that I find humanoid robots completely fascinating. I find that enthusiasm is contagious - everyone has a favourite science/music/drama teacher who was so passionate and dedicated to their subject that they made learning something you wanted to do. I hope that reading about my endeavours will encourage more people to learn about robots and the field of mechatronics. Perhaps you will start your own robotics project.
Up until now, most of the posts have fallen very much into the former category, so the remainder of this post is dedicated to the latter. Lets look at some cool robots!
First up, we have HINA by mujaki. I personally love this video - when I first saw it, it set my imagination on fire. All of the servos and parts are completley custom made, and it reminds me of Plum and Kotoko from Chobits. Not only does it bridge the uncanny valley most successfully, but the video demonstrates exactly why we all should want a tiny robotic servant within the next 10 years.
The red robot is an early version of Omni Zero - before he put on all that weight. I find it interesting the way that he jogs in place, which I assume is a method of getting feedback for him to have dynamic balance. The best thing about Robo-one is that it tackle's the problem of bipdeal robots so casually - for decades, the problem of humanoid robotics seemed unsolvable, but now it's progressed to the level that robots can not only walk - they can wrestle.
Top Posts
Recent Posts
Monday, December 14, 2009
Thursday, December 10, 2009
Son of Voltron
Enabling the robot to recharge it's own batteries was something I wanted to get done sooner rather than later. One of the primary reasons for this is that it meant I needed to periodically switch back to the default firmware if I wanted to charge up the batteries. The second reason though, was that it was a very appropriate stepping-stone on the way to getting several other features working.
You see, the atmel 128 Analog to Digital Converter has a built in multiplexer which allows the single peripheral to measure up to eight different voltage nodes relative to ground potential or other nodes, at various levels of gain. Even better, these sources and configurations are software selectable by the use of a 5-bit multiplexer.
If all that sounded like technobabble to you, the long and the short of it is that the same basic code which measures the power left in the batteries can be used to get distance readings from the IR sensor, and sound input from the microphone!
But back to the power level sensor. This version of the code uses the debug info LED configuration to report the current level of the battery. If your robot is not plugged in, you can actually see the voltage drop when PF1/2 are pressed and the servos are moving. This is achieved by setting the multiplexer ADMUX to channel ADC1, and enabling the AD conversion complete interrupt in ADCSRA, which saves the voltage to the global location gA2D. It is only occasionally necessary to know the voltage, so conversion requests are triggered manually (as opposed to continuously) by setting the ADSC bit.
Recharging is enabled by setting bit 4 on PORTB, which digitally connects the battery to the external power source. Pressing and holding PF1 and PF2 for 2.5 seconds enters recharge mode, which trickle charges the NiMH batteries. Because I'm paranoid after the previous incident, the default setting is to only charge the robot for 10 seconds at a time. If you want to fully charge the batteries, pressing PF1 while the robot is charging will keep the batteries charging indefinitely.
"But Alex!" hear you cry. "If you can measure the voltage, why not simply disable charging when it's maxed out?"
Unfortunately, it's not that simple. When the external power source is present, the RBC automatically changes over the V++ supply to the power pack and becomes the voltage source. This means that whenever the plug is in, the value of gA2D will be that of the power source - even when the battery is low. I haven't figured out a way around this - you might also have noticed that there is no automatic recharge cut-off for the default firmware either.
The code is here. I'm looking for a better hosting service, but in the meantime, remember the click the "free" tab.
You see, the atmel 128 Analog to Digital Converter has a built in multiplexer which allows the single peripheral to measure up to eight different voltage nodes relative to ground potential or other nodes, at various levels of gain. Even better, these sources and configurations are software selectable by the use of a 5-bit multiplexer.
If all that sounded like technobabble to you, the long and the short of it is that the same basic code which measures the power left in the batteries can be used to get distance readings from the IR sensor, and sound input from the microphone!
But back to the power level sensor. This version of the code uses the debug info LED configuration to report the current level of the battery. If your robot is not plugged in, you can actually see the voltage drop when PF1/2 are pressed and the servos are moving. This is achieved by setting the multiplexer ADMUX to channel ADC1, and enabling the AD conversion complete interrupt in ADCSRA, which saves the voltage to the global location gA2D. It is only occasionally necessary to know the voltage, so conversion requests are triggered manually (as opposed to continuously) by setting the ADSC bit.
Recharging is enabled by setting bit 4 on PORTB, which digitally connects the battery to the external power source. Pressing and holding PF1 and PF2 for 2.5 seconds enters recharge mode, which trickle charges the NiMH batteries. Because I'm paranoid after the previous incident, the default setting is to only charge the robot for 10 seconds at a time. If you want to fully charge the batteries, pressing PF1 while the robot is charging will keep the batteries charging indefinitely.
"But Alex!" hear you cry. "If you can measure the voltage, why not simply disable charging when it's maxed out?"
Unfortunately, it's not that simple. When the external power source is present, the RBC automatically changes over the V++ supply to the power pack and becomes the voltage source. This means that whenever the plug is in, the value of gA2D will be that of the power source - even when the battery is low. I haven't figured out a way around this - you might also have noticed that there is no automatic recharge cut-off for the default firmware either.
The code is here. I'm looking for a better hosting service, but in the meantime, remember the click the "free" tab.
Thursday, December 3, 2009
If I only had a brain
As promised, I have made some changes to the robobuilder source files so that movement commands execute properly.
The problem seemed to be that the wCK transmit interrupt was being disabled prematurely, before all of the instructions could be sent. General defensive programming practice on behalf of the designers meant that any function which placed commands into the transmit buffer intentionally waited patiently until the buffer was empty. This avoided accidentally fragmenting the instructions due to the limited size of the buffer, but meant that the program would just freeze up if (for whatever reason) the transmissions were not being sent.
With a little debugging, I identified the MakeFrame() function as the culprit, which was causing the program to get stuck waiting for the transmit queue to clear, but since the interrupt was disabled it stayed in an infinite loop. Simply placing a few lines inside the while loop making sure that the interrupts were enabled fixed the problem.
I also made a few other aesthetic changes - mostly making things more readable by replacing "magic numbers" with the names of registers. For the uninitiated, A |= (1<<X) means 'set' bit X in register A, while A &= ~(1<<X) will 'clear' the bit. The header file iom128.h in avr-libc contains the names of all the registers.
Overall, the code here is a very good starting point if you want to start messing around with your robobuilder's brain. However, the functions do a LOT of polling, which should be replaced with interrupt based timing control if you plan to implement more complicated functions.
The files can be found here. I apologise for the horrible free hosting service. Be sure you click on the "Free" tab before you hit download.
My next goal is to figure out how the recharging procedure works, and give the robot some sort of power management routine. Perhaps eventually he will be able to detect when his batteries are dying and go recharge himself.
The problem seemed to be that the wCK transmit interrupt was being disabled prematurely, before all of the instructions could be sent. General defensive programming practice on behalf of the designers meant that any function which placed commands into the transmit buffer intentionally waited patiently until the buffer was empty. This avoided accidentally fragmenting the instructions due to the limited size of the buffer, but meant that the program would just freeze up if (for whatever reason) the transmissions were not being sent.
With a little debugging, I identified the MakeFrame() function as the culprit, which was causing the program to get stuck waiting for the transmit queue to clear, but since the interrupt was disabled it stayed in an infinite loop. Simply placing a few lines inside the while loop making sure that the interrupts were enabled fixed the problem.
I also made a few other aesthetic changes - mostly making things more readable by replacing "magic numbers" with the names of registers. For the uninitiated, A |= (1<<X) means 'set' bit X in register A, while A &= ~(1<<X) will 'clear' the bit. The header file iom128.h
Overall, the code here is a very good starting point if you want to start messing around with your robobuilder's brain. However, the functions do a LOT of polling, which should be replaced with interrupt based timing control if you plan to implement more complicated functions.
The files can be found here. I apologise for the horrible free hosting service. Be sure you click on the "Free" tab before you hit download.
My next goal is to figure out how the recharging procedure works, and give the robot some sort of power management routine. Perhaps eventually he will be able to detect when his batteries are dying and go recharge himself.
Subscribe to:
Posts (Atom)