The transmitter of my cheap radio-controlled helicopter uses an RF module with an SPI interface. I'm trying to understand the data given to the RF module, with the end goal of removing the original controller from the picture and having my computer give commands to the RF module directly to fly the heli.
The pins on the RF module were actually labelled, but too small to read and obscured by solder etc. Fortunately after removing it from the main board I discovered labelling underneath it which saved me a lot of trouble:
I connected these to my Arduino Uno...
...and set it to be an SPI slave with this sketch:
void setup (void)
{
Serial.begin (115200);
pinMode(10, INPUT); // SS
pinMode(11, INPUT); // MOSI
//pinMode(12, OUTPUT); // MISO (not used)
pinMode(13, INPUT); // SCK
// enable SPI
SPCR |= (1<<SPE);
// this arduino is slave
SPCR &= ~(1<<MSTR);
// enable SPI interrupt on SS
SPCR |= (1<<SPIE);
}
// SPI interrupt routine
ISR (SPI_STC_vect)
{
byte thisByte = SPDR;
Serial.print(thisByte);
Serial.print(" ");
if ( thisByte == 255 )
Serial.println();
}
void loop (void)
{
}
Note how the MISO is not used. Before I commented out that line, the resulting output was an infinitely repeating "7 0 7 0 7 0 7 0 7 0 7 0 7 0 7 0 " etc.
After commenting out the line for MISO output, I got a much more coherent stream of data, and it responds to movements I make with the control sticks on the transmitter unit. You can see a couple of snippets of the output here: http://www.iforce2d.net/spiSlaveDataMSB.txt (no stick movements are made in those snippets)
However, there is something really strange about it, that makes me think my setup is not getting the data correctly. Firstly, there are still a bunch of "7 0 " sequences in there, which I don't think belong in this data. The occurrence of these "7 0 " sequences is fairly uniform for the most part, but never completely consistent - occasionally there are even multiple consecutive "7 0 " strings together.
Secondly, there seems to be a hiccup every now and then, where the byte that seems like it should be a 255, is something else - usually a larger number indicating many bits set. Is it possible that the data could be slipping a few bits?
The RC transmitter is a 4 channel radio, so it should be possible to send sufficient information to fly the heli with just four bytes, and then one byte as a delimiter which is what I'm assuming the 255 is for. Apart from the interfering 7's and 0's, it does indeed look like a 5 byte 'packet' format right?
At the receiving end, the heli is able to pick up this data stream from any point (ie. there is no special initialization sequence or syncing necessary). I checked this by disconnecting the clock wire, the leds blink on the heli to indicate it has lost input, then after reconnecting the clock the heli can continue flying just fine without needing to restart the transmitter again.
I'm certain there are no bad solder or shorted connections because if I plug the RF module into the other side of the breadboard instead of the Arduino, I can fly the heli as normal.
As well as the interrupt method shown above, I also tried the other method which uses a while loop:
void loop(void)
{
while ( ! (SPSR & (1<<SPIF) ) );
byte thisByte = SPDR;
... etc
}
... but that just gave me the same results.
I also played around with some other settings for data sampling (shown commented out here, but I tried each possible setting for all of these):
// data clock idle state
//SPCR &= ~(1<<CPOL);
// sample which edge
//SPCR |= (1<<CPHA);
// LSBF/MSBF
//SPCR |= (1<<DORD);
The first two of these did not make a damn bit of difference which was kinda surprising. The last one did make a difference, but brought up yet more strange results. If you check the output snippets above (using MSBF), you can see that there is a 255 quite frequently, roughly every 6-10 bytes in most cases. Unless I'm very much mistaken, 255 has every bit set so it should be the same regardless of which order (least significant bit first or most significant bit first) is used.... right? But in the output when using LSBF, the occurrence of a 255 is much less frequent: http://www.iforce2d.net/spiSlaveDataLSB.txt
Finally, another reason I'm certain that something is going wrong, is that I can get the exact same output by moving different control sticks on the transmitter. For example, moving the throttle a tiny bit upward I can get a fairly consistent reading of "0 68 0 0 63 7 255" on each line. If I return the throttle to fully down, and then move other stick to roll a little bit, I can get the exact same reading. This cannot possibly be correct because there is no way for the receiver to distinguish between throttle and roll.
So you can see I have a lot of questions...! If anybody has some ideas they could share I'd be happy to hear them.