Make RC (Radio controlled) Remote Control presentable as Joystick in Linux without any additional cables. Since we know that servos operate on PWM, I have decided that cheapest way (and easiest) to fly a RC model simulator is to translate PWM from receiver to Joystick data on computer. Mbed board was doing the translation. No need for any special cable and no dependency on RC Transmitter or Receiver whatsoever. If it can move the servos it can also move the model in computer simulator. Requirements and design are available on https://os.mbed.com/users/Letme/notebook/rc-receiver-as-joystick/
Dependencies: PwmIn USBDevice USBJoystick mbed
RC receiver as joystick
PWMIn class defines your pins which are connected to certain channels on receiver. I suggest you keep the order and just swap pins (since order defines axis identified in computer through USB and generic Joystick driver. You can also calibrate your Joystick.
Tested on mbed boards
- NUCLEO-F401RE
Initial tests were done with NUCLEO-F401RE and was tested on Chromebook, with PicaSim, Linux PC with CRRCSim and FlightGear. Because it is just Joystick it can be used in any game supporting joysticks (from car simulations to everyday games). No more need for special cables to get your transmitter to the computer.
Requirements, Test Cases and Design
Since this was done before project was started I used a simple notebook to outline the required work. It is still available on https://os.mbed.com/users/Letme/notebook/rc-receiver-as-joystick/
Revision 0:e0d0f401d8a4, committed 2018-10-18
- Comitter:
- Letme
- Date:
- Thu Oct 18 20:31:36 2018 +0000
- Commit message:
- Stable version
Changed in this revision
diff -r 000000000000 -r e0d0f401d8a4 PwmIn.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PwmIn.lib Thu Oct 18 20:31:36 2018 +0000 @@ -0,0 +1,1 @@ +http://os.mbed.com/users/simon/code/PwmIn/#6d68eb9b6bbb
diff -r 000000000000 -r e0d0f401d8a4 USBDevice.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBDevice.lib Thu Oct 18 20:31:36 2018 +0000 @@ -0,0 +1,1 @@ +http://os.mbed.com/users/mbed_official/code/USBDevice/#53949e6131f6
diff -r 000000000000 -r e0d0f401d8a4 USBJoystick.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBJoystick.lib Thu Oct 18 20:31:36 2018 +0000 @@ -0,0 +1,1 @@ +http://os.mbed.com/users/wim/code/USBJoystick/#e086541742c3
diff -r 000000000000 -r e0d0f401d8a4 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Oct 18 20:31:36 2018 +0000 @@ -0,0 +1,97 @@ +#include "mbed.h" +#include <math.h> +#include "USBJoystick.h" +#include "PwmIn.h" + +//InterruptIn button(USER_BUTTON); +//#define DEBUG_PRINTF + +DigitalOut led(LED1); + +PwmIn a(PB_1); /**< Plug channel 1 from receiver to this pin */ +PwmIn b(PC_4); /**< Plug channel 2 from receiver to this pin */ +PwmIn c(PC_5); /**< Plug channel 3 from receiver to this pin */ +PwmIn d(PC_8); /**< Plug channel 4 from receiver to this pin */ + +/**@note Do not forget to plug ground pin to GND of the board */ + +/** Covert PWM output which is in floats in range of 0.000153231 to -127..128 range + * + * PWM pulse width is in float range which needs to be offset a bit and then + * converted to int8_t range for the PC joystick driver to understand + * + * @param[in] pwm PWM float value produced by PwmIn.pulseWidth function + * + * @return Converted signed integer value in range of -127..128 + */ +int16_t covert_PWM_to_PC_range(float pwm) +{ + int32_t ipwm = pwm * 1000000; + if(ipwm != 0) { + ipwm = (((ipwm - 1100) * 255) / 870) - 127; + } + + return (int16_t) ipwm; +} + +int main(void) +{ +#ifndef DEBUG_PRINTF + USBJoystick joystick; /**< Joystick object from USBJoystick library */ +#else + Serial pc(USBTX, USBRX); /**< USB interface through debugger (/dev/ttyACM0) */ + pc.baud(115200); /** Set USB speed for the PC interface */ +#endif + uint16_t i = 0; + int16_t throttle = 0; + int16_t rudder = 0; + int16_t x = 0; + int16_t y = 0; + uint8_t tmp = 0; + uint32_t buttons = 0; + uint8_t hat = 0; + + led = 1; +#ifdef DEBUG_PRINTF + pc.printf("Hello World from Joystick!\r\n"); +#endif + + while (1) { + /** Get PWM pulsewidth via PwmIn library and covert that to simple + * int8_t range for all 4 channels */ + x = covert_PWM_to_PC_range(a.pulsewidth()); + y = covert_PWM_to_PC_range(b.pulsewidth()); + throttle = covert_PWM_to_PC_range(c.pulsewidth()); + rudder = covert_PWM_to_PC_range(d.pulsewidth()); + +/* +#if (BUTTONS4 == 1) + buttons = (i >> 8) & 0x0F; // value 0 .. 15, one bit per button +#endif +#if (BUTTONS8 == 1) + buttons = (i >> 8) & 0xFF; // value 0 .. 255, one bit per button +#endif +#if (BUTTONS32 == 1) + tmp = (i >> 8) & 0xFF; // value 0 .. 255, one bit per button + buttons = (( tmp << 0) & 0x000000FF); + buttons = buttons | ((~tmp << 8) & 0x0000FF00); + buttons = buttons | (( tmp << 16) & 0x00FF0000); + buttons = buttons | ((~tmp << 24) & 0xFF000000); +#endif + +#if (HAT4 == 1) + hat = (i >> 8) & 0x03; // value 0, 1, 2, 3 or 4 for neutral +#endif +#if (HAT8 == 1) + hat = (i >> 8) & 0x07; // value 0..7 or 8 for neutral +#endif +*/ + +#ifndef DEBUG_PRINTF + joystick.update(rudder, throttle, y, x, 0, 0); +#else + pc.printf("x (CH1): %i\t\ty (CH2): %i\t\t throttle: %i\r\n", y, x,throttle); +#endif + wait(0.005); + } +}
diff -r 000000000000 -r e0d0f401d8a4 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Thu Oct 18 20:31:36 2018 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/a7c7b631e539 \ No newline at end of file