Move control to class, Add toggleIdle, toggleModes

- Move all separately declared functions in control.hpp to a new class
  'controlledArmchair'
    - now passing other objects only one time with constructor instead
      of accessing them globally
- Create control instance in config.hpp, and passing objects in
  config.cpp

- Add functions to new control class
  - toggleIdle(): toggle between last mode and idle
  - toggleModes(mode1, mode2): toggle between two modes

- Add commands to button.cpp
  - 2x button press: call toggleIdle()
  - 6x button press: toggleModes  MASSAGE -> JOYSTICK

- Define control task in main.cpp
- Adjust button files and main.cpp to use the new command object instead
  of the previus functions
This commit is contained in:
jonny_ji7 2022-06-11 11:53:13 +02:00 committed by jonny_l480
parent adb517c7ed
commit 5e2962302d
7 changed files with 156 additions and 39 deletions

@ -7,7 +7,6 @@ extern "C"
#include "esp_log.h"
}
#include "control.hpp"
#include "button.hpp"
@ -20,9 +19,10 @@ static const char * TAG = "button";
//-----------------------------
//-------- constructor --------
//-----------------------------
buttonCommands::buttonCommands(gpio_evaluatedSwitch * button_f, buzzer_t * buzzer_f ){
buttonCommands::buttonCommands(gpio_evaluatedSwitch * button_f, controlledArmchair * control_f, buzzer_t * buzzer_f ){
//copy object pointers
button = button_f;
control = control_f;
buzzer = buzzer_f;
//TODO declare / configure evaluatedSwitch here instead of config (unnecessary that button object is globally available - only used here)?
}
@ -47,15 +47,13 @@ void buttonCommands::action (uint8_t count){
break;
case 2:
ESP_LOGW(TAG, "cmd %d: switching to IDLE", count);
control_changeMode(controlMode_t::IDLE);
buzzer->beep(1,1000,1);
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: switching to JOYSTICK", count);
control_changeMode(controlMode_t::JOYSTICK);
buzzer->beep(2,400,100);
case 6:
ESP_LOGW(TAG, "cmd %d: toggle between MASSAGE and JOYSTICK", count);
control->toggleModes(controlMode_t::MASSAGE, controlMode_t::JOYSTICK); //toggle between MASSAGE and JOYSTICK mode
break;
}
}

@ -2,6 +2,7 @@
#include "gpio_evaluateSwitch.hpp"
#include "buzzer.hpp"
#include "control.hpp"
@ -14,6 +15,7 @@ class buttonCommands {
//--- constructor ---
buttonCommands (
gpio_evaluatedSwitch * button_f,
controlledArmchair * control_f,
buzzer_t * buzzer_f
);
@ -28,6 +30,7 @@ class buttonCommands {
//--- objects ---
gpio_evaluatedSwitch* button;
controlledArmchair * control;
buzzer_t* buzzer;
//--- variables ---

@ -71,3 +71,6 @@ gpio_evaluatedSwitch buttonJoystick(GPIO_NUM_33, true, false); //pullup true, no
//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);

@ -6,6 +6,7 @@
#include "gpio_evaluateSwitch.hpp"
#include "buzzer.hpp"
#include "control.hpp"
//create global controlledMotor instances for both motors
@ -20,3 +21,7 @@ extern gpio_evaluatedSwitch buttonJoystick;
//create global buzzer object
extern buzzer_t buzzer;
//create global control object
extern controlledArmchair control;

@ -5,30 +5,38 @@ extern "C"
#include "esp_log.h"
}
#include "motordrivers.hpp"
#include "motorctl.hpp"
#include "joystick.hpp"
#include "config.hpp"
#include "control.hpp"
//=================================
//===== variable declaration ======
//=================================
//tag for logging
static const char * TAG = "control";
//definition of mode enum
controlMode_t mode = controlMode_t::IDLE;
const char* controlModeStr[6] = {"IDLE", "JOYSTICK", "MASSAGE", "MQTT", "BLUETOOTH", "AUTO"};
//-----------------------------
//-------- constructor --------
//-----------------------------
controlledArmchair::controlledArmchair (
buzzer_t * buzzer_f,
controlledMotor* motorLeft_f,
controlledMotor* motorRight_f
){
//copy object pointers
buzzer = buzzer_f;
motorLeft = motorLeft_f;
motorRight = motorRight_f;
//TODO declare / configure controlled motors here instead of config (unnecessary that button object is globally available - only used here)?
}
//==================================
//========== handle task ===========
//==================================
//task that repeatedly generates motor commands depending on the current mode
void task_control ( void * pvParameters ) {
//----------------------------------
//---------- Handle loop -----------
//----------------------------------
//function that repeatedly generates motor commands depending on the current mode
void controlledArmchair::startHandleLoop() {
while (1){
vTaskDelay(20 / portTICK_PERIOD_MS);
@ -40,17 +48,23 @@ void task_control ( void * pvParameters ) {
break;
case controlMode_t::IDLE:
motorRight.setTarget(motorstate_t::IDLE, 0);
motorLeft.setTarget(motorstate_t::IDLE, 0);
motorRight->setTarget(motorstate_t::IDLE, 0);
motorLeft->setTarget(motorstate_t::IDLE, 0);
break;
case controlMode_t::JOYSTICK:
motorCommands_t commands = joystick_generateCommandsDriving(joystick);
motorRight.setTarget(commands.right.state, commands.right.duty);
motorLeft.setTarget(commands.left.state, commands.left.duty);
commands = joystick_generateCommandsDriving(joystick);
motorRight->setTarget(commands.right.state, commands.right.duty);
motorLeft->setTarget(commands.left.state, commands.left.duty);
//TODO make motorctl.setTarget also accept motorcommand struct directly
break;
case controlMode_t::MASSAGE:
motorRight->setTarget(motorstate_t::IDLE, 0);
motorLeft->setTarget(motorstate_t::IDLE, 0);
//TODO add actual command generation here
break;
//TODO: add other modes here
}
}
@ -58,11 +72,11 @@ void task_control ( void * pvParameters ) {
//===================================
//=========== changeMode ============
//===================================
//-----------------------------------
//----------- changeMode ------------
//-----------------------------------
//function to change to a specified control mode
void control_changeMode(controlMode_t modeNew) {
void controlledArmchair::changeMode(controlMode_t modeNew) {
ESP_LOGW(TAG, "changing mode from %s to %s", controlModeStr[(int)mode], controlModeStr[(int)modeNew]);
mode = modeNew;
//TODO: add mutex
@ -70,3 +84,41 @@ void control_changeMode(controlMode_t modeNew) {
//-----------------------------------
//----------- toggleIdle ------------
//-----------------------------------
//function to toggle between IDLE and previous active mode
void controlledArmchair::toggleIdle() {
if (mode == controlMode_t::IDLE){
mode = modePrevious; //restore previous mode, or default if not switched yet
buzzer->beep(2, 200, 100);
ESP_LOGW(TAG, "switched mode from IDLE to %s", controlModeStr[(int)mode]);
} else {
modePrevious = mode; //store current mode
mode = controlMode_t::IDLE; //set mode to IDLE
buzzer->beep(1, 1000, 0);
ESP_LOGW(TAG, "switched mode from IDLE to %s", controlModeStr[(int)mode]);
}
}
//------------------------------------
//----------- toggleModes ------------
//------------------------------------
//function to toggle between two modes, but prefer first argument if entirely different mode is currently active
void controlledArmchair::toggleModes(controlMode_t modePrimary, controlMode_t modeSecondary) {
//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);
mode = 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);
mode = modePrimary;
}
}

@ -1,15 +1,60 @@
#pragma once
#include "motordrivers.hpp"
#include "motorctl.hpp"
#include "buzzer.hpp"
//enum that decides how the motors get controlled
enum class controlMode_t {IDLE, JOYSTICK, MASSAGE, MQTT, BLUETOOTH, AUTO};
//extern controlMode_t mode;
//task that repeatedly generates motor commands depending on the current mode
void task_control(void * pvParameters);
//function that changes to a specified control mode
void control_changeMode(controlMode_t modeNew);
extern const char* controlModeStr[6];
//==================================
//========= control class ==========
//==================================
//controls the mode the armchair operates
//repeatedly generates the motor commands corresponding to current mode and sends those to motorcontrol
class controlledArmchair {
public:
//--- constructor ---
controlledArmchair (
buzzer_t* buzzer_f,
controlledMotor* motorLeft_f,
controlledMotor* motorRight_f
);
//--- functions ---
//task that repeatedly generates motor commands depending on the current mode
void startHandleLoop();
//function that changes to a specified control mode
void changeMode(controlMode_t modeNew);
//function that toggle between IDLE and previous active mode (or default if not switched to certain mode yet)
void toggleIdle();
//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);
private:
//--- objects ---
buzzer_t* buzzer;
controlledMotor* motorLeft;
controlledMotor* motorRight;
//---variables ---
//struct for motor commands returned by generate functions of each mode
motorCommands_t commands;
//definition of mode enum
controlMode_t mode = controlMode_t::IDLE;
//variable to store mode when toggling IDLE mode
controlMode_t modePrevious = controlMode_t::JOYSTICK; //default mode
};

@ -53,13 +53,24 @@ void task_buzzer( void * pvParameters ){
//=======================================
//============ control task =============
//=======================================
void task_control( void * pvParameters ){
ESP_LOGI(TAG, "Initializing controlledArmchair and starting handle loop");
//start handle loop (control object declared in config.hpp)
control.startHandleLoop();
}
//======================================
//============ button task =============
//======================================
void task_button( void * pvParameters ){
ESP_LOGI(TAG, "Initializing command-button and starting handle loop");
//create button instance
buttonCommands commandButton(&buttonJoystick, &buzzer);
buttonCommands commandButton(&buttonJoystick, &control, &buzzer);
//start handle loop
commandButton.startHandleLoop();
}
@ -106,7 +117,7 @@ extern "C" void app_main(void) {
//-------------------------------
//--- create task for control ---
//-------------------------------
//task that generates motor commands depending on the current mode and sends those to motorctl task (task_control is defined in control.cpp)
//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);
//------------------------------