Here is the custom code I wrote for the thumb joystick, which you all are welcome to copy or modify:
#include <Esplora.h>
/* MWO keyboard emulator, version 10 from January 26, 2014 */
/* written by andilar */
/* The basic idea is to read the joystick on an Arduino Esplora and
use the measurements to issue throttle-setting keystrokes and turning
keystrokes for MWO. */
/* keystroke control mapping */
/* The keys can be adjusted to suit personal preferences. In the present version,
only regular keyboard keys are valid, as I haven't found Esplora support for
the numeric keypad keys. */
const char upThrottle = '='; // keystroke for a positive throttle increment
const char downThrottle = '-'; // keystroke for a negative throttle increment
const char fullStop = 'x'; // keystroke for a full stop
const char leftTurn = 'a'; // keystroke for a left turn
const char rightTurn = 'd'; // keystroke for a right turn
const char maxThrottleKey = '0'; // keystroke for 100% throttle
/* other constants */
const int maxThrottle = 10; // value of maximum throttle
/* The throttle threshold is a fix I put in because I didn't like having intermediate-high
speeds. Instead I wanted a range of slow speeds and then max speed, mainly for piloting
lights.*/
const int throttleThreshold = 6; // value at which the loop switches from intermediate
// speeds to maximum throttle. I liked 6, but it can
// be from 1 to 10. 1 will give only stop and maximum
// throttle, while 10 will give all the intermediate
// throttle settings.
const int minDelay = 47; // minimum delay in msec between turning commands
const int turnSpeeds = 10; // number of turn speed settings
const int keyPressTime = 47; // amount of time in msec to press a key
// This appears to be mandatory for turning commands, but
// not for throttle increment commands.
/* variables */
boolean joystickActive = true; // to allow or block keystroke output
int lastSwitchState = LOW; // blocking switch starts out low
/* throttle variables */
// Left-hand throttle control from the X axis of the joystick
int xValueDC; // initial x value of joystick at rest
int lastThrottleX = 0; // previous value of throttle setting
int thisThrottleX = 0; // current value of throttle setting
int deltaThrottleX; // throttle change
int throttleKeyPressed = 0; // 0 for none, 1 for upThrottle, 2 for downThrottle, 3 for fullStop, 4 for maxThrottle
unsigned long lastTimeX; // time of last throttle keystroke
unsigned long thisTimeX; // present time
unsigned long deltaTimeX; // time since last throttle keystroke
unsigned long throttleKeyStartTime;
/* turn variables */
// Left-hand turning control from the Y axis of the joystick
int yValueDC; // initial y value of joystick at rest
int turnKeyPressed = 0; // 0 for none, 1 for left, 2 for right
unsigned long turnKeyStartTime; // time when a turning key was last pressed
/* the time variables below are for the time between turning commands */
unsigned long lastTimeY; // time of last turn keystroke
unsigned long thisTimeY; // present time
unsigned long deltaTimeY; // time since last turn keystroke
void setup(){
Serial.begin(9600); // initialize serial communication with your computer
Keyboard.begin(); // take control of the keyboard
xValueDC = Esplora.readJoystickX(); // read the joystick's X position
yValueDC = Esplora.readJoystickY(); // read the joystick's Y position
Keyboard.press(fullStop); // zero throttle; this also sets the direction to forward
delay(keyPressTime); // wait for the fullStop to be accepted
Keyboard.release(fullStop);
lastThrottleX = 0; // initialize last throttle setting
thisThrottleX = 0; // initialize next throttle setting
lastTimeY = millis(); // initialize turning rate clock
thisTimeY = millis();
turnKeyStartTime = millis();
throttleKeyStartTime = millis(); // initialize throttle clock
}
void loop()
{
int switchState = Esplora.readButton(SWITCH_DOWN); // read the esplora button designated
// to lock out keystrokes when needed
if (switchState != lastSwitchState){ // On a change in switch state...
if (switchState == HIGH){
joystickActive = !joystickActive; // ...flip the joystick state.
if (joystickActive){
Esplora.writeRGB(0,10,0); // turn Esplora LED green - the Esplora now can issue MWO
// keyboard commands
}
else {
Esplora.writeRGB(10,0,0); // turn Esplora LED red - the Esplora is prevented from
// issuing further MWO keyboard commands
/* Keyboard.press(fullStop); // set throttle to 0
delay(keyPressTime);
Keyboard.release(fullStop);
lastThrottleX = 0;
Keyboard.release(rightTurn); // set right turning to 0
Keyboard.release(leftTurn); // set left turning to 0
*/
}
delay(250); // a time delay to allow the switch to go off
}
}
lastSwitchState = switchState;
// (1) Read the joystick signals
int xValue = Esplora.readJoystickX() - xValueDC; // read the joystick's X position and correct for initial reading
int yValue = Esplora.readJoystickY() - yValueDC; // read the joystick's Y position and correct for initial reading
int thisThrottleX = map( xValue,-512, 512, -10, 10); // map the X value to a range of movement for the mouse X
int thisTurnY = map(yValue,-512, 512, -turnSpeeds, turnSpeeds); // map the Y value to a range of movement for the mouse Y
// (2) Determine throttle changes and issue commands for them
deltaThrottleX = thisThrottleX - lastThrottleX;
thisTimeY = millis();
if (throttleKeyPressed > 0){ // allow throttle key releases regardless of joystick state
if (thisTimeY - throttleKeyStartTime > keyPressTime){
if (throttleKeyPressed == 1){
Keyboard.release(upThrottle);
}
else if (throttleKeyPressed == 2){
Keyboard.release(downThrottle);
}
else if (throttleKeyPressed == 3){
Keyboard.release(fullStop);
}
else if (throttleKeyPressed == 4){
Keyboard.release(maxThrottleKey);
}
throttleKeyPressed = 0; // record end of throttle key press
}
}
else if (joystickActive){ // only allow new key presses when joystick is active
if (thisThrottleX >= throttleThreshold){ // When the throttle is maximum...
Keyboard.press(maxThrottleKey); //...start a full-throttle keystroke
throttleKeyStartTime = millis(); // set the throttle keystroke timer
throttleKeyPressed = 4; // record which keystroke
lastThrottleX = maxThrottle; // record the total throttle
}
else if (thisThrottleX == 0){ // When the throttle is zero...
Keyboard.press(fullStop); // ...start a stop keystroke
throttleKeyStartTime = millis(); // set the throttle keystroke timer
throttleKeyPressed = 3; // record which keystroke
lastThrottleX = 0; // record the total throttle
}
else if (deltaThrottleX > 0){ // on a positive throttle difference...
Keyboard.press(upThrottle); // ...start an increase-throttle keystroke
throttleKeyStartTime = millis(); // set the throttle keystroke timer
throttleKeyPressed = 1; // record which keystroke
lastThrottleX += lastThrottleX; // increase the cumulative throttle
}
else if (deltaThrottleX < 0){ // on a negative throttle difference...
Keyboard.press(downThrottle); // ...start a decrease-throttle keystroke
throttleKeyStartTime = millis(); // set the throttle keystroke timer
throttleKeyPressed = 2; // record which keystroke
lastThrottleX -= lastThrottleX; // decrease the cumulative throttle
}
}
// (3) Determine steering changes and issue commands for them
thisTimeY = millis(); // get the current time
deltaTimeY = thisTimeY - lastTimeY; // get the time since the last steering key press
// The next statement determines if enough time has elapsed and
// issues an appropriate turn command.
if (turnKeyPressed > 0){ // Allow turning key releases regardless of joystick state
if (thisTimeY - turnKeyStartTime > keyPressTime){
if (turnKeyPressed == 1){
Keyboard.release(leftTurn);
}
else if (turnKeyPressed == 2);{
Keyboard.release(rightTurn);
}
turnKeyPressed = 0; // record end of turning key press
}
}
else if (joystickActive){ // only allow new key presses when joystick is active
if (thisTurnY != 0){
if (deltaTimeY >= (turnSpeeds*minDelay/abs(thisTurnY) - keyPressTime)){
if(thisTurnY < -1){ // fixed a bug where < 0 resulted in unwanted constant turning
Keyboard.press(rightTurn); // press right turn key
turnKeyStartTime = millis(); // record when turning key was pressed
turnKeyPressed = 2; // record which turning key was pressed
}
else if (thisTurnY > 1){ // fixed a bug where > 0 resulted in unwanted constant turning
Keyboard.press(leftTurn); // press left turn key
turnKeyStartTime = millis(); // record when turning key was pressed
turnKeyPressed = 1; // record which turning key was pressed
}
lastTimeY = thisTimeY; // restart inter-press time count
}
}
}
}
Edited by Andilar, 29 January 2014 - 07:05 AM.
















