From 20873b41753ac749f29e3c5250b11d76bf6964a1 Mon Sep 17 00:00:00 2001 From: jonny_ji7 Date: Sun, 19 Jun 2022 15:37:42 +0200 Subject: [PATCH] Move coordinate scaling from app to controller - joystick.cpp/hpp: - move method scaleCoordinate from joystick class to public function - modify scaleCoordinate function to accept float values instead of ADC pin, change tolerance parameters to percent instead of absolute number - change method getData to use the public function now - control.cpp: - use scaleCoordinate function in http mode - calculate radius in http mode - config.cpp - adjust tolerance thresholds for joystick to percent - App.js - disable "snap to zero" feature -> just scale joystick output to value of -1 to 1 --- main/config.cpp | 43 ++++++++++++-------- main/control.cpp | 14 ++++++- main/joystick.cpp | 96 +++++++++++++++++++++++--------------------- main/joystick.hpp | 14 ++++--- react-app/src/App.js | 21 ++++++++-- 5 files changed, 116 insertions(+), 72 deletions(-) diff --git a/main/config.cpp b/main/config.cpp index d22ffa0..b9d1e38 100644 --- a/main/config.cpp +++ b/main/config.cpp @@ -27,7 +27,7 @@ single100a_config_t configDriverRight = { .pwmFreq = 10000 }; -//configure motor contol +//--- configure motor contol --- motorctl_config_t configMotorControl = { .msFade = 900, .currentMax = 10 @@ -40,16 +40,17 @@ controlledMotor motorRight(configDriverRight, configMotorControl); + //-------------------------------------- //------- joystick configuration ------- //-------------------------------------- joystick_config_t configJoystick = { .adc_x = ADC1_CHANNEL_3, //GPIO39 .adc_y = ADC1_CHANNEL_0, //GPIO36 - //range around center-threshold of each axis the coordinates stays at 0 (adc value 0-4095) - .tolerance_zero = 100, - //threshold the coordinate snaps to -1 or 1 before configured "_max" or "_min" threshold (mechanical end) is reached (adc value 0-4095) - .tolerance_end = 80, + //range around center-threshold of each axis the coordinates stays at 0 (percentage of available range 0-100) + .tolerance_zero = 7, + //threshold the coordinate snaps to -1 or 1 before configured "_max" or "_min" threshold (mechanical end) is reached (percentage of available range 0-100) + .tolerance_end = 5, //threshold the radius jumps to 1 before the stick is at max radius (range 0-1) .tolerance_radius = 0.05, @@ -63,6 +64,27 @@ joystick_config_t configJoystick = { .y_inverted = true }; + + +//---------------------------- +//--- configure fan contol --- +//---------------------------- +fan_config_t configFanLeft = { + .gpio_fan = GPIO_NUM_2, + .msRun = 5000, + .dutyThreshold = 35 +}; +fan_config_t configFanRight = { + .gpio_fan = GPIO_NUM_15, + .msRun = 5000, + .dutyThreshold = 35 +}; + + + +//================================= +//===== create global objects ===== +//================================= //create global joystic instance evaluatedJoystick joystick(configJoystick); @@ -76,15 +98,4 @@ buzzer_t buzzer(GPIO_NUM_12, 100); controlledArmchair control(&buzzer, &motorLeft, &motorRight); -//configure fan contol -fan_config_t configFanLeft = { - .gpio_fan = GPIO_NUM_2, - .msRun = 5000, - .dutyThreshold = 35 -}; -fan_config_t configFanRight = { - .gpio_fan = GPIO_NUM_15, - .msRun = 5000, - .dutyThreshold = 35 -}; diff --git a/main/control.cpp b/main/control.cpp index 9ebd302..5c54231 100644 --- a/main/control.cpp +++ b/main/control.cpp @@ -87,11 +87,21 @@ void controlledArmchair::startHandleLoop() { //reset timestamp lastAction http_timestamp_lastData = esp_log_timestamp(); - ESP_LOGD(TAG, "received data from http queue -> generating commands\n x=%.3f y=%.3f radius=%.3f angle=%.3f", + ESP_LOGD(TAG, "received data (from queue): x=%.3f y=%.3f radius=%.3f angle=%.3f", dataRead.x, dataRead.y, dataRead.radius, dataRead.angle); + //--- scale coordinates --- + //note: scaleCoordinate function currently can not handle negative input -> add offset to input + // scaleCoordinate(input, min, max, center, tolerance_zero_per, tolerance_end_per) + dataRead.x = scaleCoordinate(dataRead.x+1, 0, 2, 1, 5, 2); //TODO: move tolerance to config (virtualJoystick or control_Config_t?) + dataRead.y = scaleCoordinate(dataRead.y+1, 0, 2, 1, 5, 2); + //--- calculate radius with new coordinates --- + dataRead.radius = sqrt(pow(dataRead.x,2) + pow(dataRead.y,2)); + ESP_LOGD(TAG, "processed/scaled data: x=%.3f y=%.3f radius=%.3f", dataRead.x, dataRead.y, dataRead.radius); + //--- generate motor commands --- //pass received joystick data from http queue to generatecommands function from joystick.hpp + ESP_LOGV(TAG, "generating commands..."); commands = joystick_generateCommandsDriving(dataRead); //--- apply commands to motors --- @@ -103,7 +113,7 @@ void controlledArmchair::startHandleLoop() { //--- timeout --- //turn off motors when motor still on and no new data received for some time if ( - (esp_log_timestamp() - http_timestamp_lastData > 3000) //no data received for x seconds + (esp_log_timestamp() - http_timestamp_lastData > 3000) //no data received for x seconds //TODO: move timeout to config && (commands.left.state != motorstate_t::IDLE || commands.right.state != motorstate_t::IDLE) //at least one motor is still running ){ ESP_LOGE(TAG, "TIMEOUT - no data received for 3s -> stopping motors"); diff --git a/main/joystick.cpp b/main/joystick.cpp index 62997c3..11e63aa 100644 --- a/main/joystick.cpp +++ b/main/joystick.cpp @@ -68,50 +68,6 @@ int evaluatedJoystick::readAdc(adc1_channel_t adc_channel, bool inverted) { -//---------------------------- -//------ getCoordinate ------- -//---------------------------- -//function to read voltage at a gpio pin and scale it to a value from -1 to 1 using the given thresholds and tolerances -float evaluatedJoystick::getCoordinate(adc1_channel_t adc_channel, bool inverted, int min, int max, int center, int tolerance_zero, int tolerance_end) { - - float coordinate = 0; - - //read voltage from adc - int input = readAdc(adc_channel, inverted); - - //define coordinate value considering the different tolerances - //--- center --- - if ((input < center+tolerance_zero) && (input > center-tolerance_zero) ) { //adc value is inside tolerance around center threshold - coordinate = 0; - } - //--- maximum --- - else if (input > max-tolerance_end) { - coordinate = 1; - } - //--- minimum --- - else if (input < min+tolerance_end) { - coordinate = -1; - } - //--- positive area --- - else if (input > center) { - float range = max - center - tolerance_zero - tolerance_end; - coordinate = (input - center - tolerance_end) / range; - } - //--- negative area --- - else if (input < center) { - float range = (center - min - tolerance_zero - tolerance_end); - coordinate = -(center-input - tolerance_end) / range; - } - - ESP_LOGD(TAG, "coordinate=%.3f, input=%d/4095, isInverted=%d", coordinate, input, inverted); - //return coordinate (-1 to 1) - return coordinate; - -} - - - - //------------------------------- //---------- getData ------------ //------------------------------- @@ -120,10 +76,11 @@ joystickData_t evaluatedJoystick::getData() { //get coordinates //TODO individual tolerances for each axis? Otherwise some parameters can be removed ESP_LOGD(TAG, "getting X coodrinate..."); - float x = getCoordinate(config.adc_x, config.x_inverted, config.x_min, config.x_max, x_center, config.tolerance_zero, config.tolerance_end); + float x = scaleCoordinate(readAdc(config.adc_x, config.x_inverted), config.x_min, config.x_max, x_center, config.tolerance_zero, config.tolerance_end); data.x = x; + ESP_LOGD(TAG, "getting Y coodrinate..."); - float y = getCoordinate(config.adc_y, config.y_inverted, config.y_min, config.y_max, y_center, config.tolerance_zero, config.tolerance_end); + float y = scaleCoordinate(readAdc(config.adc_y, config.y_inverted), config.y_min, config.y_max, y_center, config.tolerance_zero, config.tolerance_end); data.y = y; //calculate radius @@ -159,6 +116,53 @@ void evaluatedJoystick::defineCenter(){ + + +//============================== +//====== scaleCoordinate ======= +//============================== +//function that scales an input value (e.g. from adc pin) to a value from -1 to 1 using the given thresholds and tolerances +float scaleCoordinate(float input, float min, float max, float center, float tolerance_zero_per, float tolerance_end_per) { + + float coordinate = 0; + + //convert tolerance percentages to actual values of range + double tolerance_zero = (max-min) * tolerance_zero_per / 100; + double tolerance_end = (max-min) * tolerance_end_per / 100; + + //define coordinate value considering the different tolerances + //--- center --- + if ((input < center+tolerance_zero) && (input > center-tolerance_zero) ) { //adc value is inside tolerance around center threshold + coordinate = 0; + } + //--- maximum --- + else if (input > max-tolerance_end) { + coordinate = 1; + } + //--- minimum --- + else if (input < min+tolerance_end) { + coordinate = -1; + } + //--- positive area --- + else if (input > center) { + float range = max - center - tolerance_zero - tolerance_end; + coordinate = (input - center - tolerance_zero - tolerance_end) / range; + } + //--- negative area --- + else if (input < center) { + float range = (center - min - tolerance_zero - tolerance_end); + coordinate = -(center-input - tolerance_zero - tolerance_end) / range; + } + + ESP_LOGD(TAG, "scaled coordinate from %.3f to %.3f", input, coordinate); + //return coordinate (-1 to 1) + return coordinate; + +} + + + + //============================================= //========= joystick_evaluatePosition ========= //============================================= diff --git a/main/joystick.hpp b/main/joystick.hpp index f7f3a87..050c51d 100644 --- a/main/joystick.hpp +++ b/main/joystick.hpp @@ -86,8 +86,6 @@ class evaluatedJoystick { void init(); //read adc while making multiple samples with option to invert the result int readAdc(adc1_channel_t adc_channel, bool inverted = false); - //read input voltage and scale to value from -1 to 1 using the given thresholds and tolerances - float getCoordinate(adc1_channel_t adc_channel, bool inverted, int min, int max, int center, int tolerance_zero, int tolerance_end); //--- variables --- joystick_config_t config; @@ -111,9 +109,15 @@ class evaluatedJoystick { motorCommands_t joystick_generateCommandsDriving(joystickData_t data ); +//============================== +//====== scaleCoordinate ======= +//============================== +//function that scales an input value (e.g. from adc pin) to a value from -1 to 1 using the giben thresholds and tolerances +float scaleCoordinate(float input, float min, float max, float center, float tolerance_zero_per, float tolerance_end_per); -//============================================ -//========= joystick_CommandsDriving ========= -//============================================ + +//============================================= +//========= joystick_evaluatePosition ========= +//============================================= //function that defines and returns enum joystickPos from x and y coordinates joystickPos_t joystick_evaluatePosition(float x, float y); diff --git a/react-app/src/App.js b/react-app/src/App.js index 9326d2a..76921c4 100644 --- a/react-app/src/App.js +++ b/react-app/src/App.js @@ -33,7 +33,7 @@ function App() { // - snaps 0 zero for a given tolerance in percent // - rounds value do given decimal places // - TODO: add threshold it snaps to 1 / -1 (100%) toleranceEnd - const ScaleCoordinate = (input) => { + const ScaleCoordinateTolerance = (input) => { //calc tolerance threshold and available range const tolerance = joystickSize/2 * toleranceSnapToZeroPer/100; const range = joystickSize/2 - tolerance; @@ -61,6 +61,15 @@ function App() { + //---------------------------------------- + //----------- Scale coordinate ----------- + //---------------------------------------- + //simply scale coordinate from joystick to a value of -1 to 1 without applying any tolerances + const ScaleCoordinate = (input) => { + return ( input / (joystickSize/2) ).toFixed(decimalPlaces); + } + + //------------------------------------------- //------- Senda data via POST request ------- @@ -106,13 +115,19 @@ function App() { //evaluate coordinates and send to esp32 const handleMove = (e) => { //console.log("data from joystick-element X:" + e.x + " Y:" + e.y + " distance:" + e.distance); - //calculate needed variables + + //--- convert coordinates --- + //Note: tolerance (snap to zero) now handled by controller -> send raw coordinates + //const x = ScaleCoordinateTolerance(e.x); + //const y = ScaleCoordinateTolerance(e.y); const x = ScaleCoordinate(e.x); const y = ScaleCoordinate(e.y); + //--- scale radius --- const radius = (e.distance / 100).toFixed(5); + //--- calculate angle --- const angle = ( Math.atan( y / x ) * 180 / Math.PI ).toFixed(2); - //crate object with necessary data + //create object with necessary data const joystick_data={ x: x, y: y,