I’ve researched the gyro and the accelerometer on the IMU enough to at least figure out how to get data out of them. The data isn’t accurate as I’m not bothering to set up the parameters on the chips beyond the minimum needed to get data. As I delve deeper into the intricacies of using the IMU as part of the navigation system, I’ll research it further.
However, one thing is clear right away, and that new knowledge will likely steer the direction the IMU design goes. This new knowledge is that the IMU is capable of a much higher data sample rate than is practical to transmit to the Linux computer for processing. However, there is a easy solution! Adjust and filter the raw values locally at the sensor. The easiest way to do this is to use a sensor that has a dedicated processor just for this purpose. Pololu has one that looks really good:
The big gun is the CHR-UM6 Orientation Sensor This one looks like the whole solution, you even get an ARM Cortex processor that takes the samples at 1 KHz and shoots out Quaternion and Euler values that are ready to use over TTL serial. Nice!
The other item Pololu has is a 9 degree of freedom IMU that needs to have the data processed by the cpu it’s connected to: MiniMU-9 Gyro, Accelerometer, and Compass I ordered a sample of each so I can evaluate all options.
There are other IMU systems, but I think these are sufficient to research at the moment.
So I have the minimum data coming out of the Navigation Shield: Compass heading, temperature, Gyro X,Y,Z, and Accelerometer X,Y,Z. It’s not really useful data at the moment, but it’s there. The next step is to build the basics of the T1′s data processing system to route that data to a Linux process where it can do some real work.
The T1 combines a group of Arduino boards called “Ardunet” boards that have a peer to peer network built into them, onto these go the shields that connect to the T1′s hardware. At the minimum, I see the need for 3 different shields: The gateway that connects to the Linux computer, the Navigation Shield, and 2 Motor Control Shields for the brushless motors and steering servos. The Ardunet connects to the processes on the Linux computer through the Gateway Shield, and those processes control the robot.
First, the Ardunet board. The gerbers for this board are in Sparkfun’s “BatchPCB” service, with no markup on my end. the link to the board is: http://batchpcb.com/index.php/Products/63219
You also need a schematic:
Note that this is the prototype board, I’m currently working on a NEW board and will post the full info on it (including the Eagle files.) when it’s ready. The prototype has been modified slightly from this schematic: the battery charger chip is removed as well as the LED and resistor associated with it and VIN connected directly RAW. Here is a picture of the prototype board:
And here are the two modules I have so far (Gateway and Navigation) with the shields on them.
The Navigation Shield is documented in this post: Navigation Shield And here is the schematic for the button and LEDs located on the WiFly Shield:
The two Ardunet boards connect together through the UART1 connector on each board, the schematic for the interconnect cable is:
Note that the TX RX lines swap, as do the /CTS /RTS handshaking signals. All the signal levels are 3.3v serial TTL. The transmission rate is variable, but normally is 460,800 baud. I’ve been experimenting with 6 pin ribbon cables for the comm cables, and as expected, they’re iffy. They work at lengths up to 3 feet, but error out once in a while. I’m working on automatic recovery, but the smart thing to do is use shorter cables made from discreet wires. The other UART connectors on the boards are intended to extend the Ardunet by daisy chaining more boards together. On the Navigation board, I stopped the chaining by dedicating UART2 to the GPS. But on the Gateway board, UART2 will connect to the first Motor Control Shield, and it… to the second.
Now for the software. There are 4 software packages, each build either an Ardunet Sketch or a Linux Process. Note that these are in NO WAY finished programs, they are works in process, and only serve to show current status. These links download .zip packages containing the code:
WiFly Gateway This is the Arduino sketch for the Ardunet board that carries the WiFly Shield.
Navigation This is the Arduino sketch for the Ardunet board that carries the Navigation Shield.
message_hub This is the Linux process that carries the message traffic between Ardunet boards and Linux processes that actually do the work in the robot. To compile it, use the Makefile that’s in the package.
t1_nav This is the Linux process that receives the test nav info from the Navigation Shield. It’s just a shell at this point, included to show how to get the data to a Linux process for processing.
The system essentially consists of two networks connected together by a bridge between the message_hub and the WiFly Gateway. I’m using WiFly for this right now because it allows the Ardunet boards to be physically separated from the Linux computer, this is very useful for testing. I’ll eventually implement the link as a hard wired connection.
On the Linux side of the bridge, the processes communicate with each other and with the Ardunet boards over TCP/IP, sending packets that contain status and routing data. The packet format is as follows:
[esc] [esc] [length] [type] [SID] [DID] [Data section, up to 57 bytes]
The header of the packet is made up of the first [esc] to [DID] and contains 7 bytes of data. Each element is one byte long except for [type], which is an unsigned 16 bit integer. all data is sent in Intel byte order, LSB first. The two [esc] bytes (literally ESC, 0x1B hex) at the beginning serve to isolate out “bad data” that may be on the line prior to receiving a valid packet. The [length] field in the header is the length of the data section plus 4, so it’s all data after the [length] field up to the end of the packet.
The [SID] field is the Source Id. It identifies the sender of the packet.
The [DID] field is the Destination Id. It identifies the intended recipient of the packet.
SID and DID are bytes, with the Ardunet boards starting at 1 and going up, and the Linux processes starting at 255 and going down. This allows for 127 addresses on either side of the bridge. By default, the message_hub is id 255, and the Ardunet Gateway is id 1. However, there is nothing stopping you from having more than one message_hub or Gateway. In theory, it’s possible to construct an Ardunet / Linux network of global scope.
The [Data section] is the payload of the packet. Sometimes, though, no data is needed. A packet that initiates an action just be being received needs no data beyond the 7 byte header. Hence, the minimum packet length is 7 bytes.
Packets can contain bytes (8 bit unsigned int), words (16 bit unsigned int), or strings (char strings that are prefixed with a length byte). Strings are transmitted as the length of the string +1 byte containing the length. To insert data into a packet, use the corresponding packing function, to read data once the packet arrives, use the corresponding parsing function.
The protocol is implemented in the “CommManager.cpp and .h” files on the Arduino side, and in the “lxsock.cpp and .h” files on the Linux side.
To actually run the Linux side, you need a runtime directory where you place the two executables after they’ve been compiled, and three other files: You make these files with a text editor, I use “nano” that came with my Linux distro. Be sure to set the two shell scripts as “executable”.
The first file is the configuration file used by both message_hub and t1_nav to initialize themselves. It’s called “hub_config” and goes like this:
The “data dir” field does nothing. The others need to point to valid directories on the Linux machines or a valid address/port for the message_hub’s listen socket. As you can see, I just have the system running in my home directory.
The second file is called “start” and is a shell script that starts the two processes in the background:
echo “Starting Message Hub”
ps -ea |grep message_hub |grep -v grep
echo “Starting T1 Navigation”
ps -ea |grep t1_nav |grep -v grep
As it starts each process, it echoes what it’s doing, and reports the pid of the now active process.
The third file is called “stop” and kills the processes. It is also a shell script:
echo “Killing Message Hub”
echo “Killing T1 Navigation”
Logs are started in the directory specified in “hub_config”. I use these logs extensively to watch the processes run. The logs are named after the process and the date the log was started, if the date changes while the process is running, it automatically starts a new file. So, for example, logs made for the t1_nav process today go in a file called “nav.120104″. To view new entries as they are put into the log for that day, use the command “tail -f nav.120104″ from a terminal.
While I’m working on the system, I run a set of 4 terminals on my Windows computer using Tera-Term connecting with SSH. The first terminal I point to the the source directory I’m currently working on so I can compile, the second points to the runtime directory so I can run the start and stop scripts, and the last two are tailing the log files in the logs directory. I edit the code on my Windows computer using the Code::Blocks open source IDE and copy them over prior to compiling with samba. I use a simple batch file to copy the files. I keep a window up pointing to the directory where the files are so I can just double click on the batch file to copy the files over. The batch file looks like this:
cp *.cpp w:/t1_nav
cp *.h w:/t1_nav
cp Makefile w:/t1_nav
“w” is a link to the shared directory on the Linux computer. If you have been paying attention, you’ve probably guessed it points to C:/home/bsellers/core on the Linux machine.
My Linux machine is a bone stock Fedora 14 distribution with the following extra packages installed: Samba and hostapd. Samba was the biggest pain to install, but if you google “Fedora 14 Samba” you’ll eventually find what you need. I also had to disable the firewall… Yeah, bad. I know. I’ll eventually figure out how to get it to work, but the machine is safely behind another firewall on a subnet. There are no routes from the internet to my 192.168.x.x intranet.
If you’re brave enough… or foolish enough… to download that code and build a system, then I salute you, sir or madame! Here’s how to make it go:
Configure Samba (Or use sneaker net to get the files to the Linux machine… you could even just put them there in the first place, it’s your choice!) and get the source files into directories on the Linux machine.
Compile them and copy the compiled files to the runtime directory you set up. Notice that in the Makefiles, there is a “make install” section that copies the files to the runtime directory. Don’t forget to create the three extra files you need in the runtime directory… hub_config, start, and stop. (See above)
Run the start script. Note! You may need to type ./start instead of just start… depending on how your shell is set up. If they start… (The start script reports pids generated for the processes.) then go to the logs directory and start log tails. (See above.) You’ve just built a robot core capable of enormous expansion! Welcome to my world. This rabbit hole is very deep, and we will explore it!