I have a Syma S107 helicopter. It’s a decent little copter, but I wanted to control it with my USB joystick (I can’t really remember why now, but I just thought it was a really cool idea last Friday. :P) [Edit: I remember now! I have a Leap Motion controller pre-ordered from almost a year ago. When it arrives I will be able to control the Helicopter with swipe motions!! 😀]. Having decided to not go into work over the weekend, I proceeded to attempt to get this to work.
What I Have I don’t know too many people who would actually want to do this, so I’m not going to label this section “What You Need”. I have a 3-channel Syma S107 (which is apparently different than the two-channel one).
I also have a Logitech Attack 3 USB joystick. This is pretty nice, cheap USB joystick. For what I did, I suspect any 3-axis would do as well.
I also have a couple of Arduino boards that can be used to emit the IR signals. Finally, I have a Labview license from my research work, that allows me to interface the USB device with the helicopter.
Determining Signal Protocol The Syma remote uses infrared LEDs to transmit the data to the helicopter. The problem is that there is no easy way to determine the IR protocol unless you construct an IR receiver to decode it. Thankfully, because this is such a favorite of DIYers, the protocol can be found online. In fact, Arduino programs have been written to control the helicopter through the Arduino serial monitor. It might be possible to directly pipe the signal from a USB device to the serial port, but I don’t know how to do that and it’s certainly not something easily achievable over one weekend. The default program also only allowed a single command to be sent at one time, so you can only control throttle, pitch or yaw, but never at the same time. So instead, I went through the protocol and found that essentially the helicopter receives a 30-bit signal packet, with the following bit assignments: HH-00-PPPP-TTTTTTTT-YYYY-RRRRRR-CCCC where H = header (or channel ID), P = pitch control, T = throttle level, Y = yaw, R = trim (or correction for rotational zero error), and C = checksum. In addition, each true-bit (‘1’) is a 32-pulse burst, while a false-bit (‘0’) is a 16-pulse burst. Each pulse is high for 9 microseconds, low for 8 microseconds and after each burst there is a 300-microsecond pause.
Labview Program – Generating Data Packet To configure the joystick to output signal in the form of the data packet, I used a Labview interface to first determine the range of values for each axis. Then, comparing this value with the range for the helicopter, I was able to scale the output from the joystick to the various integer levels that the helicopter can receive. There are some details about the bit assignment: the fourth bit for pitch and yaw, and possibly the sixth bit for the trim are directional bits; the bits are also reversed (i.e. 1000 becomes 0001). The good thing is that Labview automatically outputs the least significant bit when performing the Boolean conversion, so there are no explicit bit reversal operations that have to be performed. I assign the header according to my Helicopter hardware (10) and the trim and checksum are set to 0 by default (the latter will be checked through the Arduino code). This is the basic data packet that is generated by the program.
Labview Interface with Arduino The initial plan was to directly write the generated data packet onto an attached Arduino board through a USB connection. To do this you’ll have to download the Labview interface for Arduino here. You’ll also have to upload the LIFA sketch (in the Labview folder after installing the interface) onto the Arduino board. After doing these, you’ll be able to use the Arduino vi’s in the Labview interface. The only vi’s needed are the Initialize, Close, and WriteDigitalPin functions. I wrote a simple pulse program to generate the LED pulses by writing directly to a digital pin. Unfortunately, the protocol requires pulses to be generated with microsecond-precision, far shorter than that achievable with a software interface like Labview (which has at most a 1 millisecond precision, probably less). That makes direct pulsing from Labview impossible.
However, since I have two Arduino boards, I figured that I could use one to generate the signal, and write to a digital-out pin, and hook that pin to the second Arduino board via a digital-in pin. Each group of pulses last 136.5ms, so the Labview program was theoretically capable of generating the sequence. Unfortunately, here I met with another challengs. The default WriteDigitalPin vi in the Arduino interface was excruciatingly slow – the fastest I could write the data was 500ms per burst, hardly fast enough. Realizing that the program probably has many error checking steps built-in (this is good programming, but bad for speed!) I opened up the WriteDigitalPin vi and deleted a bunch of commands. This gave me a much faster write performance, more than sufficient to send out the signal burst.
Programming IR Emitter The second Arduino board was programmed as an emitter. A sketch is uploaded onto the board, and it runs with just a 9V battery with no computer connection [Edit: The response is incredibly slow without a computer connection, for some reason. Needs verification!!]. The output pin from the first board is connected to a pin on the Emitter board, and read using the digitalRead function. A simple loop reads continually from the pin. Without any time delay, the Arduino loop functions too rapidly, reading the same state multiple times (e.g. 10001 will be read as 11110000000000001111). Getting the right time delay (~1.2ms) was necessary for the right readout. The function waits for a ‘1’ before storing the next 30 bits in memory (the 1 bit is a result of the Header bit describing the channel. You can just as easily send a dummy 1 bit if your helicopter channel calls for it). It then generates the pulses by writing HIGH/LOW values to a digital out pin. The key difference between the Arduino board and Labview is that it can perform these operations rapidly and with microsecond precision. As mentioned, the LEDs blink 32 times for a ‘1’, and 16 times for a ‘0’. The LEDs were scavenged from a broken remove (3 LEDs were used in series to maximize output and coverage).
The following video shows the effect of increasing the throttle on the joystick on the helicopter. I may post a full video of the helicopter in movement some time soon.