Following last week’s information on the communication data coming from the Quadcopter remote, the next logical step was to replicate it so that the Arduino can be used to communicate the quadcopter instead. Some interesting findings led to a better understanding of the communication between this particular Remote Control and the quadcopter and also a stack of code was developed to try and replicate this communication.
Understanding the Payload:
Once it was obvious that the Power-up/initialization sequence can be ignored during the code development and replace with the proper initialization for the NRF24L01 module, the main part of the code that needs replication is the Loop it goes into while trying to bind with the copter and subsequently sending information to the quadcopter regarding flight dynamics.
Considering the first few bytes sent to the communication module by the MCU of the remote are for checking the status of the Module itself, it can be ignored for now until its replication in the NRF24L01 chip. The important part of this snippet is the 16-byte data payload which is what the quadcopter can actually listens to from the Remote. Immediately, one aspect is noticeably different from the previous code being used to hack the quadcopters, which is that the previous hack codes sent 8-bytes of payload with the ID sent first.
Breaking down each code and checking against the different functions of the quadcopter (using the analog sticks and buttons on the remote), the following table was extracted;
Most of the table is pretty explanatory as seen in the table. the static values are the possible values for the specific ID the quadcopter scans for other than the Read/Write Addresses packaged together in the data packet sent over the RF frequency. Further analysis of the different functions revealed some more possible reserved bytes and after performing some tedious data capture over the logic analyzer, the range of all the different features (throttle, roll, pitch) were deciphered. One interesting finding was that the trimming works at certain intervals, so it could possibly be used to move the bot from side to side more smoothly than using the throttle and direction as these functions seem to be more sensitive to changes.
The last byte sent is a summation of all the data bytes sent during the transmission, and is probably used as a check-sum by the quadcopter when it receives the data.
Note: The 0xA0 byte is a preceding byte when sending data to notify the module that the data is on its way.
Replicating the communication protocol
Armed with this information, it was a matter of figuring out how to write a 16-byte long payload to the NRF module via the Arduino SPI looping every 4ms. Initially, the code obtained to hack the bots were used but it was found to be a bit too foreign to easily understand. It was then decided to use my own code to try and write the stack of code to replicate the data using the basics of radio communication for the NRF24L01 module. Unlike the module shown above, it is not necessary to read the status register before sending the data to the transmission buffer on the module. So, a stack of code was written to first flush the TX buffer and then directly send the 16-byte long payload. Finally the whole package in transmitting will do a status check.
During the implementation, the data sent over the SPI was checked using the logic analyzer for accuracy and some logical errors occurred which needed to be rectified. There was also some timing issues that needed to be dealt to ensure that the timing of the data payload loop was about 4ms. This was necessary because the quadcopter would proceed to un-bind when it doesn’t receive any data for a certain amount of time.
As can be seen above, the data sent matches the payload from the quadcopter and using properly placed variable the appropriate values can be used for the necessary functions of the quadcopter. The timing was also accurate taking into account the function call delays that were incurred during this implementation. These delays can further be trimmed out when the code is optimized for performance when it is confirmed to be working.
Problems with the NRF24L01 module again
The next logical step was to hook up the NRF24L01 module with the Arduino with the new looping code sending the binding request to the quadcopter. Doing so unfortunately yielded no result as the quadcopter did not respond. Checking the SPI channel for the communication revealed that the SPI commands sent were accurate but upon further study of the NRF24L01 datasheet showed that there was a problem indicated by the module.
The response for a status check returned a value of 0x1E which seemed odd at first. Later on, I discovered that this is an indication that the MAX_RT bit is set in the status register which only happens when the maximum number of retries has been reached on the modules transmission protocol. This is a very annoying issue because once this bit is set it must be manually reset before any further transmissions can be attempted. And some initial research showed that there may be a numerous amount of reasons why this is happening ranging from faulty clone devices, to problems with the initialization code. Currently, work is being done on finding the exact fault of this.
Other interesting findings
One more interesting find was some insight about the binding process. It was assumed that the quadcopter talks back to the remote control letting it know that binding is complete, but a loot at the logic levels show that the Remote very much acts like a Transmitter the whole time and presumably the quadcopter is just a receiver. The binding is done via changing of statuses on the data(byte 15 on the payload changes most and turns on all the other features like trimming on the other bytes). But there is a trick being missed and I think a bit more time spent on the way the protocol works will give me the answer. Until then I will keep hacking away at it to find the solution to my current hurdle.