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:
An Arduino UNOr3 (flashed with the sketch below).
A super-simple “IR Shield” consisting of a couple super-bright IR LEDs and a couple of status LEDs.
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:
- Make sure the IR Shield is properly connected to your Arduino.
- 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.
- Open the “Heli_IR_GUI_DualControl.exe” app.
- 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.
- 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.
- 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).
- 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.
- 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”
Please excuse the awful soldering.
Bill of Materials:
- 2 x Radioshack Super-Bright IR (940nm) LEDs
- 1 x Generic Green LED
- 1 x Generic Red LED
- 1 x 33Ohm resistor
- 2 x 1kOhm resistor
- Small Veroboard/protoboard (from Amazon, but now out of stock — it doesn’t really matter though, any 0.1″ pitch protoboard will do)
- 8 pins of male header
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:
- 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.
- 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…
- 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!
- 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:
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:
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
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):
The Processing sketch & 32/64-bit Windows Binary (zip):
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.