diff --git a/board_single/main/button.cpp b/board_single/main/button.cpp index 6b7e618..ae4a36e 100644 --- a/board_single/main/button.cpp +++ b/board_single/main/button.cpp @@ -205,7 +205,7 @@ void buttonCommands::startHandleLoop() { //-- run action with count of presses -- ESP_LOGI(TAG, "timeout: count=%d, lastPressLong=%d -> running action", count, isPressed); - buzzer->beep(count, 50, 50); + buzzer->beep(count, 50, 50, 200); //beep count, with 200ms gap before next queued beeps can start action(count, isPressed); // run action - if currently still on the last press is considered long count = 0; // reset count } diff --git a/board_single/main/config.cpp b/board_single/main/config.cpp index cd4ba20..9a7d777 100644 --- a/board_single/main/config.cpp +++ b/board_single/main/config.cpp @@ -41,7 +41,7 @@ void setLoglevels(void) // 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("speedSensor", ESP_LOG_WARN); 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); @@ -84,7 +84,7 @@ single100a_config_t configDriverRight = { //--- configure sabertooth driver --- (controls both motors in one instance) sabertooth2x60_config_t sabertoothConfig = { - .gpio_TX = GPIO_NUM_25, + .gpio_TX = GPIO_NUM_27, .uart_num = UART_NUM_2}; // TODO add motor name string -> then use as log tag? @@ -97,6 +97,7 @@ motorctl_config_t configMotorControlLeft = { .currentSensor_adc = ADC1_CHANNEL_4, // GPIO32 .currentSensor_ratedCurrent = 50, .currentMax = 30, + .currentInverted = true, .deadTimeMs = 0 // minimum time motor is off between direction change }; @@ -109,6 +110,7 @@ motorctl_config_t configMotorControlRight = { .currentSensor_adc = ADC1_CHANNEL_5, // GPIO33 .currentSensor_ratedCurrent = 50, .currentMax = 30, + .currentInverted = false, .deadTimeMs = 0 // minimum time motor is off between direction change }; @@ -154,7 +156,7 @@ joystick_config_t configJoystick = { .y_min = 1700, //=> y=-1 .y_max = 2940, //=> y=1 // invert adc measurement - .x_inverted = true, + .x_inverted = false, .y_inverted = true}; //---------------------------- @@ -175,20 +177,23 @@ fan_config_t configFans = { //-------------------------------------------- speedSensor_config_t speedLeft_config{ .gpioPin = GPIO_NUM_5, - .degreePerGroup = 360 / 5, - .minPulseDurationUs = 10000, //smallest possible pulse duration (< time from start small-pulse to start long-pulse at full speed). Set to 0 to disable this noise detection + .degreePerGroup = 360 / 16, + .minPulseDurationUs = 3000, //smallest possible pulse duration (< time from start small-pulse to start long-pulse at full speed). Set to 0 to disable this noise detection + //measured wihth scope while tires in the air: + // 5-groups: 12ms + // 16-groups: 3.7ms .tireCircumferenceMeter = 0.81, - .directionInverted = false, - .logName = "speedLeft", + .directionInverted = true, + .logName = "speedLeft" }; speedSensor_config_t speedRight_config{ .gpioPin = GPIO_NUM_14, .degreePerGroup = 360 / 12, - .minPulseDurationUs = 10000, //smallest possible pulse duration (< time from start small-pulse to start long-pulse at full speed). Set to 0 to disable this noise detection + .minPulseDurationUs = 4000, //smallest possible pulse duration (< time from start small-pulse to start long-pulse at full speed). Set to 0 to disable this noise detection .tireCircumferenceMeter = 0.81, - .directionInverted = true, - .logName = "speedRight", + .directionInverted = false, + .logName = "speedRight" }; @@ -216,7 +221,7 @@ display_config_t display_config { rotary_encoder_t encoder_config = { .pin_a = GPIO_NUM_25, .pin_b = GPIO_NUM_26, - .pin_btn = GPIO_NUM_27, + .pin_btn = GPIO_NUM_21, .code = 1, .store = 0, //encoder count .index = 0, diff --git a/board_single/main/control.cpp b/board_single/main/control.cpp index 87c3e74..0eb617f 100644 --- a/board_single/main/control.cpp +++ b/board_single/main/control.cpp @@ -447,7 +447,7 @@ void controlledArmchair::changeMode(controlMode_t modeNew) { case controlMode_t::IDLE: ESP_LOGW(TAG, "switching to IDLE mode: turning both motors off, beep"); idleBothMotors(); - buzzer->beep(1, 1000, 0); + buzzer->beep(1, 900, 0); #ifdef JOYSTICK_LOG_IN_IDLE esp_log_level_set("evaluatedJoystick", ESP_LOG_DEBUG); #endif @@ -456,7 +456,7 @@ void controlledArmchair::changeMode(controlMode_t modeNew) { case controlMode_t::ADJUST_CHAIR: ESP_LOGW(TAG, "switching to ADJUST_CHAIR mode: turning both motors off, beep"); idleBothMotors(); - buzzer->beep(4, 200, 100); + buzzer->beep(3, 100, 50); break; case controlMode_t::MENU: diff --git a/board_single/main/main.cpp b/board_single/main/main.cpp index 2621989..008d741 100644 --- a/board_single/main/main.cpp +++ b/board_single/main/main.cpp @@ -164,8 +164,8 @@ void createObjects() // 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"); + legRest = new cControlledRest(GPIO_NUM_2, GPIO_NUM_15, "legRest"); + backRest = new cControlledRest(GPIO_NUM_16, GPIO_NUM_4, "backRest"); // create control object (control.hpp) // with configuration from config.cpp diff --git a/common/buzzer.cpp b/common/buzzer.cpp index a80ec75..f698ce1 100644 --- a/common/buzzer.cpp +++ b/common/buzzer.cpp @@ -46,12 +46,18 @@ buzzer_t::buzzer_t(gpio_num_t gpio_pin_f, uint16_t msGap_f){ //=========== beep =========== //============================ //function to add a beep command to the queue +//use default/configured gap when no custom pause duration is given: void buzzer_t::beep(uint8_t count, uint16_t msOn, uint16_t msOff){ + beep(count, msOn, msOff, msGap); +} + +void buzzer_t::beep(uint8_t count, uint16_t msOn, uint16_t msOff, uint16_t msDelayFinished){ //create entry struct with provided data struct beepEntry entryInsert = { - count = count, - msOn = msOn, - msOff = msOff + count, + msOn, + msOff, + msDelayFinished }; // Send a pointer to a struct AMessage object. Don't block if the @@ -96,7 +102,7 @@ void buzzer_t::processQueue(){ vTaskDelay(entryRead.msOff / portTICK_PERIOD_MS); } //wait for minimum gap between beep events - vTaskDelay(msGap / portTICK_PERIOD_MS); + vTaskDelay(entryRead.msDelay / portTICK_PERIOD_MS); } }else{ //wait for queue to become available vTaskDelay(50 / portTICK_PERIOD_MS); diff --git a/common/buzzer.hpp b/common/buzzer.hpp index 5b48d8a..7f9476e 100644 --- a/common/buzzer.hpp +++ b/common/buzzer.hpp @@ -27,24 +27,27 @@ class buzzer_t { //--- functions --- void processQueue(); //has to be run once in a separate task, waits for and processes queued events + //add entry to queue processing beeps, last parameter is optional to delay the next entry + void beep(uint8_t count, uint16_t msOn, uint16_t msOff, uint16_t msDelayFinished); void beep(uint8_t count, uint16_t msOn, uint16_t msOff); //void clear(); (TODO - not implemented yet) //void createTask(); (TODO - not implemented yet) //--- variables --- - uint16_t msGap; //gap between beep entries (when multiple queued) private: //--- functions --- void init(); //--- variables --- + uint16_t msGap; //gap between beep entries (when multiple queued) gpio_num_t gpio_pin; struct beepEntry { uint8_t count; uint16_t msOn; uint16_t msOff; + uint16_t msDelay; }; //queue for queueing up multiple events while one is still processing diff --git a/common/currentsensor.cpp b/common/currentsensor.cpp index 2569c6d..3fd3a95 100644 --- a/common/currentsensor.cpp +++ b/common/currentsensor.cpp @@ -29,10 +29,11 @@ float getVoltage(adc1_channel_t adc, uint32_t samples){ //============================= //======== constructor ======== //============================= -currentSensor::currentSensor (adc1_channel_t adcChannel_f, float ratedCurrent_f){ +currentSensor::currentSensor (adc1_channel_t adcChannel_f, float ratedCurrent_f, bool isInverted_f){ //copy config adcChannel = adcChannel_f; ratedCurrent = ratedCurrent_f; + isInverted = isInverted_f; //init adc adc1_config_width(ADC_WIDTH_BIT_12); //max resolution 4096 adc1_config_channel_atten(adcChannel, ADC_ATTEN_DB_11); //max voltage @@ -58,6 +59,9 @@ float currentSensor::read(void){ current = 0; } + //invert calculated current if necessary + if (isInverted) current = -current; + ESP_LOGI(TAG, "read sensor adc=%d: voltage=%.3fV, centerVoltage=%.3fV => current=%.3fA", (int)adcChannel, voltage, centerVoltage, current); return current; } diff --git a/common/currentsensor.hpp b/common/currentsensor.hpp index f62fa34..3110512 100644 --- a/common/currentsensor.hpp +++ b/common/currentsensor.hpp @@ -7,12 +7,13 @@ class currentSensor{ public: - currentSensor (adc1_channel_t adcChannel_f, float ratedCurrent); + currentSensor (adc1_channel_t adcChannel_f, float ratedCurrent, bool inverted = false); void calibrateZeroAmpere(void); //set current voltage to voltage representing 0A float read(void); //get current ampere private: adc1_channel_t adcChannel; float ratedCurrent; + bool isInverted; uint32_t measure; float voltage; float current; diff --git a/common/motorctl.cpp b/common/motorctl.cpp index 0975f2e..f437417 100644 --- a/common/motorctl.cpp +++ b/common/motorctl.cpp @@ -29,7 +29,7 @@ void task_motorctl( void * ptrControlledMotor ){ //============================= //constructor, simultaniously initialize instance of motor driver 'motor' and current sensor 'cSensor' with provided config (see below lines after ':') controlledMotor::controlledMotor(motorSetCommandFunc_t setCommandFunc, motorctl_config_t config_control, nvs_handle_t * nvsHandle_f): - cSensor(config_control.currentSensor_adc, config_control.currentSensor_ratedCurrent) { + cSensor(config_control.currentSensor_adc, config_control.currentSensor_ratedCurrent, config_control.currentInverted) { //copy parameters for controlling the motor config = config_control; //pointer to update motot dury method @@ -108,7 +108,7 @@ void controlledMotor::handle(){ //--- receive commands from queue --- if( xQueueReceive( commandQueue, &commandReceive, timeoutWaitForCommand / portTICK_PERIOD_MS ) ) //wait time is always 0 except when at target duty already { - ESP_LOGD(TAG, "[%s] Read command from queue: state=%s, duty=%.2f", config.name, motorstateStr[(int)commandReceive.state], commandReceive.duty); + ESP_LOGV(TAG, "[%s] Read command from queue: state=%s, duty=%.2f", config.name, motorstateStr[(int)commandReceive.state], commandReceive.duty); state = commandReceive.state; dutyTarget = commandReceive.duty; receiveTimeout = false; @@ -159,7 +159,7 @@ void controlledMotor::handle(){ //increase timeout once when duty is the same (once) if (timeoutWaitForCommand == 0) { // TODO verify if state matches too? - ESP_LOGW(TAG, "[%s] already at target duty %.2f, slowing down...", config.name, dutyTarget); + ESP_LOGI(TAG, "[%s] already at target duty %.2f, slowing down...", config.name, dutyTarget); timeoutWaitForCommand = TIMEOUT_QUEUE_WHEN_AT_TARGET; // wait in queue very long, for new command to arrive } vTaskDelay(20 / portTICK_PERIOD_MS); // add small additional delay overall, in case the same commands get spammed @@ -168,7 +168,7 @@ void controlledMotor::handle(){ else if (timeoutWaitForCommand != 0) { timeoutWaitForCommand = 0; // dont wait additional time for new commands, handle fading fast - ESP_LOGW(TAG, "[%s] duty changed to %.2f, resuming at full speed", config.name, dutyTarget); + ESP_LOGI(TAG, "[%s] duty changed to %.2f, resuming at full speed", config.name, dutyTarget); // adjust lastRun timestamp to not mess up fading, due to much time passed but with no actual duty change timestampLastRunUs = esp_timer_get_time() - 20*1000; //subtract approx 1 cycle delay } @@ -197,7 +197,7 @@ void controlledMotor::handle(){ if (state == motorstate_t::BRAKE){ ESP_LOGD(TAG, "braking - skip fading"); motorSetCommand({motorstate_t::BRAKE, dutyTarget}); - ESP_LOGI(TAG, "[%s] Set Motordriver: state=%s, duty=%.2f - Measurements: current=%.2f, speed=N/A", config.name, motorstateStr[(int)state], dutyNow, currentNow); + ESP_LOGD(TAG, "[%s] Set Motordriver: state=%s, duty=%.2f - Measurements: current=%.2f, speed=N/A", config.name, motorstateStr[(int)state], dutyNow, currentNow); //dutyNow = 0; return; //no need to run the fade algorithm } @@ -261,7 +261,7 @@ void controlledMotor::handle(){ ESP_LOGD(TAG, "waiting dead-time... dir change %s -> %s", motorstateStr[(int)statePrev], motorstateStr[(int)state]); if (!deadTimeWaiting){ //log start deadTimeWaiting = true; - ESP_LOGW(TAG, "starting dead-time... %s -> %s", motorstateStr[(int)statePrev], motorstateStr[(int)state]); + ESP_LOGI(TAG, "starting dead-time... %s -> %s", motorstateStr[(int)statePrev], motorstateStr[(int)state]); } //force IDLE state during wait state = motorstate_t::IDLE; @@ -269,7 +269,7 @@ void controlledMotor::handle(){ } else { if (deadTimeWaiting){ //log end deadTimeWaiting = false; - ESP_LOGW(TAG, "dead-time ended - continue with %s", motorstateStr[(int)state]); + ESP_LOGI(TAG, "dead-time ended - continue with %s", motorstateStr[(int)state]); } ESP_LOGV(TAG, "deadtime: no change below deadtime detected... dir=%s, duty=%.1f", motorstateStr[(int)state], dutyNow); } diff --git a/common/types.hpp b/common/types.hpp index 450a2e6..dcc9480 100644 --- a/common/types.hpp +++ b/common/types.hpp @@ -48,6 +48,7 @@ typedef struct motorctl_config_t { adc1_channel_t currentSensor_adc; float currentSensor_ratedCurrent; float currentMax; + bool currentInverted; uint32_t deadTimeMs; //time motor stays in IDLE before direction change } motorctl_config_t;