Sunday, May 4, 2014

3 Bits is a Nom, 3 Noms is a Byte and a Bit

Wanting a long range wireless transmission from the rover I had purchased a transmit / receive pair of 433 Mhz modules last year. After some tinkering I realized these were super-slow speed, intended for 4 channel radio control of simple on/off switches based on the PT2272 chips, not data transmission. So I put them aside.

In the last couple of weeks I've been getting the rover ready for first-drives via remote control, and wanted a better way get the LiPo battery status where I could see it, and without the final configuration of software or WiFi. I thought about those wireless modules again, and thought that if I really only had a few bits of data to move, it was probably ok to try them out.

I wired up the units to two Arduinos for testing. There are four data channels that are sent / received in parallel, labeled D0, D1, D2, and D3. If any of these are set logic-high, there is a transmission. I started writing some simple test code, and worked out a simple timing scheme to get stable data transfer.

The speeds are super slow; the data pins have to be held in a state to transmit for something like 350 ms to 400 ms, and then all held low for as long for the next transmission to be recognized as changed (and for the code to work right).

I also started thinking about a timing scheme to send two nibbles (a nibble is 4 bits, half a byte); that would allow me to send 8 bits instead of 4, and get a lot more status data off the rover... and possibly up to 2km, if the documentation is to be believed.

But then I started to see some weirdness when sending groups of two nibbles. I had it transmitting a byte value, just an incrementing number, and noticed that it wasn't sending the zero value. Then I noticed it wasn't sending any all-zero nibbles. Doh!

That was a forehead-slapping moment; of course they can't send all zero's! For their intended use sending a 'no buttons pressed' message doesn't make sense. So a '0000' means 'don't transmit anything'.

But I had gotten kind of attached to the idea of getting a byte worth of bits from the rover via wireless, and wondered if I could just set one of the bits, and transfer data in the other three.

And then instead of transmitting just two nibbles, 2x 4 bits, I could send 3x 3 bits.

So three bits became a 'nom', because it's just a bit (pun intended) smaller than a nibble.

For fun, I could then use the 9th bit as a flag on the first 8 bits; one use would be to differentiate between a status byte of 8 bit flags, or a data byte, of 8 normal bits.

Now... what to transmit? Here is the list:

// Defines for bit packed positions, bit 8 is local RX failure
#define STA_L    0x01    // 1 V Logic low volts warning
#define STA_D    0x02    // 2 V Drive low volts warning 
#define STA_T    0x04    // 3 Temperature warning
#define STA_P    0x08    // 4 Pose out of range (rocker-bogie)
#define STA_A    0x10    // 5 Accelerometer out of range (pitch/roll)
#define STA_C    0x20    // 6 Route/path calculation vapour-lock
#define STA_H    0x40    // 7 Haz detected

Notice that there are only 7 bits defined; these first 7 bits come from the rover itself. The 8th bit is locally created, because I decided that I'd package this up as an I2C slave (big surprise) and use it to transmit RF status, and also receive and decode the pulses from a Vex RC controller set.

That eighth bit is a flag that says 'I'm not getting a signal from the Vex Receiver', to inform the operator that the rover is out-of-range of the Vex transmitter.

I sat down with my standard I2C boiler plate, and managed to cobble together a module that decodes the Vex signal to I2C registers, pull status and data and send them interleaved, and then summarize it all for a Neopixel visual status. I eventually removed the Neopixel status LED, as I started to see some oddities that indicated I was running out of RAM.

On the receive end is a simple I2C 16x2 LCD, which displays the bits across the top line, and a text are across the bottom. Half displays 8 character extended messages, and the other half is a scroller that rotates the characters as they come in, adding received characters to the right position. At these slow speeds it's not hard to read.

The protocol also has some hidden goodness. Because the printable ASCII set only takes up a small portion of the byte space, it's also possible to get extended status info in single byte messages, not just the status summary. The trade-off here is speed; in 2 seconds I can get a 'quick' summary, but getting 8 bytes takes about 10 seconds.

And because it would be just too geeky-cool, I reserved the last 64 positions as start-of-extended-message markers to flag the start of up to 64 byte blocks of actual non-character, pure byte data. I can't really see transmitting an image this way, but maybe a thumbnail in a pinch...

But I'll probably add a better system for mid sized data; WiFi is ok for some things 'local', but it would still be fun to add a couple of more methods; one might be higher speed RF or Synapse network, another might be using a servo-steered pulsed laser - who knows?


No comments:

Post a Comment