| No Comments
I've been very busy with other things just recently and so I haven't been able to spend much time on this project. Work has been busy as I'm working towards a new release of my code and my son Scott was born on 25th January. Right now I have very little spare time for my robotics but I'm sure that will change as things settle into a new routine. 

Bug in v7.0 of the servo controller firmware

| 1 Comment
The simple servo sequencer that I've been working on has exposed a bug in the servo controller firmware. The bug is due to stack corruption during movement completion notifications, so it only happens if you use the 'multi-move' commands or the delay move command. The problem is that at the end of SerialSendMoveCompletionNotification we jump back to the serial data accumulation loop rather than using a ret to return... Since we enter SerialSendMoveCompletionNotification via a call rather than a jump we are failing to balance the stack and so eating two bytes each time we call the function. Eventually the stack usage will  start to overwrite our data space and cause 'strangeness'. The fix is simple, remove the jump and replace it with a ret.

The sequencer has also exposed an issue which I think lies with my current servos. After continuous 'stepping'; i.e. running the single leg as if it were walking for around 40-50 commands (15 steps), some of the servos start to slow down, there doesn't seem to be anything wrong with the servo controller as the TextStar Serial LCD Display in "Servo monitor mode" was showing that the signals were still good and my multimeter showed that the servos weren't trying to pull too much power. It seems to be a torque or heat issue; more investigation is required, but things seem fine if I'm just running servos that don't have a load on them...

Where are we?

| 1 Comment
Once the servo controller code was feature complete I switched to looking at the hardware side of things and thinking about the next stage, the servo sequencing.

From a hardware point of view I had several things to work on. Firstly I needed to get the servo controller and I/O multiplexor chips off of a breadboard and onto something a little more permanent. Since I still find building things with perfboard a little hard I decided to build the controller itself on one board and build separate daughter boards for the I/O multiplexing. This should mean that I can replace the parts separately as long as the connections required remain the same. I decided that each I/O daughter board could contain 2 CD74HCT238E's with some header pins for each of the 16 output channels, 3 pins for the address selection lines and 2 more for the signal lines. I deliberately left off the power and ground pins for the servos as these really didn't work well on the perfboard. The power and ground pins are connected in one direction and the IC to servo control connections are in another direction; without some fairly hairy board trace cutting and cross soldering doing both on a single perfboard would have been impossible. My solution was to build yet another separate board from a different style of perfboard for the servo power and ground connections; this was just two long strips of headers connected as two buses.  The servo connectors themselves are then used to physically hold the two boards together. This has another advantage for me in that it will allow me to reuse the I/O board with a more complex power and ground supply board if I decide to investigate the servo torque feedback idea some more (this may require monitoring each of the servo power lines and so would require a different style of power supply board).

Here are some pictures of the resulting boards.
I now need to build another I/O board and I'll have 32 PWM channels for my servos. 

The servo controller itself ended up being on a board which could probably be used for all manner of ATMega projects. The board contains header pins for the I/O lines that I need, a reset button, a socketed crystal, power buses and an ISP programming header. About the only thing that's been specially done for the servo controller application is the fact that the I/O multiplexor address lines have 4 banks of headers broken out so that I can connect multiple I/O boards to the servo board easily. The board is pretty much complete and works well; I'm especially pleased with the ISP header as it was quite tricky to fit onto the board due to the connections required. All that's currently missing are the caps on the clock lines, but the board works pretty well without them and they're currently on order and there's space on the board for them. Note that a slight physical design error meant that the single power and ground pins that I had intended to use were in the way of the ISP plug. I cut those off and replaces them with the longer header strips which work better as they give me somewhere else to get a power or ground connection from...
Once all of this was done I tested things and then swapped out my Max232 board for the Sparkfun regulated XBee breakout board and connected the XBee in place of the hard wired RS232 connection. This worked well and left me with a set of boards that only required a power line to tether them; the battery system is on my list of things to work out. Unfortunately I managed to brick one of my XBee's. I'm still not quite sure what happened but I think it could have been either a spike on the 5v power line or a 5v splash onto the XBee TX line. The Sparkfun board regulates the 5v supply to the 3.3v required by the XBee and uses a diode to drop some voltage on the RX line so that the 5v TTL logic line from the ATMega is dropped to be within the tolerances of the 3.3v logic required by the XBee but it leaves the TX line unprotected (the 3.3v logic levels of the XBee are enough to register as valid levels for the 5v side of the circuit but if 5v were applied to it then it would cause problems...). Ideally I'd like to put together a more robustly protected circuit with level shifting on both RX and TX lines but right now I don't quite know how to do that (even the AdaFruit XBee board only level shifts the input lines and leaves the output lines vulnerable). I expect I'll use the Sparkfun level converter board when I get a replacement XBee.

With my electronics off of my breadboard I began working on the servo sequencer. This will deal with moving the servos in sequence to create various walking gaits. Once I'd played with a simple sequencer I decided that I needed to solve the 'hip joint' problem once and for all and then build more legs; after all,sequencing a single leg isn't that much fun.

The prototype leg that I built way back at the start of this project has always been weak as far as the hip joint is concerned. The need to connect two servos at right angles using only a piece of plastic window board creates many problems. My experiments with using metal brackets made from Mecanno failed as the pieces I had were insufficient to hold the servos correctly. Unfortunately I don't currently have access to the custom machining facilities that this guy has access to, so custom aluminium parts are out of the question. In the end I spent a lot of time with a craft knife and pieces of window board and eventually came up with a design that seems to work; at the very least it's stronger and more reliable than the original leg. The design is based on the custom aluminium pieces from the A-Pod hexapod. I expect it will still change somewhat but it's enough for me to move forward...
I now have 6 Hitec HS-645MG servos on order along with a couple more XBee radios and a few more bits and pieces. The plan is to build two legs with the new servos and get the sequencer working. Once I get to this point I should be able to purchase more servos, carve more legs and move to a full six legs. Perhaps this hexapod project will actually have a hexapod before we reach our one year anniversary in April.

Sensing servo torque

| 1 Comment
Whilst playing around with my servo controller I realised that the power used by a servo goes up considerably when it's under heavy load (such as when it's pressing against the table and still trying to move). I can, potentially, get an idea of this load by measuring the current that each servo is using and using this feedback somehow. I've yet to work out how, but at the very least it could be used to protect the servos against overloading; if the load gets above a certain threshold then stop moving! Ideally the servo controller could feed this information back to the user of the servo controller as well. Anyway, this requires quite a large amount of breadboarding changes, the use of some active low multiplexor chips and some playing around with the ADC on the ATMega. I don't think I'll experiment with this just yet...

New soldering iron...

I decided to treat myself to an early christmas present and bought a 60W temperature controlled soldering station (a ZD-916 which I got from Maplin). All I can say is WOW. Suddenly I can solder neatly rather than making a smeary mess. The difference between this and my cheapo 12W soldering iron is just unbelievable. It just makes the whole process SO much easier. Where in the past when soldering something with a large heat sink or onto a large pad would be painful as both items would never seem to get up to temperature now I hear the iron click on as I touch the items to be soldered and the heat stays constant and it just works... Highly recommended.
This is the AVR Studio project and assembly language source code files for the latest version (v7.0) of my 64 channel serial servo controller.

This is the latest version of the ATMega168 version of the code which includes all of the new servo commands that I wrote about here including the multi-move command and the unit tests that I spoke of here. The controller allows you to set minimum, maximum and startup servo positions for each servo which can be saved into eeprom and used every time the controller is powered up. It also includes a programmable, per servo, "centre adjust" value which can be used to adjust for servos that are installed slightly off centre.

Source code is available here.

Back to JIT testing

| No Comments
The latest version of the serial servo controller is now fully operational (I'll upload the source code shortly). There are still some bugs that I'm finding but the work I put in to getting the unit tests in place makes fixing these bugs pretty straight forward. Whilst I have pretty much 100% coverage for the simpler serial commands I've stopped writing tests for the 'multi-move' command now and I've switched to "Just in time" testing; that is I write a test in response to finding a bug. The test duplicates the input that causes the bug to show up and then I fix the bug using the test harness to exercise the code with the correct input values... It would be nice to stay focused on getting 100% coverage on the multi-move command but right now that's not a priority. 

Whilst developing the servo controller I often wished I had an oscilloscope, being able to visualise the signals that I was generating would have been useful many times. Due to the cost, choice and the fact that I eventually worked out what I was doing wrong in each situation I am continuing to delay getting an oscilloscope but today I saw a cheap little device that could be useful as I tune the controller in future. My 'new products' feed from CoolComponents had the TextStar Serial LCD Display in it this morning. This is a neat little programmable display which has a 'servo signal display' mode which enables it to display the pulse length and refresh rate of a servo signal. Given the cheap price and the fact that I'm sure the LCD display in itself will be useful I ordered one. I hope to hook it up to my controller so that I can see what's being generated. The datasheet for the device is here.

Testing backwards

| No Comments
It's taken me almost a month but I'm finally back to working on integrating the multiple servo move command into the rest of the code. Well, the integration was done long ago, unfortunately the debugging was the bit that was taking up my time.

I decided that putting 'printf' style debug output into the routine to attempt to debug it from my PC based control software was just the wrong way to go about finding the problems and so I set off on a mission to finally get some unit testing into my code. This worked out well and I now have over 80 tests for all of the serial command code. I found a few subtle bugs and I'm in a much better position for reactoring away some duplicate code and other design smells. I also feel much more confident about making the other wide ranging changes that I will eventually make when I switch to using interrupt driven serial comms and move to a 16bit control value for the PWM signals...

So now I have to write the tests for the code that I know has some bugs in it... The problem I have with the code under test is that it's quite big. In fact it's quite a bit bigger, and more complex, than all of the other serial protocol routines that I've tested. The initial tests are easy enough, parameter validation etc, but the main tests involve me testing a large block of code that appears to have at least one 'oh dear I've gone off into an infinite loop' bug in it somewhere under some input data conditions... At first I thought I would have to break the code down into smaller functions that were easier to test and then I realised that I can already test the code in smaller sections, just as long as I do so backwards.

The code is one long function that we jump into and which jumps back out to the command accumulation loop. Throughout the code there are various labels that break up the various sections of the code. If I structure my tests so that I test the code from the end back towards the front I can simply set up the environment with the data that each stage expects and then jump to a label that processes the data. So, if the code takes input data at A and then processes it via B, C, D, E and F, I can first test pushing the kind of data that E should produce by jumping to F. Once that's works I can test E with the data that D would produce, etc... Once I get to A the whole thing is tested...

We'll see how it goes...

| No Comments
For those of you interested in the kind of thing that this blog is about you might also find useful. It's a 'stackoverflow' for embedded programming and electronics people. Hopefully it will become a useful resource!

Relative branch out of reach

| No Comments
The test code for the serial command processing code for my serial servo controller is turning out to be the largest piece of assembly language that I've written. This means that all of a sudden I'm coming across "Relative branch out of reach" errors during the compile. I've got to a point where every time I add a test I have shuffled the code to such an extent that several relative branches need adjusting from rjmp to jmp or rcall to call. Not a great problem but, of course, jmp and call take up more space so the first round of adjustments often triggers a second round, etc. It seems that once you get to the point where your code needs jmp and call its size can just explode due to the fact that you now need to use jmp and call...

Ah well, it's not a problem really... I'm now at 66 tests and 59% of my code space used up. I've got pretty complete coverage up to the "stop servos" command. I have the query commands to test and then I'm finally on to the multiple servo move command... Then I have the PWM code to test, but I expect I'll take a break from the testing for a while once I get the multiple servo move command to actually work!

Find recent content on the main index or look in the archives to find all content.

Recent Comments

  • damien.miras: I have the same idea and there is many interesting read more
  • Len: It has been a while since I looked at the read more
  • I think that we could use PortB lines 0-3 and read more
  • Len: Done! I expect I'll be buying from you if I read more
  • Hello. I saw your list of UK suppliers of electronics read more
  • Len: It's a great tool; pity I've been too busy recently read more
  • Old post I know - but glad to find a read more
  • Just to make you drool: read more
  • Len: Well, if you've really used an ATMega16 then that's likely read more
  • ameldon: Hi all, I’ve made the circuit, then I’ve programmed my read more

Recent Assets

  • Legv3.0.png
  • ServoControllerBoard.png
  • IOBoardUnderside.png
  • IOAndPower.png
  • IOBoard.png
  • NewServoControlData.png
  • ExistingServoControlData.png
  • ATTiny2313-24ChannelServoController.png
  • PowerSupply3.png