Reverse-Engineering a Syma 107 RC Helicopter

The Syma 107 RC helicopter is a pretty great gadget, all things considered — it’s cheap, fun, and ridiculously good for the price. It’s also a spectacular gadget for fledgling hackers.

** 1-26-2013 UPDATE — I’ve written up a full protocol specification for the Syma 107G — If you are here looking for a purely technical description of the protocol, look here** 

I first discovered a series of articles about this RC Heli on Hackaday, where a number of people had developed proof-of-concept controllers or jammers based on a decoded IR protocol for controlling the chopper. As it happened, these Heli’s were a bit of a fad in our lab and we had a number of them lying around (both alive and dead) so naturally I decided to have a go myself. I initially created a prototype Arduino IR controller that uses Processing to provide a front-end for one helicopter, then expanded it to control two similtaneously by switching the channel bits rapidly. I won’t go on too much about this here because what I actually want to talk about is a quirk in the protocol I decoded.

So there’s a decent body of work in the hacker and RC communities to decode the protocol used by the Syma 107 — here are a couple:

This post [Kerry Wong] is a really great read and a study in methodical analysis in reverse engineering.

This site [Hamsterworks] is also a great practical guide to reverse engineering the protocol and I actually used these timings for my own controller a while back.

One thing these projects both have in common is that they arrived at a protocol specification that uses 32-bits (4 bytes).

Reverse-Engineering the controller

So enter my new Saleae Logic Analyser . I’ve never used a logic analyser or oscilloscope before, so I wanted to start with a project that I knew was possible and would have an output that I already understood (or so I thought…).

As an aside, the Saleae Logic is really an excellent tool — I had read a lot about it and there are any number of superlatives floating around, but I must say it is EXACTLY what I was looking for. Great price-point, loads of features and the software is superb. If you are curious about logic analysers and don’t want to spend too much, I really recommend the Logic — it’s been great for me so far.

I noticed immediately that the board in my controller was markedly different than the ones pictured on either the above links. Mine has way more components for a start:

I began by using a multimeter to ensure that the unlabelled IC wasn’t operating at a voltage higher than 5v and wouldn’t accidentally damage the Logic analyser. Everything was fine so I began probing the pins. Here is a rough guess at the pinout (note: I only really care about the pin that drives the IR LED transmitter circuit so I never looked into confirming how the control input works, etc…):

Now that I know which pin the transmission signal is output on (pin 8), I can sniff it and see the 32-bit control protocol right? Well, almost. I should explain a little about the protocol for those who are unfamiliar.

Decoding the Physical Packet format

The following timings are based on observations I’ve made on a sample of control packets captured with the logic analyser. Here’s a picture of the full packet:

Carrier Modulation

Modulation Freq: 38khz (50% duty cycle, 26us period, so 13us high/13us low)

38khz is a common carrier frequency for consumer Infrared communications. For the uninitiated, the white blocks in the main image above are made up of the high-frequency oscillations you can see on the left. This is usually done so that various transmitters that use the same medium (in this case the Infrared light spectrum — probably around the 940nm wavelength) can transmit on a different carrier modulation frequency and not interfere with the others’ transmissions (this is called Frequency Division Multiplexing).

Symbols

There are 4 types of symbol in the packet format: Preamble, Zero (“0”), One (“1”), and a footer:

Preamble:

High: 2ms (2000us) / Low: 2ms (2000us) / Period: 4ms (2000us)

 

Zero:

High: 0.3ms (300us) / Low: 0.3 (300us) / Period: 0.6ms (600us)

 

 

One:

High: 0.3ms (300us) / Low: 0.7ms (700ms) / Period: 1ms (1000us)

 

 

Footer:

High: 0.3ms (300us)

I almost missed this, but there is in fact a footer pulse at the end of the packet 300 microseconds long followed by a long period of low signal until the next packet header.

Channels

The Syma 107G controller appears to support 2 “channels” so that two pilots can fly their heli’s at the same time without interfering with each other. Examining the behaviour of the transmitter when switching channels indicated that the only differences between the two is a) the packet transmission interval and b) a special bit in the control packet is flipped (more on this later). The image below shows the differences in packet Tx intervals when the channel select slider is flipped (channel 1 of the Logic analyser):

The transmit interval for Channel A is 120ms (start of a packet header to the start of the next packet), or 8.33 packets per second. The transmit interval for Channel B is 180ms, or 5.55 packets per second.

So surprisingly, the carrier modulation frequency remains the same on both channels — not the most robust design, huh? I suspect the reason the transmit interval is increased is to reduce the likelihood of a collision of control packets from two controllers — if a packet collision does occur, the next control frames from each controller will almost definitely be out of phase with each other, so the chopper shouldn’t just fall out of the air (though in my experience, they do get a bit clumsy when you have two going at once…).

The Control Packet Structure

So now that we understand what a packet looks like, let’s decode one and have a look at it at a higher level:

(Click for a better look)

 And here it is again:

         |     byte 0    |     byte 1    |     byte 2    |
          0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 1 0 1 0 0 1 0
         |  Decimal: 63  |  Decimal: 63  |  Decimal: 82  |

So we have a header, followed by 3 bytes (24 bits) of information, plus a footer pulse that makes up a control packet. Now lets figure out what the data means by trying various permutations of the controls (zero throttle, full throttle, 100% left turn, 100% right turn, etc…) and see how the data changes:

Type:         Data:                     Decimal Values (byte #):
100% Throttle 001111110011111101111111  (0): 63  (1): 63  (2): 127
50% Throttle  001111110011111100111111  (0): 63  (1): 63  (2): 63
100% Left     011111100011111101000110  (0): 126 (1): 63  (2): 70
100% Right    000001100011111101001011  (0): 6   (1): 63  (2): 75
100% Forward  001111110000000001010100  (0): 63  (1): 0   (2): 84
100% Back     001111110111011101010100  (0): 63  (1): 119 (2): 84
Channel A     001111110011111101010010  (0): 63  (1): 63  (2): 82
Channel B     001111110011111111010010  (0): 63  (1): 63  (2): 210

 

Note: The controller requires that there be at least some throttle applied before it will send any packets, which is why byte 2 appears to change a little on the other tests.

From this information, we can make the following assumptions:

Byte 0

- Byte 0 represents the Yaw (left/right) control.
– Byte 0 has a range of 0–127.
– 0–62 is a right turn, 63 is centre (default) value, 64–127 is a left turn.
– the first bit, bit 0, appears to always be 0.

Byte 1

- Byte 1 represents the Pitch (forward/backwards) control.
- Byte 1 has a range of 0–127.
- 0–62 is pitch forward, 63 is centre (default) value, 64–127 is pitch backwards.
- the first bit appears to always be 0.

Byte 2

- Byte 2 represents throttle and channel.
- Byte 2 (throttle) has a range of 0–127.
- 0 is 0% throttle, 127 is 100% throttle.
- the most significant bit of Byte 2 (highlighted red above) indicates which Channel is selected. 0 for Channel A, 1 for Channel B. This is how we can have 2 channels without changing the carrier frequency.

The Mystery of the Missing Byte

You may remember that I said above that everyone else who has reverse-engineered the protocol arrived at a 4-byte control packet. So where was my 4th byte? Well there’s one more dial on the controller we haven’t discussed — Trim. Trim is used to calibrate the rotor speed balance in order to account for any idiosyncrasies in the helicopter’s build that cause it to have a rotational bias to left or right.

In the other’s work, their controller sent a fourth byte containing information about the Trim dial’s setting. My controller doesn’t have that byte, but I do have Trim control… so what’s the deal? Let’s do a bit more testing:

Type:         Data:                     Decimal Values (byte #):
Trim 100% L   010100000011111101010100  (0): 80  (1): 63  (2): 84
Trim Centre   001111110011111101010100  (0): 63  (1): 63  (2): 84
Trim 100% R   001011100011111101010100  (0): 46  (1): 63  (2): 84

We can see that the only byte that changes is Byte 0, so we can assume that rather than have a whole separate packet for trim control, the controller simply offsets the Yaw by a as much as –17 (right/clockwise compensation) or +17 (left/counter-clockwise compensation).

From a reverse engineering point of view, this is an interesting quirk. I have tried and tested both kinds of remote with the same helicopters and they both work flawlessly. What’s more, before I decoded the protocol myself, I built a whole controller based on the 4-byte protocol and never had any issues. So how does the helicopter know which protocol to use?

I think it might have something to do with the footer. The 3-byte protocol doesn’t require the helicopter to do anything in order to account for trim, while the 4-byte protocol requires the chopper’s on-board controller to offset the Yaw by the Trim value. The footer appears to consist a 300us high pulse then nothing until the next header, and this appears to be the case even on the other chaps’ 4-byte packets too. I suspect that if the helicopter’s on-board controller detects the end of a packet and it has only received 3-bytes of data, it pads the trim register with zeroes (no supplied trim offset) because it can assume trim control has been applied by the handset controller. Just a guess, but it seems logical. In any case, who would have thought the helicopter would be backwards/forwards compatible?

Conclusion

So there you have it — my first foray into hardware hacking and exploration. I think I’ve arrived at a definitive physical protocol definition, with timing values even better, perhaps, than the other projects I’ve mentioned throughout.  I put this down to the use of a logic analyser applied directly to the controller — this was unaffected by delays caused by the rise/fall times of the LEDs, IR detector, etc… that were part of the receiver circuits used by Kerry Wong and Hamsterworks to get around the issue of demodulating the 38khz IR signal. I was able to use Saleae’s excellent software to overcome those issues (albeit a little manually — it won’t demodulate the signal for you to my knowledge). The Saleae Logic also allowed me to sample at 16Mhz, certainly fast enough to get a high-resolution picture of the signals and really get some tight timing values for the transitions.

I hope this helps some new hacker get to grips with some of the ideas at play in reverse-engineering and hardware hacking, it’s certainly been a journey of discovery for me. If anyone has any questions, feel free to get in touch at jimhung [at] gmail [dot] com.

On to the next project!

Jim

 ** UPDATE — 12-8-2012 **

I’ve had a little time this weekend to compare a 4-byte controller with 3-byte controller, so here are my findings.

    • The timings for the symbols and transmission intervals are identical between the two controllers, so my timings should work equally well on any revision of the 107G you end up getting.
    • One way to distinguish between which protocol version the controller is using may be the silkscreened model number and date on the controller PCB. The 3-byte controller had the model “S107T1” and the date “20090818” printed underneath the yaw/pitch and throttle control, respectively. The 4-byte controller had “s107T2” and “20100308” printed under the yaw/pitch control and on the right of the PCB.
    • The fourth byte indeed  communicates the value of the Trim, but I actually identified something really interesting — the offsetting of the Yaw value occurs anyway, regardless of packet type! Take a look at this:
Control:         Control packet (4 byte)           Yaw:    Trim:
Trim 100% Left:  01010000001111111011010001111011   80      123
Trim Centre:     00111101001111111100100100111000   61      56
Trim 100% Right: 00101101001111111100111100000001   45      1

I suspect that the 107G doesn’t actually do anything with the Trim packet (perhaps I’ll test that with my DIY controller sometime soon), which explains how it’s able to handle both packet types — it simply ignores anything after the 3rd byte. I suspect that the 4th byte may be used by other toys using a similar design.

12 Comments

  • […] used a logic analyzer to do some in depth analysis of the Syma 107G helicopter’s IR protocol. We’ve seen work to reverse engineer this protocol in the past, but [Jim] has improved upon […]

  • A carrier frequency isn’t used for FDM. Pretty much all infrared communications use 38KHz. It’s done to minimize noise / interference from other infrared sources, since infrared light is fairly prevalent (especially in sunlight). 38khz infrared would be rather rare or impossible to occur naturally, so you get much much more reliable data transfer using a carrier frequency (it doesn’t have to be 38k, but that’s pretty much what everything uses).

  • […] utilizó un analizador lógico para hacer un poco de profundidad en el análisis del Syma 107G helicóptero IR protocolo . Hemos visto el trabajo de ingeniería inversa de este protocolo en el pasado , pero [Jim] ha […]

  • Great work! This was really interesting to read. Hope you have fun with that logic analyzer; it seems really useful.

  • […] used a logic analyzer to do some in depth analysis of the Syma 107G helicopter’s IR protocol. We’ve seen work to reverse engineer this protocol in the past, but [Jim] has improved upon it. […]

  • […] Reverse-Engineering a Syma 107 RC Helicopter […]

  • Looks like some kind of variation of original NEC IR protocol. NEC uses 4 bytes. Its — in theory — possible to fly this thing using universal tv remote.

  • Hi Jim,

    It’s great to see your detailed work here!

    I am a little surprised to see different protocols in different S107 revisions, and even more surprised to hear that either protocol can be used to control the S107.

  • Hey Kerry — thanks! I was really surprised too, it’s certainly whet my appetite to learn more about how toys like this work.

    On a side note, I want to say thanks for writing up your own analysis on this topic, I’m new to this kind of thing and I can honestly say I probably wouldn’t have been able to get my head around it without having first read your great article.

    Take care,

    Jim

  • hi,

    about the fourth byte:
    I’ve got s107 and s800g helicopters. s800g has additional axis on remote for strafe left-right (i believe it is called “roll” in planes). It is probably using the fourth byte. The remotes are exchangeable, ie. I can use any of them to any of the coppters. Of course you can not strafe with 3-axis remote :) . The trim knob is working always as the trim.

  • Ahh — that’s really interesting! I’m in the process of taking a few other IR-controlled flying toys apart right now, but based on your tip I think I’ll pick up one of those 4 channel choppers and revisit the Syma protocol.

    It’s interesting that the 3-channel S107G controller works but doesn’t allow you to strafe — based on how most of the other control registers work, I’d assume that the swash-plate servos responsible for the strafe control would be centered on ‘63’, right on ‘0−62′ and left on ’64−127′, which means that the Trim control on the S107G controller would also adjust the Strafe on the S800G. From a couple of S800G review videos on youtube, it does appear that the S800G’s strafe has a graduated control servo so I can’t really image how else they do it! I guess we’ll just have to find out…

    Jim

  • […] which would lead to the helicopter falling out of air or strange things.  Well, after reading this I compared how often a packet was sent on the three different channels.  That is in fact how it […]

Leave a Reply

Your email is never shared.Required fields are marked *