Reverse Engineering the Syma S107G IR Protocol

I got a Syma S107G IR controlled helicopter for my son a while ago. This tiny remote control helicopter is a rather amazing toy. Not only its movement is very stable, but the rotor speed, forward backward movements and turning can be all proportionally controlled as well. I thought it might be interesting to take a look at its control protocol to see how things are done. And yes, I do have a video at the very end showing controlling the S107G using the reverse engineered remote control.

Before I started decoding the IR protocol, I was hoping that I could find some useful information by examining the circuit board of the remote control. So I took it apart:

Transmitter

Transmitter

Transmitter Circuit Board

Transmitter Circuit Board

Well, it appeared that the transmitter for the S107G uses an MCU to do all the encoding which means that without taking a look at the actual code, there isn’t too much information I could get by just staring at the board. Unfortunately, the marking of the MCU was purposefully sanded off (a rather common practice in the commercial world) so I couldn’t figure out the actual microcontroller used in the circuit easily either.

By looking at the silkscreen though, it seemed that the transmitter works at either 38kHz or 57kHz, which corresponds to either channel A or B that the transmitter can operate on. Another piece of information I gathered is that three potentiometers are used to control the throttle and directions. Presumably, the voltage outputs from these potentiometers are coupled onto the ADC pins of the microcontroller.

So I decided to dig a little big further by analyzing the actual IR signal. The first step I took was to view the IR signal sent from the transmitter. This can be done in a couple of ways, one way is to measure the waveform directly from the output photo diode on the transmitter and the other way is to use a receiver circuit and measure its signal output. Here, I used the latter method. The following schematic shows the simple IR receiver I made to analyze the signal.

IR Sensor

IR Sensor

IR Detector

IR Detector

First I wanted to see the modulated IR waveform so I used a standard IR photo diode as the sensor and hooked up the output to an oscilloscope. From the data capture, we can see that the IR command repeats at an interval of 184 milliseconds. Zooming in onto each section we can see the modulated IR signal. The image below on the right shows the modulated waveform of a command, repeating at an interval of 184 milliseconds.

IR Signal Frame

IR Signal Frame

Modulated IR Signal

Modulated IR Signal

And by zooming in further, we can see that the IR signal is modulated at roughly 38kHz which corresponds to one of the transmitter’s operation modes. The carrier waveform has a duty cycle of roughly 50%.

IR Frequency (38 KHz)

IR Frequency (38 KHz)

In order to analyze the IR encoding scheme, we will need to use the demodulated waveform. IR demodulation can be done by replacing the IR photo diode I used earlier with an IR sensor as most IR sensors designed for remote controls demodulate the carrier signal automatically.

Here is an output of the demodulated IR command signal:

Demodulated IR Signal

Demodulated IR Signal

Since the transmitter’s output waveform would vary depending on the control levers’ positions, I decided to record a few waveforms with different control positions. And by comparing these recorded waveforms, hopefully we can infer how the control positions are encoded.

The following waveforms are recorded using a combination of throttle and direction control lever settings (click to enlarge). To obtain these waveforms, the oscilloscope was set to deep memory mode and the results from each individual run were trimmed so that the beginning of the commands are aligned. Note that the X axis does not represent time, it simply represents the number of pixels in my oscilloscope screen capture.

Captured Waveforms

Captured Waveforms

As you can see from the waveform capture above, each signal is consist of 34 pulses. Since for digital systems information is represented in bytes, it is reasonable to assume that the pulses form a 4-byte signal with the extra two pulses as the header. Based on this assumption, the first high-low-high transition marks the beginning of a command. And herein I will refer to it as the header. Since the pulse widths are the same (except for the header), the ones and zeros are distinguished by the duration of the lows. The following graph shows the timing of the signal:

Signal Timing

Signal Timing

So far, we have gathered the following information:

For 38kHz mode:

Command duration:     180  ms
Header High Duration: 2.04 ms
Header Low Duration:  2    us
Pulse width:          380  us 
Low duration for 0:   220  us
Low duration for 1:   600  us

For 57kHz mode, everything is the same except the following:

Command duration:     160  ms
Low duration for 1:   660  us

With this information on hand, we can decode each of the IR signals captured above as follows (in the stacked waveform graph above, No. 00 is the one on the bottom):

No. Throttle  Direction                  Binary                              Dec(Hex)
00    ~0%      Middle       00111100 00111111 10001011 00110100    60(3C)  63(3F)  139(8B) 52(34)
01   ~25%      Middle       00111100 00111111 10100111 00110100    60(3C)  63(3F)  167(A7) 52(34)
02   ~50%      Middle       00111100 00111111 11001000 00110100    60(3C)  63(3F)  200(C8) 52(34)
03   ~75%      Middle       00111100 00111111 11100110 00110100    60(3C)  63(3F)  230(E6) 52(34)
04   100%      Middle       00111100 00111111 11111101 00110100    60(3C)  63(3F)  253(FD) 52(34)
05   100%      Left         01101010 00111111 11111101 00110100    106(6A) 63(3F)  253(FD) 52(34)
06   100%      Right        00001000 00111111 11111101 00110100    8(8)    63(3F)  253(FD) 52(34)
07   100%      Forward      01000000 00000001 11111101 00110100    64(40)  1(1)    253(FD) 52(34)
08   100%      Backward     00111100 01111110 11111111 00110100    60(3C)  126(7E) 255(FF) 52(34)
09    ~0%      Left         01101010 00111111 10001101 00110100    106(6A) 63(3F)  141(8D) 52(34)
10    ~0%      Right        00001000 00111111 10001101 00110100    8(8)    63(3F)  141(8D) 52(34)
11    ~0%      Forward      01000000 00000001 10001101 00110100    64(40)  1(1)    141(8D) 52(34)
12    ~0%      Backward     00111100 01111101 10010001 00110100    60(3C)  125(7D) 145(91) 52(34)

From line No. 00 to No. 04, I only changed the throttle position and left the direction control in the middle. From the decoded waveform you can clearly see that the only number that was changing is the third byte and it is apparent that this value is proportional to the rotor speed. Note that throttle value does not start from zero, this is probably mainly for practical reasons as in only higher RPM range could the rotor generate sufficient lift. And by limiting the potentiometer’s output to this range, a finer adjustment in higher RPM range can be obtained.

In line No. 05 and 06, the throttle was placed at 100% and I changed the direction from full left to full right. This resulted a change in the first byte (from 106 to 8). So I inferred that 60 must be corresponding to the center position and the left-right control has roughly 6 bit of resolution from the center.

Line No. 07 and No. 08 are the results from moving the direction lever full forward and full backward while leaving the throttle at 100%. As you can see from the decoded data above, the second byte changed accordingly from 1 to 126. So the forward and backward control is coded in the second byte and it has 7 bit of resolution in each direction.

No. 09 through No. 12 are basically repeating No. 05 to No. 09 except that the throttle was set to 0. Because potentiometers are used for all the controls, the digitized values may be slightly different from the theoretical values even when the controls are set to the same positions each time.

The only byte we have not accounted for so far is the last one. It seems to be fixed at 52 across all the different runs. As it turned out, this byte stores the calibration information and is controlled by the calibration knob on the transmitter. The calibration knob is used to make the helicopter hover without rotating when only the throttle is applied. When the calibration knob is turned right (the helicopter will rotate right when no directional control is applied), this number increases accordingly and when the calibration knob is turned left (the helicopter will rotate left when no directional control is applied), this number will decrease. When trimmed to the appropriate value, the helicopter will be calibrated and will not rotate unless directional control is applied.

So now we have decoded the control scheme. Each IR command is consisted of a header, followed by four bytes which encode the rotational direction (left/right), forward/backward movements, throttle and the calibration data.

To validate the IR control protocol, I wrote a simple program using an Arduino board. The full code listing can be found towards the end of the post. Basically, I used Timer1 to generate the 180ms command repeat interval. Timer2 is used to generate the 38kHz 50% duty cycle PWM carrier signal. Zeros and Ones are generated by turning on and off the 38kHz signal for the desired duration using delayMicroseconds. Three potentiometers were used to control rotor speed (throttle), forward/backward movement and left/right rotations respectively. Since the calibration can be done ahead of time, I chose to hard code the calibrated value in code to simply the control a little bit. Of course, you could always use a fourth potentiometer for this purpose.

IR Transmitter

IR Transmitter

Here is a short video demonstrating the reverse engineered IR control.


View on YouTube in a new window

Conclusion

Reverse engineering is all about methodology, patience and of course lots of luck…

Source code

#include <TimerOne.h>

//comment this out to see the demodulated waveform
//it is useful for debugging purpose.
#define MODULATED 1 

const int IR_PIN = 3;
const unsigned long DURATION = 180000l;
const int HEADER_DURATION = 2000;
const int HIGH_DURATION = 380;
const int ZERO_LOW_DURATION = 220;
const int ONE_LOW_DURATION = 600;
const byte ROTATION_STATIONARY = 60;
const byte CAL_BYTE = 52; 

int Throttle, LeftRight, FwdBack;

void sendHeader()
{
  #ifndef MODULATED
    digitalWrite(IR_PIN, HIGH);
  #else
    TCCR2A |= _BV(COM2B1);
  #endif
  
  delayMicroseconds(HEADER_DURATION);
  
  #ifndef MODULATED
    digitalWrite(IR_PIN, LOW);
  #else
    TCCR2A &= ~_BV(COM2B1);
  #endif
  
  delayMicroseconds(HEADER_DURATION);
  
  #ifndef MODULATED
    digitalWrite(IR_PIN, HIGH);
  #else
    TCCR2A |= _BV(COM2B1);
  #endif
  
  delayMicroseconds(HIGH_DURATION);
  
  #ifndef MODULATED
    digitalWrite(IR_PIN, LOW);
  #else
    TCCR2A &= ~_BV(COM2B1);
  #endif
}

void sendZero()
{
  delayMicroseconds(ZERO_LOW_DURATION);

  #ifndef MODULATED
    digitalWrite(IR_PIN, HIGH);
  #else  
    TCCR2A |= _BV(COM2B1);
  #endif
  
  delayMicroseconds(HIGH_DURATION);
  
  #ifndef MODULATED
    digitalWrite(IR_PIN, LOW);
  #else
    TCCR2A &= ~_BV(COM2B1);
  #endif
}

void sendOne()
{
  delayMicroseconds(ONE_LOW_DURATION);
  
  #ifndef MODULATED
    digitalWrite(IR_PIN, HIGH);
  #else
    TCCR2A |= _BV(COM2B1);
  #endif
  
  delayMicroseconds(HIGH_DURATION);
  
  #ifndef MODULATED
    digitalWrite(IR_PIN, LOW);  
  #else
    TCCR2A &= ~_BV(COM2B1);
  #endif
}

void sendCommand(int throttle, int leftRight, int forwardBackward)
{
  byte b;

  sendHeader();
  
  for (int i = 7; i >=0; i--)
  {
    b = ((ROTATION_STATIONARY + leftRight) & (1 << i)) >> i;    
    if (b > 0) sendOne(); else sendZero();
  }
  
  for (int i = 7; i >=0; i--)
  {
    b = ((63 + forwardBackward) & (1 << i)) >> i;    
    if (b > 0) sendOne(); else sendZero();
  } 
  
  for (int i = 7; i >=0; i--)
  {
    b = (throttle & (1 << i)) >> i;    
    if (b > 0) sendOne(); else sendZero();
  }
  
  for (int i = 7; i >=0; i--)
  {
    b = (CAL_BYTE & (1 << i)) >> i;    
    if (b > 0) sendOne(); else sendZero();
  } 
}

void setup()
{
  pinMode(IR_PIN, OUTPUT);
  digitalWrite(IR_PIN, LOW);

  //setup interrupt interval: 180ms  
  Timer1.initialize(DURATION);
  Timer1.attachInterrupt(timerISR);
  
  //setup PWM: f=38Khz PWM=0.5  
  byte v = 8000 / 38;
  TCCR2A = _BV(WGM20);
  TCCR2B = _BV(WGM22) | _BV(CS20); 
  OCR2A = v;
  OCR2B = v / 2;
}

void loop()
{  
   
}

void timerISR()
{
  //read control values from potentiometers
  Throttle = analogRead(0);
  LeftRight = analogRead(1);
  FwdBack = analogRead(2);
  
  Throttle = Throttle / 4; //convert to 0 to 255
  LeftRight = LeftRight / 8 - 64; //convert to -64 to 63
  FwdBack = FwdBack / 4 - 128; //convert to -128 to 127
  
  sendCommand(Throttle, LeftRight, FwdBack);
}
Be Sociable, Share!

42 Comments

  1. [...] [Kerry Wong] seems to be in this boat. He bought a Syma S107G helicopter for his son. The flying toy is IR controlled and he reverse engineered the protocol it uses. This isn’t the first time we’ve seen this type of thing with the toy. In fact, we [...]

  2. Francisco says:

    Hi Kerry
    Very well done!
    Are you using Rigol DS1052 E scope.The image of the captured waveforms? How was that taken.
    Many thanks for your inspiring work.
    Francisco
    Green Valley, Canada

    • kwong says:

      Hi Francisco,

      Thanks for your comment. Yes, the oscilloscope is an RIGOL 1052E. In order to capture the waveforms and stack them up for comparison, I used the long memory (1 meg) option, and saved the results to a thumb drive using the wfm format.

      The files are then imported in the RIGOL oscilloscope software (the software came with the scope) so that I could convert the wfm format into a readable CSV format. There are many WFM readers out there that could achieve the same.

      After converted to CSV, I trimmed the waveform so that they start at the same location. I also down-sampled and cleaned the waveform a little bit (e.g. using a threshold to make the 0′s and 1′s cleaner) to make it easier for plotting.

      Nothing magic here…

  3. Greg says:

    void timerISR()
    {
    //read control values from potentiometers
    Throttle = analogRead(0);
    LeftRight = analogRead(1);
    FwdBack = analogRead(2);

    Throttle = Throttle / 4; //convert to 0 to 255
    LeftRight = LeftRight / 8 - 64; //convert to -64 to 63
    FwdBack = FwdBack / 4 - 128; //convert to -128 to 127

    sendCommand(Throttle/4, LeftRight, FwdBack);
    }

    Is the line
    sendCommand(Throttle/4
    Correct? You have already /4 in the line
    Throttle = Throttle / 4; //convert to 0 to 255

    If it is correct, why not do
    Throttle = Throttle / 16; //convert to 0 to 255

    sendCommand(Throttle, LeftRight, FwdBack);

    • kwong says:

      Hi Greg,

      Thanks for spotting the error. I was trying to make the code look easier to look by breaking out the calculations of Throttle, LeftRight/FwdBack, and evidently forgot to remove the /4 in sendCommand function call. I have fixed it. Again, thank you for pointing it out.

  4. [...] [Kerry Wong] seems to be in this boat. He bought a Syma S107G helicopter for his son. The flying toy is IR controlled and he reverse engineered the protocol it uses. This isn’t the first time we’ve seen this type of thing with the toy. In fact, we [...]

  5. Anthony Orquiales says:

    i have an error occured..
    day2.cpp: In function ‘void setup()’:
    day2:125: error: ‘Timer1′ was not declared in this scope

    • kwong says:

      Hi Anthony,

      Timer1 is an Arduino library, which you can download from here (http://www.arduino.cc/playground/code/timer1). After download, you will need to extract and copy the folder into your arduino installation folder under libraries.

      • Anthony Orquiales says:

        thank you soo much sir kwong! this would help.. im really2 desperate to make a project like this for my technical electives class. im a computer engineering student, and we are into arduino projects right now.. im trying to save my grades through this project of yours.. thanks a lot.. but im still having a problem about the circuit. i cant figure out that picture. and the components to be use. =(

        • kwong says:

          For the potentiometers, you can use any linear ones from 5K to 50K (the value doesn’t matter much) and one end needs to tie to the ground, the other end needs to tie to Vcc, the wiper feeds into the ADC pins on the Arduino board. For the IR diode, you can simply connect it to the digital pin 3 via a resistor (say 470 Ohm).

          For more information, I’d recommend you looking at some tutorials on the Arduino site. Good luck.

  6. [...] the QuadHybrid controller board. Syma helicopters integrated boards are harder to hack into – however some people have managed to hack into them and reverse engineer the [...]

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

  8. [...] Reverse Engineering the Syma S107G IR Protocol [...]

  9. Mike says:

    I also have decoded the signals for some Radio Controlled(RC) toys. The steps is very similar as you done. great hacking!
    I wounder it be good if we can developed an universal decoder (i.e. it can decode any signals from some kind of toys using IR or RC) and store the commands, finally it become the controller of the toys.

    http://blog.yahoo.com/_AAOOSSJL6CMKNYHGQTEXZOTMVU/articles/326493

    http://blog.yahoo.com/_AAOOSSJL6CMKNYHGQTEXZOTMVU/articles/326494

  10. Jonah Kif says:

    Hi Kerrt D.Wong,

    I was wondering if you could upload the schematic diagram of the breadboard circuit.

    Kind regards
    Jonah

  11. JSarao says:

    Do you have a part number for the IR LED emitter you used?

    • kwong says:

      Sorry… I don’t. You can pretty much use any IR LED for this purpose. The bigger ones are better in general as they can be driven with higher current (e.g. 25 to 50 mA), which translates into greater control distance.

  12. Matt says:

    Mr. Wong,
    Fist off, thank you for your work here! I have completed functional code to fly the s107g using a PS3
    Navigation controller. I’m stuck at one point though, and that is trying to code using 2 separate buttons to change
    the CALBYTE value. Specifically, changing the value from 52 to any number does not have any effect on the copter. I’m still new to writing code, but was wondering what your thoughts were on this. I even commented out
    the calbyte portion of code with no change in copter behavior. Also, could you elaborate on the ROTATION STATIONARY variable? One more note, since the ps3 navi controller is all 0-255 data values, I had to change the math in void send command. I did have some (overflow?) Issues such as throttle, which by your code, should be
    looking for 0-255. Anything over 127 would shut down the rotors. I’ve figured it all out, but just wondering why this is. Thank you for any input on these issues!

    • kwong says:

      Hi Matt,

      According to Jim (http://www.jimhung.co.uk/?p=901), S107G has at least two different revisions and the command structures are different among the two. Could you check yours? From what you described, it sounds like your S107G protocol might be different then the one I reverse engineered?

      • Matt says:

        Kerry, Thanks for that link! It makes sense of several issues, but at the same time, causes more confusion!
        I took apart my controller, and it is identical to the one you have pictured here. It does NOT at all look as the one
        posted by Jim. It also appears to have a newer date code though(purchased this several months ago from Amazon), with
        “S107T4″ and 20110623 date code. What’s now confusing me, is that Jim’s explained control structure of 0-127 is
        exactly what my math equals for control of the the heli, although i’m using ” / 2 – 64 ” math instead of mapping
        0-255 to 0-127( or just simply ” / 2″ ?? . I think i will do that next and see what happens. From what I understand now,
        the fourth byte doesn’t do anything with the control of the S107G, which is why changing the CAL_BYTE value had no effect.
        It’s simple enough to code two remote buttons to change the “center” value to adjust trim. I guess what I’m confused about
        now, is that my controller is identical to yours, but needs the 0-127 for ALL control values. If i’m understanding
        your Analog to Digital math, throttle is 0-255, left/right is 0-128, and forward/backward is 0-255 ??

        • kwong says:

          Well, the fourth byte does control calibration if your controller uses the 4-byte format, but if it is 3 byte my understanding is that the calibration is embedded in the 3-byte code. Do you have an oscilloscope/logic analyzer to take a look at the waveform?

          • Matt says:

            Looking at Jim’s page, at the very bottom he has an update with new findings of the 3 and 4 byte controllers. He says that even though the trim control on the 4 byte
            controller does indeed send trim data on byte 4, both transmitters actually adjust byte 1 yaw/left/right bits with the trim control knob. His theory is that byte 4
            is used for other toys which use similar protocalls and/or hardware, but the S107g does not use that byte. To me this makes sense, because he also says that he used both
            transmitters on the same helicopter without issue.

            One more finding, which I think Jim has hinted at, but not explained in much detail- Channel selection of A or B still nets 34khz. The channel is selected by changing the
            first bit in byte 3. 0 = channel B, 1 = channel A. You have decoded channel B, Jim has decoded Channel A. This is why your throttle values are to 255, and his are to 127.
            When the controller is set to channel A, the copter sees the minimum 0 bits, and follows this to stay on that channel. If it sees over 128 at power up, it knows to
            use Channel B, which goes from 128 to 255. From my findings, the control duration is not channel specific, as i’m using your code for channel B, but using Jim’s
            channel A throttle bits(0-127, or all 1′s in the first bit of byte 3) and it works just fine.

            I’m suspecting the channel selector on “our” transmitters is nothing more than a simple voltage divider that goes to the throttle lever input.
            Channel A may send 0-2.5 volts to the lever, Channel B may send 2.5-5 volts. Then ADC is done in the controller. I believe it also sets a pulse duration change
            in the controller as well.

            Looking at both of your and Jim’s decoded bytes, they all pretty much match except throttle data, but after really looking at it, its the channel selection bit on
            the first bit of byte 3 that is only different. So I believe your throttle math should be 127-255(to select channel B), not 0-255. I think you inadvertently hint on
            this by saying throttle does not start at 0. I’m not sure how you were able to start the throttle at 128, unless you mapped this electrically at the pot(or maybe I’m
            missing this somewhere in your code?).

            Unfortunately, I do not have any testing equipment, but If you feel so inclined, see what byte 1 does with the trim control, and what byte 3 does
            with A and B selection, although I gather Jim has already done this test. Again, thank you for your work on this, I have learned quite a bit with
            this project!

          • Jim Hung says:

            Hey Matt,

            I think you’re on the right track – a few points:

            1) I think that the 4th byte is just ignored by the S107G, Trim/calibration is definitely controlled by offsetting the Yaw value. I picked up a Syma S800G which has sideways (slide) control and took a peek at it’s control packets. It does appear that the S800G uses the 4th byte for left/right slide control, whilst Trim is again applied by offsetting the Yaw. Interestingly, using the S107G controller (a 4-byte model – S107T2) with the S800G and applying a little throttle while holding it in your hand, the helicopter responds – altering the Trim dial makes the slide servo’s move! Sadly you can’t use the S107G controller to control Slide in the air because the Trim dial is bound to Yaw and the 4th byte, and it makes the chopper go into a crazy spiral..

            2) For control purposes, channel selection is just a matter of changing bit #16 to 0 or 1 – though for the physical controllers, the channels also change the packet transmission intervals to avoid packet collisions (channel B’s interval is 1.5x the interval of channel A). As an example of the use of the Channel Bit in practice, I built a controller using an Arduino controlled by a Processing sketch that can control 2 helicopters simultaneously (and independently) with one transmitter by just alternating the channel bit (and using 2 different control value arrays).

            I actually just finished writing up a proper technical protocol definition for this protocol (to make it easier to use than my blog post for proper development) – you can take a look here: http://www.jimhung.co.uk/?page_id=1076

            Hope that helps!

            Jim

  13. Nat Klopper says:

    Hi I’ve been following your tutorial i have set up all the hardware and loaded your code, but when i try to run the helicopter it links up (the green led stops flashing) but the blades wont spin at all when i turn the potentiometers which is very irritating any help would be much appreciated many thanks in advance

  14. [...] 3ch helicopter and standing in for the Netduino is an Arduino.  I had a go at implementing the IR protocol in the .NET Micro Framework but it proved a little tricky.  More information can be found in this [...]

  15. [...] to upgrade my old project by swapping the RC car out for a Syma S107G.  I tried to implement the IR protocol in C# using the .NET Micro Framework for the Netduino but it proved more than a little tricky to [...]

  16. Stuart says:

    When i followed the link at the top of the page it says it has 3 channels but you said it has 2 frequencies. Is that the same helicopter you used for this? i am planning to get one and do this and just wanted to double check incase its not and it uses a different protocol for control

  17. Kerry -

    Excellent piece of work. I used the Syma helicopter two years ago when I taught a sophomore level engineering design class at TCNJ. The students – all engineering disciplines – we split into groups of four and given a helicopter to “play” with. The goal of the exercise was to give the students an initial reverse engineering experience. The groups determined parameters such as maximum flight time for hovering flight, maximum duration of operation under max throttle, maximum range for IR remote in different flight environments, e.g. narrow hallway, large open space, dark rooms, brightly lit rooms, outdoors in shade, outdoors in direct sunlight.

    The students also used a scope to observe the IR signal and were able to “with some help” determine that the scope was showing them a 38 kHz modulated signal with 4 bytes of information. Most were also able to determine which of the bytes corresponded to what channel. I am now at UMass-Lowell and I am preparing to teach a similar type of class. I will be using arduino boards and have decided to create a blimp-bot to show off during introductory lecture. I didn’t keep any notes on what I had done previously with the Syma remote and was starting from scratch – with no scope handy I was using the arduino to decode the signal using a combination of sample codes from adafruit and Ken Shirriff’s IR Library. I had just about pulled it all together when I cam across your post. I am an ME by training and I love learning from well-written code.

    The blimp-bot will use the helicopter to provide enough thrust to hover in place (the helium blimp will provide lift for the majority of the structure. The system will determine its height using a Ping ultrasonic sensor and a simple PID loop will be used to provide control signals to the Syma. Should work… I’ll send a link to a write-up.

    Thanks again

  18. Octavian says:

    Hi.
    I ended up on your page looking for ways to hack a micro heli rc system. I want to built a micro plane with proportional solenoid actuators. I was interested in IR as it is light and cheap. I already have a couple of old micro helies around and was looking on how to hack them. The problem is that theese helies are single rotor type and there is some mixing between the two chanels. The microcontroller in the transmitter has it’s model erased just as yours. Can you think of a way to get read of the mixing and get two clean proportional channels?
    Thank you and great job with this post.

    • kwong says:

      If the controls are digital, you can record some commands just like what I did with some known states and see if you could see a pattern from these recorded waveforms.

      If your controls are wireless, you will need to measure the waveform after it is demodulated.

  19. Octavian says:

    Well. Don’t have the equipment to measure that. However from the board i’ve noticed that the microcontoller is 18 pin with vcc vdd on the central pins. That is consistent with pic chips. I will try to read it and see if I can rewrite it. If so, I will still have to descifer the code and change it but my assembler knowlege is quite limited.

  20. Charlie Fowler says:

    Hey guys. Maybe someone can help me out here. I have the 107G mini metal and its doing something odd. So the trim dial went bad on the remote. I do electronics repair so I just ordered another same type same model and installed it. Well during the install I noticed the remote main board had a bunch of just horrible solder joints. Its for my 7 year old and we all know they like to drop things so I went ahead and re soldered a bunch of spots. I didnt move any resistors or change their location in way. I just put a little more so it would hold better (in case of a drop). Now… the stupid thing is turning left and right way faster than it should and its no longer flyable for either of us. Its like I changed the response speed or something… Can anyone tell me how to reverse what I did or even an idea as to what I could have done for that to happen. I really like the little bugger and my son… he would like to fly it again too… CAN ANYONE HELP??? I need and would really appreciate it. Thanks Guys.

  21. Jake says:

    Mr. Wong,

    I am adapting your code to make an autonomous drone and I am wondering if…

    FwdBack = FwdBack / 4 – 128; //convert to -128 to 127

    should really read…

    FwdBack = FwdBack / 8 – 64; //convert to -64 to 63

    The reason I suspect this is because once the value goes less than -63 the rotation reverses to forward thrust.

    Nice work by the way and thank you very much for making your work available. I was unsuccessful in my attempt to reverse engineer the signal so your code was a huge help.

    Thanks again,

    Jake

  22. JC says:

    I was just thinking of picking up a s107 and I’ve been looking at various mods. I was also thinking how hard could it be to set up a computer program that controls one. Thanks to your work it doesn’t look that hard. My thought was to add in a kinect, get the kinect to see the helicopter and then experiment with AI control.

  23. Tibia says:

    Amazing work. Really.
    Thank you for sharing !

  24. apoorv says:

    sir i want to upgrade my 2 ch rc helicoter into 3 ch i found that in my helicopter chip MF and MB are written but there is no connection and the M+,M- for motor L+,L- for led are mention and in my remote controll the same ic is used which is used on the helicopter but no name is there on it i have a motor with me which i want to attatch at the back to give fw and back movement pls guide me through this

Leave a Reply