I made a RC system-to-joystick interface with UnoJoy! It uses the PinChangeInt library to read the signals and maps them to HID values. Then, they are sent to the computer. I use it for the (free) ClearViewRC simulator and a game written in Processing by Paul Lager, Gcp_Tanker. It is an example for his Game Control Plus library, which can be installed by:
- Open Sketch>Import Library>Add Library (menu.png).
- Then search "game" in Library Manager (library manager.png).
- Click "Install" on Game Control Plus and look at the examples for it.
Open Gcp_Tanker and configure your controller.
Click Use and play away! (Tanker.png)
Here is my code:
/*
This is my RC simulator code.
It reads a 4-channel RC receiver and translates the input to joystick values.
The channel connections are trial-and-error. I have no clue which is which.
There are also 4 active-low buttons on pins 2,3,4,5.
*/
#include <PinChangeInt.h>
#include "UnoJoy.h"
byte RX_PIN_THROTTLE = 14;
byte RX_PIN_YAW = 15;
byte RX_PIN_ROLL = 16;
byte RX_PIN_PITCH = 17;
volatile int rxPrev[4] = {
0, 0, 0, 0
};
volatile int rxVal[4] = {
0, 0, 0, 0
};
volatile int rStickXdata = 128;
volatile int rStickYdata = 128;
volatile int lStickXdata = 128;
volatile int lStickYdata = 128;
void setup() {
setupPins();
rxInit();
setupUnoJoy();
}
void loop() {
// Always be getting fresh data
mapRcData();
dataForController_t controllerData = getControllerData();
setControllerData(controllerData);
}
void setupPins() {
pinMode(RX_PIN_YAW, INPUT_PULLUP);
pinMode(RX_PIN_ROLL, INPUT_PULLUP);
pinMode(RX_PIN_PITCH, INPUT_PULLUP);
pinMode(RX_PIN_THROTTLE, INPUT_PULLUP);
pinMode(2,INPUT_PULLUP);
pinMode(3,INPUT_PULLUP);
pinMode(4,INPUT_PULLUP);
pinMode(5,INPUT_PULLUP);
}
void rxInit() {
attachPinChangeInterrupt(RX_PIN_YAW, rxGoesHigh1, RISING);
attachPinChangeInterrupt(RX_PIN_ROLL, rxGoesHigh2, RISING);
attachPinChangeInterrupt(RX_PIN_PITCH, rxGoesHigh3, RISING);
attachPinChangeInterrupt(RX_PIN_THROTTLE, rxGoesHigh4, RISING);
}
dataForController_t getControllerData(void) {
dataForController_t controllerData = getBlankDataForController();
controllerData.triangleOn = !digitalRead(2);
controllerData.circleOn = !digitalRead(3);
controllerData.squareOn = !digitalRead(4);
controllerData.crossOn = !digitalRead(5);
controllerData.leftStickX = lStickXdata;
controllerData.leftStickY = lStickYdata;
controllerData.rightStickX = rStickXdata;
controllerData.rightStickY = rStickYdata;
// And return the data!
return controllerData;
}
void mapRcData() {
lStickXdata = map(rxVal[0], 1000, 2000, 0, 255);
lStickYdata = map(rxVal[3], 1000, 2000, 255, 0);
rStickXdata = map(rxVal[1], 1000, 2000, 0, 255);
rStickYdata = map(rxVal[2], 1000, 2000, 0, 255);
}
void rxGoesHigh1() {
attachPinChangeInterrupt(RX_PIN_YAW, rxGoesLow1, FALLING);
rxPrev[0] = micros();
}
void rxGoesLow1() {
attachPinChangeInterrupt(RX_PIN_YAW, rxGoesHigh1, RISING);
rxVal[0] = micros() - rxPrev[0];
}
void rxGoesHigh2() {
attachPinChangeInterrupt(RX_PIN_ROLL, rxGoesLow2, FALLING);
rxPrev[1] = micros();
}
void rxGoesLow2() {
attachPinChangeInterrupt(RX_PIN_ROLL, rxGoesHigh2, RISING);
rxVal[1] = micros() - rxPrev[1];
}
void rxGoesHigh3() {
attachPinChangeInterrupt(RX_PIN_PITCH, rxGoesLow3, FALLING);
rxPrev[2] = micros();
}
void rxGoesLow3() {
attachPinChangeInterrupt(RX_PIN_PITCH, rxGoesHigh3, RISING);
rxVal[2] = micros() - rxPrev[2];
}
void rxGoesHigh4() {
attachPinChangeInterrupt(RX_PIN_THROTTLE, rxGoesLow4, FALLING);
rxPrev[3] = micros();
}
void rxGoesLow4() {
attachPinChangeInterrupt(RX_PIN_THROTTLE, rxGoesHigh4, RISING);
rxVal[3] = micros() - rxPrev[3];
}