diff --git a/board_single/main/auto.hpp b/board_single/main/auto.hpp index 8b799fb..3f37646 100644 --- a/board_single/main/auto.hpp +++ b/board_single/main/auto.hpp @@ -85,3 +85,50 @@ class automatedArmchair { }; +//=========== EXAMPLE USAGE ============ +//the following was once used in button.cpp to make move that ejects the leg support of armchair v1 +/** +if (trigger){ + //define commands + cmds[0] = + { + .motorCmds = { + .left = {motorstate_t::REV, 90}, + .right = {motorstate_t::REV, 90} + }, + .msDuration = 1200, + .fadeDecel = 800, + .fadeAccel = 1300, + .instruction = auto_instruction_t::NONE + }; + cmds[1] = + { + .motorCmds = { + .left = {motorstate_t::FWD, 70}, + .right = {motorstate_t::FWD, 70} + }, + .msDuration = 70, + .fadeDecel = 0, + .fadeAccel = 300, + .instruction = auto_instruction_t::NONE + }; + cmds[2] = + { + .motorCmds = { + .left = {motorstate_t::IDLE, 0}, + .right = {motorstate_t::IDLE, 0} + }, + .msDuration = 10, + .fadeDecel = 800, + .fadeAccel = 1300, + .instruction = auto_instruction_t::SWITCH_JOYSTICK_MODE + }; + + //send commands to automatedArmchair command queue + armchair.addCommands(cmds, 3); + + //change mode to AUTO + control->changeMode(controlMode_t::AUTO); + return; +} +*/ diff --git a/board_single/main/button.cpp b/board_single/main/button.cpp index 0974fdc..0efb449 100644 --- a/board_single/main/button.cpp +++ b/board_single/main/button.cpp @@ -72,55 +72,17 @@ void buttonCommands::action (uint8_t count, bool lastPressLong){ case 2: //run automatic commands to lift leg support when pressed 1x short 1x long if (lastPressLong){ - //define commands - cmds[0] = - { - .motorCmds = { - .left = {motorstate_t::REV, 90}, - .right = {motorstate_t::REV, 90} - }, - .msDuration = 1200, - .fadeDecel = 800, - .fadeAccel = 1300, - .instruction = auto_instruction_t::NONE - }; - cmds[1] = - { - .motorCmds = { - .left = {motorstate_t::FWD, 70}, - .right = {motorstate_t::FWD, 70} - }, - .msDuration = 70, - .fadeDecel = 0, - .fadeAccel = 300, - .instruction = auto_instruction_t::NONE - }; - cmds[2] = - { - .motorCmds = { - .left = {motorstate_t::IDLE, 0}, - .right = {motorstate_t::IDLE, 0} - }, - .msDuration = 10, - .fadeDecel = 800, - .fadeAccel = 1300, - .instruction = auto_instruction_t::SWITCH_JOYSTICK_MODE - }; - - //send commands to automatedArmchair command queue - armchair.addCommands(cmds, 3); - - //change mode to AUTO - control->changeMode(controlMode_t::AUTO); - return; + ESP_LOGW(TAG, "cmd %d: toggle ADJUST_CHAIR", count); + control->toggleMode(controlMode_t::ADJUST_CHAIR); } //toggle idle when 2x pressed + else { ESP_LOGW(TAG, "cmd %d: toggle IDLE", count); control->toggleIdle(); //toggle between idle and previous/default mode + } break; - case 3: ESP_LOGW(TAG, "cmd %d: switch to JOYSTICK", count); control->changeMode(controlMode_t::JOYSTICK); //switch to JOYSTICK mode diff --git a/board_single/main/config.cpp b/board_single/main/config.cpp index ef53343..60a0d3d 100644 --- a/board_single/main/config.cpp +++ b/board_single/main/config.cpp @@ -195,5 +195,9 @@ controlledArmchair control(configControl, &buzzer, &motorLeft, &motorRight, &joy //create global automatedArmchair object (for auto-mode) (auto.hpp) automatedArmchair armchair; +//create global objects for controlling the chair position +// gpio_up, gpio_down, name +cControlledRest legRest(GPIO_NUM_4, GPIO_NUM_16, "legRest"); +cControlledRest backRest(GPIO_NUM_2, GPIO_NUM_15, "backRest"); diff --git a/board_single/main/config.hpp b/board_single/main/config.hpp index d9b8d1b..6549f89 100644 --- a/board_single/main/config.hpp +++ b/board_single/main/config.hpp @@ -11,11 +11,12 @@ #include "http.hpp" #include "auto.hpp" #include "speedsensor.hpp" +#include "chairAdjust.hpp" //in IDLE mode: set loglevel for evaluatedJoystick to DEBUG //and repeatedly read joystick e.g. for manually calibrating / testing joystick -#define JOYSTICK_LOG_IN_IDLE +//#define JOYSTICK_LOG_IN_IDLE //TODO outsource global variables to e.g. global.cpp and only config options here? @@ -49,3 +50,7 @@ extern fan_config_t configCooling; extern speedSensor speedLeft; extern speedSensor speedRight; +//create global objects for controlling the chair position +extern cControlledRest legRest; +extern cControlledRest backRest; + diff --git a/board_single/main/control.cpp b/board_single/main/control.cpp index fc9e4e3..5976c70 100644 --- a/board_single/main/control.cpp +++ b/board_single/main/control.cpp @@ -11,6 +11,7 @@ extern "C" #include "config.hpp" #include "control.hpp" +#include "chairAdjust.hpp" //used definitions moved from config.hpp: @@ -19,7 +20,7 @@ extern "C" //tag for logging static const char * TAG = "control"; -const char* controlModeStr[7] = {"IDLE", "JOYSTICK", "MASSAGE", "HTTP", "MQTT", "BLUETOOTH", "AUTO"}; +const char* controlModeStr[8] = {"IDLE", "JOYSTICK", "MASSAGE", "HTTP", "MQTT", "BLUETOOTH", "AUTO", "ADJUST_CHAIR"}; //----------------------------- @@ -169,6 +170,19 @@ void controlledArmchair::startHandleLoop() { break; + case controlMode_t::ADJUST_CHAIR: + vTaskDelay(100 / portTICK_PERIOD_MS); + //--- read joystick --- + stickData = joystick_l->getData(); + //--- idle motors --- + commands = cmds_bothMotorsIdle; + motorRight->setTarget(commands.right.state, commands.right.duty); + motorLeft->setTarget(commands.left.state, commands.left.duty); + //--- control armchair position with joystick input --- + controlChairAdjustment(joystick_l->getData(), &legRest, &backRest); + break; + + //TODO: add other modes here } @@ -322,12 +336,13 @@ void controlledArmchair::changeMode(controlMode_t modeNew) { ESP_LOGI(TAG, "noting to execute when changing FROM this mode"); break; -#ifdef JOYSTICK_LOG_IN_IDLE case controlMode_t::IDLE: +#ifdef JOYSTICK_LOG_IN_IDLE ESP_LOGI(TAG, "disabling debug output for 'evaluatedJoystick'"); esp_log_level_set("evaluatedJoystick", ESP_LOG_WARN); //FIXME: loglevel from config - break; #endif + buzzer->beep(1,200,100); + break; case controlMode_t::HTTP: ESP_LOGW(TAG, "switching from http mode -> disabling http and wifi"); @@ -367,6 +382,14 @@ void controlledArmchair::changeMode(controlMode_t modeNew) { motorLeft->setFade(fadeType_t::ACCEL, true); motorRight->setFade(fadeType_t::ACCEL, true); break; + + case controlMode_t::ADJUST_CHAIR: + ESP_LOGW(TAG, "switching from ADJUST_CHAIR mode => turning off adjustment motors..."); + //prevent motors from being always on in case of mode switch while joystick is not in center thus motors currently moving + legRest.setState(REST_OFF); + backRest.setState(REST_OFF); + break; + } @@ -384,6 +407,11 @@ void controlledArmchair::changeMode(controlMode_t modeNew) { #endif break; + case controlMode_t::ADJUST_CHAIR: + ESP_LOGW(TAG, "switching to ADJUST_CHAIR mode -> beep"); + buzzer->beep(4,200,100); + break; + case controlMode_t::HTTP: ESP_LOGW(TAG, "switching to http mode -> enabling http and wifi"); //start wifi @@ -445,13 +473,13 @@ void controlledArmchair::toggleModes(controlMode_t modePrimary, controlMode_t mo //switch to secondary mode when primary is already active if (mode == modePrimary){ ESP_LOGW(TAG, "toggleModes: switching from primaryMode %s to secondarMode %s", controlModeStr[(int)mode], controlModeStr[(int)modeSecondary]); - buzzer->beep(2,200,100); + //buzzer->beep(2,200,100); changeMode(modeSecondary); //switch to secondary mode } //switch to primary mode when any other mode is active else { ESP_LOGW(TAG, "toggleModes: switching from %s to primary mode %s", controlModeStr[(int)mode], controlModeStr[(int)modePrimary]); - buzzer->beep(4,200,100); + //buzzer->beep(4,200,100); changeMode(modePrimary); } } diff --git a/board_single/main/control.hpp b/board_single/main/control.hpp index 8ed1e66..63b8234 100644 --- a/board_single/main/control.hpp +++ b/board_single/main/control.hpp @@ -11,9 +11,9 @@ //---- struct, enum, variable declarations --- //-------------------------------------------- //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, ADJUST_CHAIR}; //string array representing the mode enum (for printing the state as string) -extern const char* controlModeStr[7]; +extern const char* controlModeStr[8]; //--- control_config_t --- //struct with config parameters diff --git a/board_single/main/main.cpp b/board_single/main/main.cpp index 693e1c2..9b24e78 100644 --- a/board_single/main/main.cpp +++ b/board_single/main/main.cpp @@ -154,6 +154,7 @@ void setLoglevels(void){ esp_log_level_set("display", ESP_LOG_INFO); //esp_log_level_set("current-sensors", ESP_LOG_INFO); //esp_log_level_set("speedSensor", ESP_LOG_INFO); + esp_log_level_set("chair-adjustment", ESP_LOG_INFO); } diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 00a73f9..bdbe43d 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -10,6 +10,7 @@ idf_component_register( "joystick.cpp" "http.cpp" "speedsensor.cpp" + "chairAdjust.cpp" INCLUDE_DIRS "." PRIV_REQUIRES nvs_flash mdns json spiffs esp_http_server diff --git a/common/chairAdjust.cpp b/common/chairAdjust.cpp new file mode 100644 index 0000000..355959d --- /dev/null +++ b/common/chairAdjust.cpp @@ -0,0 +1,111 @@ +extern "C" +{ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/gpio.h" +#include "esp_log.h" +#include +} + +#include "chairAdjust.hpp" + + + +//--- gloabl variables --- +// strings for logging the rest state +const char* restStateStr[] = {"REST_OFF", "REST_DOWN", "REST_UP"}; + +//--- local variables --- +//tag for logging +static const char * TAG = "chair-adjustment"; + + + +//============================= +//======== constructor ======== +//============================= +cControlledRest::cControlledRest(gpio_num_t gpio_up_f, gpio_num_t gpio_down_f, const char * name_f){ + strcpy(name, name_f); + gpio_up = gpio_up_f; + gpio_down = gpio_down_f; + init(); +} + + + +//==================== +//======= init ======= +//==================== +// init gpio pins for relays +void cControlledRest::init() +{ + ESP_LOGW(TAG, "[%s] initializing gpio pins %d, %d for relays...", name, gpio_up, gpio_down); + // configure 2 gpio pins + gpio_pad_select_gpio(gpio_up); + gpio_set_direction(gpio_up, GPIO_MODE_OUTPUT); + gpio_pad_select_gpio(gpio_down); + gpio_set_direction(gpio_down, GPIO_MODE_OUTPUT); + // both relays off initially + gpio_set_level(gpio_down, 0); + gpio_set_level(gpio_up, 0); +} + + + +//============================ +//========= setState ========= +//============================ +void cControlledRest::setState(restState_t targetState) +{ + //check if actually changed + if (targetState == state){ + ESP_LOGD(TAG, "[%s] state already at '%s', nothing to do", name, restStateStr[state]); + return; + } + + //apply new state + ESP_LOGI(TAG, "[%s] switching from state '%s' to '%s'", name, restStateStr[state], restStateStr[targetState]); + state = targetState; + timestamp_lastChange = esp_log_timestamp(); //TODO use this to estimate position + switch (state) + { + case REST_UP: + gpio_set_level(gpio_down, 0); + gpio_set_level(gpio_up, 1); + break; + case REST_DOWN: + gpio_set_level(gpio_down, 1); + gpio_set_level(gpio_up, 0); + break; + case REST_OFF: + gpio_set_level(gpio_down, 1); + gpio_set_level(gpio_up, 0); + break; + } +} + + + +//==================================== +//====== controlChairAdjustment ====== +//==================================== +//function that controls the two rests according to joystick data (applies threshold, defines direction) +//TODO: +// - add separate task that controls chair adjustment +// - timeout +// - track position +// - auto-adjust: move to position while driving +// - control via app +// - add delay betweem direction change +void controlChairAdjustment(joystickData_t data, cControlledRest * legRest, cControlledRest * backRest){ + //--- variables --- + float stickThreshold = 0.3; //min coordinate for motor to start + + //--- control rest motors --- + //leg rest (x-axis) + if (data.x > stickThreshold) legRest->setState(REST_UP); + else if (data.x < -stickThreshold) legRest->setState(REST_DOWN); + //back rest (y-axis) + if (data.y > stickThreshold) backRest->setState(REST_UP); + else if (data.y < -stickThreshold) backRest->setState(REST_DOWN); +} diff --git a/common/chairAdjust.hpp b/common/chairAdjust.hpp new file mode 100644 index 0000000..60bce18 --- /dev/null +++ b/common/chairAdjust.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "joystick.hpp" + +typedef enum { + REST_OFF = 0, + REST_DOWN, + REST_UP +} restState_t; + +extern const char* restStateStr[]; + + +//===================================== +//======= cControlledRest class ======= +//===================================== +//class that controls 2 relays powering a motor that moves a rest of the armchair up or down +//2 instances will be created one for back and one for leg rest +class cControlledRest { + public: + cControlledRest(gpio_num_t gpio_up, gpio_num_t gpio_down, const char * name); + void setState(restState_t targetState); + void stop(); + + private: + void init(); + + char name[32]; + gpio_num_t gpio_up; + gpio_num_t gpio_down; + restState_t state; + const uint32_t travelDuration = 5000; + uint32_t timestamp_lastChange; + float currentPosition = 0; +}; + +//==================================== +//====== controlChairAdjustment ====== +//==================================== +//function that controls the two rests according to joystick data (applies threshold, defines direction) +void controlChairAdjustment(joystickData_t data, cControlledRest * legRest, cControlledRest * backRest); \ No newline at end of file diff --git a/common/joystick.cpp b/common/joystick.cpp index 93d2097..e9c54b5 100644 --- a/common/joystick.cpp +++ b/common/joystick.cpp @@ -569,4 +569,4 @@ motorCommands_t joystick_generateCommandsShaking(joystickData_t data){ ESP_LOGI(TAG_CMD, "motor right: state=%s, duty=%.3f", motorstateStr[(int)commands.right.state], commands.right.duty); return commands; -} +} \ No newline at end of file diff --git a/connection-plan.drawio.pdf b/connection-plan.drawio.pdf index 8264a57..21102a6 100644 Binary files a/connection-plan.drawio.pdf and b/connection-plan.drawio.pdf differ