Major Rework all files - Pass pointers to tasks, Remove gloabl variables
- All files:
  Modify almost all files to adjust functions and classes to
  work with pointers to objects passed at task creation
  instead of global variables from config.hpp
- Remove/clear config.hpp to get rid of all global variables
- main.cpp
    - Create pointer to all shared (used in multiple tasks) objects in main
- remove evaluatedSwitch button object,
  since joystick library is used to get switch events
- changes HTTP-mode
    - always init http-server (do not enable/disable at mode change)
    - pass url-handle function to init-htpp function
    - add lambda function to pass method of instance for thatMajor Rework all files - Remove global variables, pass pointers to tasks
- All files:
  Modify almost all files to adjust functions and classes to
  work with pointers to objects passed at task creation
  instead of global variables from config.hpp
- Remove/clear config.hpp to get rid of all global variables
- main.cpp
    - Create pointer to all shared (used in multiple tasks) objects in main
- remove evaluatedSwitch button object,
  since joystick library is used to get switch events
- changes HTTP-mode
    - always init http-server (do not enable/disable at mode change)
    - pass url-handle function to init-htpp function
    - add lambda function to pass method of instance for that
NOTES:  - tested on breakoutboard only
        - known issue that slow encoder events are not recognized
        (especially in menu) - slowing down motorctl helps
			
			
This commit is contained in:
		
							parent
							
								
									40a0f56208
								
							
						
					
					
						commit
						2fcf17feda
					
				| @ -8,9 +8,12 @@ static const char * TAG = "automatedArmchair"; | ||||
| //=============================
 | ||||
| //======== constructor ========
 | ||||
| //=============================
 | ||||
| automatedArmchair::automatedArmchair(void) { | ||||
|     //create command queue
 | ||||
|     commandQueue = xQueueCreate( 32, sizeof( commandSimple_t ) ); //TODO add max size to config?
 | ||||
| automatedArmchair_c::automatedArmchair_c(controlledMotor *motorLeft_f, controlledMotor *motorRight_f) | ||||
| { | ||||
|     motorLeft = motorLeft_f; | ||||
|     motorRight = motorRight_f; | ||||
|     // create command queue
 | ||||
|     commandQueue = xQueueCreate(32, sizeof(commandSimple_t)); // TODO add max size to config?
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @ -18,7 +21,7 @@ automatedArmchair::automatedArmchair(void) { | ||||
| //==============================
 | ||||
| //====== generateCommands ======
 | ||||
| //==============================
 | ||||
| motorCommands_t automatedArmchair::generateCommands(auto_instruction_t * instruction) { | ||||
| motorCommands_t automatedArmchair_c::generateCommands(auto_instruction_t * instruction) { | ||||
|     //reset instruction
 | ||||
|     *instruction = auto_instruction_t::NONE; | ||||
|     //check if previous command is finished
 | ||||
| @ -29,10 +32,10 @@ motorCommands_t automatedArmchair::generateCommands(auto_instruction_t * instruc | ||||
|             //copy instruction to be provided to control task
 | ||||
|             *instruction = cmdCurrent.instruction; | ||||
|             //set acceleration / fading parameters according to command
 | ||||
|             motorLeft.setFade(fadeType_t::DECEL, cmdCurrent.fadeDecel); | ||||
|             motorRight.setFade(fadeType_t::DECEL, cmdCurrent.fadeDecel); | ||||
|             motorLeft.setFade(fadeType_t::ACCEL, cmdCurrent.fadeAccel); | ||||
|             motorRight.setFade(fadeType_t::ACCEL, cmdCurrent.fadeAccel); | ||||
|             motorLeft->setFade(fadeType_t::DECEL, cmdCurrent.fadeDecel); | ||||
|             motorRight->setFade(fadeType_t::DECEL, cmdCurrent.fadeDecel); | ||||
|             motorLeft->setFade(fadeType_t::ACCEL, cmdCurrent.fadeAccel); | ||||
|             motorRight->setFade(fadeType_t::ACCEL, cmdCurrent.fadeAccel); | ||||
|             //calculate timestamp the command is finished
 | ||||
|             timestampCmdFinished = esp_log_timestamp() + cmdCurrent.msDuration; | ||||
|             //copy the new commands
 | ||||
| @ -55,7 +58,7 @@ motorCommands_t automatedArmchair::generateCommands(auto_instruction_t * instruc | ||||
| //======== addCommand ========
 | ||||
| //============================
 | ||||
| //function that adds a basic command to the queue
 | ||||
| void automatedArmchair::addCommand(commandSimple_t command) { | ||||
| void automatedArmchair_c::addCommand(commandSimple_t command) { | ||||
|     //add command to queue
 | ||||
|      if ( xQueueSend( commandQueue, ( void * )&command, ( TickType_t ) 0 ) ){ | ||||
|          ESP_LOGI(TAG, "Successfully inserted command to queue"); | ||||
| @ -64,7 +67,7 @@ void automatedArmchair::addCommand(commandSimple_t command) { | ||||
|      } | ||||
| } | ||||
| 
 | ||||
| void automatedArmchair::addCommands(commandSimple_t commands[], size_t count) { | ||||
| void automatedArmchair_c::addCommands(commandSimple_t commands[], size_t count) { | ||||
|     for (int i = 0; i < count; i++) { | ||||
|          ESP_LOGI(TAG, "Reading command no. %d from provided array", i); | ||||
|         addCommand(commands[i]); | ||||
| @ -77,7 +80,7 @@ void automatedArmchair::addCommands(commandSimple_t commands[], size_t count) { | ||||
| //===============================
 | ||||
| //function that deletes all pending/queued commands
 | ||||
| //e.g. when switching modes
 | ||||
| motorCommands_t automatedArmchair::clearCommands() { | ||||
| motorCommands_t automatedArmchair_c::clearCommands() { | ||||
|     //clear command queue
 | ||||
|     xQueueReset( commandQueue ); | ||||
|     ESP_LOGW(TAG, "command queue was successfully emptied"); | ||||
|  | ||||
| @ -33,13 +33,13 @@ typedef struct commandSimple_t{ | ||||
| 
 | ||||
| 
 | ||||
| //------------------------------------
 | ||||
| //----- automatedArmchair class  -----
 | ||||
| //----- automatedArmchair_c class  -----
 | ||||
| //------------------------------------
 | ||||
| class automatedArmchair { | ||||
| class automatedArmchair_c { | ||||
|     public: | ||||
|         //--- methods ---
 | ||||
|         //constructor
 | ||||
|         automatedArmchair(void); | ||||
|         automatedArmchair_c(controlledMotor * motorLeft, controlledMotor * motorRight); | ||||
|         //function to generate motor commands
 | ||||
|         //can be also seen as handle function 
 | ||||
|         //TODO: go with other approach: separate task for handling auto mode
 | ||||
| @ -62,6 +62,8 @@ class automatedArmchair { | ||||
|     private: | ||||
|         //--- methods ---
 | ||||
|         //--- objects ---
 | ||||
|         controlledMotor * motorLeft; | ||||
|         controlledMotor * motorRight; | ||||
|         //TODO: add buzzer here
 | ||||
|         //--- variables ---
 | ||||
|         //queue for storing pending commands
 | ||||
| @ -124,7 +126,7 @@ if (trigger){ | ||||
|         .instruction = auto_instruction_t::SWITCH_JOYSTICK_MODE | ||||
|     }; | ||||
| 
 | ||||
|     //send commands to automatedArmchair command queue
 | ||||
|     //send commands to automatedArmchair_c command queue
 | ||||
|     armchair.addCommands(cmds, 3); | ||||
| 
 | ||||
|     //change mode to AUTO
 | ||||
|  | ||||
| @ -10,29 +10,44 @@ extern "C" | ||||
| #include "button.hpp" | ||||
| #include "encoder.hpp" | ||||
| 
 | ||||
| // tag for logging
 | ||||
| static const char *TAG = "button"; | ||||
| 
 | ||||
| 
 | ||||
| //tag for logging
 | ||||
| static const char * TAG = "button"; | ||||
| 
 | ||||
| 
 | ||||
| //======================================
 | ||||
| //============ button task =============
 | ||||
| //======================================
 | ||||
| // task that handles the button interface/commands
 | ||||
| void task_button(void *task_button_parameters) | ||||
| { | ||||
|     task_button_parameters_t *objects = (task_button_parameters_t *)task_button_parameters; | ||||
|     ESP_LOGI(TAG, "Initializing command-button and starting handle loop"); | ||||
|     // create button instance
 | ||||
|     buttonCommands commandButton(objects->control, objects->joystick, objects->encoderQueue, objects->motorLeft, objects->motorRight, objects->buzzer); | ||||
|     // start handle loop
 | ||||
|     commandButton.startHandleLoop(); | ||||
| } | ||||
| 
 | ||||
| //-----------------------------
 | ||||
| //-------- constructor --------
 | ||||
| //-----------------------------
 | ||||
| buttonCommands::buttonCommands(gpio_evaluatedSwitch * button_f, evaluatedJoystick * joystick_f, controlledArmchair * control_f, buzzer_t * buzzer_f, controlledMotor * motorLeft_f, controlledMotor * motorRight_f){ | ||||
|     //copy object pointers
 | ||||
|     button = button_f; | ||||
|     joystick = joystick_f; | ||||
| buttonCommands::buttonCommands( | ||||
|     controlledArmchair *control_f, | ||||
|     evaluatedJoystick *joystick_f, | ||||
|     QueueHandle_t encoderQueue_f, | ||||
|     controlledMotor *motorLeft_f, | ||||
|     controlledMotor *motorRight_f, | ||||
|     buzzer_t *buzzer_f) | ||||
| { | ||||
|     // copy object pointers
 | ||||
|     control = control_f; | ||||
|     buzzer = buzzer_f; | ||||
|     joystick = joystick_f; | ||||
|     encoderQueue = encoderQueue_f; | ||||
|     motorLeft = motorLeft_f; | ||||
|     motorRight = motorRight_f; | ||||
|     //TODO declare / configure evaluatedSwitch here instead of config (unnecessary that button object is globally available - only used here)?
 | ||||
|     buzzer = buzzer_f; | ||||
|     // TODO declare / configure evaluatedSwitch here instead of config (unnecessary that button object is globally available - only used here)?
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //----------------------------
 | ||||
| //--------- action -----------
 | ||||
| //----------------------------
 | ||||
| @ -40,7 +55,7 @@ buttonCommands::buttonCommands(gpio_evaluatedSwitch * button_f, evaluatedJoystic | ||||
| void buttonCommands::action (uint8_t count, bool lastPressLong){ | ||||
|     //--- variables ---
 | ||||
|     bool decelEnabled; //for different beeping when toggling
 | ||||
|     commandSimple_t cmds[8]; //array for commands for automatedArmchair
 | ||||
|     commandSimple_t cmds[8]; //array for commands for automatedArmchair_c
 | ||||
| 
 | ||||
|     //--- get joystick position ---
 | ||||
|     //in case joystick is used for additional cases:
 | ||||
|  | ||||
| @ -17,14 +17,13 @@ | ||||
| class buttonCommands { | ||||
|     public: | ||||
|         //--- constructor ---
 | ||||
|         buttonCommands ( | ||||
|                 gpio_evaluatedSwitch * button_f, | ||||
|                 evaluatedJoystick * joystick_f, | ||||
|                 controlledArmchair * control_f, | ||||
|                 buzzer_t * buzzer_f, | ||||
|                 controlledMotor * motorLeft_f,  | ||||
|                 controlledMotor * motorRight_f | ||||
|                 );  | ||||
|         buttonCommands( | ||||
|             controlledArmchair *control_f, | ||||
|             evaluatedJoystick *joystick_f, | ||||
|             QueueHandle_t encoderQueue_f, | ||||
|             controlledMotor * motorLeft_f, | ||||
|             controlledMotor *motorRight_f, | ||||
|             buzzer_t *buzzer_f); | ||||
| 
 | ||||
|         //--- functions ---
 | ||||
|         //the following function has to be started once in a separate task. 
 | ||||
| @ -36,12 +35,12 @@ class buttonCommands { | ||||
|         void action(uint8_t count, bool lastPressLong); | ||||
| 
 | ||||
|         //--- objects ---
 | ||||
|         gpio_evaluatedSwitch* button; | ||||
|         evaluatedJoystick* joystick; | ||||
|         controlledArmchair * control; | ||||
|         buzzer_t* buzzer; | ||||
|         evaluatedJoystick* joystick; | ||||
|         controlledMotor * motorLeft; | ||||
|         controlledMotor * motorRight; | ||||
|         buzzer_t* buzzer; | ||||
|         QueueHandle_t encoderQueue; | ||||
| 
 | ||||
|         //--- variables ---
 | ||||
|         uint8_t count = 0; | ||||
| @ -51,3 +50,21 @@ class buttonCommands { | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //======================================
 | ||||
| //============ button task =============
 | ||||
| //======================================
 | ||||
| // struct with variables passed to task from main
 | ||||
| typedef struct task_button_parameters_t | ||||
| { | ||||
|     controlledArmchair *control; | ||||
|     evaluatedJoystick *joystick; | ||||
|     QueueHandle_t encoderQueue; | ||||
|     controlledMotor *motorLeft; | ||||
|     controlledMotor *motorRight; | ||||
|     buzzer_t *buzzer; | ||||
| } task_button_parameters_t; | ||||
| 
 | ||||
| //task that handles the button interface/commands
 | ||||
| void task_button( void * task_button_parameters ); | ||||
| @ -1,8 +1,54 @@ | ||||
| #include "config.hpp" | ||||
| // NOTE: this file is included in main.cpp only.
 | ||||
| // outsourced all configuration related functions and structures to this file:
 | ||||
| 
 | ||||
| //===================================
 | ||||
| //======= motor configuration =======
 | ||||
| //===================================
 | ||||
| #include "motordrivers.hpp" | ||||
| #include "motorctl.hpp" | ||||
| #include "joystick.hpp" | ||||
| #include "http.hpp" | ||||
| #include "speedsensor.hpp" | ||||
| 
 | ||||
| #include "buzzer.hpp" | ||||
| #include "control.hpp" | ||||
| #include "fan.hpp" | ||||
| #include "auto.hpp" | ||||
| #include "chairAdjust.hpp" | ||||
| 
 | ||||
| //==================================
 | ||||
| //======== define loglevels ========
 | ||||
| //==================================
 | ||||
| void setLoglevels(void) | ||||
| { | ||||
|     // set loglevel for all tags:
 | ||||
|     esp_log_level_set("*", ESP_LOG_WARN); | ||||
| 
 | ||||
|     //--- set loglevel for individual tags ---
 | ||||
|     esp_log_level_set("main", ESP_LOG_INFO); | ||||
|     esp_log_level_set("buzzer", ESP_LOG_ERROR); | ||||
|     // esp_log_level_set("motordriver", ESP_LOG_DEBUG);
 | ||||
|     esp_log_level_set("motor-control", ESP_LOG_WARN); | ||||
|     // esp_log_level_set("evaluatedJoystick", ESP_LOG_DEBUG);
 | ||||
|     // esp_log_level_set("joystickCommands", ESP_LOG_DEBUG);
 | ||||
|     esp_log_level_set("button", ESP_LOG_INFO); | ||||
|     esp_log_level_set("control", ESP_LOG_INFO); | ||||
|     // esp_log_level_set("fan-control", ESP_LOG_INFO);
 | ||||
|     esp_log_level_set("wifi", ESP_LOG_INFO); | ||||
|     esp_log_level_set("http", ESP_LOG_INFO); | ||||
|     // esp_log_level_set("automatedArmchair", ESP_LOG_DEBUG);
 | ||||
|     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); | ||||
|     esp_log_level_set("menu", ESP_LOG_INFO); | ||||
|     esp_log_level_set("encoder", ESP_LOG_INFO); | ||||
| } | ||||
| 
 | ||||
| //==================================
 | ||||
| //======== configuration ===========
 | ||||
| //==================================
 | ||||
| 
 | ||||
| //-----------------------------------
 | ||||
| //------- motor configuration -------
 | ||||
| //-----------------------------------
 | ||||
| /* ==> currently using other driver
 | ||||
| //--- configure left motor (hardware) ---
 | ||||
| single100a_config_t configDriverLeft = { | ||||
| @ -11,8 +57,8 @@ single100a_config_t configDriverLeft = { | ||||
|     .gpio_b = GPIO_NUM_4, | ||||
|     .ledc_timer = LEDC_TIMER_0, | ||||
|     .ledc_channel = LEDC_CHANNEL_0, | ||||
| 	.aEnabledPinState = false, //-> pins inverted (mosfets)
 | ||||
| 	.bEnabledPinState = false, | ||||
|     .aEnabledPinState = false, //-> pins inverted (mosfets)
 | ||||
|     .bEnabledPinState = false, | ||||
|     .resolution = LEDC_TIMER_11_BIT, | ||||
|     .pwmFreq = 10000 | ||||
| }; | ||||
| @ -24,180 +70,114 @@ single100a_config_t configDriverRight = { | ||||
|     .gpio_b = GPIO_NUM_14, | ||||
|     .ledc_timer = LEDC_TIMER_1, | ||||
|     .ledc_channel = LEDC_CHANNEL_1, | ||||
| 	.aEnabledPinState = false, //-> pin inverted (mosfet)
 | ||||
| 	.bEnabledPinState = true,  //-> not inverted (direct)
 | ||||
|     .aEnabledPinState = false, //-> pin inverted (mosfet)
 | ||||
|     .bEnabledPinState = true,  //-> not inverted (direct)
 | ||||
|     .resolution = LEDC_TIMER_11_BIT, | ||||
|     .pwmFreq = 10000 | ||||
| 	}; | ||||
| 	*/ | ||||
|     }; | ||||
|     */ | ||||
| 
 | ||||
| //--- configure sabertooth driver --- (controls both motors in one instance)
 | ||||
| sabertooth2x60_config_t sabertoothConfig = { | ||||
| 	.gpio_TX = GPIO_NUM_25, | ||||
| 	.uart_num = UART_NUM_2 | ||||
| }; | ||||
|     .gpio_TX = GPIO_NUM_25, | ||||
|     .uart_num = UART_NUM_2}; | ||||
| 
 | ||||
| 
 | ||||
| //TODO add motor name string -> then use as log tag?
 | ||||
| // TODO add motor name string -> then use as log tag?
 | ||||
| //--- configure left motor (contol) ---
 | ||||
| motorctl_config_t configMotorControlLeft = { | ||||
|     .msFadeAccel = 1500, //acceleration of the motor (ms it takes from 0% to 100%)
 | ||||
|     .msFadeDecel = 1000, //deceleration of the motor (ms it takes from 100% to 0%)
 | ||||
| 	.currentLimitEnabled = false, | ||||
| 	.currentSensor_adc =  ADC1_CHANNEL_4, //GPIO32
 | ||||
| 	.currentSensor_ratedCurrent = 50, | ||||
|     .msFadeAccel = 1500, // acceleration of the motor (ms it takes from 0% to 100%)
 | ||||
|     .msFadeDecel = 1000, // deceleration of the motor (ms it takes from 100% to 0%)
 | ||||
|     .currentLimitEnabled = false, | ||||
|     .currentSensor_adc = ADC1_CHANNEL_4, // GPIO32
 | ||||
|     .currentSensor_ratedCurrent = 50, | ||||
|     .currentMax = 30, | ||||
| 	.deadTimeMs = 0 //minimum time motor is off between direction change
 | ||||
|     .deadTimeMs = 0 // minimum time motor is off between direction change
 | ||||
| }; | ||||
| 
 | ||||
| //--- configure right motor (contol) ---
 | ||||
| motorctl_config_t configMotorControlRight = { | ||||
|     .msFadeAccel = 1500, //acceleration of the motor (ms it takes from 0% to 100%)
 | ||||
|     .msFadeDecel = 1000, //deceleration of the motor (ms it takes from 100% to 0%)
 | ||||
| 	.currentLimitEnabled = false, | ||||
| 	.currentSensor_adc =  ADC1_CHANNEL_5, //GPIO33
 | ||||
| 	.currentSensor_ratedCurrent = 50, | ||||
|     .msFadeAccel = 1500, // acceleration of the motor (ms it takes from 0% to 100%)
 | ||||
|     .msFadeDecel = 1000, // deceleration of the motor (ms it takes from 100% to 0%)
 | ||||
|     .currentLimitEnabled = false, | ||||
|     .currentSensor_adc = ADC1_CHANNEL_5, // GPIO33
 | ||||
|     .currentSensor_ratedCurrent = 50, | ||||
|     .currentMax = 30, | ||||
| 	.deadTimeMs = 0 //minimum time motor is off between direction change
 | ||||
|     .deadTimeMs = 0 // minimum time motor is off between direction change
 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //==============================
 | ||||
| //======= control config =======
 | ||||
| //==============================
 | ||||
| //------------------------------
 | ||||
| //------- control config -------
 | ||||
| //------------------------------
 | ||||
| control_config_t configControl = { | ||||
|     .defaultMode = controlMode_t::JOYSTICK, //default mode after startup and toggling IDLE
 | ||||
|     //--- timeout ---    
 | ||||
|     .timeoutMs = 3*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
 | ||||
|     .defaultMode = controlMode_t::JOYSTICK, // default mode after startup and toggling IDLE
 | ||||
|     //--- timeout ---
 | ||||
|     .timeoutMs = 3 * 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 -----
 | ||||
| //-------------------------------
 | ||||
| httpJoystick_config_t configHttpJoystickMain{ | ||||
|     .toleranceZeroX_Per = 1,  //percentage around joystick axis the coordinate snaps to 0
 | ||||
|     .toleranceZeroX_Per = 1, // percentage around joystick axis the coordinate snaps to 0
 | ||||
|     .toleranceZeroY_Per = 6, | ||||
|     .toleranceEndPer = 2,   //percentage before joystick end the coordinate snaps to 1/-1
 | ||||
|     .timeoutMs = 2500       //time no new data was received before the motors get turned off
 | ||||
|     .toleranceEndPer = 2, // percentage before joystick end the coordinate snaps to 1/-1
 | ||||
|     .timeoutMs = 2500     // time no new data was received before the motors get turned off
 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //======================================
 | ||||
| //======= joystick configuration =======
 | ||||
| //======================================
 | ||||
| //--------------------------------------
 | ||||
| //------- joystick configuration -------
 | ||||
| //--------------------------------------
 | ||||
| joystick_config_t configJoystick = { | ||||
|     .adc_x = ADC1_CHANNEL_0, //GPIO36
 | ||||
|     .adc_y = ADC1_CHANNEL_3, //GPIO39
 | ||||
|     //percentage of joystick range the coordinate of the axis snaps to 0 (0-100)
 | ||||
|     .tolerance_zeroX_per = 7, //6
 | ||||
|     .tolerance_zeroY_per = 10, //7
 | ||||
|     //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 = 4,  | ||||
|     //threshold the radius jumps to 1 before the stick is at max radius (range 0-1)
 | ||||
|     .adc_x = ADC1_CHANNEL_0, // GPIO36
 | ||||
|     .adc_y = ADC1_CHANNEL_3, // GPIO39
 | ||||
|     // percentage of joystick range the coordinate of the axis snaps to 0 (0-100)
 | ||||
|     .tolerance_zeroX_per = 7,  // 6
 | ||||
|     .tolerance_zeroY_per = 10, // 7
 | ||||
|     // 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 = 4, | ||||
|     // threshold the radius jumps to 1 before the stick is at max radius (range 0-1)
 | ||||
|     .tolerance_radius = 0.09, | ||||
| 
 | ||||
|     //min and max adc values of each axis, !!!AFTER INVERSION!!! is applied:
 | ||||
|     // min and max adc values of each axis, !!!AFTER INVERSION!!! is applied:
 | ||||
|     .x_min = 1710, //=> x=-1
 | ||||
|     .x_max = 2980, //=> x=1
 | ||||
|     .y_min = 1700, //=> y=-1
 | ||||
|     .y_max = 2940, //=> y=1
 | ||||
|     //invert adc measurement
 | ||||
|     // invert adc measurement
 | ||||
|     .x_inverted = true, | ||||
|     .y_inverted = true | ||||
| }; | ||||
|     .y_inverted = true}; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //============================
 | ||||
| //=== configure fan contol ===
 | ||||
| //============================
 | ||||
| //----------------------------
 | ||||
| //--- configure fan contol ---
 | ||||
| //----------------------------
 | ||||
| fan_config_t configCooling = { | ||||
|     .gpio_fan = GPIO_NUM_13, | ||||
|     .dutyThreshold = 40, | ||||
| 	.minOnMs = 1500, | ||||
| 	.minOffMs = 3000, | ||||
| 	.turnOffDelayMs = 5000, | ||||
|     .minOnMs = 1500, | ||||
|     .minOffMs = 3000, | ||||
|     .turnOffDelayMs = 5000, | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //============================================
 | ||||
| //======== speed sensor configuration ========
 | ||||
| //============================================
 | ||||
| //--------------------------------------------
 | ||||
| //-------- speed sensor configuration --------
 | ||||
| //--------------------------------------------
 | ||||
| speedSensor_config_t speedLeft_config{ | ||||
| 	.gpioPin = GPIO_NUM_5, | ||||
| 		.degreePerGroup = 360/5, | ||||
| 		.tireCircumferenceMeter = 210.0*3.141/1000.0, | ||||
| 		.directionInverted = false, | ||||
| 		.logName = "speedLeft", | ||||
|     .gpioPin = GPIO_NUM_5, | ||||
|     .degreePerGroup = 360 / 5, | ||||
|     .tireCircumferenceMeter = 210.0 * 3.141 / 1000.0, | ||||
|     .directionInverted = false, | ||||
|     .logName = "speedLeft", | ||||
| }; | ||||
| 
 | ||||
| speedSensor_config_t speedRight_config{ | ||||
| 	.gpioPin = GPIO_NUM_14, | ||||
| 		.degreePerGroup = 360/12, | ||||
| 		.tireCircumferenceMeter = 210.0*3.141/1000.0, | ||||
| 		.directionInverted = true, | ||||
| 		.logName = "speedRight", | ||||
|     .gpioPin = GPIO_NUM_14, | ||||
|     .degreePerGroup = 360 / 12, | ||||
|     .tireCircumferenceMeter = 210.0 * 3.141 / 1000.0, | ||||
|     .directionInverted = true, | ||||
|     .logName = "speedRight", | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //=================================
 | ||||
| //===== create global objects =====
 | ||||
| //=================================
 | ||||
| //TODO outsource global variables to e.g. global.cpp and only config options here?
 | ||||
| //create sabertooth motor driver instance
 | ||||
| sabertooth2x60a sabertoothDriver(sabertoothConfig); | ||||
| 
 | ||||
| 
 | ||||
| //--- controlledMotor ---
 | ||||
| //functions for updating the duty via certain/current driver that can then be passed to controlledMotor
 | ||||
| //-> makes it possible to easily use different motor drivers
 | ||||
| //note: ignoring warning "capture of variable 'sabertoothDriver' with non-automatic storage duration", since sabertoothDriver object does not get destroyed anywhere - no lifetime issue
 | ||||
| motorSetCommandFunc_t setLeftFunc = [&sabertoothDriver](motorCommand_t cmd) { | ||||
|     sabertoothDriver.setLeft(cmd); | ||||
| }; | ||||
| motorSetCommandFunc_t setRightFunc = [&sabertoothDriver](motorCommand_t cmd) { | ||||
|     sabertoothDriver.setRight(cmd); | ||||
| }; | ||||
| //create controlled motor instances (motorctl.hpp)
 | ||||
| controlledMotor motorLeft(setLeftFunc, configMotorControlLeft); | ||||
| controlledMotor motorRight(setRightFunc, configMotorControlRight); | ||||
| 
 | ||||
| //create speedsensor instances
 | ||||
| speedSensor speedLeft (speedLeft_config); | ||||
| speedSensor speedRight (speedRight_config); | ||||
| 
 | ||||
| //create global joystic instance (joystick.hpp)
 | ||||
| evaluatedJoystick joystick(configJoystick); | ||||
| 
 | ||||
| //create global evaluated switch instance for button next to joystick
 | ||||
| gpio_evaluatedSwitch buttonJoystick(GPIO_NUM_21, 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 (http.hpp)
 | ||||
| httpJoystick httpJoystickMain(configHttpJoystickMain); | ||||
| 
 | ||||
| //create global control object (control.hpp)
 | ||||
| controlledArmchair control(configControl, &buzzer, &motorLeft, &motorRight, &joystick, &httpJoystickMain); | ||||
| 
 | ||||
| //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"); | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -13,44 +13,45 @@ | ||||
| #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
 | ||||
| 
 | ||||
| 
 | ||||
| //TODO outsource global variables to e.g. global.cpp and only config options here?
 | ||||
| 
 | ||||
| //create global controlledMotor instances for both motors
 | ||||
| extern controlledMotor motorLeft; | ||||
| extern controlledMotor motorRight; | ||||
| 
 | ||||
| //create global joystic instance
 | ||||
| extern evaluatedJoystick joystick; | ||||
| 
 | ||||
| //create global evaluated switch instance for button next to joystick
 | ||||
| extern gpio_evaluatedSwitch buttonJoystick; | ||||
| 
 | ||||
| //create global buzzer object
 | ||||
| extern buzzer_t buzzer; | ||||
| 
 | ||||
| //create global control object
 | ||||
| extern controlledArmchair control; | ||||
| 
 | ||||
| //create global automatedArmchair object (for auto-mode)
 | ||||
| extern automatedArmchair armchair; | ||||
| 
 | ||||
| //create global httpJoystick object
 | ||||
| //extern httpJoystick httpJoystickMain;
 | ||||
| 
 | ||||
| //configuration for fans / cooling
 | ||||
| extern fan_config_t configCooling; | ||||
| 
 | ||||
| //create global objects for measuring speed
 | ||||
| extern speedSensor speedLeft; | ||||
| extern speedSensor speedRight; | ||||
| 
 | ||||
| //create global objects for controlling the chair position
 | ||||
| extern cControlledRest legRest; | ||||
| extern cControlledRest backRest; | ||||
| 
 | ||||
| //
 | ||||
| ////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
 | ||||
| //
 | ||||
| //
 | ||||
| ////TODO outsource global variables to e.g. global.cpp and only config options here?
 | ||||
| //
 | ||||
| ////create global controlledMotor instances for both motors
 | ||||
| //extern controlledMotor motorLeft;
 | ||||
| //extern controlledMotor motorRight;
 | ||||
| //
 | ||||
| ////create global joystic instance
 | ||||
| //extern evaluatedJoystick joystick;
 | ||||
| //
 | ||||
| ////create global evaluated switch instance for button next to joystick
 | ||||
| //extern gpio_evaluatedSwitch buttonJoystick;
 | ||||
| //
 | ||||
| ////create global buzzer object
 | ||||
| //extern buzzer_t buzzer;
 | ||||
| //
 | ||||
| ////create global control object
 | ||||
| //extern controlledArmchair control;
 | ||||
| //
 | ||||
| ////create global automatedArmchair object (for auto-mode)
 | ||||
| //extern automatedArmchair_c armchair;
 | ||||
| //
 | ||||
| ////create global httpJoystick object
 | ||||
| ////extern httpJoystick httpJoystickMain;
 | ||||
| //
 | ||||
| ////configuration for fans / cooling
 | ||||
| //extern fan_config_t configCooling;
 | ||||
| //
 | ||||
| ////create global objects for measuring speed
 | ||||
| //extern speedSensor speedLeft;
 | ||||
| //extern speedSensor speedRight;
 | ||||
| //
 | ||||
| ////create global objects for controlling the chair position
 | ||||
| //extern cControlledRest legRest;
 | ||||
| //extern cControlledRest backRest;
 | ||||
| //
 | ||||
| //
 | ||||
| @ -26,14 +26,17 @@ const char* controlModeStr[9] = {"IDLE", "JOYSTICK", "MASSAGE", "HTTP", "MQTT", | ||||
| //-----------------------------
 | ||||
| //-------- constructor --------
 | ||||
| //-----------------------------
 | ||||
| controlledArmchair::controlledArmchair ( | ||||
|         control_config_t config_f, | ||||
|         buzzer_t * buzzer_f, | ||||
|         controlledMotor* motorLeft_f, | ||||
|         controlledMotor* motorRight_f, | ||||
|         evaluatedJoystick* joystick_f, | ||||
|         httpJoystick* httpJoystick_f | ||||
|         ){ | ||||
| controlledArmchair::controlledArmchair( | ||||
|     control_config_t config_f, | ||||
|     buzzer_t *buzzer_f, | ||||
|     controlledMotor *motorLeft_f, | ||||
|     controlledMotor *motorRight_f, | ||||
|     evaluatedJoystick *joystick_f, | ||||
|     httpJoystick *httpJoystick_f, | ||||
|     automatedArmchair_c *automatedArmchair_f, | ||||
|     cControlledRest *legRest_f, | ||||
|     cControlledRest *backRest_f) | ||||
| { | ||||
| 
 | ||||
|     //copy configuration
 | ||||
|     config = config_f; | ||||
| @ -43,13 +46,28 @@ controlledArmchair::controlledArmchair ( | ||||
|     motorRight = motorRight_f; | ||||
|     joystick_l = joystick_f, | ||||
|     httpJoystickMain_l = httpJoystick_f; | ||||
|     automatedArmchair = automatedArmchair_f; | ||||
|     legRest = legRest_f; | ||||
|     backRest = backRest_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)?
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| //=======================================
 | ||||
| //============ control task =============
 | ||||
| //=======================================
 | ||||
| //task that controls the armchair modes and initiates commands generation and applies them to driver
 | ||||
| //parameter: pointer to controlledArmchair object 
 | ||||
| void task_control( void * pvParameters ){ | ||||
|     //control_task_parameters_t * objects = (control_task_parameters_t *)pvParameters;
 | ||||
|     controlledArmchair * control = (controlledArmchair *)pvParameters; | ||||
|     ESP_LOGI(TAG, "Initializing controlledArmchair and starting handle loop"); | ||||
|     //start handle loop (control object declared in config.hpp)
 | ||||
|     //objects->control->startHandleLoop();
 | ||||
|     control->startHandleLoop(); | ||||
| } | ||||
| 
 | ||||
| //----------------------------------
 | ||||
| //---------- Handle loop -----------
 | ||||
| @ -70,7 +88,7 @@ void controlledArmchair::startHandleLoop() { | ||||
|                 commands = cmds_bothMotorsIdle; | ||||
|                 motorRight->setTarget(commands.right.state, commands.right.duty);  | ||||
|                 motorLeft->setTarget(commands.left.state, commands.left.duty);  | ||||
|                 vTaskDelay(200 / portTICK_PERIOD_MS); | ||||
|                 vTaskDelay(300 / portTICK_PERIOD_MS); | ||||
| #ifdef JOYSTICK_LOG_IN_IDLE | ||||
| 				//get joystick data here (without using it)
 | ||||
| 				//since loglevel is DEBUG, calculateion details is output
 | ||||
| @ -132,7 +150,7 @@ void controlledArmchair::startHandleLoop() { | ||||
|             case controlMode_t::AUTO: | ||||
|                 vTaskDelay(20 / portTICK_PERIOD_MS); | ||||
|                //generate commands
 | ||||
|                commands = armchair.generateCommands(&instruction); | ||||
|                commands = automatedArmchair->generateCommands(&instruction); | ||||
|                 //--- apply commands to motors ---
 | ||||
|                 //TODO make motorctl.setTarget also accept motorcommand struct directly
 | ||||
|                motorRight->setTarget(commands.right.state, commands.right.duty);  | ||||
| @ -179,7 +197,7 @@ void controlledArmchair::startHandleLoop() { | ||||
|                 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); | ||||
|                 controlChairAdjustment(joystick_l->getData(), legRest, backRest); | ||||
|                 break; | ||||
| 
 | ||||
| 
 | ||||
| @ -359,21 +377,6 @@ void controlledArmchair::changeMode(controlMode_t modeNew) { | ||||
|             buzzer->beep(1,200,100); | ||||
| 			break; | ||||
| 
 | ||||
| 		case controlMode_t::HTTP: | ||||
| 			ESP_LOGW(TAG, "switching from http mode -> disabling http and wifi"); | ||||
| 			//stop http server
 | ||||
| 			ESP_LOGI(TAG, "disabling http server..."); | ||||
| 			http_stop_server(); | ||||
| 
 | ||||
| 			//FIXME: make wifi function work here - currently starting wifi at startup (see notes main.cpp)
 | ||||
|             //stop wifi
 | ||||
|             //TODO: decide whether ap or client is currently used - which has to be disabled?
 | ||||
|             //ESP_LOGI(TAG, "deinit wifi...");
 | ||||
|             //wifi_deinit_client();
 | ||||
|             //wifi_deinit_ap();
 | ||||
|             ESP_LOGI(TAG, "done stopping http mode"); | ||||
|             break; | ||||
| 
 | ||||
|         case controlMode_t::MASSAGE: | ||||
|             ESP_LOGW(TAG, "switching from MASSAGE mode -> restoring fading, reset frozen input"); | ||||
|             //TODO: fix issue when downfading was disabled before switching to massage mode - currently it gets enabled again here...
 | ||||
| @ -401,8 +404,8 @@ void controlledArmchair::changeMode(controlMode_t modeNew) { | ||||
|         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); | ||||
|             legRest->setState(REST_OFF); | ||||
|             backRest->setState(REST_OFF); | ||||
|             break; | ||||
| 
 | ||||
|     } | ||||
| @ -427,26 +430,6 @@ void controlledArmchair::changeMode(controlMode_t modeNew) { | ||||
|             buzzer->beep(4,200,100); | ||||
|             break; | ||||
| 
 | ||||
|         case controlMode_t::HTTP: | ||||
|             ESP_LOGW(TAG, "switching to http mode -> enabling http and wifi"); | ||||
|             //start wifi
 | ||||
|             //TODO: decide wether ap or client should be started
 | ||||
|             ESP_LOGI(TAG, "init wifi..."); | ||||
| 
 | ||||
|             //FIXME: make wifi function work here - currently starting wifi at startup (see notes main.cpp)
 | ||||
|             //wifi_init_client();
 | ||||
|             //wifi_init_ap();
 | ||||
| 
 | ||||
|             //wait for wifi
 | ||||
|             //ESP_LOGI(TAG, "waiting for wifi...");
 | ||||
|             //vTaskDelay(1000 / portTICK_PERIOD_MS);
 | ||||
| 
 | ||||
|             //start http server
 | ||||
|             ESP_LOGI(TAG, "init http server..."); | ||||
|             http_init_server(); | ||||
|             ESP_LOGI(TAG, "done initializing http mode"); | ||||
|             break; | ||||
| 
 | ||||
|         case controlMode_t::MASSAGE: | ||||
|             ESP_LOGW(TAG, "switching to MASSAGE mode -> reducing fading"); | ||||
|             uint32_t shake_msFadeAccel = 500; //TODO: move this to config
 | ||||
|  | ||||
| @ -5,6 +5,8 @@ | ||||
| #include "buzzer.hpp" | ||||
| #include "http.hpp" | ||||
| #include "auto.hpp" | ||||
| #include "speedsensor.hpp" | ||||
| #include "chairAdjust.hpp" | ||||
| 
 | ||||
| 
 | ||||
| //--------------------------------------------
 | ||||
| @ -25,6 +27,13 @@ typedef struct control_config_t { | ||||
| } control_config_t; | ||||
| 
 | ||||
| 
 | ||||
| //=======================================
 | ||||
| //============ control task =============
 | ||||
| //=======================================
 | ||||
| //task that controls the armchair modes and initiates commands generation and applies them to driver
 | ||||
| //parameter: pointer to controlledArmchair object 
 | ||||
| void task_control( void * pvParameters ); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //==================================
 | ||||
| @ -41,7 +50,10 @@ class controlledArmchair { | ||||
|                 controlledMotor* motorLeft_f, | ||||
|                 controlledMotor* motorRight_f, | ||||
|                 evaluatedJoystick* joystick_f, | ||||
|                 httpJoystick* httpJoystick_f | ||||
|                 httpJoystick* httpJoystick_f, | ||||
|                 automatedArmchair_c* automatedArmchair, | ||||
|                 cControlledRest * legRest, | ||||
|                 cControlledRest * backRest | ||||
|                 ); | ||||
| 
 | ||||
|         //--- functions ---
 | ||||
| @ -85,6 +97,9 @@ class controlledArmchair { | ||||
|         controlledMotor* motorRight; | ||||
|         httpJoystick* httpJoystickMain_l; | ||||
|         evaluatedJoystick* joystick_l; | ||||
|         automatedArmchair_c *automatedArmchair; | ||||
|         cControlledRest * legRest; | ||||
|         cControlledRest * backRest; | ||||
| 
 | ||||
|         //---variables ---
 | ||||
|         //struct for motor commands returned by generate functions of each mode
 | ||||
| @ -103,7 +118,7 @@ class controlledArmchair { | ||||
|         bool freezeInput = false; | ||||
| 
 | ||||
|         //variables for AUTO mode
 | ||||
|         auto_instruction_t instruction = auto_instruction_t::NONE; //variable to receive instructions from automatedArmchair
 | ||||
|         auto_instruction_t instruction = auto_instruction_t::NONE; //variable to receive instructions from automatedArmchair_c
 | ||||
|          | ||||
|         //variable to store button event
 | ||||
|         uint8_t buttonCount = 0; | ||||
|  | ||||
| @ -204,7 +204,7 @@ float getBatteryPercent(){ | ||||
| //-----------------------
 | ||||
| //shows overview on entire display:
 | ||||
| //percentage, voltage, current, mode, rpm, speed
 | ||||
| void showScreen1() | ||||
| void showScreen1(display_task_parameters_t * objects) | ||||
| { | ||||
| 	//-- battery percentage --
 | ||||
| 	// TODO update when no load (currentsensors = ~0A) only
 | ||||
| @ -214,24 +214,24 @@ void showScreen1() | ||||
| 	//-- voltage and current --
 | ||||
| 	displayTextLine(&dev, 3, false, false, "%04.1fV %04.1f:%04.1fA", | ||||
| 				   getBatteryVoltage(), | ||||
| 				   fabs(motorLeft.getCurrentA()), | ||||
| 				   fabs(motorRight.getCurrentA())); | ||||
| 				   fabs(objects->motorLeft->getCurrentA()), | ||||
| 				   fabs(objects->motorRight->getCurrentA())); | ||||
| 
 | ||||
| 	//-- control state --
 | ||||
| 	//print large line
 | ||||
| 	displayTextLine(&dev, 4, true, false, "%s ", control.getCurrentModeStr()); | ||||
| 	displayTextLine(&dev, 4, true, false, "%s ", objects->control->getCurrentModeStr()); | ||||
| 
 | ||||
| 	//-- speed and RPM --
 | ||||
| 	displayTextLine(&dev, 7, false, false, "%3.1fkm/h %03.0f:%03.0fR", | ||||
| 				   fabs((speedLeft.getKmph() + speedRight.getKmph()) / 2), | ||||
| 				   speedLeft.getRpm(), | ||||
| 				   speedRight.getRpm()); | ||||
| 				   fabs((objects->speedLeft->getKmph() + objects->speedRight->getKmph()) / 2), | ||||
| 				   objects->speedLeft->getRpm(), | ||||
| 				   objects->speedRight->getRpm()); | ||||
| 
 | ||||
| 	// debug speed sensors
 | ||||
| 	ESP_LOGD(TAG, "%3.1fkm/h %03.0f:%03.0fR", | ||||
| 				   fabs((speedLeft.getKmph() + speedRight.getKmph()) / 2), | ||||
| 				   speedLeft.getRpm(), | ||||
| 				   speedRight.getRpm()); | ||||
| 				   fabs((objects->speedLeft->getKmph() + objects->speedRight->getKmph()) / 2), | ||||
| 				   objects->speedLeft->getRpm(), | ||||
| 				   objects->speedRight->getRpm()); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @ -264,6 +264,9 @@ void showStartupMsg(){ | ||||
| 
 | ||||
| void display_task(void *pvParameters) | ||||
| { | ||||
| 	//get struct with pointers to all needed global objects from task parameter
 | ||||
| 	display_task_parameters_t *objects = (display_task_parameters_t *)pvParameters; | ||||
| 
 | ||||
| 	// initialize display
 | ||||
| 	display_init(); | ||||
| 	// TODO check if successfully initialized
 | ||||
| @ -276,14 +279,14 @@ void display_task(void *pvParameters) | ||||
| 	// repeatedly update display with content
 | ||||
| 	while (1) | ||||
| 	{ | ||||
| 		if (control.getCurrentMode() == controlMode_t::MENU) | ||||
| 		if (objects->control->getCurrentMode() == controlMode_t::MENU) | ||||
| 		{ | ||||
| 			//uses encoder events to control menu and updates display
 | ||||
| 			handleMenu(&dev); | ||||
| 			handleMenu(objects, &dev); | ||||
| 		} | ||||
| 		else //show status screen in any other mode
 | ||||
| 		{ | ||||
| 			showScreen1(); | ||||
| 			showScreen1(objects); | ||||
| 			vTaskDelay(STATUS_SCREEN_UPDATE_INTERVAL / portTICK_PERIOD_MS); | ||||
| 		} | ||||
| 		// TODO add pages and menus
 | ||||
|  | ||||
| @ -13,7 +13,22 @@ extern "C" { | ||||
| #include "font8x8_basic.h" | ||||
| } | ||||
| 
 | ||||
| #include "config.hpp" | ||||
| 
 | ||||
| #include "joystick.hpp" | ||||
| #include "control.hpp" | ||||
| #include "speedsensor.hpp" | ||||
| 
 | ||||
| // struct with variables passed to task from main()
 | ||||
| typedef struct display_task_parameters_t { | ||||
|     controlledArmchair * control; | ||||
|     evaluatedJoystick * joystick; | ||||
|     QueueHandle_t encoderQueue; | ||||
|     controlledMotor * motorLeft; | ||||
|     controlledMotor * motorRight; | ||||
|     speedSensor * speedLeft; | ||||
|     speedSensor * speedRight; | ||||
|     buzzer_t *buzzer; | ||||
| } display_task_parameters_t; | ||||
| 
 | ||||
| 
 | ||||
| //task that inititialized the display, displays welcome message 
 | ||||
|  | ||||
| @ -39,11 +39,17 @@ rotary_encoder_t encoderConfig = { | ||||
| //==================================
 | ||||
| //========== encoder_init ==========
 | ||||
| //==================================
 | ||||
| //initialize encoder
 | ||||
| void encoder_init(){ | ||||
| 	encoderQueue = xQueueCreate(QUEUE_SIZE, sizeof(rotary_encoder_event_t)); | ||||
| //initialize encoder //TODO pass config to this function
 | ||||
| QueueHandle_t encoder_init() | ||||
| { | ||||
| 	QueueHandle_t encoderQueue = xQueueCreate(QUEUE_SIZE, sizeof(rotary_encoder_event_t)); | ||||
| 	rotary_encoder_init(encoderQueue); | ||||
| 	rotary_encoder_add(&encoderConfig); | ||||
| 	if (encoderQueue == NULL) | ||||
| 		ESP_LOGE(TAG, "Error initializing encoder or queue"); | ||||
| 	else | ||||
| 		ESP_LOGW(TAG, "Initialized encoder and encoderQueue"); | ||||
| 	return encoderQueue; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @ -52,7 +58,9 @@ void encoder_init(){ | ||||
| //====== task_encoderExample =======
 | ||||
| //==================================
 | ||||
| //receive and handle all available encoder events
 | ||||
| void task_encoderExample(void *arg) { | ||||
| void task_encoderExample(void * arg) { | ||||
| 	//get queue with encoder events from task parameter:
 | ||||
| 	QueueHandle_t encoderQueue = (QueueHandle_t)arg; | ||||
| 	static rotary_encoder_event_t ev; //store event data
 | ||||
| 	while (1) { | ||||
| 		if (xQueueReceive(encoderQueue, &ev, portMAX_DELAY)) { | ||||
|  | ||||
| @ -10,11 +10,11 @@ extern "C" { | ||||
| #define PIN_B GPIO_NUM_26 | ||||
| #define PIN_BUTTON GPIO_NUM_27 | ||||
| 
 | ||||
| //global encoder queue
 | ||||
| extern QueueHandle_t encoderQueue; | ||||
| 
 | ||||
| //init encoder with config in encoder.cpp
 | ||||
| void encoder_init(); | ||||
| QueueHandle_t encoder_init(); //TODO pass config to function
 | ||||
| 
 | ||||
| 
 | ||||
| //task that handles encoder events
 | ||||
| void task_encoderExample(void *arg); | ||||
| //note: queue obtained from encoder_init() has to be passed to that task
 | ||||
| void task_encoderExample(void *encoderQueue); | ||||
| //example: xTaskCreate(&task_encoderExample, "task_buzzer", 2048, encoderQueue, 2, NULL);
 | ||||
| @ -1,6 +1,3 @@ | ||||
| #include "hal/uart_types.h" | ||||
| #include "motordrivers.hpp" | ||||
| #include "types.hpp" | ||||
| extern "C" | ||||
| { | ||||
| #include <stdio.h> | ||||
| @ -14,44 +11,88 @@ extern "C" | ||||
| #include "sdkconfig.h" | ||||
| #include "esp_spiffs.h"     | ||||
| 
 | ||||
| #include "driver/ledc.h" | ||||
| 
 | ||||
| //custom C files
 | ||||
| #include "wifi.h" | ||||
| } | ||||
| 
 | ||||
| //custom C++ files
 | ||||
| //folder common
 | ||||
| #include "uart_common.hpp" | ||||
| #include "motordrivers.hpp" | ||||
| #include "http.hpp" | ||||
| #include "types.hpp" | ||||
| #include "speedsensor.hpp" | ||||
| #include "motorctl.hpp" | ||||
| 
 | ||||
| //folder single_board
 | ||||
| #include "config.hpp" | ||||
| #include "control.hpp"  | ||||
| #include "button.hpp" | ||||
| #include "http.hpp" | ||||
| 
 | ||||
| #include "uart_common.hpp" | ||||
| 
 | ||||
| #include "display.hpp" | ||||
| #include "encoder.hpp" | ||||
| 
 | ||||
| 
 | ||||
| //only extends this file (no library):
 | ||||
| //outsourced all configuration related structures
 | ||||
| #include "config.cpp" | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //================================
 | ||||
| //======== declarations ==========
 | ||||
| //================================
 | ||||
| //--- declare all pointers to shared objects ---
 | ||||
| controlledMotor *motorLeft; | ||||
| controlledMotor *motorRight; | ||||
| 
 | ||||
| sabertooth2x60a *sabertoothDriver; | ||||
| 
 | ||||
| evaluatedJoystick *joystick; | ||||
| 
 | ||||
| buzzer_t *buzzer; | ||||
| 
 | ||||
| controlledArmchair *control; | ||||
| 
 | ||||
| automatedArmchair_c *automatedArmchair; | ||||
| 
 | ||||
| httpJoystick *httpJoystickMain; | ||||
| 
 | ||||
| speedSensor *speedLeft; | ||||
| speedSensor *speedRight; | ||||
| 
 | ||||
| cControlledRest *legRest; | ||||
| cControlledRest *backRest; | ||||
| 
 | ||||
| 
 | ||||
| //--- lambda functions motor-driver ---
 | ||||
| // functions for updating the duty via currently used motor driver (hardware) that can then be passed to controlledMotor
 | ||||
| //-> makes it possible to easily use different motor drivers
 | ||||
| motorSetCommandFunc_t setLeftFunc = [&sabertoothDriver](motorCommand_t cmd) | ||||
| { | ||||
|     sabertoothDriver->setLeft(cmd); | ||||
| }; | ||||
| motorSetCommandFunc_t setRightFunc = [&sabertoothDriver](motorCommand_t cmd) | ||||
| { | ||||
|     sabertoothDriver->setRight(cmd); | ||||
| }; | ||||
| 
 | ||||
| //--- lambda function http-joystick ---
 | ||||
| // function that initializes the http server requires a function pointer to function that handels each url
 | ||||
| // the httpd_uri config struct does not accept a pointer to a method of a class instance, directly
 | ||||
| // thus this lambda function is necessary:
 | ||||
| // 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); | ||||
| } | ||||
| 
 | ||||
| //tag for logging
 | ||||
| static const char * TAG = "main"; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //====================================
 | ||||
| //========== motorctl task ===========
 | ||||
| //====================================
 | ||||
| //task for handling the motors (ramp, current limit, driver)
 | ||||
| void task_motorctl( void * pvParameters ){ | ||||
|     ESP_LOGI(TAG, "starting handle loop..."); | ||||
|     while(1){ | ||||
|         motorRight.handle(); | ||||
|         motorLeft.handle(); | ||||
|         //10khz -> T=100us
 | ||||
|         vTaskDelay(10 / portTICK_PERIOD_MS); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //======================================
 | ||||
| //============ buzzer task =============
 | ||||
| //======================================
 | ||||
| @ -61,33 +102,7 @@ void task_buzzer( void * pvParameters ){ | ||||
|     ESP_LOGI("task_buzzer", "Start of buzzer task..."); | ||||
|         //run function that waits for a beep events to arrive in the queue
 | ||||
|         //and processes them
 | ||||
|         buzzer.processQueue(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //=======================================
 | ||||
| //============ control task =============
 | ||||
| //=======================================
 | ||||
| //task that controls the armchair modes and initiates commands generation and applies them to driver
 | ||||
| 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 =============
 | ||||
| //======================================
 | ||||
| //task that handles the button interface/commands
 | ||||
| void task_button( void * pvParameters ){ | ||||
|     ESP_LOGI(TAG, "Initializing command-button and starting handle loop"); | ||||
|     //create button instance
 | ||||
|     buttonCommands commandButton(&buttonJoystick, &joystick, &control, &buzzer, &motorLeft, &motorRight); | ||||
|     //start handle loop
 | ||||
|     commandButton.startHandleLoop(); | ||||
|         buzzer->processQueue(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @ -95,11 +110,12 @@ void task_button( void * pvParameters ){ | ||||
| //=======================================
 | ||||
| //============== fan task ===============
 | ||||
| //=======================================
 | ||||
| //TODO: move this definition to fan.cpp
 | ||||
| //task that controlls fans for cooling the drivers
 | ||||
| void task_fans( void * pvParameters ){ | ||||
|     ESP_LOGI(TAG, "Initializing fans and starting fan handle loop"); | ||||
|     //create fan instances with config defined in config.cpp
 | ||||
|     controlledFan fan(configCooling, &motorLeft, &motorRight); | ||||
|     controlledFan fan(configCooling, motorLeft, motorRight); | ||||
|     //repeatedly run fan handle function in a slow loop
 | ||||
|     while(1){ | ||||
|         fan.handle(); | ||||
| @ -132,31 +148,54 @@ void init_spiffs(){ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //==================================
 | ||||
| //======== define loglevels ========
 | ||||
| //==================================
 | ||||
| void setLoglevels(void){ | ||||
|     //set loglevel for all tags:
 | ||||
|     esp_log_level_set("*", ESP_LOG_WARN); | ||||
| 
 | ||||
|     //--- set loglevel for individual tags ---
 | ||||
|     esp_log_level_set("main", ESP_LOG_INFO); | ||||
|     esp_log_level_set("buzzer", ESP_LOG_ERROR); | ||||
|     //esp_log_level_set("motordriver", ESP_LOG_DEBUG);
 | ||||
|     //esp_log_level_set("motor-control", ESP_LOG_INFO);
 | ||||
| 	//esp_log_level_set("evaluatedJoystick", ESP_LOG_DEBUG);
 | ||||
|     //esp_log_level_set("joystickCommands", ESP_LOG_DEBUG);
 | ||||
|     esp_log_level_set("button", ESP_LOG_INFO); | ||||
|     esp_log_level_set("control", ESP_LOG_INFO); | ||||
|     //esp_log_level_set("fan-control", ESP_LOG_INFO);
 | ||||
|     esp_log_level_set("wifi", ESP_LOG_INFO); | ||||
|     esp_log_level_set("http", ESP_LOG_INFO); | ||||
|     //esp_log_level_set("automatedArmchair", ESP_LOG_DEBUG);
 | ||||
|     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); | ||||
|     esp_log_level_set("menu", ESP_LOG_INFO); | ||||
| 
 | ||||
| //=================================
 | ||||
| //========= createObjects =========
 | ||||
| //=================================
 | ||||
| //create all shared objects
 | ||||
| //their references can be passed to the tasks that need access in main
 | ||||
| 
 | ||||
| //Note: the configuration structures (e.g. configMotorControlLeft) are outsourced to file 'config.cpp'
 | ||||
| 
 | ||||
| void createObjects() | ||||
| { | ||||
|     // create sabertooth motor driver instance
 | ||||
|     // sabertooth2x60a sabertoothDriver(sabertoothConfig);
 | ||||
|     // with configuration above
 | ||||
|     sabertoothDriver = new sabertooth2x60a(sabertoothConfig); | ||||
| 
 | ||||
|     // create controlled motor instances (motorctl.hpp)
 | ||||
|     // with configurations above
 | ||||
|     motorLeft = new controlledMotor(setLeftFunc, configMotorControlLeft); | ||||
|     motorRight = new controlledMotor(setRightFunc, configMotorControlRight); | ||||
| 
 | ||||
|     // create speedsensor instances
 | ||||
|     // with configurations above
 | ||||
|     speedLeft = new speedSensor(speedLeft_config); | ||||
|     speedRight = new speedSensor(speedRight_config); | ||||
| 
 | ||||
|     // create joystic instance (joystick.hpp)
 | ||||
|     joystick = new evaluatedJoystick(configJoystick); | ||||
| 
 | ||||
|     // create httpJoystick object (http.hpp)
 | ||||
|     httpJoystickMain = new httpJoystick(configHttpJoystickMain); | ||||
|     http_init_server(on_joystick_url); | ||||
| 
 | ||||
|     // create buzzer object on pin 12 with gap between queued events of 100ms
 | ||||
|     buzzer = new buzzer_t(GPIO_NUM_12, 100); | ||||
| 
 | ||||
|     // create control object (control.hpp)
 | ||||
|     // with configuration above
 | ||||
|     control = new controlledArmchair(configControl, buzzer, motorLeft, motorRight, joystick, httpJoystickMain, automatedArmchair, legRest, backRest); | ||||
| 
 | ||||
|     // create automatedArmchair_c object (for auto-mode) (auto.hpp)
 | ||||
|     automatedArmchair = new automatedArmchair_c(motorLeft, motorRight); | ||||
| 
 | ||||
|     // create objects for controlling the chair position
 | ||||
|     //                       gpio_up, gpio_down, name
 | ||||
|     legRest = new cControlledRest(GPIO_NUM_4, GPIO_NUM_16, "legRest"); | ||||
|     backRest = new cControlledRest(GPIO_NUM_2, GPIO_NUM_15, "backRest"); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @ -166,25 +205,53 @@ void setLoglevels(void){ | ||||
| //=========== app_main ============
 | ||||
| //=================================
 | ||||
| extern "C" void app_main(void) { | ||||
| 	//enable 5V volate regulator
 | ||||
| 
 | ||||
| 	ESP_LOGW(TAG, "===== INITIALIZING COMPONENTS ====="); | ||||
| 	//--- define log levels ---
 | ||||
| 	setLoglevels(); | ||||
| 
 | ||||
| 	//--- enable 5V volate regulator ---
 | ||||
| 	ESP_LOGW(TAG, "enabling 5V regulator..."); | ||||
| 	gpio_pad_select_gpio(GPIO_NUM_17);                                                   | ||||
| 	gpio_set_direction(GPIO_NUM_17, GPIO_MODE_OUTPUT); | ||||
| 	gpio_set_level(GPIO_NUM_17, 1);                                                       | ||||
| 
 | ||||
| 	//---- define log levels ----
 | ||||
| 	setLoglevels(); | ||||
| 	//--- initialize nvs-flash and netif (needed for wifi) ---
 | ||||
| 	wifi_initNvs_initNetif(); | ||||
| 
 | ||||
| 	//--- initialize spiffs ---
 | ||||
| 	init_spiffs(); | ||||
| 
 | ||||
| 	//--- initialize and start wifi ---
 | ||||
| 	ESP_LOGD(TAG,"starting wifi..."); | ||||
| 	//wifi_init_client(); //connect to existing wifi
 | ||||
| 	wifi_init_ap(); //start access point
 | ||||
| 	ESP_LOGD(TAG,"done starting wifi"); | ||||
| 
 | ||||
| 	// init encoder
 | ||||
| 	//--- initialize encoder ---
 | ||||
| 	encoder_init(); | ||||
| 	// now global encoderQueue providing all encoder events is available
 | ||||
| 	const QueueHandle_t encoderQueue = encoder_init(); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 	//--- create all objects ---
 | ||||
| 	ESP_LOGW(TAG, "===== CREATING SHARED OBJECTS ====="); | ||||
| 
 | ||||
| 	//create all class instances used below
 | ||||
| 	//see 'createObjects.hpp'
 | ||||
| 	createObjects(); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #ifndef ENCODER_TEST | ||||
| 	//--- create tasks ---
 | ||||
| 	ESP_LOGW(TAG, "===== CREATING TASKS ====="); | ||||
| 
 | ||||
| 	//----------------------------------------------
 | ||||
| 	//--- create task for controlling the motors ---
 | ||||
| 	//----------------------------------------------
 | ||||
| 	//task that receives commands, handles ramp and current limit and executes commands using the motordriver function
 | ||||
| 	xTaskCreate(&task_motorctl, "task_motor-control", 2*4096, NULL, 6, NULL); | ||||
| 	task_motorctl_parameters_t motorctl_param = {motorLeft, motorRight}; | ||||
| 	xTaskCreate(&task_motorctl, "task_motor-control", 2*4096, &motorctl_param, 6, NULL); | ||||
| 
 | ||||
| 	//------------------------------
 | ||||
| 	//--- create task for buzzer ---
 | ||||
| @ -195,46 +262,38 @@ 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
 | ||||
| 	xTaskCreate(&task_control, "task_control", 4096, NULL, 5, NULL); | ||||
| 	//note: pointer to shared object 'control' is passed as task parameter:
 | ||||
| 	xTaskCreate(&task_control, "task_control", 4096, control, 5, NULL); | ||||
| 
 | ||||
| 	//------------------------------
 | ||||
| 	//--- create task for button ---
 | ||||
| 	//------------------------------
 | ||||
| 	//task that evaluates and processes the button input and runs the configured commands
 | ||||
| 	xTaskCreate(&task_button, "task_button", 4096, NULL, 4, NULL); | ||||
| 	//task that handles button/encoder events in any mode except 'MENU' (e.g. switch modes by pressing certain count)
 | ||||
| 	task_button_parameters_t button_param = {control, joystick, encoderQueue, motorLeft, motorRight, buzzer}; | ||||
| 	xTaskCreate(&task_button, "task_button", 4096, &button_param, 4, NULL); | ||||
| 
 | ||||
| 	//-----------------------------------
 | ||||
| 	//--- create task for fan control ---
 | ||||
| 	//-----------------------------------
 | ||||
| 	//task that evaluates and processes the button input and runs the configured commands
 | ||||
| 	//task that controls cooling fans of the motor driver
 | ||||
| 	xTaskCreate(&task_fans, "task_fans", 2048, NULL, 1, NULL); | ||||
| 
 | ||||
| 
 | ||||
| 	//-----------------------------------
 | ||||
| 	//----- create task for display -----
 | ||||
| 	//-----------------------------------
 | ||||
| 	//task that handles the display
 | ||||
| 	xTaskCreate(&display_task, "display_task", 3*2048, NULL, 1, NULL); | ||||
| 	////task that handles the display (show stats, handle menu in 'MENU' mode)
 | ||||
| 	display_task_parameters_t display_param = {control, joystick, encoderQueue, motorLeft, motorRight, speedLeft, speedRight, buzzer}; | ||||
| 	xTaskCreate(&display_task, "display_task", 3*2048, &display_param, 1, NULL); | ||||
| 
 | ||||
| 
 | ||||
| 	//beep at startup
 | ||||
| 	buzzer.beep(3, 70, 50); | ||||
| #endif | ||||
| 
 | ||||
| 	//--- initialize nvs-flash and netif (needed for wifi) ---
 | ||||
| 	wifi_initNvs_initNetif(); | ||||
| 
 | ||||
| 	//--- initialize spiffs ---
 | ||||
| 	init_spiffs(); | ||||
| 
 | ||||
| 	//--- initialize and start wifi ---
 | ||||
| 	//FIXME: run wifi_init_client or wifi_init_ap as intended from control.cpp when switching state 
 | ||||
| 	//currently commented out because of error "assert failed: xQueueSemaphoreTake queue.c:1549 (pxQueue->uxItemSize == 0)" when calling control->changeMode from button.cpp
 | ||||
| 	//when calling control.changeMode(http) from main.cpp it worked without error for some reason?
 | ||||
| 	ESP_LOGI(TAG,"starting wifi..."); | ||||
| 	//wifi_init_client(); //connect to existing wifi
 | ||||
| 	wifi_init_ap(); //start access point
 | ||||
| 	ESP_LOGI(TAG,"done starting wifi"); | ||||
| 	//--- startup finished ---
 | ||||
| 	ESP_LOGW(TAG, "===== STARTUP FINISHED ====="); | ||||
| 	buzzer->beep(3, 70, 50); | ||||
| 
 | ||||
| 	//--- testing encoder ---
 | ||||
| 	//xTaskCreate(&task_encoderExample, "task_buzzer", 2048, encoderQueue, 2, NULL);
 | ||||
| 
 | ||||
| 	//--- testing http server ---
 | ||||
| 	//    wifi_init_client(); //connect to existing wifi
 | ||||
| @ -243,8 +302,8 @@ extern "C" void app_main(void) { | ||||
| 	//    http_init_server();
 | ||||
| 
 | ||||
| 
 | ||||
| 	//--- testing force http mode after startup ---
 | ||||
| 	//control.changeMode(controlMode_t::HTTP);
 | ||||
| 	//--- testing force specific mode after startup ---
 | ||||
| 	//control->changeMode(controlMode_t::MENU);
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -30,12 +30,14 @@ static int value = 0; | ||||
| //#########################
 | ||||
| //#### center Joystick ####
 | ||||
| //#########################
 | ||||
| void item_centerJoystick_action(int value, SSD1306_t * display){ | ||||
| void item_centerJoystick_action(display_task_parameters_t * objects, SSD1306_t * display, int value){ | ||||
|     if (!value) return; | ||||
|     ESP_LOGW(TAG, "defining joystick center"); | ||||
|     joystick.defineCenter(); | ||||
|     (*objects).joystick->defineCenter(); | ||||
|     //objects->joystick->defineCenter();
 | ||||
|     //joystick->defineCenter();
 | ||||
| } | ||||
| int item_centerJoystick_value(){ | ||||
| int item_centerJoystick_value(display_task_parameters_t * objects){ | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| @ -59,7 +61,7 @@ menuItem_t item_centerJoystick = { | ||||
| //#### debug Joystick ####
 | ||||
| //########################
 | ||||
| //continously show/update joystick data on display
 | ||||
| void item_debugJoystick_action(int value, SSD1306_t * display) | ||||
| void item_debugJoystick_action(display_task_parameters_t * objects, SSD1306_t * display, int value) | ||||
| { | ||||
|     //--- variables ---
 | ||||
|     bool running = true; | ||||
| @ -77,10 +79,10 @@ void item_debugJoystick_action(int value, SSD1306_t * display) | ||||
| 
 | ||||
|     //-- show/update values --
 | ||||
|     // stop when button pressed or control state changes (timeouts to IDLE)
 | ||||
|     while (running && control.getCurrentMode() == controlMode_t::MENU) | ||||
|     while (running && objects->control->getCurrentMode() == controlMode_t::MENU) | ||||
|     { | ||||
|         // repeatedly print all joystick data
 | ||||
|         joystickData_t data = joystick.getData(); | ||||
|         joystickData_t data = objects->joystick->getData(); | ||||
|         displayTextLine(display, 1, false, false, "x = %.3f     ", data.x); | ||||
|         displayTextLine(display, 2, false, false, "y = %.3f     ", data.y); | ||||
|         displayTextLine(display, 3, false, false, "radius = %.3f", data.radius); | ||||
| @ -88,7 +90,7 @@ void item_debugJoystick_action(int value, SSD1306_t * display) | ||||
|         displayTextLine(display, 5, false, false, "pos=%-12s ", joystickPosStr[(int)data.position]); | ||||
| 
 | ||||
|         // exit when button pressed
 | ||||
|         if (xQueueReceive(encoderQueue, &event, 20 / portTICK_PERIOD_MS)) | ||||
|         if (xQueueReceive(objects->encoderQueue, &event, 20 / portTICK_PERIOD_MS)) | ||||
|         { | ||||
|             switch (event.type) | ||||
|             { | ||||
| @ -105,7 +107,7 @@ void item_debugJoystick_action(int value, SSD1306_t * display) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int item_debugJoystick_value(){ | ||||
| int item_debugJoystick_value(display_task_parameters_t * objects){ | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| @ -128,12 +130,12 @@ menuItem_t item_debugJoystick = { | ||||
| //########################
 | ||||
| //##### set max duty #####
 | ||||
| //########################
 | ||||
| void maxDuty_action(int value, SSD1306_t * display) | ||||
| void maxDuty_action(display_task_parameters_t * objects, SSD1306_t * display, int value) | ||||
| { | ||||
|     //TODO actually store the value
 | ||||
|     ESP_LOGW(TAG, "set max duty to %d", value); | ||||
| } | ||||
| int maxDuty_currentValue() | ||||
| int maxDuty_currentValue(display_task_parameters_t * objects) | ||||
| { | ||||
|     //TODO get real current value
 | ||||
|     return 84; | ||||
| @ -156,14 +158,14 @@ menuItem_t item_maxDuty = { | ||||
| //######################
 | ||||
| //##### accelLimit #####
 | ||||
| //######################
 | ||||
| void item_accelLimit_action(int value, SSD1306_t * display) | ||||
| void item_accelLimit_action(display_task_parameters_t * objects, SSD1306_t * display, int value) | ||||
| { | ||||
|     motorLeft.setFade(fadeType_t::ACCEL, (uint32_t)value); | ||||
|     motorRight.setFade(fadeType_t::ACCEL, (uint32_t)value); | ||||
|     objects->motorLeft->setFade(fadeType_t::ACCEL, (uint32_t)value); | ||||
|     objects->motorRight->setFade(fadeType_t::ACCEL, (uint32_t)value); | ||||
| } | ||||
| int item_accelLimit_value() | ||||
| int item_accelLimit_value(display_task_parameters_t * objects) | ||||
| { | ||||
|     return motorLeft.getFade(fadeType_t::ACCEL); | ||||
|     return objects->motorLeft->getFade(fadeType_t::ACCEL); | ||||
| } | ||||
| menuItem_t item_accelLimit = { | ||||
|     item_accelLimit_action, // function action
 | ||||
| @ -183,14 +185,14 @@ menuItem_t item_accelLimit = { | ||||
| // ######################
 | ||||
| // ##### decelLimit #####
 | ||||
| // ######################
 | ||||
| void item_decelLimit_action(int value, SSD1306_t * display) | ||||
| void item_decelLimit_action(display_task_parameters_t * objects, SSD1306_t * display, int value) | ||||
| { | ||||
|     motorLeft.setFade(fadeType_t::DECEL, (uint32_t)value); | ||||
|     motorRight.setFade(fadeType_t::DECEL, (uint32_t)value); | ||||
|     objects->motorLeft->setFade(fadeType_t::DECEL, (uint32_t)value); | ||||
|     objects->motorRight->setFade(fadeType_t::DECEL, (uint32_t)value); | ||||
| } | ||||
| int item_decelLimit_value() | ||||
| int item_decelLimit_value(display_task_parameters_t * objects) | ||||
| { | ||||
|     return motorLeft.getFade(fadeType_t::DECEL); | ||||
|     return objects->motorLeft->getFade(fadeType_t::DECEL); | ||||
| } | ||||
| menuItem_t item_decelLimit = { | ||||
|     item_decelLimit_action, // function action
 | ||||
| @ -210,11 +212,11 @@ menuItem_t item_decelLimit = { | ||||
| //#####################
 | ||||
| //###### example ######
 | ||||
| //#####################
 | ||||
| void item_example_action(int value, SSD1306_t * display) | ||||
| void item_example_action(display_task_parameters_t * objects, SSD1306_t * display, int value) | ||||
| { | ||||
|     return; | ||||
| } | ||||
| int item_example_value(){ | ||||
| int item_example_value(display_task_parameters_t * objects){ | ||||
|     return 53; | ||||
| } | ||||
| menuItem_t item_example = { | ||||
| @ -342,7 +344,7 @@ void showValueSelect(SSD1306_t *display, int selectedItem) | ||||
| //function is repeatedly called by display task when in menu state
 | ||||
| #define QUEUE_TIMEOUT 3000 //timeout no encoder event - to handle timeout and not block the display loop
 | ||||
| #define MENU_TIMEOUT 60000 //inactivity timeout (switch to IDLE mode)
 | ||||
| void handleMenu(SSD1306_t *display) | ||||
| void handleMenu(display_task_parameters_t * objects, SSD1306_t *display) | ||||
| { | ||||
|     static uint32_t lastActivity = 0; | ||||
|     static int selectedItem = 0; | ||||
| @ -358,7 +360,7 @@ void handleMenu(SSD1306_t *display) | ||||
|         // update display
 | ||||
|         showItemList(display, selectedItem); // shows list of items with currently selected one on display
 | ||||
|         // wait for encoder event
 | ||||
|         if (xQueueReceive(encoderQueue, &event, QUEUE_TIMEOUT / portTICK_PERIOD_MS)) | ||||
|         if (xQueueReceive(objects->encoderQueue, &event, QUEUE_TIMEOUT / portTICK_PERIOD_MS)) | ||||
|         { | ||||
|             lastActivity = esp_log_timestamp(); | ||||
|             switch (event.type) | ||||
| @ -387,7 +389,7 @@ void handleMenu(SSD1306_t *display) | ||||
|                 // change state (menu to set value)
 | ||||
|                 menuState = SET_VALUE; | ||||
|                 // get currently configured value
 | ||||
|                 value = menuItems[selectedItem].currentValue(); | ||||
|                 value = menuItems[selectedItem].currentValue(objects); | ||||
|                 // clear display
 | ||||
|                 ssd1306_clear_screen(display, false); | ||||
|                 break; | ||||
| @ -395,7 +397,7 @@ void handleMenu(SSD1306_t *display) | ||||
|             //exit menu mode
 | ||||
|             case RE_ET_BTN_LONG_PRESSED: | ||||
|                 //change to previous mode (e.g. JOYSTICK)
 | ||||
|                 control.toggleMode(controlMode_t::MENU); //currently already in MENU -> changes to previous mode
 | ||||
|                 objects->control->toggleMode(controlMode_t::MENU); //currently already in MENU -> changes to previous mode
 | ||||
|                 ssd1306_clear_screen(display, false); | ||||
|                 break; | ||||
| 
 | ||||
| @ -413,7 +415,7 @@ void handleMenu(SSD1306_t *display) | ||||
|         // wait for encoder event
 | ||||
|         showValueSelect(display, selectedItem); | ||||
| 
 | ||||
|         if (xQueueReceive(encoderQueue, &event, QUEUE_TIMEOUT / portTICK_PERIOD_MS)) | ||||
|         if (xQueueReceive(objects->encoderQueue, &event, QUEUE_TIMEOUT / portTICK_PERIOD_MS)) | ||||
|         { | ||||
|             lastActivity = esp_log_timestamp(); | ||||
|             switch (event.type) | ||||
| @ -434,7 +436,7 @@ void handleMenu(SSD1306_t *display) | ||||
|             case RE_ET_BTN_CLICKED: | ||||
|                 //-- apply value --
 | ||||
|                 ESP_LOGI(TAG, "Button pressed - running action function with value=%d for item '%s'", value, menuItems[selectedItem].title); | ||||
|                 menuItems[selectedItem].action(value, display); | ||||
|                 menuItems[selectedItem].action(objects, display, value); | ||||
|                 menuState = MAIN_MENU; | ||||
|                 break; | ||||
|             case RE_ET_BTN_PRESSED: | ||||
| @ -459,7 +461,7 @@ void handleMenu(SSD1306_t *display) | ||||
|         menuState = MAIN_MENU; | ||||
|         ssd1306_clear_screen(display, false); | ||||
|         // change control mode
 | ||||
|         control.changeMode(controlMode_t::IDLE); | ||||
|         objects->control->changeMode(controlMode_t::IDLE); | ||||
|         return; | ||||
|     } | ||||
| } | ||||
| @ -13,9 +13,10 @@ typedef enum { | ||||
| 
 | ||||
| //--- menuItem_t ---
 | ||||
| // struct describes one menu element (all defined in menu.cpp)
 | ||||
| typedef struct { | ||||
|     void (*action)(int value, SSD1306_t * display);   // pointer to function run when confirmed
 | ||||
|     int (*currentValue)(); // pointer to function to get currently configured value
 | ||||
| typedef struct | ||||
| { | ||||
|     void (*action)(display_task_parameters_t * objects, SSD1306_t * display, int value);   // pointer to function run when confirmed
 | ||||
|     int (*currentValue)(display_task_parameters_t * objects); // pointer to function to get currently configured value
 | ||||
|     int valueMin;          // min allowed value
 | ||||
|     int valueMax;          // max allowed value
 | ||||
|     int valueIncrement;    // amount changed at one encoder tick (+/-)
 | ||||
| @ -28,5 +29,4 @@ typedef struct { | ||||
|     const char line7[17];  // below value
 | ||||
| } menuItem_t; | ||||
| 
 | ||||
| 
 | ||||
| void handleMenu(SSD1306_t * display); | ||||
| void handleMenu(display_task_parameters_t * objects, SSD1306_t *display); | ||||
| @ -140,10 +140,10 @@ CONFIG_I2C_INTERFACE=y | ||||
| # CONFIG_SPI_INTERFACE is not set | ||||
| # CONFIG_SSD1306_128x32 is not set | ||||
| CONFIG_SSD1306_128x64=y | ||||
| CONFIG_OFFSETX=0 | ||||
| CONFIG_OFFSETX=2 | ||||
| # CONFIG_FLIP is not set | ||||
| CONFIG_SCL_GPIO=22 | ||||
| CONFIG_SDA_GPIO=21 | ||||
| CONFIG_SDA_GPIO=23 | ||||
| CONFIG_RESET_GPIO=15 | ||||
| CONFIG_I2C_PORT_0=y | ||||
| # CONFIG_I2C_PORT_1 is not set | ||||
| @ -1246,6 +1246,17 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y | ||||
| # CONFIG_WPA_MBO_SUPPORT is not set | ||||
| # CONFIG_WPA_DPP_SUPPORT is not set | ||||
| # end of Supplicant | ||||
| 
 | ||||
| # | ||||
| # Rotary encoders | ||||
| # | ||||
| CONFIG_RE_MAX=1 | ||||
| CONFIG_RE_INTERVAL_US=1000 | ||||
| CONFIG_RE_BTN_DEAD_TIME_US=10000 | ||||
| CONFIG_RE_BTN_PRESSED_LEVEL_0=y | ||||
| # CONFIG_RE_BTN_PRESSED_LEVEL_1 is not set | ||||
| CONFIG_RE_BTN_LONG_PRESS_TIME_US=500000 | ||||
| # end of Rotary encoders | ||||
| # end of Component config | ||||
| 
 | ||||
| # | ||||
|  | ||||
| @ -201,27 +201,17 @@ joystickData_t httpJoystick::getData(){ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| //--------------------------------------------
 | ||||
| //--- 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); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //============================
 | ||||
| //===== init http server =====
 | ||||
| //============================
 | ||||
| //function that initializes http server and configures available urls
 | ||||
| void http_init_server() | ||||
| //function that initializes http server and configures available url's
 | ||||
| 
 | ||||
| //parameter: provide pointer to function that handle incomming joystick data (for configuring the url)
 | ||||
| //TODO add handle functions to future additional endpoints/urls here too
 | ||||
| void http_init_server(http_handler_t onJoystickUrl) | ||||
| { | ||||
|   ESP_LOGI(TAG, "initializing HTTP-Server..."); | ||||
| 
 | ||||
|   //---- configure webserver ----
 | ||||
|   httpd_config_t config = HTTPD_DEFAULT_CONFIG(); | ||||
| @ -236,7 +226,7 @@ void http_init_server() | ||||
|     httpd_uri_t joystick_url = { | ||||
|       .uri = "/api/joystick", | ||||
|       .method = HTTP_POST, | ||||
|       .handler = on_joystick_url, | ||||
|       .handler = onJoystickUrl, | ||||
|       }; | ||||
|   httpd_register_uri_handler(server, &joystick_url); | ||||
| 
 | ||||
| @ -265,8 +255,8 @@ void http_init_server() | ||||
| //function that destroys the http server
 | ||||
| void http_stop_server() | ||||
| { | ||||
|     printf("stopping http\n"); | ||||
|     httpd_stop(server); | ||||
|   ESP_LOGW(TAG, "stopping HTTP-Server"); | ||||
|   httpd_stop(server); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -13,7 +13,18 @@ extern "C" | ||||
| //===== init http server =====
 | ||||
| //============================
 | ||||
| //function that initializes http server and configures available urls
 | ||||
| void http_init_server(); | ||||
| //parameter: provide pointer to function that handles incomming joystick data (for configuring the url)
 | ||||
| //TODO add handle functions to future additional endpoints/urls here too
 | ||||
| typedef esp_err_t (*http_handler_t)(httpd_req_t *req); | ||||
| void http_init_server(http_handler_t onJoystickUrl); | ||||
| 
 | ||||
| //example with lambda function to pass method of a class instance:
 | ||||
| //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);
 | ||||
| //}
 | ||||
| //http_init_server(on_joystick_url);
 | ||||
| 
 | ||||
| 
 | ||||
| //==============================
 | ||||
| @ -27,7 +38,7 @@ void start_mdns_service(); | ||||
| //===== stop http server =====
 | ||||
| //============================
 | ||||
| //function that destroys the http server
 | ||||
| void http_stop_server(); | ||||
| void http_stop_server(httpd_handle_t * httpServer); | ||||
| 
 | ||||
| 
 | ||||
| //==============================
 | ||||
| @ -47,7 +58,7 @@ typedef struct httpJoystick_config_t { | ||||
| class httpJoystick{ | ||||
|     public: | ||||
|         //--- constructor ---
 | ||||
|         httpJoystick( httpJoystick_config_t config_f ); | ||||
|         httpJoystick(httpJoystick_config_t config_f); | ||||
| 
 | ||||
|         //--- functions ---
 | ||||
|         joystickData_t getData(); //wait for and return joystick data from queue, if timeout return CENTER
 | ||||
| @ -67,11 +78,4 @@ class httpJoystick{ | ||||
|             .radius = 0, | ||||
|             .angle = 0 | ||||
|         }; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //===== global object =====
 | ||||
| //create global instance of httpJoystick
 | ||||
| //note: is constructed/configured in config.cpp
 | ||||
| extern httpJoystick httpJoystickMain; | ||||
| }; | ||||
| @ -7,6 +7,24 @@ static const char * TAG = "motor-control"; | ||||
| 
 | ||||
| #define TIMEOUT_IDLE_WHEN_NO_COMMAND 8000 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //====================================
 | ||||
| //========== motorctl task ===========
 | ||||
| //====================================
 | ||||
| //task for handling the motors (ramp, current limit, driver)
 | ||||
| void task_motorctl( void * task_motorctl_parameters ){ | ||||
| 	task_motorctl_parameters_t *objects = (task_motorctl_parameters_t *)task_motorctl_parameters; | ||||
|     ESP_LOGW(TAG, "Task-motorctl: starting handle loop..."); | ||||
|     while(1){ | ||||
|     	objects->motorRight->handle(); | ||||
|     	objects->motorLeft->handle(); | ||||
|         vTaskDelay(20 / portTICK_PERIOD_MS); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| //=============================
 | ||||
| //======== constructor ========
 | ||||
| //=============================
 | ||||
| @ -33,6 +51,11 @@ controlledMotor::controlledMotor(motorSetCommandFunc_t setCommandFunc,  motorctl | ||||
| //============================
 | ||||
| void controlledMotor::init(){ | ||||
|     commandQueue = xQueueCreate( 1, sizeof( struct motorCommand_t ) ); | ||||
|     if (commandQueue == NULL) | ||||
|     ESP_LOGE(TAG, "Failed to create command-queue"); | ||||
|     else | ||||
|     ESP_LOGW(TAG, "Initialized command-queue"); | ||||
| 
 | ||||
| 	//cSensor.calibrateZeroAmpere(); //currently done in currentsensor constructor TODO do this regularly e.g. in idle?
 | ||||
| } | ||||
| 
 | ||||
| @ -252,11 +275,11 @@ void controlledMotor::setTarget(motorstate_t state_f, float duty_f){ | ||||
|         .state = state_f, | ||||
|         .duty = duty_f | ||||
|     }; | ||||
| 
 | ||||
|     ESP_LOGD(TAG, "Inserted command to queue: state=%s, duty=%.2f", motorstateStr[(int)commandSend.state], commandSend.duty); | ||||
|     ESP_LOGI(TAG, "setTarget: Inserting command to queue: state='%s'(%d), duty=%.2f", motorstateStr[(int)commandSend.state], (int)commandSend.state, commandSend.duty); | ||||
|     //send command to queue (overwrite if an old command is still in the queue and not processed)
 | ||||
|     xQueueOverwrite( commandQueue, ( void * )&commandSend); | ||||
|     //xQueueSend( commandQueue, ( void * )&commandSend, ( TickType_t ) 0 );
 | ||||
|     ESP_LOGD(TAG, "finished inserting new command"); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -86,3 +86,21 @@ class controlledMotor { | ||||
| 		uint32_t timestamp_commandReceived = 0; | ||||
| 		bool receiveTimeout = false; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| // struct with variables passed to task from main
 | ||||
| typedef struct task_motorctl_parameters_t { | ||||
|     controlledMotor * motorLeft; | ||||
|     controlledMotor * motorRight; | ||||
| } task_motorctl_parameters_t; | ||||
| 
 | ||||
| 
 | ||||
| //====================================
 | ||||
| //========== motorctl task ===========
 | ||||
| //====================================
 | ||||
| //task that inititialized the display, displays welcome message 
 | ||||
| //and releatedly updates the display with certain content
 | ||||
| //note: pointer to required objects have to be provided as task-parameter
 | ||||
| void task_motorctl( void * task_motorctl_parameters ); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user