The Memoirs of Jim 'ung

Arduino-based Syma 107G Controller with Dual-Channel Multiplexing

Arduino-based Syma 107G Controller with Dual-Channel Multiplexing

Arduino-based Syma 107G Controller with Dual-Channel Multiplexing

Hey everyone – I’ve been getting steady traffic and requests from visitors about the Syma S107G controller I’ve alluded to in earlier posts, so I guess it’s about time to write it up properly. Here we go…

Introduction & A little history

Way back in December, 2012, I posted a write-up of the reverse engineering work I did on the control protocol used by the cheap $20 Syma S107G infrared helicopters that are pretty popular at the time.  I guess it turns out they are still pretty popular as the Hackaday post still generates regular traffic to my blog – and a steady stream of emails from other curious makers interested in these awesome choppers.

Before I started reversing the protocol myself, I built a rudimentary controller to learn about how to implement other hacker’s descriptions of the IR protocol used by the S107G. It wasn’t very good, but it did teach me a lot about the importance of writing efficient code for the Arduino and some of the pitfalls of generating communication signals with microcontrollers. After playing around with the controller with my colleagues, I revisited the design of it to clean it up and start exploring how you might be able to pull off some fun stuff – thus the Dual-Channel Multiplexing Controller was born!

An Overview of the Controller

I think that the controller makes for a fun and relatively straightforward project for people interested in playing with robots/remote control vehicles – and more importantly it’s got potential to be the basis for some pretty cool projects in the future. Here’s the breakdown on how it works:

What does the Dual-Channel Multiplexing Controller actually do?

Basically, the controller simply allows you to control two helicopters at the same time from the same unit (using a computer for the controls). It does this by transmitting the control packets alternately for the two helicopters very quickly.

The control method – using the keyboard – is definitely NOT ideal (particularly for two-people at once!), in fact, it’s a real pain in the arse, but this is more of a proof-of-concept for a bigger project that I’ll explain later.

It’s important to note that all of the issues with this method of controlling the heli(s) has nothing to do with the controller itself, just the limitations of having to design a way to control the helicopters with a keyboard.

How to use the Controller

The controller consists of 3 major parts:

arduinorev31s

An Arduino UNOr3 (flashed with the sketch below).

IR_Shield_small

A super-simple “IR Shield” consisting of a couple super-bright IR LEDs and a couple of status LEDs.

GUI_Controller

A Windows app for controlling the heli(s) written in Processing.

Instructions – SYnchronizing

Assuming you have all the parts above, here’s how to get the thing going:

  1. Make sure the IR Shield is properly connected to your Arduino.
  2. Connect the Arduino via USB to your PC. You have to do this first otherwise the controller app can’t enumerate the Serial port and won’t start.
  3. Open the “Heli_IR_GUI_DualControl.exe” app.
  4. Make sure both your heli’s are turned off.
    Note: obviously we don’t want to synchronize our helicopters to the same channel as we wouldn’t be able to control them independently. The following steps are the best way I’ve come up with to sync them separately.
  5. Press either “6” (heli #1) or “7” (heli #2) on your keyboard depending on which heli you want to sync. The appropriate LED (red or green) will turn on indicating you have 10 seconds to sync the heli.
  6. Turn on your Syma S107G helicopter and position it over the IR LEDs on the IR Shield.
    Note: you may notice there’s a flashing light on the heli’s PCB – I think some people believe this is related to the helicopter synchronizing with the controller, but I don’t think that is correct. I think it indicates the status of the on-board gyroscopic stabilization sensor – you need to hold the heli very still and the light will stop blinking. If you’re having trouble holding it still enough, you can try to power it on and place it on a table top while the Controller’s sync LED is lit – I found that the heli’s still synced quite reliably (probably due to the IR signal reflecting off the walls).
  7. Test that the helicopter synced successfully by pressing the helicopter’s Pitch Forward/Pitch Backwards key (W/S or I/K respectively). If the tail rotor spins, you’re good to go, if not, turn the helicopter off and repeat steps 5-7 again.
  8. Repeat for a second helicopter (if you want to).

Instructions – Flying the helicopters

I’ll say up front, flying these things with a keyboard is …sub-optimal at best. Here are some tips on how to get the choppers off the ground:

  • Rule #1: Make sure you hover one finger over the Engine Shut-off Key (Spacebar for #1, “\” for #2). You are going to need this, a LOT. This just cuts the Throttle to zero instantly, and can get you out of trouble when the heli is going out of control.
  • Throttle: This doesn’t work like on the original controller – this is increased/decreased in steps, and the throttle level is maintained until you change it. Press “1” or “]” to increase the throttle, and “2” or “[” to decrease it. Remember, you can always kill the throttle with the Engine Cutoff key.
  • Yaw: Unlike the original controller, this will make your heli turn at a constant rate. Generally this isn’t hard to adjust to, the original controller wasn’t exactly that great either – it’s just more coarse this way.
  • Pitch: Again, this will control the heli’s Pitch at a fixed rate (unlike the variable rate on the original controller).
  • Pro-tip: You probably want to hold it in one hand at first (or have someone else hold it) while you increase the throttle enough for it to hover – using the keyboard can be so slow/clumsy that you wont be able to increase the throttle enough not to send the heli careening off due to wake turbulence near the ground, or slam into the ceiling by overcompensating.

The Controller Hardware

The controller hardware is super simple – just an Arduino UNO and a few LEDs. As I’ve been playing with IR a fair bit, I wanted something a little more robust so I put the LEDs and a couple status LEDs on some Veroboard with some pin-header – we’ll (very generously) call it the “IR-Shield”

The “IR Shield”

IR_Shield

Please excuse the awful soldering.

Schematic:

IR_Shield_Schematic

Bill of Materials:

A few notes on the design:

  • The IR LEDs are wired in series, NOT independently. This is because the reason for two LEDs is for maximum coverage of transmission, not to control one helicopter per LED.
    As I discovered in the protocol reversing, the interval between control packets is surprisingly long, so I found that simply alternating between channel A & B on each loop was more than fast enough to maintain consistent control over both heli’s.
  • As you can see in the photos, I soldered to the Veroboard upside down – this was to accommodate the pin headers which aren’t easily soldered to the Veroboard the right way round (in a Shield-like configuration, at least).
  • The status LEDs are connected to pins 8 and 9 of the Arduino, whilst the IR LEDs are controlled by pin 12.
  • If you look closely at the top right image, I used to use some hot glue as an insulating buffer so the few leads that protrude (ever-so-slightly) didn’t short out to the metal casing of the Arduino’s USB port. Ugly, but functional.
  • The IR LEDs are bent at approximately 45 degrees-ish in opposite directions to maximize their coverage area.

The Controller Sketch

You can download the Arduino IDE sketch here:

The design goals of the Arduino controller sketch were as follows:

  1. To be atomic, and not rely on constant communication from the head-end (PC) to operate.
    This is to ensure simplicity and efficiency in the relationship between the head-end and the microcontroller. I don’t want to have to worry about synchronization of the control messages, filling up the Serial buffer, etc… I just want simple and efficient interactions.
  2. To provide a straight-forward interface to build future work upon.
    Being able to control the choppers with a computer begs for all sorts of great hacks like autopilots, flying Helicopters over IP (HoIP, or really-remote control…), etc…
  3. To be as efficient as possible, given the Arduino’s limited processing power.

    This was due to a lesson learned in an earlier controller project which was woefully inefficient – the helicopter is extremely clumsy when the Arduino can’t keep up with a poorly written sketch!

  4. To reflect the protocol definitions identified during reverse-engineering as closely as possible.
    No sense wasting all that work by using loose timings, eh!

The basic system flow is depicted here:

Controller_Flow_2

This design satisfies the requirements as follows:

  • The controller is atomic and independent (#1) as the head-end only has to be concerned with sending changes to the control registers and doesn’t require continuous synchronous communications to operate. The controller will continue to transmit the values for each control axis until they are changed.
  • The way the control sequences are designed makes implementing the interface on any head-end application very easy (#2). The first value (0, 1, or 2) indicates what type of message it is (helicopter A or B control, or a Sync signal), the second identifies the control axis to update, and the third value is the axis’ new parametric value. A truth table of the control messages can be found below.
  • Using short control sequences, only transmitting changes in control axis values from the head-end (instead of full Syma control packets or whatever), and mostly efficient techniques to construct and transmit the control packets, the Arduino has no issue keeping up with even periods of intense control changes (#3).
  • Other than having to tweak the timings due to the Arduino’s oddly slow pin transition times, the controller sketch implements the definitions I arrived at through reversing nicely (#4).

Controller Interface Truth Table

All you have to do to interface with the controller from any head-end application you want is to send a message sequence consistent with the following table via the Serial connection. Each message should be sent on a consecutive line:

Truth_Table

(click to enlarge)

An example of a control sequence from the head-end might be:

Message 1: "0" - Helicopter A
Message 2: "2" - Change Pitch...
Message 3: "98" - ...to the value "98".

The Controller Application

GUI_Controller

The controller app is written in Processing and uses the ControlP5 GUI library for windowing, etc… The application is very simple and can be split up into 3 major parts: setting up and rendering the GUI, setting up the key-press event listeners, and the subroutines for sending the control updates to the Arduino.

The GUI is super simple – I experimented with having sliders for helicopter control, but it is SO clunky that it’s suicidal. One of the major things was that without some sort of feedback and a PID control routine for maintaining a steady altitude, controlling the other flight axes with GUI controls is far too slow to not crash and burn pretty quickly. So the GUI ended up as instructions and a basic set of feedback on what the current control values are.

The input mechanism ended up being a mixture of aggregating key presses (for things like the throttle where granular control is important), and toggling key presses (for things like Yaw and Pitch, where the keyboard is too clunky for granular control). Aggregate controls either add or subtract from the current control value. Toggle controls just jump to a preset value when pressed, and back to the center value. Ultimately, it turns out that the keyboard ROYALLY SUCKS for piloting helicopters – this is why I had to have an emergency engine cut-off key.

Using the Serial library, we can very simply communicate with the Uno and send the control messages in the format described above. As the coupling between the head-end and the controller is asynchronous and loose, this is basically all we have to do – nice and simple!

Code and Downloads

The Arduino Uno sketch (zip):

UNOr3_Syma107G_Dual_Heli_Controller_JimHung_com

The Processing sketch & 32/64-bit Windows Binary (zip):

JimHung_Processing_Dual_Helicopter_GUI

Conclusion

I hope this has been informative and useful for anyone interested in playing with Arduinos and these awesome helicopters. The control scheme design is very flexible and can be implemented with all sorts of head-end applications. I’ve toyed with the idea of autopilots, flight paths, choreographed flights with 2 heli’s – all of which are possible (with varying degrees of complexity). The controller communication scheme means that in these projects, sending commands to the helicopter is all but taken care of.

If anyone wants to give it a go and has any trouble, please don’t hesitate to pick my brain in the comments. Stay tuned for more reverse-engineering fun.

7 thoughts on “Arduino-based Syma 107G Controller with Dual-Channel Multiplexing

  1. Myles

    Hi Jim
    In your code you have a comment about using a 16MHz ic. Have you got this to work on an 8MHz pro mini 3V? I’m keen to get it running off this platform as I want to attach and power the pro mini from the heli battery.
    Myles

    1. Jim Post author

      Hi Myles,

      That’s a great question – I think I can imagine the hacks you have in mind! I took another look at the Arduino code in my controller to refresh my memory and I think you might be ok with it as it is on an 8MHz CPU. Here’s my thinking:

      We basically need to generate a 38KHz carrier signal for the helicopter’s IR receiver diode to see our signal – this is achieved using the following function:

      void sendPulse(long us) {
      for(int i = 0; i < (us / 26) - 1; i++) { digitalWrite(LED, HIGH); delayMicroseconds(10); digitalWrite(LED, LOW); delayMicroseconds(10); The logic behind this is that 38KHz (or in other words, 38000 oscillations per second) is 1 pulse every 26 microseconds (1/38000). The transition time for the output pin of the Arduino and the IR diode is roughly 3 microseconds, so we have to wait 10 microseconds after each transition to make up the rest of the time. The delayMicroseconds (like most of the convenient timer functions used by Arduino's) is based on the VARIANT_MCK constant which is specific to each Arduino model - this means that it will automatically adjust for the appropriate clock speed of your board so the timings should still be accurate. Now, one thing I'm not sure about is whether the pin transition times will be consistent, so you may wish to tweak the timings a little (by reducing the amount of time you wait after the transition). Best of luck, Jim

      1. Jim Post author

        Also, I just thought on, if you are thinking of mounting the Pro Mini to the helicopter itself, I’d look at two things:

        1) Does the IR receiver demodulate the carrier signal too? In other words, does the helicopter’s microcontroller expect 38KHz modulated pulses, or just the control packet pulses?
        2) From the look of this Instructable, it looks like the logic level is actually inverted on the helicopter’s control board (look at Step 3): http://www.instructables.com/id/Add-Radio-to-an-Syma-S107-IR-Helicopter-or-any-oth/?ALLSTEPS

        Assuming you plan to connect to the input signal pin of the helicopter’s uC directly from the Pro Mini: If (1) is true, you don’t need to worry about the 38KHz carrier at all, and if (2) is true, you need to make sure you invert the high and low signals output.

        Hope that helps,

        Jim

        1. Myles

          Thanks for the reply. I used your IR control code as is (except I’m reading sensor inputs in the 60ms delay in sendFooter), without wiring directly to the heli receiver board. I went ahead and bought a very small 5V voltage step up module from pololu. It only weighs 0.37g https://www.pololu.com/product/2115 This allows me to run a standard 5V pro mini. I have a resistor soldered directly to the arduino with the IR LED attached to it. The arduino is powered from the heli lipo battery. Also using a MS5611 barometer sensor and the I2C interface. This whole assembly is attached to the bottom of the heli centered on its COG. It weighs about 3g. I had to put the heli through some weight reduction to save these 3gs but it’s all possible just through removing various screw on parts. Thanks to your library I was able to have the heli controlled autonomously with PID altitude hold implemented so far. My next step is to to include a digital compass sensor input. I’ll let you know when I have the finished setup. The S107g is a great stable platform for autonomous control. It really is great to see these micro helis taking off and flying on their own!

          1. Jim Post author

            Myles – that sounds very cool, I’d love to see a writeup or photos of it working! I’m curious, what kind of battery life you get with the Pro Mini running off the heli’s LiPo? I’m working on a similar autonomous PID control with some little Hubsan X4 quadcopters, but I’m using computer vision (AR marker tracking using a webcam attached to my laptop) to map the quad’s location in 3D space and generating my positional sensing from that – until now I thought that kind of outside-in control was all that was feasible on these small RC toys, but you’ve given me some food for thought. I think the X4’s carrying weight is probably a bit less (out of the box at least) than the S107G, but I wonder if I can use an IMU with a barometer and digital compass to achieve the same end.

            How are you planning to provide navigation information to the heli?

            Jim

  2. Myles

    I think I’ll put up a YouTube video after the S107 maiden outdoor flight. I’m not adding navigation to the S107 other than using the baro for altitude and a compass to set a particular heading for wind compensation. The compass can be problematic with the strong magnetic field from the motors. Also with the baro sensor the best is the MS5611, it has an accuracy of +-20cm compared to +-50cm for a BMP180 sensor. I’ll be using the BMP180 on a 10DOF board for outdoor altitude control only. The purpose of my current S107 project is to launch the heli vertically 50m, 100m?, hover for a bit, then land. I’ll take the tail boom off for more weight savings and add a microSD DVR to record the flight if possible. For full indoor navigation you are probably limited to the external computer vision control you mentioned above. That would go for a quadcopter project too as the GPS signal is not accurate indoors. But you could use ultrasonic sensors and a compass on a large enough quad. I have a 4g GPS module that could be carried by an S107 but I think I’ll be putting that on a v911 heli and getting that to fly outdoors.

  3. Juris Perkons

    Hello! Thank You for sharing your work! I am electronics hobbyist and engineer for decades. but, I am weak at programming. I would like short question here: would it be difficult to add here physical controls, by analog reading values from pots? Even if it would take another additional MCU (Arduino) for that (for not introducing any delays in original code). Or, maybe you could point me to some project where it has been done already. I am searching for such solutions right now – I have IR helicopter without original remote.
    Thanks in advance!

Leave a Reply

Your email address will not be published. Required fields are marked *