Student Robotics hardware development is heating up. The support for the currently shipped kit has almost reached a point where we don’t need to spend all our time on it, and a bunch of people eager to get involved in developing the new stuff have joined the group.
After a summer of racing to get the old kit into a shippable state, the Student Robotics hardware schedule is finally (ok, almost) in line with the rest of the groups agenda! We get to think about the new hardware design at the beginning of the academic year, giving us the maximum amount of time to both get new people involved and develop the new kit.
One of the major targets for the 2011 kit (uh, the 2010 kit is currently shipping — think of it like magazines) is the I2C bus that connects all the peripheral boards together. It’s getting replaced. From almost day one the bus has been misery and pain. If you’re thinking about using I2C as an interconnect between boards on a robot platform, I encourage you to think in a different direction. Due to the capacitance of the bus in our kit, we’ve had to knock the bus down to something like 20KHz. Furthermore, this bus gets along abysmally with the RFI emitted by the robot’s motors, so many transactions get repeated over and over until the checksums align.
So, what’s going to replace our I2C interconnect? I’ve been thinking about this in the back of my mind for a while, and discussion recently began on the mailing list. Right now, we have two options in front of us: asynchronous serial over RS485 or USB. Both of these are differential buses, and both appear that they could serve us well.
The USB option involves the least explaining. We’d stick a USB-to-serial chip (probably a FT232RL) on each board that’d interface with the board’s microcontroller. All the boards would plug into a USB hub, which would end up plugged into the BeagleBoard.
RS485 feels like it’s been around since the beginning of time. I expect that somewhere there’s a wire-wrapped array of 555 timers (with the requisite heatsinks…) that are doing something they shouldn’t over RS485, or a central heating control system sitting in some large company’s basement brimming with valves rocking out to RS485. However, the fact it’s still around and is still used extensively in many industrial applications is a good thing. RS485 transceivers are cheap! RS485 is compatible with daisy-chaining, which means that one could just plug another board in without having to get hold of any additional hardware (e.g. a hub).
The downside of RS485 having been around for ages is that most of the cheap transceiver chips are 5V supply only. 5V went out with the dinosaurs. All the cool kids use 3.3V and lower these days. Somewhat surprisingly, it looks like it’s cheaper to get a 5V linear regulator and RS485 transceiver to suit, rather than a 3.3V transceiver. Sounds disgusting, but it’s cheaper and performs just as well.
If we went for a master-slave relationship like we had in I2C, then we’d be OK. However, I’ve always been annoyed that the boards connected to our robot can’t generate interrupts of their own. This simple code:
from sr import * def main(): yield io.pin == 1 print "Beans"
Results in the JointIO board being continuously polled over the I2C bus to see if pin 2 has gone high. This sucks in terms of latency. It gets worse when there’s more than one coroutine running on the robot, and latency goes through the roof. So, I’d really like a multi-master bus. One where boards can shout at the BeagleBoard with an interrupt. That interrupt message can contain information about what the interrupt was as well, so the BeagleBoard doesn’t have to ask it, resulting in a nice short interrupt response time.
However, with multiple-masters come collisions: two boards may try to both write to the bus at the same time. There are a variety of methods of dealing with collisions that we could use, and many of these involve things like random-backoff times and detecting whether the line was driven in the way it was supposed to etc. My current favourite is a token-ring like approach, where we add point-to-point connections between boards that are adjacent in the chain, and get them to act like a big shift register with a single ‘1’ bit passing through it. When a board has the ‘1’, a.k.a. “the token”, it’s the master of the bus. When it’s done with the token, it just passes it on to the next board in the line. This way, there are no collisions to deal with, and each board gets a chance to transmit its data.
Which will win?
I’m not sure which will win at the moment. The RS485 option seems safe, and USB could allow for future exciting expansions. I’ll be doing more reading on USB over the next week or two to try and work out how it’ll perform in noisy situations. A possible option is sticking both the USB and the RS485 transceivers on the PCB design, and only populating one of them when it’s time to ship. Depends on how costly the board space would be.
Image used under CC license from flickr user viriyincy.
I just wrote a udev rule that would make any userspace i2c devices be owned by the i2c group:
(You can stick that in a file in /etc/udev/rules.d if you’re using Fedora).
- Add 4 lines to the firmware for the MSP430s that sequence the stepper motor drivers so that they half-step (so that there are sometimes two active coils).
- One’s resolution has doubled.
- Push changes up to public firmware git repository.
We did have a resolution of 0.2mm per step. Now we have 0.1mm. w00t.
Have just spent an hour or so setting up an RSS for John’s New Zealand adventures. Should update every half an hour.
Source used to generate it available here :-)
2012-08-10 Edit: John’s site has been down for a long time now, so this is definitely not going to work any more!
- 0830: Received a text from Tom containing a highly compressed set of questions relating to the power board. Set about answering them when I got up.
- Processed some paperwork.
- Worked on Farnell screen scraping – progressing nicely. Some nasty problems involving Unicode strings getting munged about though.
- Read about John’s escapades.
- Had some xbee related conversations with Phil. Sadly massively diverged into setting up his ssh config.
- The random period of immense internet laggyness started early today. Around 7pm I guess. Moaned profusely.
- Performed a very short investigation investigation into radio modules for general stuff-monitoring projects. Decided that the CC2420 might be good – but a little expensive (~£5 a chip from Farnell). Will continue search for cheaper alternatives. Would be good to produce a large number of devices that use them.
- Looked for an extension lead casing manufacturer. Was pretty unsuccessful. Wanted to find an extension lead casing with space for some extra electronics in it…
I want to be able to program and debug PICs with my MPLAB ICD 2. Unfortunately, Microchip doesn’t spec the USB interface to the ICD 2, so unless I reverse engineer it there’s not much I can do but use the Windows software they provide.
I don’t like windows.
So, I installed Windows Server 2003 in the version of QEMU that the KVM people produce. The install ran really smoothly up until there were 39 estimated minutes remaining. It then took around 4 hours to complete. I installed MPLAB in the VM, plugged the ICD 2 into my laptop and then “plugged” it into the VM’s USB. One of those annoying little “you’ve just done something” balloons appeared and I selected “automagically locate driver”. It failed to find a driver. Urgh.
I then thought “Hmm. I haven’t actually tested that MPLAB works in the VM”. I ran MPLAB. It said something along the lines of “MPLAB doesn’t work in this operating system”. Damn.
So, I started to create a new VM containing XP. Many hours later I had a fresh install of XP. Installed MPLAB. Ran MPLAB. Worked. “Plugged” ICD 2 in. No magic bubble. Rats.
“Perhaps I need SP2… I’ll run Windows Update.”
I ran Windows update. Many many many hours later I have SP2 installed. Plugged in ICD 2 and joy – magic bubble appears. Automagic search for driver successfully installs the driver.
From when I’ve used the ICD 2 before, I remembered that when one plugs it in, you get two magic windows “device connected” beeps – and one has to install two drivers. I’d only installed one on the VM and the magic bubble generator appeared to have run out of fuel.
Then I noticed that the USB Device ID of the ICD 2 had changed. Presumably the first driver changes it in some way after loading firmware into the ICD 2. Telling QEMU to connect the second device caused Windows to locate the device and to generate another magic bubble.
I ran MPLAB and it successfully updated the “operating system” on the ICD 2:
I have yet to try it with a PIC… That’s the next step :-)
I spent the first half of today learning Tcl. Then I started writing a gumsense extension for it:
load ./libgumsense.so gumsense::open puts "The time is [gumsense::read_time]" gumsense::set_time 3 puts "The time is [gumsense::read_time]"
(NB: I’m experiencing problems with making it a package at the moment because the gumstix buildroot doesn’t install everything (I think) it should – wasn’t a priority.)
# ./test.tcl The time is 1176423144 The time is 3 #
So now I just have to spend a few hours wrapping Tcl around the C library, and I’ll have got somewhere…
Four days ago I started working on getting the Gumsense to turn the Gumstix supply rail off when Linux has shutdown. I started writing a blog post containing all the things that I had examined. I’m still writing that post; it’s getting pretty long, and will arrive soon.
During that process, I realised that I was going to have to write a kernel driver for the Gumsense. I’ve now written that driver. It’s the first kernel driver I’ve written. It’s a relatively simple driver, but it represents a big increase in my knowledge of Linux internals, and I’m pretty pleased with it. It’s an I2C chip driver and hooks into the Gumstix platform code (which I also had to slightly modify so that I could hook into it).
After a surprisingly straightforward and pleasing construction and debugging session, the Gumstix is now on the Gumsense mark 2 :-) The Gumstix powers up fine and communicates with the MSP430 successfully.
So far I’ve found two mistakes and two slight annoyance on the board:
- I’d missed a ground connection to the output capacitor and diode of the Gumstix switchmode supply. Easily fixed by a short piece of thin blue wire soldered between the diode and a nearby grounded via.
- I’d done something weird in the Eagle schematic editor. Eagle has an annoying feature that allows two unconnected wires on the schematic to become part of the same net. That’s not so bad – normally I promote using netnames to connect different parts together. The problem is that in this case, only one of those tracks is labelled. So, I ended up with the MSP430 supply being connected straight to the voltage regulator rather than going through a schottky diode first. This meant that the button cell initially didn’t do anything. Fixing this required the cutting of 4 tracks and the addition of 2 very short pieces of blue wire.
- The first slight annoyance is that I’ve put a dual diode (BAT54C) too close to a capacitor. It all fits, it’s just a little tight.
- I neglected to put a decoupling/resevoir capacitor on the MSP430 internal reference output pin. The datasheet recommends this. I’d written it down in my list of things to do before the board went off to made too. For some reason, I just completely ignored it.
So, the blue wire count is now three. Analogue section next.
|Older Posts >>|
Site by Rob Gilton. © 2008 - 2019