Merge branch 'origin/dev'
This commit is contained in:
commit
fd90ca0bb2
@ -27,7 +27,7 @@ single100a_config_t configDriverRight = {
|
|||||||
.pwmFreq = 10000
|
.pwmFreq = 10000
|
||||||
};
|
};
|
||||||
|
|
||||||
//configure motor contol
|
//--- configure motor contol ---
|
||||||
motorctl_config_t configMotorControl = {
|
motorctl_config_t configMotorControl = {
|
||||||
.msFade = 900,
|
.msFade = 900,
|
||||||
.currentMax = 10
|
.currentMax = 10
|
||||||
@ -39,6 +39,31 @@ controlledMotor motorRight(configDriverRight, configMotorControl);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------
|
||||||
|
//------- control config -------
|
||||||
|
//------------------------------
|
||||||
|
control_config_t configControl = {
|
||||||
|
.defaultMode = controlMode_t::JOYSTICK, //default mode after startup and toggling IDLE
|
||||||
|
//--- timeout ---
|
||||||
|
.timeoutMs = 5*60*1000, //time of inactivity after which the mode gets switched to IDLE
|
||||||
|
.timeoutTolerancePer = 5, //percentage the duty can vary between timeout checks considered still inactive
|
||||||
|
//--- http mode ---
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------
|
||||||
|
//----- httpJoystick config -----
|
||||||
|
//-------------------------------
|
||||||
|
httpJoystick_config_t configHttpJoystickMain{
|
||||||
|
.toleranceZeroX_Per = 3, //percentage around joystick axis the coordinate snaps to 0
|
||||||
|
.toleranceZeroY_Per = 10,
|
||||||
|
.toleranceEndPer = 2, //percentage before joystick end the coordinate snaps to 1/-1
|
||||||
|
.timeoutMs = 3000 //time no new data was received before the motors get turned off
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------
|
//--------------------------------------
|
||||||
//------- joystick configuration -------
|
//------- joystick configuration -------
|
||||||
@ -46,10 +71,11 @@ controlledMotor motorRight(configDriverRight, configMotorControl);
|
|||||||
joystick_config_t configJoystick = {
|
joystick_config_t configJoystick = {
|
||||||
.adc_x = ADC1_CHANNEL_3, //GPIO39
|
.adc_x = ADC1_CHANNEL_3, //GPIO39
|
||||||
.adc_y = ADC1_CHANNEL_0, //GPIO36
|
.adc_y = ADC1_CHANNEL_0, //GPIO36
|
||||||
//range around center-threshold of each axis the coordinates stays at 0 (adc value 0-4095)
|
//percentage of joystick range the coordinate of the axis snaps to 0 (0-100)
|
||||||
.tolerance_zero = 100,
|
.tolerance_zeroX_per = 7,
|
||||||
//threshold the coordinate snaps to -1 or 1 before configured "_max" or "_min" threshold (mechanical end) is reached (adc value 0-4095)
|
.tolerance_zeroY_per = 3,
|
||||||
.tolerance_end = 80,
|
//percentage of joystick range the coordinate snaps to -1 or 1 before configured "_max" or "_min" threshold (mechanical end) is reached (0-100)
|
||||||
|
.tolerance_end_per = 5,
|
||||||
//threshold the radius jumps to 1 before the stick is at max radius (range 0-1)
|
//threshold the radius jumps to 1 before the stick is at max radius (range 0-1)
|
||||||
.tolerance_radius = 0.05,
|
.tolerance_radius = 0.05,
|
||||||
|
|
||||||
@ -63,20 +89,11 @@ joystick_config_t configJoystick = {
|
|||||||
.y_inverted = true
|
.y_inverted = true
|
||||||
};
|
};
|
||||||
|
|
||||||
//create global joystic instance
|
|
||||||
evaluatedJoystick joystick(configJoystick);
|
|
||||||
|
|
||||||
//create global evaluated switch instance for button next to joystick
|
|
||||||
gpio_evaluatedSwitch buttonJoystick(GPIO_NUM_33, true, false); //pullup true, not inverted (switch to GND use pullup of controller)
|
|
||||||
|
|
||||||
//create buzzer object on pin 12 with gap between queued events of 100ms
|
|
||||||
buzzer_t buzzer(GPIO_NUM_12, 100);
|
|
||||||
|
|
||||||
//create global control object
|
|
||||||
controlledArmchair control(&buzzer, &motorLeft, &motorRight);
|
|
||||||
|
|
||||||
|
|
||||||
//configure fan contol
|
//----------------------------
|
||||||
|
//--- configure fan contol ---
|
||||||
|
//----------------------------
|
||||||
fan_config_t configFanLeft = {
|
fan_config_t configFanLeft = {
|
||||||
.gpio_fan = GPIO_NUM_2,
|
.gpio_fan = GPIO_NUM_2,
|
||||||
.msRun = 5000,
|
.msRun = 5000,
|
||||||
@ -88,3 +105,25 @@ fan_config_t configFanRight = {
|
|||||||
.dutyThreshold = 35
|
.dutyThreshold = 35
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=================================
|
||||||
|
//===== create global objects =====
|
||||||
|
//=================================
|
||||||
|
//create global joystic instance
|
||||||
|
evaluatedJoystick joystick(configJoystick);
|
||||||
|
|
||||||
|
//create global evaluated switch instance for button next to joystick
|
||||||
|
gpio_evaluatedSwitch buttonJoystick(GPIO_NUM_33, true, false); //pullup true, not inverted (switch to GND use pullup of controller)
|
||||||
|
|
||||||
|
//create buzzer object on pin 12 with gap between queued events of 100ms
|
||||||
|
buzzer_t buzzer(GPIO_NUM_12, 100);
|
||||||
|
|
||||||
|
//create global httpJoystick object
|
||||||
|
httpJoystick httpJoystickMain(configHttpJoystickMain);
|
||||||
|
|
||||||
|
//create global control object
|
||||||
|
controlledArmchair control(configControl, &buzzer, &motorLeft, &motorRight, &httpJoystickMain);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "buzzer.hpp"
|
#include "buzzer.hpp"
|
||||||
#include "control.hpp"
|
#include "control.hpp"
|
||||||
#include "fan.hpp"
|
#include "fan.hpp"
|
||||||
|
#include "http.hpp"
|
||||||
|
|
||||||
|
|
||||||
//create global controlledMotor instances for both motors
|
//create global controlledMotor instances for both motors
|
||||||
@ -26,6 +27,9 @@ extern buzzer_t buzzer;
|
|||||||
//create global control object
|
//create global control object
|
||||||
extern controlledArmchair control;
|
extern controlledArmchair control;
|
||||||
|
|
||||||
|
//create global httpJoystick object
|
||||||
|
extern httpJoystick httpJoystickMain;
|
||||||
|
|
||||||
//configuration for fans
|
//configuration for fans
|
||||||
extern fan_config_t configFanLeft;
|
extern fan_config_t configFanLeft;
|
||||||
extern fan_config_t configFanRight;
|
extern fan_config_t configFanRight;
|
||||||
|
125
main/control.cpp
125
main/control.cpp
@ -12,7 +12,6 @@ extern "C"
|
|||||||
|
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "control.hpp"
|
#include "control.hpp"
|
||||||
#include "http.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
//tag for logging
|
//tag for logging
|
||||||
@ -24,15 +23,23 @@ const char* controlModeStr[7] = {"IDLE", "JOYSTICK", "MASSAGE", "HTTP", "MQTT",
|
|||||||
//-------- constructor --------
|
//-------- constructor --------
|
||||||
//-----------------------------
|
//-----------------------------
|
||||||
controlledArmchair::controlledArmchair (
|
controlledArmchair::controlledArmchair (
|
||||||
|
control_config_t config_f,
|
||||||
buzzer_t * buzzer_f,
|
buzzer_t * buzzer_f,
|
||||||
controlledMotor* motorLeft_f,
|
controlledMotor* motorLeft_f,
|
||||||
controlledMotor* motorRight_f
|
controlledMotor* motorRight_f,
|
||||||
|
httpJoystick* httpJoystick_f
|
||||||
){
|
){
|
||||||
|
|
||||||
|
//copy configuration
|
||||||
|
config = config_f;
|
||||||
//copy object pointers
|
//copy object pointers
|
||||||
buzzer = buzzer_f;
|
buzzer = buzzer_f;
|
||||||
motorLeft = motorLeft_f;
|
motorLeft = motorLeft_f;
|
||||||
motorRight = motorRight_f;
|
motorRight = motorRight_f;
|
||||||
|
httpJoystickMain_l = httpJoystick_f;
|
||||||
|
//set default mode from config
|
||||||
|
modePrevious = config.defaultMode;
|
||||||
|
|
||||||
//TODO declare / configure controlled motors here instead of config (unnecessary that button object is globally available - only used here)?
|
//TODO declare / configure controlled motors here instead of config (unnecessary that button object is globally available - only used here)?
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,38 +90,92 @@ void controlledArmchair::startHandleLoop() {
|
|||||||
joystickData_t dataRead = { };
|
joystickData_t dataRead = { };
|
||||||
|
|
||||||
//--- get joystick data from queue ---
|
//--- get joystick data from queue ---
|
||||||
if( xQueueReceive( joystickDataQueue, &dataRead, pdMS_TO_TICKS(500) ) ) {
|
//Note this function waits several seconds (httpconfig.timeoutMs) for data to arrive, otherwise Center data or NULL is returned
|
||||||
//reset timestamp lastAction
|
//TODO: as described above, when changing modes it might delay a few seconds for the change to apply
|
||||||
http_timestamp_lastData = esp_log_timestamp();
|
dataRead = httpJoystickMain_l->getData();
|
||||||
|
|
||||||
ESP_LOGD(TAG, "received data from http queue -> generating commands\n x=%.3f y=%.3f radius=%.3f angle=%.3f",
|
|
||||||
dataRead.x, dataRead.y, dataRead.radius, dataRead.angle);
|
|
||||||
|
|
||||||
//--- generate motor commands ---
|
//--- generate motor commands ---
|
||||||
//pass received joystick data from http queue to generatecommands function from joystick.hpp
|
ESP_LOGD(TAG, "generating commands from x=%.3f y=%.3f radius=%.3f angle=%.3f", dataRead.x, dataRead.y, dataRead.radius, dataRead.angle);
|
||||||
|
//Note: timeout (no data received) is handled in getData method
|
||||||
commands = joystick_generateCommandsDriving(dataRead);
|
commands = joystick_generateCommandsDriving(dataRead);
|
||||||
|
|
||||||
//--- apply commands to motors ---
|
//--- apply commands to motors ---
|
||||||
//TODO make motorctl.setTarget also accept motorcommand struct directly
|
//TODO make motorctl.setTarget also accept motorcommand struct directly
|
||||||
motorRight->setTarget(commands.right.state, commands.right.duty);
|
motorRight->setTarget(commands.right.state, commands.right.duty);
|
||||||
motorLeft->setTarget(commands.left.state, commands.left.duty);
|
motorLeft->setTarget(commands.left.state, commands.left.duty);
|
||||||
}
|
|
||||||
|
|
||||||
//--- 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
|
|
||||||
&& (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");
|
|
||||||
//copy preset commands for idling both motors
|
|
||||||
commands = cmds_bothMotorsIdle;
|
|
||||||
motorRight->setTarget(commands.right.state, commands.right.duty);
|
|
||||||
motorLeft->setTarget(commands.left.state, commands.left.duty);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
//TODO: add other modes here
|
|
||||||
|
// //TODO: add other modes here
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------
|
||||||
|
//------ slow loop ------
|
||||||
|
//-----------------------
|
||||||
|
//this section is run about every 5s (+500ms)
|
||||||
|
if (esp_log_timestamp() - timestamp_SlowLoopLastRun > 5000) {
|
||||||
|
ESP_LOGV(TAG, "running slow loop... time since last run: %.1fs", (float)(esp_log_timestamp() - timestamp_SlowLoopLastRun)/1000);
|
||||||
|
timestamp_SlowLoopLastRun = esp_log_timestamp();
|
||||||
|
|
||||||
|
//run function which detects timeout (switch to idle)
|
||||||
|
handleTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
}//end while(1)
|
||||||
|
}//end startHandleLoop
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------
|
||||||
|
//---------- resetTimeout -----------
|
||||||
|
//-----------------------------------
|
||||||
|
void controlledArmchair::resetTimeout(){
|
||||||
|
//TODO mutex
|
||||||
|
timestamp_lastActivity = esp_log_timestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------
|
||||||
|
//---------- handleTimeout -----------
|
||||||
|
//------------------------------------
|
||||||
|
float inactivityTolerance = 10; //percentage the duty can vary since last timeout check and still counts as incative
|
||||||
|
|
||||||
|
//local function that checks whether two values differ more than a given tolerance
|
||||||
|
bool validateActivity(float dutyOld, float dutyNow, float tolerance){
|
||||||
|
float dutyDelta = dutyNow - dutyOld;
|
||||||
|
if (fabs(dutyDelta) < tolerance) {
|
||||||
|
return false; //no significant activity detected
|
||||||
|
} else {
|
||||||
|
return true; //there was activity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//function that evaluates whether there is no activity/change on the motor duty for a certain time. If so, a switch to IDLE is issued. - has to be run repeatedly in a slow interval
|
||||||
|
void controlledArmchair::handleTimeout(){
|
||||||
|
//check for timeout only when not idling already
|
||||||
|
if (mode != controlMode_t::IDLE) {
|
||||||
|
//get current duty from controlled motor objects
|
||||||
|
float dutyLeftNow = motorLeft->getStatus().duty;
|
||||||
|
float dutyRightNow = motorRight->getStatus().duty;
|
||||||
|
|
||||||
|
//activity detected on any of the two motors
|
||||||
|
if (validateActivity(dutyLeft_lastActivity, dutyLeftNow, inactivityTolerance)
|
||||||
|
|| validateActivity(dutyRight_lastActivity, dutyRightNow, inactivityTolerance)
|
||||||
|
){
|
||||||
|
ESP_LOGD(TAG, "timeout check: detected [activity] since last check -> reset");
|
||||||
|
//reset last duty and timestamp
|
||||||
|
timestamp_lastActivity = esp_log_timestamp();
|
||||||
|
dutyLeft_lastActivity = dutyLeftNow;
|
||||||
|
dutyRight_lastActivity = dutyRightNow;
|
||||||
|
}
|
||||||
|
//no activity on any motor and msTimeout exceeded
|
||||||
|
else if (esp_log_timestamp() - timestamp_lastActivity > config.timeoutMs){
|
||||||
|
ESP_LOGI(TAG, "timeout check: [TIMEOUT], no activity for more than %.ds -> switch to idle", config.timeoutMs/1000);
|
||||||
|
//toggle to idle mode
|
||||||
|
toggleIdle();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ESP_LOGD(TAG, "timeout check: [inactive], last activity %.1f seconds ago", (float)(esp_log_timestamp() - timestamp_lastActivity)/1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,6 +187,9 @@ void controlledArmchair::startHandleLoop() {
|
|||||||
//-----------------------------------
|
//-----------------------------------
|
||||||
//function to change to a specified control mode
|
//function to change to a specified control mode
|
||||||
void controlledArmchair::changeMode(controlMode_t modeNew) {
|
void controlledArmchair::changeMode(controlMode_t modeNew) {
|
||||||
|
//reset timeout timer
|
||||||
|
resetTimeout();
|
||||||
|
|
||||||
//copy previous mode
|
//copy previous mode
|
||||||
controlMode_t modePrevious = mode;
|
controlMode_t modePrevious = mode;
|
||||||
|
|
||||||
@ -161,6 +225,10 @@ void controlledArmchair::changeMode(controlMode_t modeNew) {
|
|||||||
ESP_LOGI(TAG, "noting to execute when changing TO this mode");
|
ESP_LOGI(TAG, "noting to execute when changing TO this mode");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case controlMode_t::IDLE:
|
||||||
|
buzzer->beep(1, 1500, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
case controlMode_t::HTTP:
|
case controlMode_t::HTTP:
|
||||||
ESP_LOGW(TAG, "switching to http mode -> enabling http and wifi");
|
ESP_LOGW(TAG, "switching to http mode -> enabling http and wifi");
|
||||||
//start wifi
|
//start wifi
|
||||||
@ -197,12 +265,11 @@ void controlledArmchair::toggleIdle() {
|
|||||||
if (mode == controlMode_t::IDLE){
|
if (mode == controlMode_t::IDLE){
|
||||||
changeMode(modePrevious); //restore previous mode, or default if not switched yet
|
changeMode(modePrevious); //restore previous mode, or default if not switched yet
|
||||||
buzzer->beep(2, 200, 100);
|
buzzer->beep(2, 200, 100);
|
||||||
ESP_LOGW(TAG, "switched mode from IDLE to %s", controlModeStr[(int)mode]);
|
ESP_LOGW(TAG, "toggle idle: switched mode from IDLE to %s", controlModeStr[(int)mode]);
|
||||||
} else {
|
} else {
|
||||||
modePrevious = mode; //store current mode
|
modePrevious = mode; //store current mode
|
||||||
changeMode(controlMode_t::IDLE); //set mode to IDLE
|
changeMode(controlMode_t::IDLE); //set mode to IDLE
|
||||||
buzzer->beep(1, 1000, 0);
|
ESP_LOGW(TAG, "toggle idle: switched mode from %s to IDLE", controlModeStr[(int)mode]);
|
||||||
ESP_LOGW(TAG, "switched mode from IDLE to %s", controlModeStr[(int)mode]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,13 +3,26 @@
|
|||||||
#include "motordrivers.hpp"
|
#include "motordrivers.hpp"
|
||||||
#include "motorctl.hpp"
|
#include "motorctl.hpp"
|
||||||
#include "buzzer.hpp"
|
#include "buzzer.hpp"
|
||||||
|
#include "http.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------
|
||||||
|
//---- struct, enum, variable declarations ---
|
||||||
|
//--------------------------------------------
|
||||||
//enum that decides how the motors get controlled
|
//enum that decides how the motors get controlled
|
||||||
enum class controlMode_t {IDLE, JOYSTICK, MASSAGE, HTTP, MQTT, BLUETOOTH, AUTO};
|
enum class controlMode_t {IDLE, JOYSTICK, MASSAGE, HTTP, MQTT, BLUETOOTH, AUTO};
|
||||||
//extern controlMode_t mode;
|
//string array representing the mode enum (for printing the state as string)
|
||||||
extern const char* controlModeStr[7];
|
extern const char* controlModeStr[7];
|
||||||
|
|
||||||
|
//struct with config parameters
|
||||||
|
typedef struct control_config_t {
|
||||||
|
controlMode_t defaultMode; //default mode after startup and toggling IDLE
|
||||||
|
//--- timeout ---
|
||||||
|
uint32_t timeoutMs; //time of inactivity after which the mode gets switched to IDLE
|
||||||
|
float timeoutTolerancePer; //percentage the duty can vary between timeout checks considered still inactive
|
||||||
|
} control_config_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//==================================
|
//==================================
|
||||||
@ -21,9 +34,11 @@ class controlledArmchair {
|
|||||||
public:
|
public:
|
||||||
//--- constructor ---
|
//--- constructor ---
|
||||||
controlledArmchair (
|
controlledArmchair (
|
||||||
|
control_config_t config_f,
|
||||||
buzzer_t* buzzer_f,
|
buzzer_t* buzzer_f,
|
||||||
controlledMotor* motorLeft_f,
|
controlledMotor* motorLeft_f,
|
||||||
controlledMotor* motorRight_f
|
controlledMotor* motorRight_f,
|
||||||
|
httpJoystick* httpJoystick_f
|
||||||
);
|
);
|
||||||
|
|
||||||
//--- functions ---
|
//--- functions ---
|
||||||
@ -39,16 +54,26 @@ class controlledArmchair {
|
|||||||
//function that toggles between two modes, but prefers first argument if entirely different mode is currently active
|
//function that toggles between two modes, but prefers first argument if entirely different mode is currently active
|
||||||
void toggleModes(controlMode_t modePrimary, controlMode_t modeSecondary);
|
void toggleModes(controlMode_t modePrimary, controlMode_t modeSecondary);
|
||||||
|
|
||||||
|
//function that restarts timer which initiates the automatic timeout (switch to IDLE) after certain time of inactivity
|
||||||
|
void resetTimeout();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
//--- functions ---
|
||||||
|
//function that evaluates whether there is no activity/change on the motor duty for a certain time, if so a switch to IDLE is issued. - has to be run repeatedly in a slow interval
|
||||||
|
void handleTimeout();
|
||||||
|
|
||||||
//--- objects ---
|
//--- objects ---
|
||||||
buzzer_t* buzzer;
|
buzzer_t* buzzer;
|
||||||
controlledMotor* motorLeft;
|
controlledMotor* motorLeft;
|
||||||
controlledMotor* motorRight;
|
controlledMotor* motorRight;
|
||||||
|
httpJoystick* httpJoystickMain_l;
|
||||||
|
|
||||||
//---variables ---
|
//---variables ---
|
||||||
//struct for motor commands returned by generate functions of each mode
|
//struct for motor commands returned by generate functions of each mode
|
||||||
motorCommands_t commands;
|
motorCommands_t commands;
|
||||||
|
//struct with config parameters
|
||||||
|
control_config_t config;
|
||||||
|
|
||||||
//variables for http mode
|
//variables for http mode
|
||||||
uint32_t http_timestamp_lastData = 0;
|
uint32_t http_timestamp_lastData = 0;
|
||||||
@ -57,7 +82,7 @@ class controlledArmchair {
|
|||||||
controlMode_t mode = controlMode_t::IDLE;
|
controlMode_t mode = controlMode_t::IDLE;
|
||||||
|
|
||||||
//variable to store mode when toggling IDLE mode
|
//variable to store mode when toggling IDLE mode
|
||||||
controlMode_t modePrevious = controlMode_t::JOYSTICK; //default mode
|
controlMode_t modePrevious; //default mode
|
||||||
|
|
||||||
//command preset for idling motors
|
//command preset for idling motors
|
||||||
const motorCommand_t cmd_motorIdle = {
|
const motorCommand_t cmd_motorIdle = {
|
||||||
@ -68,6 +93,14 @@ class controlledArmchair {
|
|||||||
.left = cmd_motorIdle,
|
.left = cmd_motorIdle,
|
||||||
.right = cmd_motorIdle
|
.right = cmd_motorIdle
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//variable for slow loop
|
||||||
|
uint32_t timestamp_SlowLoopLastRun = 0;
|
||||||
|
|
||||||
|
//variables for detecting timeout (switch to idle, after inactivity)
|
||||||
|
float dutyLeft_lastActivity = 0;
|
||||||
|
float dutyRight_lastActivity = 0;
|
||||||
|
uint32_t timestamp_lastActivity = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
105
main/http.cpp
105
main/http.cpp
@ -3,7 +3,6 @@ extern "C"
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "mdns.h"
|
#include "mdns.h"
|
||||||
#include "cJSON.h"
|
#include "cJSON.h"
|
||||||
#include "esp_http_server.h"
|
|
||||||
#include "esp_spiffs.h"
|
#include "esp_spiffs.h"
|
||||||
#include "esp_wifi.h"
|
#include "esp_wifi.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
@ -14,14 +13,13 @@ extern "C"
|
|||||||
}
|
}
|
||||||
|
|
||||||
#include "http.hpp"
|
#include "http.hpp"
|
||||||
#include "joystick.hpp"
|
#include "config.hpp"
|
||||||
|
|
||||||
|
|
||||||
//tag for logging
|
//tag for logging
|
||||||
static const char * TAG = "http";
|
static const char * TAG = "http";
|
||||||
static httpd_handle_t server = NULL;
|
static httpd_handle_t server = NULL;
|
||||||
|
|
||||||
QueueHandle_t joystickDataQueue = xQueueCreate( 1, sizeof( struct joystickData_t ) );
|
|
||||||
|
|
||||||
|
|
||||||
//joystickData_t http_readFromJoystickQueue
|
//joystickData_t http_readFromJoystickQueue
|
||||||
@ -99,12 +97,25 @@ static esp_err_t on_default_url(httpd_req_t *req)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
//===============================
|
//==============================
|
||||||
//====== joystick endpoint ======
|
//===== httpJoystick class =====
|
||||||
//===============================
|
//==============================
|
||||||
//function that is called when data is received with post request at /api/joystick
|
//-----------------------
|
||||||
esp_err_t on_joystick_url(httpd_req_t *req)
|
//----- constructor -----
|
||||||
{
|
//-----------------------
|
||||||
|
httpJoystick::httpJoystick( httpJoystick_config_t config_f ){
|
||||||
|
//copy config struct
|
||||||
|
config = config_f;
|
||||||
|
//initialize queue for joystick data
|
||||||
|
QueueHandle_t joystickDataQueue = xQueueCreate( 1, sizeof( struct joystickData_t ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------
|
||||||
|
//---- receiveHttpData -----
|
||||||
|
//--------------------------
|
||||||
|
//joystick endpoint - function that is called when data is received with post request at /api/joystick
|
||||||
|
esp_err_t httpJoystick::receiveHttpData(httpd_req_t *req){
|
||||||
//--- add header ---
|
//--- add header ---
|
||||||
//to allow cross origin (otherwise browser fails when app is running on another host)
|
//to allow cross origin (otherwise browser fails when app is running on another host)
|
||||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||||
@ -122,8 +133,6 @@ esp_err_t on_joystick_url(httpd_req_t *req)
|
|||||||
//--- extract relevant items from json object ---
|
//--- extract relevant items from json object ---
|
||||||
cJSON *x_json = cJSON_GetObjectItem(payload, "x");
|
cJSON *x_json = cJSON_GetObjectItem(payload, "x");
|
||||||
cJSON *y_json = cJSON_GetObjectItem(payload, "y");
|
cJSON *y_json = cJSON_GetObjectItem(payload, "y");
|
||||||
cJSON *radius_json = cJSON_GetObjectItem(payload, "radius");
|
|
||||||
cJSON *angle_json = cJSON_GetObjectItem(payload, "angle");
|
|
||||||
|
|
||||||
//--- save items to struct ---
|
//--- save items to struct ---
|
||||||
joystickData_t data = { };
|
joystickData_t data = { };
|
||||||
@ -132,34 +141,87 @@ esp_err_t on_joystick_url(httpd_req_t *req)
|
|||||||
//convert json to double to float
|
//convert json to double to float
|
||||||
data.x = static_cast<float>(x_json->valuedouble);
|
data.x = static_cast<float>(x_json->valuedouble);
|
||||||
data.y = static_cast<float>(y_json->valuedouble);
|
data.y = static_cast<float>(y_json->valuedouble);
|
||||||
data.radius = static_cast<float>(radius_json->valuedouble);
|
//log received and parsed values
|
||||||
data.angle = static_cast<float>(angle_json->valuedouble);
|
ESP_LOGI(TAG, "received values: x=%.3f y=%.3f",
|
||||||
|
data.x, data.y);
|
||||||
|
|
||||||
//--- evaluate joystick position enum ---
|
// scaleCoordinate(input, min, max, center, tolerance_zero_per, tolerance_end_per)
|
||||||
|
data.x = scaleCoordinate(data.x+1, 0, 2, 1, config.toleranceZeroX_Per, config.toleranceEndPer);
|
||||||
|
data.y = scaleCoordinate(data.y+1, 0, 2, 1, config.toleranceZeroY_Per, config.toleranceEndPer);
|
||||||
|
|
||||||
|
//--- calculate radius with new/scaled coordinates ---
|
||||||
|
data.radius = sqrt(pow(data.x,2) + pow(data.y,2));
|
||||||
|
//TODO: radius tolerance? (as in original joystick func)
|
||||||
|
//limit radius to 1
|
||||||
|
if (data.radius > 1) {
|
||||||
|
data.radius = 1;
|
||||||
|
}
|
||||||
|
//--- calculate angle ---
|
||||||
|
data.angle = (atan(data.y/data.x) * 180) / 3.141;
|
||||||
|
//--- evaluate position ---
|
||||||
data.position = joystick_evaluatePosition(data.x, data.y);
|
data.position = joystick_evaluatePosition(data.x, data.y);
|
||||||
|
|
||||||
|
//log processed values
|
||||||
//log received and parsed values
|
ESP_LOGI(TAG, "processed values: x=%.3f y=%.3f radius=%.3f angle=%.3f pos=%s",
|
||||||
ESP_LOGI(TAG, "parsed values from received json: \n x=%.3f y=%.3f radius=%.3f angle=%.3f",
|
data.x, data.y, data.radius, data.angle, joystickPosStr[(int)data.position]);
|
||||||
data.x, data.y, data.radius, data.angle);
|
|
||||||
|
|
||||||
//--- free memory ---
|
//--- free memory ---
|
||||||
cJSON_Delete(payload);
|
cJSON_Delete(payload);
|
||||||
|
|
||||||
|
|
||||||
//--- send data to control task via queue ---
|
//--- send data to control task via queue ---
|
||||||
//xQueueSend( joystickDataQueue, ( void * )&data, ( TickType_t ) 0 );
|
//xQueueSend( joystickDataQueue, ( void * )&data, ( TickType_t ) 0 );
|
||||||
//changed to length = 1 -> overwrite - older values are no longer relevant
|
//changed to length = 1 -> overwrite - older values are no longer relevant
|
||||||
xQueueOverwrite( joystickDataQueue, ( void * )&data );
|
xQueueOverwrite( joystickDataQueue, ( void * )&data );
|
||||||
|
|
||||||
|
|
||||||
//--- return http response ---
|
//--- return http response ---
|
||||||
httpd_resp_set_status(req, "204 NO CONTENT");
|
httpd_resp_set_status(req, "204 NO CONTENT");
|
||||||
httpd_resp_send(req, NULL, 0);
|
httpd_resp_send(req, NULL, 0);
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------
|
||||||
|
//----- getData -----
|
||||||
|
//-------------------
|
||||||
|
//wait for and return joystick data from queue, if timeout return NULL
|
||||||
|
joystickData_t httpJoystick::getData(){
|
||||||
|
|
||||||
|
//--- get joystick data from queue ---
|
||||||
|
if( xQueueReceive( joystickDataQueue, &dataRead, pdMS_TO_TICKS(config.timeoutMs) ) ) {
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "getData: received data (from queue): x=%.3f y=%.3f radius=%.3f angle=%.3f",
|
||||||
|
dataRead.x, dataRead.y, dataRead.radius, dataRead.angle);
|
||||||
|
}
|
||||||
|
//--- timeout ---
|
||||||
|
//no new data received within configured timeout
|
||||||
|
else {
|
||||||
|
//send error message when last received data did NOT result in CENTER position
|
||||||
|
if (dataRead.position != joystickPos_t::CENTER) {
|
||||||
|
//change data to "joystick center" data to stop the motors
|
||||||
|
dataRead = dataCenter;
|
||||||
|
ESP_LOGE(TAG, "TIMEOUT - no data received for 3s -> set to center");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dataRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------
|
||||||
|
//--- receiveHttpData for httpJoystickMain ---
|
||||||
|
//--------------------------------------------
|
||||||
|
//function that wraps pointer to member function of httpJoystickMain instance in a "normal" function which the webserver can run on joystick URL
|
||||||
|
|
||||||
|
//declare pointer to receiveHttpData method of httpJoystick class
|
||||||
|
esp_err_t (httpJoystick::*pointerToReceiveFunc)(httpd_req_t *req) = &httpJoystick::receiveHttpData;
|
||||||
|
|
||||||
|
esp_err_t on_joystick_url(httpd_req_t *req){
|
||||||
|
//run pointer to receiveHttpData function of httpJoystickMain instance
|
||||||
|
return (httpJoystickMain.*pointerToReceiveFunc)(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============================
|
//============================
|
||||||
@ -169,9 +231,6 @@ esp_err_t on_joystick_url(httpd_req_t *req)
|
|||||||
void http_init_server()
|
void http_init_server()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//configure webserver
|
//configure webserver
|
||||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||||
config.uri_match_fn = httpd_uri_match_wildcard;
|
config.uri_match_fn = httpd_uri_match_wildcard;
|
||||||
|
@ -1,6 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
extern QueueHandle_t joystickDataQueue;
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "esp_http_server.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "joystick.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============================
|
//============================
|
||||||
//===== init http server =====
|
//===== init http server =====
|
||||||
@ -21,3 +29,43 @@ void start_mdns_service();
|
|||||||
//============================
|
//============================
|
||||||
//function that destroys the http server
|
//function that destroys the http server
|
||||||
void http_stop_server();
|
void http_stop_server();
|
||||||
|
|
||||||
|
|
||||||
|
//==============================
|
||||||
|
//===== httpJoystick class =====
|
||||||
|
//==============================
|
||||||
|
//class that receices that from a HTTP post request, generates and scales joystick data and provides the data in a queue
|
||||||
|
|
||||||
|
//struct with configuration parameters
|
||||||
|
typedef struct httpJoystick_config_t {
|
||||||
|
float toleranceZeroX_Per;//percentage around joystick axis the coordinate snaps to 0
|
||||||
|
float toleranceZeroY_Per;
|
||||||
|
float toleranceEndPer; //percentage before joystick end the coordinate snaps to 1/-1
|
||||||
|
uint32_t timeoutMs; //time no new data was received before the motors get turned off
|
||||||
|
} httpJoystick_config_t;
|
||||||
|
|
||||||
|
|
||||||
|
class httpJoystick{
|
||||||
|
public:
|
||||||
|
//--- constructor ---
|
||||||
|
httpJoystick( httpJoystick_config_t config_f );
|
||||||
|
|
||||||
|
//--- functions ---
|
||||||
|
joystickData_t getData(); //wait for and return joystick data from queue, if timeout return CENTER
|
||||||
|
|
||||||
|
esp_err_t receiveHttpData(httpd_req_t *req); //function that is called when data is received with post request at /api/joystick
|
||||||
|
|
||||||
|
private:
|
||||||
|
//--- variables ---
|
||||||
|
httpJoystick_config_t config;
|
||||||
|
QueueHandle_t joystickDataQueue = xQueueCreate( 1, sizeof( struct joystickData_t ) );
|
||||||
|
//struct for receiving data from http function, and storing data of last update
|
||||||
|
joystickData_t dataRead;
|
||||||
|
const joystickData_t dataCenter = {
|
||||||
|
.position = joystickPos_t::CENTER,
|
||||||
|
.x = 0,
|
||||||
|
.y = 0,
|
||||||
|
.radius = 0,
|
||||||
|
.angle = 0
|
||||||
|
};
|
||||||
|
};
|
||||||
|
@ -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 ------------
|
//---------- getData ------------
|
||||||
//-------------------------------
|
//-------------------------------
|
||||||
@ -120,10 +76,11 @@ joystickData_t evaluatedJoystick::getData() {
|
|||||||
//get coordinates
|
//get coordinates
|
||||||
//TODO individual tolerances for each axis? Otherwise some parameters can be removed
|
//TODO individual tolerances for each axis? Otherwise some parameters can be removed
|
||||||
ESP_LOGD(TAG, "getting X coodrinate...");
|
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_zeroX_per, config.tolerance_end_per);
|
||||||
data.x = x;
|
data.x = x;
|
||||||
|
|
||||||
ESP_LOGD(TAG, "getting Y coodrinate...");
|
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_zeroY_per, config.tolerance_end_per);
|
||||||
data.y = y;
|
data.y = y;
|
||||||
|
|
||||||
//calculate radius
|
//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) / range;
|
||||||
|
}
|
||||||
|
//--- negative area ---
|
||||||
|
else if (input < center) {
|
||||||
|
float range = (center - min - tolerance_zero - tolerance_end);
|
||||||
|
coordinate = -(center-input - tolerance_zero) / range;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "scaled coordinate from %.3f to %.3f, tolZero=%.3f, tolEnd=%.3f", input, coordinate, tolerance_zero, tolerance_end);
|
||||||
|
//return coordinate (-1 to 1)
|
||||||
|
return coordinate;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=============================================
|
//=============================================
|
||||||
//========= joystick_evaluatePosition =========
|
//========= joystick_evaluatePosition =========
|
||||||
//=============================================
|
//=============================================
|
||||||
|
@ -31,10 +31,11 @@ typedef struct joystick_config_t {
|
|||||||
adc1_channel_t adc_x;
|
adc1_channel_t adc_x;
|
||||||
adc1_channel_t adc_y;
|
adc1_channel_t adc_y;
|
||||||
|
|
||||||
//range around center-threshold of each axis the coordinates stays at 0 (adc value 0-4095)
|
//percentage of joystick range the coordinate of the axis snaps to 0 (0-100)
|
||||||
int tolerance_zero;
|
int tolerance_zeroX_per;
|
||||||
//threshold the coordinate snaps to -1 or 1 before configured "_max" or "_min" threshold (mechanical end) is reached (adc value 0-4095)
|
int tolerance_zeroY_per;
|
||||||
int tolerance_end;
|
//percentage of joystick range the coordinate snaps to -1 or 1 before configured "_max" or "_min" threshold (mechanical end) is reached (0-100)
|
||||||
|
int tolerance_end_per;
|
||||||
//threshold the radius jumps to 1 before the stick is at max radius (range 0-1)
|
//threshold the radius jumps to 1 before the stick is at max radius (range 0-1)
|
||||||
float tolerance_radius;
|
float tolerance_radius;
|
||||||
|
|
||||||
@ -86,8 +87,6 @@ class evaluatedJoystick {
|
|||||||
void init();
|
void init();
|
||||||
//read adc while making multiple samples with option to invert the result
|
//read adc while making multiple samples with option to invert the result
|
||||||
int readAdc(adc1_channel_t adc_channel, bool inverted = false);
|
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 ---
|
//--- variables ---
|
||||||
joystick_config_t config;
|
joystick_config_t config;
|
||||||
@ -111,9 +110,15 @@ class evaluatedJoystick {
|
|||||||
motorCommands_t joystick_generateCommandsDriving(joystickData_t data );
|
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
|
//function that defines and returns enum joystickPos from x and y coordinates
|
||||||
joystickPos_t joystick_evaluatePosition(float x, float y);
|
joystickPos_t joystick_evaluatePosition(float x, float y);
|
||||||
|
@ -169,7 +169,7 @@ extern "C" void app_main(void) {
|
|||||||
//--- create task for control ---
|
//--- create task for control ---
|
||||||
//-------------------------------
|
//-------------------------------
|
||||||
//task that generates motor commands depending on the current mode and sends those to motorctl task
|
//task that generates motor commands depending on the current mode and sends those to motorctl task
|
||||||
xTaskCreate(&task_control, "task_control", 2048, NULL, 5, NULL);
|
xTaskCreate(&task_control, "task_control", 4096, NULL, 5, NULL);
|
||||||
|
|
||||||
//------------------------------
|
//------------------------------
|
||||||
//--- create task for button ---
|
//--- create task for button ---
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
/>
|
/>
|
||||||
<title>armchair ctl</title>
|
<title>armchair ctl</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body style="background-color:#001427; color:white;">
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<!--
|
<!--
|
||||||
|
46
react-app/src/App.js
vendored
46
react-app/src/App.js
vendored
@ -7,11 +7,9 @@ import React, { useState} from 'react';
|
|||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
//declare variables that can be used and updated in html
|
//declare variables that can be used and updated in html
|
||||||
const [angle_html, setAngle_html] = useState(0);
|
|
||||||
const [x_html, setX_html] = useState(0);
|
const [x_html, setX_html] = useState(0);
|
||||||
const [y_html, setY_html] = useState(0);
|
const [y_html, setY_html] = useState(0);
|
||||||
const [ip, setIp] = useState("10.0.0.66");
|
const [ip, setIp] = useState("10.0.0.66");
|
||||||
const [radius_html, setRadius_html] = useState(0);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -19,7 +17,7 @@ function App() {
|
|||||||
//=========== config ============
|
//=========== config ============
|
||||||
//===============================
|
//===============================
|
||||||
const decimalPlaces = 3;
|
const decimalPlaces = 3;
|
||||||
const joystickSize = 200; //affects scaling of coordinates and size of joystick on website
|
const joystickSize = 250; //affects scaling of coordinates and size of joystick on website
|
||||||
const throttle = 300; //throtthe interval the joystick sends data while moving (ms)
|
const throttle = 300; //throtthe interval the joystick sends data while moving (ms)
|
||||||
const toleranceSnapToZeroPer = 20;//percentage of moveable range the joystick can be moved from the axix and value stays at 0
|
const toleranceSnapToZeroPer = 20;//percentage of moveable range the joystick can be moved from the axix and value stays at 0
|
||||||
|
|
||||||
@ -33,7 +31,7 @@ function App() {
|
|||||||
// - snaps 0 zero for a given tolerance in percent
|
// - snaps 0 zero for a given tolerance in percent
|
||||||
// - rounds value do given decimal places
|
// - rounds value do given decimal places
|
||||||
// - TODO: add threshold it snaps to 1 / -1 (100%) toleranceEnd
|
// - TODO: add threshold it snaps to 1 / -1 (100%) toleranceEnd
|
||||||
const ScaleCoordinate = (input) => {
|
const ScaleCoordinateTolerance = (input) => {
|
||||||
//calc tolerance threshold and available range
|
//calc tolerance threshold and available range
|
||||||
const tolerance = joystickSize/2 * toleranceSnapToZeroPer/100;
|
const tolerance = joystickSize/2 * toleranceSnapToZeroPer/100;
|
||||||
const range = joystickSize/2 - tolerance;
|
const range = joystickSize/2 - tolerance;
|
||||||
@ -61,6 +59,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 -------
|
//------- Senda data via POST request -------
|
||||||
@ -106,27 +113,26 @@ function App() {
|
|||||||
//evaluate coordinates and send to esp32
|
//evaluate coordinates and send to esp32
|
||||||
const handleMove = (e) => {
|
const handleMove = (e) => {
|
||||||
//console.log("data from joystick-element X:" + e.x + " Y:" + e.y + " distance:" + e.distance);
|
//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 x = ScaleCoordinate(e.x);
|
||||||
const y = ScaleCoordinate(e.y);
|
const y = ScaleCoordinate(e.y);
|
||||||
const radius = (e.distance / 100).toFixed(5);
|
|
||||||
const angle = ( Math.atan( y / x ) * 180 / Math.PI ).toFixed(2);
|
|
||||||
|
|
||||||
//crate object with necessary data
|
//create object with necessary data
|
||||||
const joystick_data={
|
const joystick_data={
|
||||||
x: x,
|
x: x,
|
||||||
y: y,
|
y: y
|
||||||
radius: radius,
|
|
||||||
angle: angle
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//send object with joystick data as json to controller
|
//send object with joystick data as json to controller
|
||||||
httpSendObject(joystick_data);
|
httpSendObject(joystick_data);
|
||||||
|
|
||||||
//update variables for html
|
//update variables for html
|
||||||
setX_html(joystick_data.x);
|
setX_html(joystick_data.x);
|
||||||
setY_html(joystick_data.y);
|
setY_html(joystick_data.y);
|
||||||
setRadius_html(joystick_data.radius);
|
|
||||||
setAngle_html(joystick_data.angle);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -139,15 +145,11 @@ function App() {
|
|||||||
const joystick_data={
|
const joystick_data={
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
radius: 0,
|
|
||||||
angle: 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//update variables for html
|
//update variables for html
|
||||||
setX_html(0);
|
setX_html(0);
|
||||||
setY_html(0);
|
setY_html(0);
|
||||||
setRadius_html(0);
|
|
||||||
setAngle_html(0);
|
|
||||||
//send object with joystick data as json to controller
|
//send object with joystick data as json to controller
|
||||||
httpSendObject(joystick_data);
|
httpSendObject(joystick_data);
|
||||||
};
|
};
|
||||||
@ -162,14 +164,14 @@ function App() {
|
|||||||
|
|
||||||
<div style={{display:'flex', justifyContent:'center', alignItems:'center', height:'100vh'}}>
|
<div style={{display:'flex', justifyContent:'center', alignItems:'center', height:'100vh'}}>
|
||||||
<div>
|
<div>
|
||||||
<div style={{position: 'absolute', top: '0'}}>
|
<div style={{position: 'absolute', top: '0', left: '0', width: '100%'}}>
|
||||||
<h1>Joystick ctl</h1>
|
<h1 style={{width:'100%', textAlign:'center'}}>Armchair ctl</h1>
|
||||||
</div>
|
</div>
|
||||||
<Joystick
|
<Joystick
|
||||||
size={joystickSize}
|
size={joystickSize}
|
||||||
sticky={false}
|
sticky={false}
|
||||||
baseColor="red"
|
baseColor="#8d0801"
|
||||||
stickColor="blue"
|
stickColor="#708d81"
|
||||||
throttle={throttle}
|
throttle={throttle}
|
||||||
move={handleMove}
|
move={handleMove}
|
||||||
stop={handleStop}
|
stop={handleStop}
|
||||||
@ -178,8 +180,6 @@ function App() {
|
|||||||
<ul>
|
<ul>
|
||||||
<li> x={x_html} </li>
|
<li> x={x_html} </li>
|
||||||
<li> y={y_html} </li>
|
<li> y={y_html} </li>
|
||||||
<li> radius={radius_html} </li>
|
|
||||||
<li> angle={angle_html} </li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user