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.