A few weeks ago a friend of mine gave me a small broken RC helicopter to fix & play. I replaced the broken parts and then started flying around my flat. Unfortunately the original transmitter is a bit uncomfortable but what is more important it was in the wrong stick mode (http://http://www.rc-airplane-world.com/rc-transmitter-modes.html) for me so I found it difficult to control the helicopter especially when a quick reaction was necessary.
Because of all that and just a sudden impulse to create something easy and new I created a removable module which converts the standard RC PPM (http://http://trandi.wordpress.com/2011/01/04/graupner-r700-ppm-signal/) into the IR used by the toy. I decided this will be the first project I will make real use of the Logic Sniffer. I used it before but just to confirm my signals.. and now it was finally used to reverse engineer something :)
Ready to use module based on ATtiny25 which fitted into a JR module case I had lying around.
In this thread I will describe the development of the project including software and hardware. It took 3 evenings to get everything done including programming, etching and soldering.
Should there be any questions I will be happy to answer them. My project will also be described and discussed in Polish on our RC Club forum ( this is just a note for possible Polish readers :) ).
Following steps will be discussed:
1. Reverse engineering the transmission protocol using a photo transistor and the OLS
2. Circuit design and a breadboard prototype
3. AVR Firmware
4. Final design, encountered problems and hints for further projects
I will do my best to add one part every day, the first part will be added later tonight.
1. IR transmission protocol reverse engineering
I didn't really want to disassemble the transmitter and connect to it from inside ( it wasn't mine and metal-plastic screws don't work well when they are this "crappy") so I decided to use a non invasive method to capture the transmission protocol. I made a simple circuit including a photo transistor and a resistor, powered it up with a single LiPo cell and connected to the Logic Sniffer.I would also like to mention, that just after I finished working on reverse engineering the IR transmission scheme I found it on a RC forum.. so I could have saved myself one evening.. but it was fun to work on it anyway, so I don't regret it :)
The resistor was selected big enough to smooth the 38KHz carrier frequency and leave just the data blocks on the output.
Once the test circuit was completed I made a series of recording including all possible combination of input one after another. Single frame transmission scheme was quite easy to guess and now was the time to decode the data.
Example frame captured during the initial analysis. It begins with a preamble ( high level for 3,6ms then low level for 1ms), then 32 data bits each taking 1ms and coded by pulse length ( "1" - 0,3ms high & 0,7ms low, a "0" - 0,7ms high & 0,3ms low). The last bit is the stop bit "1".
During the further analysis I assumed, as it turned out correctly :), that each frame consists of four, somehow related, 8-bit words. I prepared a shell script to convert the captured data into 4 column CSV file which I could later import into Google Docs Spreadsheet. I know I could have used something more geeky like GNU Plot but the spreadsheet was just enough.
As you can see in this screen shot I have already identified the throttle byte and partly computed the check sum. I found charts really useful when it came to finding relations between input and produced frames. It took some guessing and after about an hour it was ready to be implemented :)
Eventually I was able to reproduce the entire frame as follows:
MSB transmitted first
31| 0 fixed
30| MSB throttle
24| LSB throttle
23| MSB rudder
20| LSB rudder
19| MSB forward/backward
16| LSB forward/backward
15| FLAG 1 - rudder left, 0 - rudder right
14| FLAG 1 - backward, 0 - forward
13| FLAG 1 - trim left, 0 - trim right
12| MSB trim
08| LSB trim
07| MSB CHANNEL, A - 11
06| LSB CHANNEL
05| MSB CRC
03| ... CRC = (0x0F + B3 + B2 + B1) & 0x3F
00| LSB CRC
The next part will cover the test circuit and micro controller selection.
2. Circuit prototype
Back in high school when I was introduced to microprocessors we started from scratch by manually computing op-codes, converting them into hexadecimal numbers and eventually entering into memory by taking control of the bus pressing several buttons, clocking etc. This was really frustrating whenever you made a mistake but it taught me to write short and small code ( not always readable/understandable though :P ). I also learned to use the smallest/cheapest devices available as everything used to be expensive and hard to get.
For this project I was going to use ATTiny13 and a NE555 timer for 38kHz carrier frequency generation. Unfortunately I didn't have a spare ATTiny13 so I went for ATTiny25 which is also a 8-pin uC with a bit more RAM & program memory as well as a few other features like two 8bit timers which meant I didn't have to use NE555 after all. It also had enough memory to squeeze a small boot loader which was really nice especially when you hate to connect 6 cables just to upload the new FW.
The circuit itself is really simple. I ain't good at designing circuits, even though I went to a technical high school where I was taught how everything works.. I just didn't pay much attention.. so the circuit could probably be improved. Some of the parts were used only because I had them laying around and not because they are the best for this purpose.
The RC transmitter only provides 9-12V supply so I couldn't power the CPU directly but had to use a 7805 voltage regulator. IR emitting diodes are connected directly to the 12V supply and controlled by a NPN transistor by AVR.
In the breadboard version I used a single cell LiPo battery to power both the CPU and a single IR emitter. The final design includes a few emitters in series instead.
[quote author="pppd"]The RC transmitter only provides 9-12V supply so I couldn't power the CPU directly but had to use a 7805 voltage regulator. IR emitting diodes are connected directly to the 12V supply and controlled by a NPN transistor by AVR.[/quote]
Nice! As soon as you mentioned feeding a 7805 with 9-12 V, I thought of suggesting that you could bleed off some of the excess voltage by placing the LED power indicator in line ... and then I opened the schematic and saw that you did exactly this!
I'm curious, though, does R3 dissipate a lot of heat because of the 12 V supply?
[quote author="rsdio"]I'm curious, though, does R3 dissipate a lot of heat because of the 12 V supply?[/quote] I was afraid of that too, and actually surprised that it didn't get hot ( it's a 1206 SMD resistor in the final design ). Maybe the base resistor R2 should be smaller than 1k to enable 500mA maximum current?
[quote author="pppd"]Maybe the base resistor R2 should be smaller than 1k to enable 500mA maximum current?[/quote]
What is the exact part number for your IR LED? The schematic seems to show the connector only, not the actual IR LED. The reason I ask is that some IR LED parts can handle 1 A or even 2.5 A, but you really need to scrutinize the graphs on the data sheet and compare the range of your design to the limits.
LEDs I used can handle up to 1A in short pulses.. ( no part number, just info from the store ), but the transistor I used can only provide 500mA. I could replace it with a SOT23 MOSFET if I got better LEDs as I will need to change them anyway. Their emitting angle is really low .. only about 30 degrees :/
[quote author="pppd"]LEDs I used can handle up to 1A in short pulses.. ( no part number, just info from the store ), but the transistor I used can only provide 500mA. I could replace it with a SOT23 MOSFET if I got better LEDs as I will need to change them anyway. Their emitting angle is really low .. only about 30 degrees :/[/quote]
Personally, I find LEDs to be somewhat mysterious, because every model seems to be a little different. Sure, you can treat them all the same within a certain range, but if you're going to push the limits then you need to know exactly what you're working with.
I guess you could push that 500 mA transistor to its limits, but you'd still have the 30-degree emission dispersion. Probably best to find a better IR LED that also comes with a data sheet.
[quote author="rsdio"]Probably best to find a better IR LED that also comes with a data sheet.[/quote] Yup.. I will order some from Farnell next time I make an order. I have already found a few that could be used with 120-degree emission angle.
I used these because I already had them and paying 10EUR for shipping just to get a few LEDs is not reasonable :)
The code itself is not very long ( ~ 300 lines including all comments, includes, and macro definitions ) and is licensed under the CC BY-NC-SA 3.0 (http://http://creativecommons.org/licenses/by-nc-sa/3.0/). It produces a ~ 1.3kB binary which could be further reduced by removing some extra checks and immediate variables.
The main program loop is shown on the flow chart below:
3.1 Peripherals configuration
For the PPM input I used the PB2 and INT0 external interrupt triggered by falling edge. 38kHz carrier frequency is generated by timer1 running at 8MHz ( full speed ) in the CTC (Clear Timer on Compare match ) mode toggling the OCA1 (PB1) output pin which drives NPN transistor controlling IR emitters. The frequency generation is keyed by either enabling 'toggle on compare' or 'keep low on compare' bits in the timer configuration registers. The last I/O pin is PB0 which drives the status LED.
3.2 PPM analysis
PPM analysis is done by measuring time between consecutive pulses using the timer0 which is also used for controlling transmission ( see 3.4 ). The timer is extended to 16 bits by using overflow interrupt and an extra variable. During the analysis the timer runs at 1MHz ( 1/8th of the clock speed ) counting 1us intervals which is convenient for 1000-2000us pulses. Because it is not known at what stage the PPM is when starting the analysis it has to synchronize itself by waiting for the 10ms+ low/high state.
3.3 IR packet preparation
Once the analysis is finished, either success or failure, the IR packet is generated. There's really much to say here. This part of code is pretty much self-explanatory. I just scale down 1000-2000us to appropriate bit numbers and add sign when necessary. Please see the code for further details.
3.4 IR transmission
IR Transmission begins with configuring the timer0 by scaling it down to 31,250kHz changing its working mode to CTC counting N x 32us intervals. Then the 38KHz carrier is keyed by the output bits. When the output state is high the OCA1 output is toggling and when it is low the IR output is held low as well. If you are reading the code TX_LOW() and TX_HIGH() macros control the output line. Timer's compare register is changed every time either high or low state ends in the TIMER0_COMPA_vect interrupt handler. Once the last bit is sent timer is shut down and execution continues with next analysis ( 3.2 ).
3.5 Timeout/error handling
Even though the module is powered up from the transmitter.. and as long as the transmitter is working you get the PPM I decided to include a simple error/timeout checking. When there are no changes on input for more than 12ms ( maximum sync frame length ) I cut down the throttle but still keep transmitting so the helicopter receives signal. If there are more than 10 consecutive errors execution is held until a PPM pulse is detected.
Source code attached :)
4. Final design, encountered problems and hints for further projects
The final circuit is pretty much the same I used for the prototype ( see my earlier posts ). For the PCB I used the DIY toner transfer method and a "hybrid" SMD/Through-hole build. I am not a fan through-hole elements as I hate drilling and cutting leads but I wanted to use a few recycled parts and a DIP version of AVR reduced the hassle of making programming connectors.
There is a connector for the IR emitters as it needs to be replaced anyway. The other connector is for the status LED, but for now I just soldered a 0805 SMD LED on the other side.
I really enjoyed working on this project.. to be honest writing comments and preparing this project log took more time than the project itself :) As I mentioned in the first post I should have searched if someone else have done the protocol decoding and documented it.. this would have saved some precious time. Also I need to change the transmitting LEDs to ones with wider emitting angle and probably higher forward current / emission power.
If anyone needs the Eagle file please ask, but as this is pretty specific project and the schematic is really easy I don't think anyone wants it.