Tu(r)ning a 40MHz RC Ferrari (from digital into a 2.4GHz analog one) (Part 1)

Winter has come… and with it long evenings that can be used for working on new projects.

One of them is a follow up on the Reverse Engineering a Quadrocopter RC series, using its 2.4GHz remote to control a 40MHz RC car.

But from the beginning: Being very much into cars or anything that has an engine and makes some noise, our eldest got a 1:24 RC Ferrari for christmas from a very good friend of ours. Unfortunately, the enthusiasm for the big shiny Italian Stallion turned into frustration when it turned out to be rather… digital. There was only five modes:

  • Do nothing
  • Go forward / backward at full speed
  • Turn left / right at full speed

No matter how big the room and how much those little hands tried to be careful on the inputs, the car just smashed into walls and furniture after short sprints. Only moving back and forth in the hallway was not much fun either, long story short: The Ferrari needed some serious tuning.

Step 1: Looking inside

Due to lack of documetation, we started with opening the car and found this:

ferrary-rc-interior

Under the hood

Given that the manufacturer apparently had to register with Ferrari to use their brand (there was a “genuinity sticker” on the box… and I’m a little worried to use the name on my blog without asking for permission, so dear law experts, please let me know if this might be an issue BEFORE suing me or sending any cease and desist letters…), the quality of what we found under the hood was rather… pragmatic:

  • Two DC motors, one for moving forward / backward, one for the steering left / right
  • A control board based on a RX-2-G and a MX1508 dual brush motor driver
  • Four diodes, two each on the front / rear

The control board followed the basic design suggestions you can find in the RX-2/TX-2 datasheets:

ferrari-control-board

Control board chipset

Step 2: Checking Documentation

A quick research on “Arduino 40MHz” did not reveal much. Apparently the ancient masters of analog radio comms seem to be rather quiet on the web or don’t play much with digital prototyping boards. Appart from being an interesting learning experience, building a 40MHz transmitter from scratch would not be an option, since one winter might be too short to achieve quick results and kids are known for many things, but not so much known for their patience (neither are fathers…)

The closest to interfacing anything with the car’s original design I could find was to tap into the remote control and connect the inputs to the digital I/Os of an Arduino. Unfortunately this would not add any preciscion to controlling the car. Also the fruit was hanging so low it even touched the ground. Further research showed, that the RX-2 receiver IC is not designed for analog inputs either, so I finally decided to reuse the 2.4GHz quadcopter RC, which already caught quite some attention by our eldest anyways.

Step 3: Design and Proof of Concept

Without elaborating much on the iterations that led to the final desing, here is what it contains:

  • Arduino Nano
  • nRF24L01+
  • L293D Dual H-Bridge
  • 1 x 100uF Capacitor
  • 1 x Diode
  • 2 x 100 Ohm Resistors
  • 2 x 22pF Capacitors
  • 1 x Micro Servo
  • 1 x 9V battery with connector

The layout looks like this

Layout.png

Layout

For better overview, this is the pin settings (the 100uF capacitor is missing, which would buffer the 9V source):

pin settings.png

Pin Settings

The real world thing looks like this:

Ferrari PoC.jpg

All connected

 

The source code needs a little cleaning and commenting, but will be available soon on my github repository.

Advertisements
Posted in Projects, RC | Tagged , , , , | 1 Comment

Reverse Engineering a Quadcopter RC, or: How to not miss the needle while throwing the haystack in the air (Part 4)

Part three of this series covered tagging into the SPI communication between an Arduino Uno and a nRF24L01+, followed by the transceiver inside the quadcopter RC. We have seen registers being read from and written to for initializing the transceivers and how the pairing of the quadcopter might be initiated.

In this part we will look at what really happens during pairing, have a brief look at the messages sent by the RC during normal operations and then we’ll try to create our own RC.

Step 8 Pairing and normal operation

As we have seen in step 7, the RC is initializing the transceiver and then starts sending messages on alternating addresses with alternating payload. Below is the part that would actually interrupt the transmission cycles and make the quadcopter stop blinking, indicating that the pairing was successful:

SPI RC pairing.png

RC pairing procedure

So the pairing process seems to go like this:

  • Set TX and RX address to 101 101 101 101 101
  • Send out RC address
  • Check for acknowledge package
  • Set TX and RX address to RC address

The SPI interface of the RC goes silent after the pairing and would only become active again after moving the throttle to max and then to min (probably a precaution to make sure the throttle is set to zero before sending anything to the quadcopter). Moving the throttle stops the RC LED from blinking and the RC would beep. Since the beeping was a bit annoying and too loud for testing over and over during the nights (wife and kids already started asking questions…), I soldered the little piezo speaker out.

The procedure during normal operation (after successfully pairing and setting the throttle) looks like this:

SPI RC sending 3.png

RC procedure during normal operation

Again, a very simple procedure, repeating itself every 4ms:

  • Read the status register
  • Flush the transmission register
  • Clear the status flags
  • Send the control data
  • Power up the transceiver (which is actually a bit strange)

The data package seems to be quite simple, too:

The data packages sent by the RC during normal operation

As we might have expected from the init process, there is 8 bytes per package.

  • Byte 0 and 1 controlling throttle and yaw would range between 0 and 255
  • Byte 3 and 4 controlling pitch and roll, ranging between 65 and 191 or 1 and 255, depending on the position of the +/- switch
  • Byte 7 indicates the positin of the +/- switch with ‘-‘ is equal to setting bit 4, resulting in a value of 16. For the “flip over” command, which is being activated by pressing down the pitch/roll stick on the RC, bits 0 to 3 of the last byte seem to get set, adding 15 to the switch value.

As for the counters in bytes 2, 5 and 6, I’m not sure what they are supposed to indicate. Counter 0 would start somewhere at around 50 and count up, while the time intervals for each step seem to get longer and longer starting from about 1700 ms. Counter 1 and counter 2 start with values 101 and 116 (sometimes more, sometimes less) and would count backwards at totally different intervals. All counters jump back and forth between the numbers at each step, indicating that the numbers might be rather measurements than hard counters. I started playing with the voltage for the RC, changing it between 2.7 and 4.0 VDC and it does seem to have an effect on the counters. Maybe there is even a feedback from the quadcopter concerning its battery status. Unfortunately the quadcopter seems to be quite particular about the power input and won’t work when connected to a regulated external power supply.

EDIT: With a fully charged quadcopter, the counters start at 11, 124 and 125, so it is quite possible that there is a feedback coming from the aircraft regarding the battery power. Maybe when we start sending stuff ourselves to it, we will have more details…

EDIT2: As it seems, the quadcopter does not send any feedback to the RC, which is quite bad when reaching battery low, as the aircraft just drops dead from the sky without any warning. Would be nice to have the RC beep before the battery is dying.

Anyhow, we seem to have everything we need to create our own RC, so let’s move on to the next step:

Step 9: Wrapping it all up – DIY RC with an Arduino Uno Nano and a Wii Nunchuck

The DIY RC

DIY RC

EDIT: Just out of my own experience with quadcopters disappearing on neighboring grounds, before you start building and using the DIY RC, please note the disclaimer, especially the part where it says “at your own risk”…

The grand finale. And this is what you need:

  • Arduino Nano (low footprint, can run from a 9V battery without any converters)
  • nRF04L01+ transceiver
  • Wii Nunchuck
  • 9V battery holder with battery
  • Small breadboard
  • 11 wires
  • Source code from my github repository

This is how to hook it up:

RC pins.png

Connecting the DIY quadcopter RC

The grey part on top of the wiring matrix is what you see looking at the nunchuck connector. Make sure to connect its VCC only to 3.3VDC, even though it might be running fine with 5VDC, it is not recommended according to most of the nunchuck tutorials.

The source code should be pretty much self explanatory. It’s using the same RF24 library as in the earlier steps, together with a lightweight nunchuck library based on what I found on the Arduino Playground and todbots github repository. (Back in 2008 Tod created these neat adapters for the nunchuck, not sure if he is still selling them. Sticking the pins of the jumper wires into the connector did work for me just fine)

Adding a few calibration values matching your own controller (minimum / maximum range of the joystick x and y axis obtained by defining DEBUG mode and commenting out the pairing, tweaking pitch and roll for more or less agility) and… off you go.

As soon as I get a little practice, I might add a video to this step (if the quadcopter doesn’t crash and burn in the meantime, but so far it seems to be quite forgiving…).
A few battery charges and many more crashes later, here’s a quick demo:

Demo of the DIY RC

Just in case you are wondering why on earth I would want to start the quadcopter from a soccer goal: First, the video was taken during the 2016 European soccer championship in France. And second… due to it’s very small size and weight, the quadcopter was quite sensitive to ground effect, so I figured starting out of ground effect (HOGE) would be easier…

Summary

It’s been quite a journey from reading the documentation over listening to the radio communication and eavesdropping on the SPI interface to the DIY quadcopter RC.

My wife, rational as she is, asked me “what was it good for”? Well, first of all: It was fun. There was a mystery and I was able to solve it (even though there might be a few little secrets left). Second: I learned more about reverse engineering in general and the SPI interface in particular, and that it is not as hard as it might seem. Third: I created my own RC, which might not be that big of a deal or more accurate than the original one, but still, it is working and that’s a big reward.

But where to go from here? Anything is possible, you could…

  • …add channel hopping to the DIY RC

As it seems, the original RC switches channels during normal operation, probably based on the number of lost transmissions. This might explain why my aircraft is acting up a little from time to time (it cannot be all pilot induced…!). You have to keep in mind that Wifi and Bluetooth are both working on the same frequency and if you’re living in a crowded neighborhood with a lot of access points and chordless speakers… well, you do the math.

  • …add a different input to the DIY RC

The Wii Nunchuck was rather easy to use. You might even try and hook up the Arduino to the trainer port of your much fancier RC. (Did that to use the two free channels of my Futaba T7C, controlling the pan / tilt of a camera mounted to my RC plane, but that’s a different story to be told) Or control it with a smartphone like the Parrot AR.Drone.

  • …watch the quadcopter with a camera or a kinect and have your PC control it autonomously
  • …add some sensors or even a camera to the quadcopter
  • use the RC for other projects (control other things, have it act as a USB joystick or connect it to the trainer port of another RC and practice with your favorite RC simulator)

The list could continue forever (e.g. adding an on/off switch to the quadcopter or a bigger battery). For me, apart from the promised video, this project seems to be complete.

Posted in Projects, QC-360-A1 | Tagged , , , , , | 1 Comment

Reverse Engineering a Quadcopter RC, or: How to not miss the needle while throwing the haystack in the air (Part 3)

In part two of this series, we first tried to interpret the data received in promiscuous mode from the quadcopter RC radio. We then started collecting data from the SPI interface of an Arduino Uno controlling a nRF24L01+ transceiver.

In this part we will compare the collected SPI data we some documentation, trying to understand both (data and documentation). At the end we will even start listening to the SPI interface of the RC.

Step 6: Verification of the collected data by comparing it to the datasheets and libraries

This step is more or less exactly the same as coloring by numbers. As we have access to the datasheet of the nRF24L01+ and also to the source code of the library, we just need to compare the received data to what can be found in the documentation. No fantasy needed, no mysteries to be solved. The spreadsheet below is showing the commands captured during the RF24SlaveTest. The columns from left to right show the procedure calls used in the application, the invoked procedure calls within the library and the triggered SPI messages starting from column 3 with command, corresponding register and values.

SPI1 interpret

The SPI messages sent from the Arduino UNO to the nRF24L01+

As we can see, calling begin() is already invoking a few commands to the transceiver:

  • CRC gets turned on
  • Data rate set to 250kbps
  • The result is being checked
  • Data rate is being set to 1Mbps
  • Features are being toggled
  • Features are being turned off
  • Dynamic payload is being turned off
  • Status bits are being cleared
  • Channel 76 is being selected
  • TX and RX buffers are being flushed
  • The transceiver is being powered up

Calling the setChannel(), setDataRate() and setAutoAck() methods are again invoking commands writing to the respective registers.

There is (almost) no surprises and the proof of concept is worthy of its name.

But what’s with the orange line? The command is not documented in the nRF24L01+ datasheet and its even more surprising since it is being mentioned in the datasheets of its cheaper cousins. So who is the hen and who is the egg here? And how come that this undocumented command found its way into the RF24 library? But before losing time on tracking down conspiracies, let’s move on to the next step:

EDIT: As it turned out, the datasheet linked on the sparkfun product page was outdated. Version 2.0 of the datasheet on the nordicsemi page does contain the ACTIVATE command (marked orange in the spreadsheet) on page 46. So let’s move on to the next step:

Step 7: Eavesdropping on the RC SPI communication

As mentioned in part two, I did not have an oscilloscope to verify the pinout of the RC transceiver. I was just hoping that it would be the same as in Dzl’s post. Another thing I had to hope for was the data rate used by the MCU for the SPI interface. If it was too high like in the first tries with the RF24 library in step 5, the whole setup would not work. But I was fortunate enough and all went well.

The RC transceiver pinout with the wires attached

The RC transceiver pinout with the wires attached

Similar to the setup used in Step 5, only the MOSI, SCK and CSN got connected to the Arduino Mega. The MISO was left so it would not interfere with the replies sent by the transceiver to the MCU.

There was one thing that came to my mind, though: The RC is working on 3VDC while the Arduino is working on 5VDC. I didn’t want to fry the RC, even though according to the datasheets, the transceiver should be able to withstand 5VDC, but I was not so sure about the MCU. And there was of course the signal levels, so I decided to put a level converter in between the RC and the Arduino. (In the middle of testing, one channel of the converter failed and cost me another night of scratching my head over my software, but that shall not distract us from the main task.)

Another thing I got reminded of during the tests: When it comes to signals and busses, one of the most important things is the ground level! Just like in real life, if you are not on the same level as the person you are trying to communicate with, the conversation might not be working that well, in other words, the RC grounds had to be connected to the Arduino grounds for the SPISpy to receive any messages.

So here is what I got during the RC initializing the transceiver:

RC initializing the transceiver

RC initializing the transceiver

Pretty straight forward. The MCU is going through the registers one by one and sets the necessary values. At the end it sets the addresses for the receiver and transmitter, followed by a few settings on “bank1” (which does not seem to exist on the nRF24L01).

What comes after switching back to bank0 is a bit confusing, though: The receiver is being powered on again and then the RX / TX addresses and channel are being set again, the addresses even twice. Guess the code could need some streamlining here…

Then comes the first transmission loop:

Transmission loop during pairing phase

Again, the principle is quite simple:

  • Flush the TX buffer
  • Clear the Status bits
  • Send out the first package
  • Power up the transceiver (after the sending command?!?)
  • Read the Status register (~46 to 54 times in either ~25 or ~45 ms intervals)
  • Clear the Status bits

The loop is being repeated 14 times within ~540 ms before the following is happening:

RC changing the address for TX and RX

RC changing the address for TX and RX

The RC is changing its addresses for RX and TX to 101 101 101 101 101. Then the transmission loop starts again, this time with a different payload:

Different payload

Different payload

A closer look reveals that the first four bytes of the payload are actually the same as the address used in the first transmission cycle (and as we will see later, also during the normal operation). The purpose of the other four bytes is presently unknown.

So this is exactly what we were looking for: The setup of the transceiver and the pairing messages!

In part 4 we will look briefly at the normal operation (again, there will be no surprises here) and then move on to create our own RC with an Arduino and the nRF24L01+ transceiver.

Posted in Projects, QC-360-A1 | Tagged , , , , , | 2 Comments

Reverse Engineering a Quadcopter RC, or: How to not miss the needle while throwing the haystack in the air (Part 2)

Part one of this series covered the first three steps towards reverse engineering a quadcopter RC. The steps were “check the documentation“, “listen to the radio” to get the right channel and “listen to that channel intensively” in promiscuous mode. The second part is covering steps 4 and 5, showing the interpretation of the received data and how to start eavesdropping on the SPI interface.

Step 4: Interpretation of the received data – Now that I know how it’s supposed to work, I finally understand the manual!

Collecting data is one thing, “reading” it is a totally different one. I have to admit that this step was not too successful at first and the information below evolved only with the subsequent steps. Nevertheless, here is what I got:

There was two phases to look at:

  • The pairing process
  • Normal operation

The pairing process as per manual goes like this:

  1. Turn on the RC
  2. Connect the quadcopter to the battery
  3. Wait for the quadcopter to stop blinking
  4. Move the throttle to max and back to min again for the RC to stop blinking

The RC would beep twice and the quadcopter should be paired and ready for departure.

So I started listening to the traffic on channel 60, turned on the RC and received the following messages:

Messages received from the RC

Messages received from the RC

Each of the 8 messages shown in the chart above is being sent for about 2 seconds at a rate of about 800 messages per second. This is a little strange, since the “retransmission” setting for both, the nRF24 and it’s cousins has a maximum of 15 retries with a minimum delay of 250us in between. So either my receiver software is not working correctly or there must be some other mistake creating the impression of receiving the very same message (same package number) about 1.600 times before the RC is switching to the next message.

In the image above, you can see the received raw bytes in the upper part and the deriving values in the lower part. In order to get to these values, you have to keep the 9(!) bit packet control in mind, which is located between the address and the actual payload (ref. nRF24L01 product specification v2.0 p.25) . The packet control part of the message is “stealing” the MSB of the first data byte, which has to be shifted 1 bit to the left and then steal the MSB of the next byte and so on. The mechanism should become a little clearer in the image below.

How to get to the actual values sent by the RC

How to get to the actual values sent by the RC

In order to make things more reproducible, I connected the RC and the quadcopter to an external power supply. I then turned them on one after another via simple transistors circuits controlled by the Arduino. It showed me that the pairing would only be successful during the transmissions of the 101 address messages, and even then only during half of them. For the other half, the RC would still indicate a successful pairing, but the quadcopter would not start flying.

Initially the results have not been as clear as shown above and a few factors had to be kept in mind:

  • There was a lot of noise between the messages
  • The trigger for any received message was again noise, thus
  • Many of the actual message will have been lost half way through the reception
  • The actual messages could have been hidden anywhere in the 32 bytes of payload
  • The serial output is quite counter productive when it comes to time critical operations, thus
  • The received data needs to be buffered well before making it available

So I had to move on to the next step:

Step 5: Eavesdropping on the SPI communication – Second haystack

What I thought might be the most difficult part was in fact the most simple one: Connecting an Arduino to the SPI port of the RC MCU and listen to the commands it is sending to the transceiver. I was lacking an oscilloscope to check the pinout, so I was just hoping that it would be the same as in the very similar looking transceiver Dzl was using in his post.

But before soldering any wires into the RC, I wanted to try the procedure on my nRF24 module, just to see if it is really working and also to reduce the unknowns in the equation if it wasn’t. The setup was quite simple:

  • The transceiver was controlled by the Arduino Uno, which did some very simple settings (turn on the transceiver, set the channel, set the data rate, set the auto acknowledge)
  • Each setting was followed by a 1 second pause
  • The Arduino Mega was connected just the same, except of the MISO, to prevent any interference with the messages coming from the transceiver as the actual slave.

When searching for similar projects, I found that there was quite some confusion about how to connect to the SPI. Some people would suggest crossing MOSI and MISO, confusing them with the TX / RX of a serial connection. In fact, the direction of communication is determined by the CSN line: Who ever pulls this line low is the master and thus should be sending on MOSI, while the slave should be replying on MISO at the same time, bit by bit. You still would receive data when connecting the MOSI of the spying board to the MISO of the other one, but in that case you would be getting the feedback of the slave instead of the commands sent out by the master.

The most comprehensive description I could find on the SPI interface was put together by Nick Gammon. He not only describes the interface itself down to the level of zeroes and ones using a logic analyzer, but also has a lot of examples for the Arduino. In fact, I used his Master / Slave example to analyze the issue I had with the LSB in the setup shown below.

Arduino Mega eavesdropping on the SPI of an Arduino Uno talking to a nRF24L01+

Connection scheme

For the Uno I used a very simple sketch, calling begin(), setChannel(), setDataRate() and setAutoAck() in the setup, each call followed by a 1000ms delay and then just idling in the main loop.

#include <RF24.h>

RF24 myRF24(9, 10);

void setup() {
    myRF24.begin();
    delay(1000);

    myRF24.setChannel(60);
    delay(1000);

    myRF24.setDataRate(RF24_1MBPS);
    delay(1000);

    myRF24.setAutoAck(false);

} // void setup() {

void loop() {
    asm volatile("nop");
} // void loop() {

The code for the R24Slave can also be found on my github repository.

As hinted above, I experienced some issues with the messages I received from the SPI interface during the first tries. While the master / slave example Nick posted in his Forum was working fine, the data coming from the RF24 transmissions was just not as expected. It took a few hours to find the reason: The main difference between both setups (in terms of how the SPI library was being used) was the transmission speed. Nevertheless, reducing the speed in the RF24 library did not work either. I then found out that the setting for the speed did not have any effect, since the definition, that was necessary for it, was not effective. This was due to the fact, that it was set before including the SPI library, which contained an important prerequisite for the definition. Long story short:

In RF24_config.h, move lines 28..30 below line 102 to look like this (I just commented the lines 28-30 out and copied them in between the #endif in line 102 and the #ifdef in line 104):

  #define _SPI SPI
#endif

// Lines 28 - 30 moved here, since it was not working above
// RF24_SPI_TRANSACTIONS is only defined AFTER including spi.h!
/***************/
    #if defined SPI_HAS_TRANSACTION && !defined SPI_UART && !defined SOFTSPI
        #define RF24_SPI_TRANSACTIONS
    #endif
/***************/  

#ifdef SERIAL_DEBUG
    #define IF_SERIAL_DEBUG(x) ({x;})

Change RF24_SPI_SPEED in line 64 (or wherever it might end up after moving the lines mentioned above) to 5000000

// RF modules support 10 Mhz SPI bus speed
//  const uint32_t RF24_SPI_SPEED = 10000000;
  const uint32_t RF24_SPI_SPEED = 5000000;

The code for the RF24SPISpy running on the Arduino Mega can be found on my github repository.

If you let the SPISpy run on the Arduino Mega and start the RF24Slave on the Aruino Uno, the result using printBytes() should look like this:

0
32 12
36 95
6 255
38 39
6 255
6 255
6 255
38 7
6 255
80 115
61 0
60 0
39 112
37 76
226
225
0 255
32 14
0 255
32 14
37 60
6 255
38 7
6 255
33 0

Which is a great success!

More on the interpretation of the data in part 3 of this series.

Pitfalls of listening to SPI – Second Haystack

As mentioned before, the serial output is interfering quite a bit with collecting data and I received only scrambled messages or even lost them at the beginning. To roughly estimate the size of the second haystack: From starting up the RC (with the quadcopter already waiting) until the first pairing, the RC MCU sends about 3.100 commands to the transceiver, using about 6.400 bytes within about 1 second. The haystack might not be as big as the first one, and 51,2 kb/s might not be that fast (according to its product specification, the nRF24L01 could go as fast as 8 Mb/s on the SPI), but collecting the straws, sorting and making them visible at the same time caused a bit of scratching my head. The following two techniques helped in the end:

  • Ring of buffers (two dimensional ring buffer)
  • Interrupts

The data collection itself is being triggered by the SPI interrupt, filling the active buffer. A rising CSN signal is then triggering an interrupt on PIN2, indicating the end of a transmission, which would then result in switching to the next buffer in the ring. In the main loop, the Arduino is looping through the ring, waiting for the “dirty” flag to be set on each buffer. The content would then be sent out on the serial interface, but this time without interfering with the data collection, since the latter is being handled with a higher priority due to the interrupts. To keep the serial output cycles short, an array is keeping track of the actual number of bytes used in a single buffer, sending out only as many bytes as necessary.

The magic lies in balancing the size of the buffers and keeping the action during interrupt handling as short and simple as possible. The SPI messages would usually contain only a one byte command and one byte of data, in some rare cases 8 bytes of data (e.g. when setting the RX / TX addresses) or even 32 bytes (e.g. when transmitting a 32 byte message), so the size of the buffer can be adjusted accordingly. During the interrupt handling, the tasks are simply “store the received byte” and “advance to the next buffer index” for the SPI interrupt and “set buffer dirty flag” and “advance to the next buffer in the ring” for the external interrupt on PIN2.

It took a few iterations to get there, but in the end the SPISpy seems to be working fairly well (as long as the speed is low enough). During my research and trials, I came accross quite a few articles discussing “interrupt vs. polling” when using SPI. I tried both, but they did not make much of a difference, neither on the speed issue I had with the RF24 library nor on the scrambled or lost messages. On the other hand, I am also using the overhead that comes with the Arduino language (uhm, wait… there is no Arduino “language”!), so I guess the difference would only be visible when going lower level on programming the AVR. Either way, I did not need to buy a bus pirate or logic analyzer(, yet,) to make it work(, but they are already pretty high up on my list).

Posted in Projects, QC-360-A1 | Tagged , , , , , | 2 Comments

Reverse Engineering a Quadcopter RC, or: How to not miss the needle while throwing the haystack in the air (Part 1)

EDIT: The series got featured on my favorite hackspiration site…! Thanks to Brian Benchoff for his very kind and encouraging review. It got me hovering around like a quadcopter all day with a big smile on my face, asking my wife to ask me again what the hours and nights spent on this project were for… And it won’t be the last ;o)

Discounters. Perfect for basic groceries, good quality at a fair price and above all: clear. I mean, who needs ten different brands for milk with twenty different prices when they all come from the same cow?!? But that’s a different topic…

The other day, LIDL offered this nice little quaocopter for only 30 Euro. I just couldn’t resist, especially not after reading through Dzls’ post on controlling a toy quaocopter with an Arduino (also featured on Hackaday.com). Unfortunately he doesn’t go much into detail when it comes to the SPI eavesdropping part (probably because it was just too easy and not worth elaborating on it). As I only had little to no experience with that specific interface other than using pre-defined libraries to let my Arduino talk to sensors and radio modules, I accepted the challenge. In the end, I managed to reverse engineer the protocol, pair the quaocopter with an Arduino UNO and build my own RC. It is even possible to change the address and use a different one than the original remote control does…

There is still three misterious bytes in the data packets, which seem to be somewhat of a counter (one counting up, the other two counting down), but they don’t seem to influence the operation much. I had the Arduino “move” the throttle up and down for almost 30 minutes and did not change the values seeing no impact.

copter and box

Quadcopter on the box, remote already disassembled

Part one of this project will describe the way from zero to finding the right channel up to listening to ALL the communication on a specific channel (promiscuous mode). Later parts will talk about how to interpret the received data and how to tap into the SPI communication (and the pitfalls of it) to finally bring all the bits and pieces together. To keep things short and simple, I will not go into detail on things like how to connect an nRF24L01 transceiver to the arduino board, as there are already plenty of examples all over the web. The project shall be more about the (quite rewarding) learning curve experienced through reverse engineering.

So this is what I did (of course only after taking the quadcopter for a short spin):

Step 1: Check Documentation (yes, this includes the manual!)

The box and also the 75 page manual (4 languages) did not give away much. The only half useful information was the specification of the remote control:

  • Transmitting Frequency 2.4 GHz
  • Range: max 30m
  • Operating Voltage: 3 x 1.5V Batteries

The remote itself has a “4-CH” sticker on it, which most probably refers rather to the transmitted information (throttle, yaw, pitch and roll) than the radio characteristics.

So nothing on used channels, CE certificates or anything. What the manual does talk about is “intended use”, which I probably violated a litte here…

Step 2: Listen to the radio

In one of my drawers I had two Sparkfun nRF24L01+ breakout boards, which are also operating on 2.4GHz. Following the scanner example, which came with the RF24 library written by J.Coliz, I started scanning the 127 channels. The code needed a little adjustment to 1) make the range of scanned channels a bit more narrow and 2) to reduce overhead and make the scanning faster. The code can be found in my github repository.

The serial output during a few scans showed increased activity between channels 58 and 62, and closing the range and threshold, the most traffic was found on channel 60.

Step 3: Listen to Channel 60 – First haystack

A rather challenging step. The nRF24L01 board is meant to receive make messages only visible when they have been

  • received on a chosen channel (0 .. 127)
  • at a chose data rate (250kbps, 1Mbit or 2Mbit)
  • with a chosen header that can be anything between 3 to 5 bytes long

It is able to listen on six “pipes” simultaniously, though, but they would be sharing the first 2 – 4 bytes of the address. This seemed to be quite a haystack (about 2,3xE^29 straws, given that we already know the right frequency).

SDR would have been one option, but probably too timeconsuming. So I did a quick search on promiscuous mode, which is not officially supported by the nRF24L01. It led me to Travis Goodspeed’s blog on which he is desribing in detail how to tag into the radio stream of a wireless 2.4GHz keyboard. He was using an “illegal” register setting for the address length on the nRF24L01 along with the fact that the preamble byte of each transmission would be either 01010101 (0x55) or 10101010 (0xAA), depending on whether the first bit of the address in use is set to 0 or 1. So with CRC turned off, one byte of the address being either 0x00 or 0xFF (hoping for noise to trigger it) and the second byte being either 0x55 or 0xAA, chances were pretty high to catch whole transmission packets including the address, packet control field, payload and CRC byte(s) as described on p.28 of the nRF24L01+ product specification. I also had to hope the protocol used by the RC transceiver would be similar to the one used by the nRF24 (which in fact it is. As it turned out, those low cost modules like the RFM70 or the Beken BK2423 are pretty similar to the nRF24L01).

This is what the normal transmission Flow would look like: The receiver gets triggered by the preamble, checks the CRC and address and would make the payload availabletransmission flow normal

This is what the “promiscuous” reception looks like: The receiver gets triggered by random noise, uses more noise as first byte of the address and the the preamble of the RC is being interpreted as the second byte of the address. CRC check was deactivated, thus whatever might be in the following 32 byte is being concidered as payload.transmission flow promiscuousIf the data comes from the RC (and follows the RF24 protocol), the received message will definitely contain the address bytes and also the packet control bits, if there are any. Depending on the RC address length (up to 5 bytes), there might be a worst case overlap of 25 bytes and 7 bits for the RC payload. Expecting a rather small ammout of data to be sent (supposedly one byte each for throttle, yaw, pitch and roll, maybe some control bytes, so probably no more than 8 bytes), the whole transmission might even fit into the received payload (and as we will see in the serial output and when , it does!)

The code for the promiscuous receiver can be found in my github repository.

 

 

Posted in Projects, QC-360-A1 | Tagged , , , , | 9 Comments

Kids Music Box

Basic Idea

My wife and I are big fans of the Montessori Education approach, trying to use all kinds of non-plastic alternatives (both in material and methods) for the entertainment of to raise and educate our children. Music is a great way to keep kids happy and so we came accross Hörbert, a nice little MP3 player in a wood casing, durable and designed specially for kids.

We almost bought one right away, but appart from them being quite expensive (even though most probably worth every dime), where would be the fun in that? It’s an MP3 player in a wooden box, I love tinkering and so I had a new project (and one, that would actually be allowed to sit in the middle of our living room!).

Hardware

Initial Design

The task should have been a quite easy one: Take a wooden box, put an MP3 player inside, add some speakers, a volume knob, a switch to turn the box on and off… and of course buttons to jump forward and backwards… and another pair start and stop the playback… and what about switching playlists…? As you can see, even such a simple thing can easily be over-designed.

design


First idea for the box

But when carefully studying the original box, the most apparent part was its simplistic design. I started asking myself: Does it really have to be stereo? When there’s already a switch to turn the box on and off, do we really need buttons to start / stop the playback? Kids can’t read, so why bother adding a display to the box?

And while there is quite a few people out there, who used an old or cheap MP3 player for a similar project and just soldered a few extra wires on it to extend the built-in functions to the buttons, I wanted to use an Arduino board with a MP3 shield, so I could add a playlist functionality. But what about the box? I sure do love working with wood, but there was not much time left before Christmas and I was missing the right tools and experience to pass the WAF, which should never be underestimated..!

Actual Design

Searching for the right material, I found that the speaker might be the highest cost factor for that project, followed by the wooden box. So instead of buying them seperately, I decided to get both of them in a package. On Amazon I found a nice retro design radio that was only a little more expensive than a decent single speaker and came in a nice wooden box.

radio

The speaker came in a recyable box

So the material list looked like this:

Switch, Poti, 3.5mm plug, spacers,  and screws I had lying around, so the total cost for material was less than EUR 80,-.

The challenging part of putting the parts together was to fit the board inside the box while still having access to the micro SD card and the battery holder. Also choosing the positions for the buttons and poti so they would not collide with the rest of the parts and still look nice took one or two drawings in sketchup. But then I finally had everything in place.

The first version of the box

 The front and back covers were replaced by wooden sheets, added a few screws and… voilà.

Software

Since I bought the Music Shield from Seeed Studio (very nice piece of hardware btw.), it was quite obvious to use the Music Shield library in their github repository. It has been written by Jack Shao and released under the MIT License. There were no changes made to the library, so for the buttons (next / previous song) I kept the pins D4 and D6. The only “creative” part for the software was to map the A5 pin to the volume range, which I limited to 70 to avoid any hearing damage if the kids would get too close to the speaker. You can find the software in my github repository.

Future steps and lessons learned

Switch vs. Strenght

Kids hands are amazingly quick and quite accurate, especially when it comes to reaching for tools, keyboards, remote controls and all the little gadgets that haven’t been hidden away fast enough. But unforunately they are not very strong. The switch I used for the box was an old aircraft toggle switch, so rather heavy to move. To lower the level of frustration for the target group, I added the case of a pen to the shaft of the switch (I know… plastic… but it’s recycled…!).

lever

“Give me a place to stand and with a lever I will move the whole world.” – Archimedes

Playlist and haptic

As mentioned before, there is supposed to be some play list functionality in the next version of the music box. For this I would like to add some haptic feature involving a RFID reader and some colored RFID tags, representing the play lists.

Room for improvement

  • Mounting the hardware more securely to prevent things from coming lose when the box is falling off a table or is being dragged around
  • Raising the lower limit of the volume to prevent the battery from being drained by leaving the box running in low volume
  • Prevent the battery from being drained too far. I am using rechargable batteries and even though they are not LiIon, they might still not like it too much
  • Add external USB port to charge the battery / access the micro SD card, so it won’t be necessary anymore to open the box each time to change the battery / playlist
  • Add a status LED indicating the box is on / battery low status
Posted in KidsMusicBox, Projects | Tagged , , | Leave a comment

Building the ArduPilot APM2.x firmware with Eclipse on Windows (for real)

A few years ago, I wanted to start a professional UAV business. I did some tests with the Multiplex EasyStar II as a rather unexpensive and easy to fly R/C plane and after it went quite well (which shall be covered in another post), I started buying some more fancy equipment along with an APM2.5 from diydrones.com.

The EasyStar II with a FlyCamOne and a Wii Nunchuk to control the camera head

The EasyStar II with a FlyCamOne and a Wii Nunchuk to control the camera head

The APM is an open source autopilot board based on the AVR Atmega2560. It was supposed to do the flying, so I could have concentrated on other tasks.

diydrones APM2.5 Autopilot Board

diydrones APM2.5 Autopilot Board

As life went a different direction (but definitely not south ;o) ), the UAV thing never happened(, yet).

Just recently I found the board in my drawer and I wanted to use it in a HIL setup together with FlightGear. The firmware for the board has become quite complex since the last time I looked at it, so I wanted to use Eclipse as the IDE instead of the Arduino IDE. It took a while to find the latest and greatest firmware for the board, though, since diydrones has discontinued the AVR based APM. While their page had some not so clear infos on which software version was the most recent and final one that would still run on the Atmega, I somehow found it was V3.4.0. After downloading and importing the package into Eclipse and trying to compile the code, all I got was a bunch of error messages and none of the pages I found about the topic had a real solution…

Long story short, here is how I made it work:

  1. Download ArduPilot-Arduino-1.0.3, basicly a customized Arduino IDE
  2. Download ArduPlane-release-AVR
  3. Unzip 1) to a folder that has no spaces in its name. (Actually we are only interested in the WinAVR package inside (ArduPilot-Arduino-1.0.3-windows\hardware\tools\avr\), so it would be sufficient to unzip that part to a folder that has no spaces in its name and forget about the rest.) Note that the no-spaces rule does apply to the parent folders, too!
  4. Unpack 2) anywhere you want, preferably to your project folder.

I happened to put 1) on the desktop (it wasn’t going to stay long) and 2) inside 1)

Inside the package of 2), there is a folder named “mk”. It contains some *.mk files, which are being used by make and are referring back and forth to each other, since they try to cover all kinds of OSes and setups. You have to edit three files:

  • environ.mk:
    – Anywhere before line 32 (preferably right before it) enter the following:
    SKETCHBOOK := ..
    This will help the compiler find the libraries
    – At line 107 (which was 106 before adding the line above), change the line as following:
    BUILDROOT := build
    This will put the compiled files into a folder named “build” inside the same folder as the firmware that you are trying to compile (ArduCopter, ArduMrover2 or ArduPlane).
  • find_tools.mk:
    – Change line 27 to
    TOOLPATH := <path to the avr/bin/ of 1)>
    This will help make find the right compilers
    Note that the backslashes need to be normal slashes!
  • board_avr.mk:
    – Comment out lines 77 – 85 by adding a # in front of each line to avoid some unnecessary error messages
    – Change lines 88 to 91 to
    MCU := atmega2560
    F_CPU := 16000000L
    HARDWARE_CORE := arduino
    UPLOAD_SPEED := 115200
    – Change line 109 to
    UPLOAD_PROTOCOL := wiring

Now you can import the package to Eclipse

  • Create a new project
  • Choose “C/C++ – Makefile Project with Existing Code”

    Create a new C/C++ project, "Makefile Project with Existing Code"

    Create a new C/C++ project, “Makefile Project with Existing Code”

  • Choose “<none>” as Toolchain

    Since we are going to use the customized WinAVR, chose "" as toolchain

    Since we are going to use the customized WinAVR, chose “” as toolchain

  • Create a new target called “apm2”
    Create a new target for the project...

    Create a new target for the project…

    Name the target "apm2"

    …and name it “apm2”

While building the firmware should already be working fine, the intellisense of Eclipse would still need a few infos to work correctly:

  • In the project properties, C/C++ General, Paths and Symbols, add the path to the “libraries” folder inside of 2) to the GNU C and GNU C++ settings
  • Same for the “avr/include” and “lib/gcc/avr/4.8.2/include” folders inside of 1)
Add some include paths for intellisense

Add some include paths for intellisense

There would still be some issues for the intellisense for the files
– ArduPlane.cpp
– GCS_Mavlink.cpp
– Plane.cpp
– Plane.h
– system.cpp
but the code would still compile fine.

Posted in Projects, UAV | Tagged , , , , | 2 Comments