English / Deutsch

Teensy - RC, RC PAD, Play games with the RC Controller as Game Controller, RC servo, Radio Controlled, play games handicapped

This page is under construction!

I like RC (radio controlled) vehicles and thought it would be great to play racing games with the RC controller. I checked the internet and as always, someone else had already that idea. One solution is using the Andurino and another is using Flightsim. I decided to use my own solution. I am using a Teensy, some wires and a 6 channel RC sender/receiver.

It is also a great soluton for handicapped people to play racing games.


  • Teensy 3.2 with pins soldered
  • Absima CR6S RC Transmitter Receiver 2.4Ghz 6 Channel
  • USB cable - USB 2.0 Cable A to Micro M/M
  • Jumper Wires 10cm
  • USB Serial Cable COM-FOUR PL2303HX USB to TTL RS232 COM for debugging

Source code

This Software is

  • Free for private and educational use. Add a note about the original Author.
  • Commercial use is not allowed without permission.

Download: teensy3-rc-20220728.zip

Download: teensy3-rcpad-20220728.zip


How it works

The RC receiver gives continuous pulses as output. The pulse length is between a minimum and a maximum length. The length of the pulse is corresponding with the angle of the servo or the speed of the motor. Every channel has its own pulse output. I read the output of the RC receiver with the Teensy using the digital input pins and interrupts on state change. The RC receiver can work with 4,8V-12V and is powered by the 5V of the Teensy USB connection.

Output from the Teensy as Serial USB device (program teensy3-rc) and minicom

Channel example

Channel 1, controlled by the steering wheel of the RC sender.
Note, your receiver may have different pulse rates. Mine starts around every 14700µs a pulse. The minimum length of a pulse is about 936µs, the maximum is about 2000µs.

  • Steering wheel in neutral position: Pulse length about 1480µs.
  • Turning the steering wheel left: According to the angle between 963µs and 1480µs.
  • Turning the steering wheel maximum left: Pulse length about 936µs.
  • Turning the steering wheel right: According to the angle between 1480µs and 2000µs.
  • Turning the steering wheel maximum right: Pulse length about 2000µs.

Pulse diagram

These values are from my receiver. Use the output option to get the values from your hardware.

RC PAD - Game Controller

TODO: Desciptions for
Identify as Xbox 360 Controller or PlayStation 3 Controller.
Debugging with USB Serial.

RC sender buttons - emulate buttons

The RC sender buttons are acting as switches. For example, when you press the button for channel 6, the button changes the state (pulse duration > 1000µs) and keeps it. When you press again, it changes the state (pulse duration < 1000µs) and keeps it. This behaviour is useful for RC vehicles, but for gaming you need buttons that are acting as buttons. The Two-State Button function emulates a 200ms button press when the sender button state switches.

Code snippets: Two-State Button

 * channel    : Receiver channel.
 * toggle_time: Pulse time tipping point.
 * press_ms   : Keep pressed state for num milli seconds.
 * Return: Emulated button is/isn't pressed.

unsigned char RC_HandleButton (int channel, int toggle_time, int press_ms)
    unsigned int  idx = channel - 1;
    unsigned long ms  = millis();
    unsigned char is_pressed = 0;

    if ((rc_bt_state[idx] == 0) && (rc_time_up[idx] > toggle_time))
        rc_bt_state[idx] = 1;
        rc_bt_pressed_time[idx] = ms + press_ms;
    else if ((rc_bt_state[idx] == 1) && (rc_time_up[idx] < toggle_time))
        rc_bt_state[idx] = 0;
        rc_bt_pressed_time[idx] = ms + press_ms;

    // Is pressed time over? If not then set is_pressed.
    if (rc_bt_pressed_time[idx] > ms)
        is_pressed = 1;

    return is_pressed;
#define PRESS_MS 200

    report[3] = 0;

    report[3] |= RC_HandleButton (6, 1000, PRESS_MS) << 4;
    report[3] |= RC_HandleButton (5, 1800, PRESS_MS) << 5;
    report[3] |= RC_HandleButton (3, 1200, PRESS_MS) << 6;

Code snippets: Tri-State Switch

unsigned char RC_GetTriStateSwitch (int channel, int time1, int time2)
    unsigned int idx = channel - 1;

    if (rc_time_up[idx] < time1) return 0;
    else if (rc_time_up[idx] < time2) return 1;

    return 2;
#define RC_MODE1 1000
#define RC_MODE2 2000

    unsigned char mode = RC_GetTriStateSwitch (4, RC_MODE1, RC_MODE2);

    switch (mode)
	case 0:

Debug output

For debugging, you can connect the Teensy with an USB Serial Cable an view the output for example with the program minicom. Wire details are shown at the "Teensy - RC/RC PAD" schematic and in the "Teensy - USB/UART" area.

Mode information

Various blink modes when sender is not powered on startup and for "gaming mode", "menu mode", "alternate buttons mode".

Controller mapping

Using handicapped



© 2022 by Elmar Hanlhofer