Why should I do this?

When it comes to flying RC aircraft using a simulator can be a great way to hone your skills during the off season or even prepare for your first flight. The major disadvantage to using a simulator is that using a mouse, keyboard, touchscreen device, or standard video game controller, can be quite a different experience than the bulky transmitter with gimbals. There are commercial solutions available, depending on your interface type, but if you have an arduino ( and who doesn't? ) you can very easily connect a transmitter that supports PPM trainer / buddy box connections.

I can't say that it works with any transmitter, but I can say that it's compatible with the Spektrum DX6

But what software can I use it with?

I wanted to practice in my favorite simulator RC-AirSim by Fabricated Reality. It's an amazingly simple and accurate simulation (Not Game!) for electric RC airplanes. It's very inexpensive and if you are satisfied with the trainer plane, it has an unlimited use free demo. For less than $10 (the price fluctuates from 5 - 9 US dollars throughout the year) you can unlock all the plane models. They each fly different and realist, so you can learn the basics of a different type of plane before you try it in real life. This tutorial creates a game controller compatible with RC-AirSim with no configuration in the game. It just works.

How does it work?

Many RC transmitters allow you to share control of a plane with a second transmitter, so an inexperienced pilot can try taking over flight without having to hand over the transmitter in the event they loose control of the plane. This is a great feature supported by many transmitters. The setup can be complicated but it depends on the transmitter.

Basically with some transmitters, the data sent though the buddy cable (this tutorial will show you how to interface with a 2 wire cable such as a mono 3.5mm audio cable) is identical to the data that the receiver in the plane receives. They call this PPM, it's a series of pulses that can be turned into numerical values for percentage movement of servos. In Transmitters like the Spektrum DX6. The data can easily be deciphered using an arduino interrupt pin. Mike McCauley released an arduino library called RcTrainer that allows for capturing Spektrum PPM trainer communication in just this manner. I've used this library for the signal decoding.

Creating HID USB devices on the arduino can be accomplished in server different ways. The newer arduinos come with this ability built into the serial adapter chip, and some of the older arduinos can use a firmware hack on their serial adapters to do the same. But I wanted a solution that didn't depend on the arduino form factor and would work with just an atmega (eventually making it into a custom board) The solution here is the VUSB library for Atmel avr micro controllers. It's a software USB HID 1.1 emulation library. it has been ported to arduino as a library multiple times by multiple people. I created a HID gamepad descriptor that appears to the system as a standard gamepad, Works on windows, linux, and mac with no extra drivers needed, and matches the standard pattern for twin joystick controllers to little configuration is typically needed.

Step 1: Required Materials

  • Arduino (I'll be using an uno, but you can use any atmega328p based arduino)
  • A Spektrum compatible transmitter ( they all speak the same language, but the cables are different and the channel order may differ from brand to brand. If you have another brand you can can read the values of each channel out to the serial port and determine what settings need to be changed. The code is dirt simple)
  • For Spektrum you'll need a mono 3.5mm audio cable
  • Either a 3.5mm mono receptacle, or you can just cut the cable as they are cheap
  • a usb cable you can part with (you'll have to cut it up!)
  • 2 - 1N5227 or similar 3.6V biased zener diodes.
  • 2 - 68 ohm resistors
  • 1 - 2.2k ohm resistor
  • breadboard and breadboard wires
  • for optional calibration button you'll need a10K resistor, a tact switch, an led, and a current limiting resistor (value depends on led but 120 ohm - 200 ohm usually works fine with any led and 5v power) this is completely optional as you can just code the values that work into the arduino sketch.

Of course you'll need a computer, the arduino software, and some basic arduino knowledge.

This tutorial is not geared toward someone who has never used an arduino before so if you find any of these steps hard to follow please refer back to a tutorial on basic arduino.

<p>Ok figured this out. Basically everything was there but needed a bit bug fixing. I had to enable to send bigger data packages for gamepad_report_t struct (9 bytes) and thus use &quot;write&quot; instead of &quot;usbSetInterrupt&quot;. See the gist mentioned before to get an 8 axes and 8 buttons gamepad.<br><br>I have 2 hardware related questions:<br><br>1. According to the instructions VIN has to be connected to USB 5V. This means that +5V on the board will only be about 4V. While this might be fine for usual operation, what happens when connecting the USB on the board too, e.g. for serial debugging? This USBs 5V is connected to the boards +5V. Wouldn't it make more sense to connect our USBs 5V to +5V instead of VIN?<br><br>2. I miss resistors between the arduino digital pins and USB D+, D- lines as they would be needed for the voltage drop down to 3.6V given by the zener diodes. As this should not be a big issue with USB 5V connected to VIN, it might become one when connecting to +5V (and increasing +5V from about 4V to 5V). Is there a deep reason for your design? Is this a 68 ohms USB termination or impedance thing? Or is it possible that you accidentally swapped USB D+,D- pins with the arduino digital pins when writing down these instructions?</p>
Thank DrTrigon!<br>1) yes it definitely should be to +5v pin if you're going to use serial debugging (I personally use this project on a headless chip (just an atmega328p on perfboard or sometimes on a digispark with different firmware). So I didn't overthink the power connection. +5V pin is the best choice for the usb power input.<br><br>2) In the design there are 68 OHM resistors in series with the D- and D+, this is so the zener/controller can't load down the usb interface and fry your USB ports. It would technically work without it but it's not recommended. I need to amend this instructable with a schematic.<br><br>The circuit this is based from is the example config on the VUSB official website. https://www.obdev.at/Images/vusb/circuit-zoomed.gif<br>
<p>Thanks a lot for your answers!</p><p>2) All you said is true! The PC USB port is safe! My question was more in the other direction, here I am more concerned about the arduino, since currently there are 3.6V zener diodes connected directly to the atmega chip pins, which output up to 5V.</p><p>A schematic for this instructable would be perfect! :)</p><p>In your link the zener diodes are missing, so I found this: <a href="https://www.insidegadgets.com/wp-content/uploads/2011/05/with-zener.png" rel="nofollow">https://www.insidegadgets.com/wp-content/uploads/...</a> (the zener diodes are in between USB and 68 ohm resistors and not in between 68 ohm resistors and atmega)</p>
<p>Thanks a lot for this nice tutorial. It was very useful to me! I Made it! :)</p><p>If you want to add a schematic, I did it in fritzing and can share it.</p>
<p>I'm glad you liked the tutorial, Feel free to add the image in a comment, everyone will be able to see it.</p>
<p>Sure I'll do that.</p><p>Meanwhile I also tested it with my old Futaba FC-28 and that works too! Very nice! ;)</p><p>I do have the issue that it does not work with <a href="https://fpv-freerider.itch.io/fpv-freerider" rel="nofollow">https://fpv-freerider.itch.io/fpv-freerider</a> (source engine based I guess). I assume it is related to how libudev handles the device. I found I need a joystick with at least 1 button in order for the software/game to assign and use it. Can you give me a hint how to emulate a button?</p><p>Another thing I noticed by using (&quot;udevadm info -q all -n /dev/input/js0&quot;) was that it reports &quot;ID_INPUT_ACCELEROMETER=1&quot; but &quot;ID_INPUT_JOYSTICK&quot; is missing. However I guess this is not relevant.</p>
<p>That's very common, some input driver packages look for minimal configurations. Its really simple to add an arbitrary button to the device descriptor. There is a usnHidReportDescriptor array of bytes written in hex that tells the HID device interface on the computer what type of data, and what the data will look like, that is being sent. I don't currently have the time to play with it but when I do I'll modify the HID to have a couple buttons for digital channels. If I don't get to it first, just google v-usb hid descriptor for joystick and look at the part they have for a button that is missing from the one I included. (it's a little more complicated than that but its fun to learn!) if you can't get it by the time I have a chance, I'll updated this and eventually host it on git hub too.</p>
<p>Thanks for your hints. I had to modify libraries/HIDJoy/HIDJoy.cpp, libraries/HIDJoy/HIDJoy.h and libraries/HIDJoy/usbconfig.h according to e.g. <a href="http://eleccelerator.com/tutorial-about-usb-hid-report-descriptors/" rel="nofollow"> http://eleccelerator.com/tutorial-about-usb-hid-r...</a> . It works very nicely with 1 button (and is trivially expandable up to 8) and also with 6 axes. What I was not able to get running yet is 8 axes. Even though the gamepad does get recognized by the OS, the values don't change. What is the size limit on the gameReport struct? I would guess 64 byte, but it seams that 9 does not work either... Or I used the wrong axes (&quot;Slider&quot;)?</p><p>For convenience I put it on gist: <a href="https://gist.github.com/drtrigon/0458d5d3bb55c841c669dd02333c63dd" rel="nofollow"> https://gist.github.com/drtrigon/0458d5d3bb55c841...</a></p>
<p>Here the picture of my box. It is an Arduino UNO with a shield on top; lower-left corner is the USB interface, upper-right is the PPM port. Enjoy!</p>
<p>Thanks for this great instrubtable! </p><p>But I have two questions:</p><p>1. Is it possible to transmit more than four channels?</p><p>2. Do you know why it doesn't work on an Arduino Pro Mini (clone) with Atmega328? Under Win10 I get the message that my hardware isn't recognized correctly...</p>
<p>Yes you can transmit more than 2 channels, but you'll have to modify the HID descriptor in the controller library. Not very difficult but will take hours of fiddling. Over-all scheme of things it's not difficult</p>
<p>So, which version of Arduino did you modify, exactly? I just installed v1.6.8 and WInterrupts.c is considerably different than your modified one. I suspect Arduino itself has been updated with important changes since your post. This means that using your WInterrupts.c could be out of sync and break something else for Arduino. </p><p>So... what did you modify, exactly? That way, folks here will be armed with the info needed to keep their latest Arduino up to date by changing WInterrupts.c for HIDJoy, and not downgrade things and get out of sync.</p>
<p>It looks like all I need to do in Arduino v1.6.8 (or v1.6.x?) WInterrupts.c is replace this:</p><p> IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_0)</p><p>with this:</p><p> #ifndef INT0_vect</p><p> IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_0)</p><p> #endif</p><p>Basically, wrap the INT0_vect initialization in a compiler if statement. Does that look right? Anything else? BTW, Arduino does let you _compile_ without this modification, but I'm not sure if it runs right on the device (haven't tried it). Also, I don't see where RCTrainer refers to INT0_vect, but maybe I'm not good at my string searches through the files.</p>
Also that string doesn't come up, you won't see where it's used. The functions called in the user code calls that interrupt vector in the Arduino code base. There's a lot of code you just don't see, such as the winterrups.c file. You have the right idea though. Just that compile directive. But if they already fixed it in the platform then you won't have to change it.
The vusb lib in conjunction with the transmitter interrupt code comflixts with the old winterrups file in previous versions. If it compiles with no changes then you don't have to worry About it. It will work. The error you would have gotten is that the symbol INT0_VECTOR had already been defined. If you don't get that error then you should be good.
It's described in detail in the post. Just add an #ifndef for INT0_VECTOR. so you can't define it twice.
<p>Hi! Thanks for sharring!</p><p>I assembled everything exactly the &quot;textual scheme&quot; and it works!</p><p>But i am newbie, and try to get all this stuff.</p><p>According to your scheme zender diods and 2.2k resistor connected AFTER 68ohm resistors (if we look in direction from USB to Chip). I want to stay clear here, because every scheme I looked at Internet (incl. V-SUB site) are very different. It messed me up a little bit.</p><p>I'd appreciate it if you confirm this scheme is right - <a href="http://savepic.su/6944086.jpg" rel="nofollow"> http://savepic.su/6944086.jpg</a></p>
<p>They are different because I'm driving the arduino at it's native 5v, USB power is 5v but usb signal is 3.3v logic. To tell the usb host on the computer that a device is connected as a low speed (usb1.1 speed) device, the d- line has to be pulled high to 3.3v with reasonably high impedance. Really there are a wide range of pull up resistor that would work, but too low will over load the UBS port and short out the signal you are sending while possibly damaging the zener diode, too high and the voltage drop becomes inconsistent. 2.2k works well in my experience.<br><br>Yes your schematic appears to be correct!<br></p><p>I can't speak for how commercial USB products are wired but I've been using my Transmitter adapter for HOURS a day for months. It's always connected to my computer, and my computer is always on. I feel I've provided a solid test to this design and it works very reliably.</p>
<p>So fast reply! =) I thik i got it.</p><p>Thank you very very much, your advice was great! Good luck.</p>
This is awesome. I'm having issues getting my computer to recognize the device at all though. So that's bumming me out. The sketches load up just fine (both versions) but once its plugged in windows just sits there like a goob and does nothing. Im going to continue to mess with things and see if i can get it working. Maybe try an older version of windows (I'm using Windows 10).<br><br>Thanks for the excellent tutorial.
It should work fine on windows 10 but it can be picky, USB uses pull ups/downs on the data lines to tell the host what speed the device will try to communicate at, be sure you're not missing the 3.3v data pull-up
As far as i can tell, I've got things setup correctly. I'll admit I'm pretty new to the arduino. Thanks for the reply.
<p>I know it's been a while, But after taking a close look at the picture it's clear that your zener diodes are backwards. They should be flowing from ground TO signal. A property of the zener diodes causes them to conduct in reverse if the voltage goes over 3.6v, the orientation you have them hooked up is limiting the voltage on the pins to 0.7v ( forward voltage drop), which is why it didn't work. The black stripe on the zener should point away from ground. I realize that this is incorrect in my picture as well, I apologize for that mix up!</p><p>Sorry I didn't catch this sooner.</p>
<p>Thanks very much for the reply. I took things apart for another project but with this bit of info I'm going to have to try it out again. I'll post again on how it all turns out.</p>
<p>Thanks for sharing. I have build a few thousand interfaces using PIC 12F675 (serial) and PIC16C745, PIC18F2550 (USB) for use with the old FMS PC simulator. This gives me an idea to play around with this, ans simple USB interfaces.</p>

About This Instructable




More by DiamondDrake:RC Transmitter to USB Gamepad Using Arduino 
Add instructable to: