Merge branch 'dev' into driving-behavior
This commit is contained in:
commit
179c608638
@ -1,7 +1,6 @@
|
||||
idf_component_register(
|
||||
SRCS
|
||||
"main.cpp"
|
||||
"config.cpp"
|
||||
"control.cpp"
|
||||
"button.cpp"
|
||||
"fan.cpp"
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include "auto.hpp"
|
||||
#include "config.hpp"
|
||||
|
||||
//tag for logging
|
||||
static const char * TAG = "automatedArmchair";
|
||||
|
@ -96,15 +96,16 @@ void buttonCommands::action (uint8_t count, bool lastPressLong){
|
||||
// ## switch to ADJUST_CHAIR mode ##
|
||||
if (lastPressLong)
|
||||
{
|
||||
ESP_LOGW(TAG, "cmd %d: toggle ADJUST_CHAIR", count);
|
||||
control->toggleMode(controlMode_t::ADJUST_CHAIR);
|
||||
}
|
||||
// ## toggle IDLE ##
|
||||
else {
|
||||
ESP_LOGW(TAG, "cmd %d: switch to ADJUST_CHAIR", count);
|
||||
control->changeMode(controlMode_t::ADJUST_CHAIR);
|
||||
}
|
||||
// ## toggle IDLE ##
|
||||
else
|
||||
{
|
||||
ESP_LOGW(TAG, "cmd %d: toggle IDLE", count);
|
||||
control->toggleIdle(); //toggle between idle and previous/default mode
|
||||
}
|
||||
break;
|
||||
control->toggleIdle(); // toggle between idle and previous/default mode
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// ## switch to JOYSTICK mode ##
|
||||
@ -114,14 +115,14 @@ void buttonCommands::action (uint8_t count, bool lastPressLong){
|
||||
|
||||
case 4:
|
||||
// ## switch to HTTP mode ##
|
||||
ESP_LOGW(TAG, "cmd %d: toggle between HTTP and JOYSTICK", count);
|
||||
control->toggleModes(controlMode_t::HTTP, controlMode_t::JOYSTICK); //toggle between HTTP and JOYSTICK mode
|
||||
ESP_LOGW(TAG, "cmd %d: switch to HTTP", count);
|
||||
control->changeMode(controlMode_t::HTTP); //switch to HTTP mode
|
||||
break;
|
||||
|
||||
case 6:
|
||||
// ## switch to MASSAGE mode ##
|
||||
ESP_LOGW(TAG, "cmd %d: toggle between MASSAGE and JOYSTICK", count);
|
||||
control->toggleModes(controlMode_t::MASSAGE, controlMode_t::JOYSTICK); //toggle between MASSAGE and JOYSTICK mode
|
||||
ESP_LOGW(TAG, "switch to MASSAGE");
|
||||
control->changeMode(controlMode_t::MASSAGE); //switch to MASSAGE mode
|
||||
break;
|
||||
|
||||
case 8:
|
||||
@ -129,7 +130,7 @@ void buttonCommands::action (uint8_t count, bool lastPressLong){
|
||||
//toggle deceleration fading between on and off
|
||||
//decelEnabled = motorLeft->toggleFade(fadeType_t::DECEL);
|
||||
//motorRight->toggleFade(fadeType_t::DECEL);
|
||||
decelEnabled = motorLeft->toggleFade(fadeType_t::ACCEL);
|
||||
decelEnabled = motorLeft->toggleFade(fadeType_t::ACCEL); //TODO remove/simplify this using less functions
|
||||
motorRight->toggleFade(fadeType_t::ACCEL);
|
||||
ESP_LOGW(TAG, "cmd %d: toggle deceleration fading to: %d", count, (int)decelEnabled);
|
||||
if (decelEnabled){
|
||||
@ -155,7 +156,7 @@ void buttonCommands::action (uint8_t count, bool lastPressLong){
|
||||
// when not in MENU mode, repeatedly receives events from encoder button
|
||||
// and takes the corresponding action
|
||||
// this function has to be started once in a separate task
|
||||
#define INPUT_TIMEOUT 800 // duration of no button events, after which action is run (implicitly also is 'long-press' time)
|
||||
#define INPUT_TIMEOUT 700 // duration of no button events, after which action is run (implicitly also is 'long-press' time)
|
||||
void buttonCommands::startHandleLoop()
|
||||
{
|
||||
//-- variables --
|
||||
@ -178,7 +179,7 @@ void buttonCommands::startHandleLoop()
|
||||
//-- get events from encoder --
|
||||
if (xQueueReceive(encoderQueue, &ev, INPUT_TIMEOUT / portTICK_PERIOD_MS))
|
||||
{
|
||||
control->resetTimeout(); //reset inactivity IDLE timeout
|
||||
control->resetTimeout(); // user input -> reset switch to IDLE timeout
|
||||
switch (ev.type)
|
||||
{
|
||||
break;
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include "control.hpp"
|
||||
#include "motorctl.hpp"
|
||||
#include "auto.hpp"
|
||||
#include "config.hpp"
|
||||
#include "joystick.hpp"
|
||||
|
||||
|
||||
|
@ -132,11 +132,9 @@ motorctl_config_t configMotorControlRight = {
|
||||
//------------------------------
|
||||
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
|
||||
//--- http mode ---
|
||||
|
||||
//--- timeouts ---
|
||||
.timeoutSwitchToIdleMs = 5 * 60 * 1000, // time of inactivity after which the mode gets switched to IDLE
|
||||
.timeoutNotifyPowerStillOnMs = 6 * 60 * 60 * 1000 // time in IDLE after which buzzer beeps in certain interval (notify "forgot to turn off")
|
||||
};
|
||||
|
||||
//-------------------------------
|
||||
@ -214,16 +212,21 @@ speedSensor_config_t speedRight_config{
|
||||
//-------------------------
|
||||
//-------- display --------
|
||||
//-------------------------
|
||||
display_config_t display_config {
|
||||
display_config_t display_config{
|
||||
// hardware initialization
|
||||
.gpio_scl = GPIO_NUM_22,
|
||||
.gpio_sda = GPIO_NUM_23,
|
||||
.gpio_reset = -1, //negative number disables reset feature
|
||||
.gpio_reset = -1, // negative number disables reset feature
|
||||
.width = 128,
|
||||
.height = 64,
|
||||
.offsetX = 2,
|
||||
.flip = false,
|
||||
.contrast = 0xff, //max: 255
|
||||
};
|
||||
.contrastNormal = 170, // max: 255
|
||||
// display task
|
||||
.contrastReduced = 30, // max: 255
|
||||
.timeoutReduceContrastMs = 5 * 60 * 1000, // actions at certain inactivity
|
||||
.timeoutSwitchToScreensaverMs = 30 * 60 * 1000
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
6
board_single/main/config.h
Normal file
6
board_single/main/config.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
// outsourced macros / definitions
|
||||
|
||||
//-- control.cpp --
|
||||
//#define JOYSTICK_LOG_IN_IDLE
|
@ -1,57 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "motordrivers.hpp"
|
||||
#include "motorctl.hpp"
|
||||
#include "joystick.hpp"
|
||||
|
||||
#include "gpio_evaluateSwitch.hpp"
|
||||
#include "buzzer.hpp"
|
||||
#include "control.hpp"
|
||||
#include "fan.hpp"
|
||||
#include "http.hpp"
|
||||
#include "auto.hpp"
|
||||
#include "speedsensor.hpp"
|
||||
#include "chairAdjust.hpp"
|
||||
|
||||
//
|
||||
////in IDLE mode: set loglevel for evaluatedJoystick to DEBUG
|
||||
////and repeatedly read joystick e.g. for manually calibrating / testing joystick
|
||||
////#define JOYSTICK_LOG_IN_IDLE
|
||||
//
|
||||
//
|
||||
////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;
|
||||
//
|
||||
//
|
@ -9,13 +9,14 @@ extern "C"
|
||||
#include "wifi.h"
|
||||
}
|
||||
|
||||
#include "config.hpp"
|
||||
#include "config.h"
|
||||
#include "control.hpp"
|
||||
#include "chairAdjust.hpp"
|
||||
#include "display.hpp" // needed for getBatteryPercent()
|
||||
|
||||
|
||||
//used definitions moved from config.hpp:
|
||||
//#define JOYSTICK_TEST
|
||||
//used definitions moved from config.h:
|
||||
//#define JOYSTICK_LOG_IN_IDLE
|
||||
|
||||
|
||||
//tag for logging
|
||||
@ -70,7 +71,6 @@ controlledArmchair::controlledArmchair(
|
||||
void task_control( void * pvParameters ){
|
||||
controlledArmchair * control = (controlledArmchair *)pvParameters;
|
||||
ESP_LOGW(TAG, "Initializing controlledArmchair and starting handle loop");
|
||||
//start handle loop (control object declared in config.hpp)
|
||||
control->startHandleLoop();
|
||||
}
|
||||
|
||||
@ -95,13 +95,15 @@ void controlledArmchair::startHandleLoop() {
|
||||
//motorLeft->setTarget(commands.left.state, commands.left.duty);
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
#ifdef JOYSTICK_LOG_IN_IDLE
|
||||
//get joystick data here (without using it)
|
||||
//since loglevel is DEBUG, calculation details are output
|
||||
joystick_l->getData();
|
||||
// get joystick data and log it
|
||||
joystickData_t data joystick_l->getData();
|
||||
ESP_LOGI("JOYSTICK_LOG_IN_IDLE", "x=%.3f, y=%.3f, radius=%.3f, angle=%.3f, pos=%s, adcx=%d, adcy=%d",
|
||||
data.x, data.y, data.radius, data.angle,
|
||||
joystickPosStr[(int)data.position],
|
||||
objects->joystick->getRawX(), objects->joystick->getRawY());
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
||||
break;
|
||||
//------- handle JOYSTICK mode -------
|
||||
case controlMode_t::JOYSTICK:
|
||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||
//get current joystick data with getData method of evaluatedJoystick
|
||||
@ -113,6 +115,7 @@ void controlledArmchair::startHandleLoop() {
|
||||
// only generate when the stick data actually changed (e.g. stick stayed in center)
|
||||
if (stickData.x != stickDataLast.x || stickData.y != stickDataLast.y)
|
||||
{
|
||||
resetTimeout(); //user input -> reset switch to IDLE timeout
|
||||
commands = joystick_generateCommandsDriving(stickData, &joystickGenerateCommands_config);
|
||||
// apply motor commands
|
||||
motorRight->setTarget(commands.right);
|
||||
@ -121,27 +124,34 @@ void controlledArmchair::startHandleLoop() {
|
||||
else
|
||||
{
|
||||
vTaskDelay(20 / portTICK_PERIOD_MS);
|
||||
ESP_LOGD(TAG, "analog joystick data unchanged at %s not updating commands", joystickPosStr[(int)stickData.position]);
|
||||
ESP_LOGV(TAG, "analog joystick data unchanged at %s not updating commands", joystickPosStr[(int)stickData.position]);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
//------- handle MASSAGE mode -------
|
||||
case controlMode_t::MASSAGE:
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
//--- read joystick ---
|
||||
//only update joystick data when input not frozen
|
||||
if (!freezeInput){
|
||||
// only update joystick data when input not frozen
|
||||
stickDataLast = stickData;
|
||||
if (!freezeInput)
|
||||
stickData = joystick_l->getData();
|
||||
}
|
||||
//--- generate motor commands ---
|
||||
//pass joystick data from getData method of evaluatedJoystick to generateCommandsShaking function
|
||||
commands = joystick_generateCommandsShaking(stickData);
|
||||
//apply motor commands
|
||||
motorRight->setTarget(commands.right);
|
||||
motorLeft->setTarget(commands.left);
|
||||
// only generate when the stick data actually changed (e.g. stick stayed in center)
|
||||
if (stickData.x != stickDataLast.x || stickData.y != stickDataLast.y)
|
||||
{
|
||||
resetTimeout(); // user input -> reset switch to IDLE timeout
|
||||
// pass joystick data from getData method of evaluatedJoystick to generateCommandsShaking function
|
||||
commands = joystick_generateCommandsShaking(stickData);
|
||||
// apply motor commands
|
||||
motorRight->setTarget(commands.right);
|
||||
motorLeft->setTarget(commands.left);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
//------- handle HTTP mode -------
|
||||
case controlMode_t::HTTP:
|
||||
//--- get joystick data from queue ---
|
||||
stickDataLast = stickData;
|
||||
@ -152,6 +162,7 @@ void controlledArmchair::startHandleLoop() {
|
||||
//--- generate motor commands ---
|
||||
//only generate when the stick data actually changed (e.g. no new data recevied via http)
|
||||
if (stickData.x != stickDataLast.x || stickData.y != stickDataLast.y ){
|
||||
resetTimeout(); // user input -> reset switch to IDLE timeout
|
||||
// Note: timeout (no data received) is handled in getData method
|
||||
commands = joystick_generateCommandsDriving(stickData, &joystickGenerateCommands_config);
|
||||
|
||||
@ -166,6 +177,7 @@ void controlledArmchair::startHandleLoop() {
|
||||
break;
|
||||
|
||||
|
||||
//------- handle AUTO mode -------
|
||||
case controlMode_t::AUTO:
|
||||
vTaskDelay(20 / portTICK_PERIOD_MS);
|
||||
//generate commands
|
||||
@ -206,26 +218,26 @@ void controlledArmchair::startHandleLoop() {
|
||||
break;
|
||||
|
||||
|
||||
//------- handle ADJUST_CHAIR mode -------
|
||||
case controlMode_t::ADJUST_CHAIR:
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
//--- read joystick ---
|
||||
stickDataLast = stickData;
|
||||
stickData = joystick_l->getData();
|
||||
//--- idle motors ---
|
||||
//commands = cmds_bothMotorsIdle; - now done once at mode change
|
||||
//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);
|
||||
// dont update when stick data did not change
|
||||
if (stickData.x != stickDataLast.x || stickData.y != stickDataLast.y)
|
||||
{
|
||||
resetTimeout(); // user input -> reset switch to IDLE timeout
|
||||
controlChairAdjustment(joystick_l->getData(), legRest, backRest);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
//------- handle MENU mode -------
|
||||
case controlMode_t::MENU:
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
//nothing to do here, display task handles the menu
|
||||
//--- idle motors ---
|
||||
//commands = cmds_bothMotorsIdle; - now done once at mode change
|
||||
//motorRight->setTarget(commands.right.state, commands.right.duty);
|
||||
//motorLeft->setTarget(commands.left.state, commands.left.duty);
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
break;
|
||||
|
||||
//TODO: add other modes here
|
||||
@ -238,8 +250,7 @@ void controlledArmchair::startHandleLoop() {
|
||||
if (esp_log_timestamp() - timestamp_SlowLoopLastRun > 5000) {
|
||||
ESP_LOGV(TAG, "running slow loop... time since last run: %.1fs", (float)(esp_log_timestamp() - timestamp_SlowLoopLastRun)/1000);
|
||||
timestamp_SlowLoopLastRun = esp_log_timestamp();
|
||||
|
||||
//run function that detects timeout (switch to idle)
|
||||
//run function that detects timeout (switch to idle, or notify "forgot to turn off")
|
||||
handleTimeout();
|
||||
}
|
||||
|
||||
@ -310,59 +321,58 @@ void controlledArmchair::idleBothMotors(){
|
||||
motorLeft->setTarget(cmd_motorIdle);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------
|
||||
//---------- resetTimeout -----------
|
||||
//-----------------------------------
|
||||
void controlledArmchair::resetTimeout(){
|
||||
//TODO mutex
|
||||
timestamp_lastActivity = esp_log_timestamp();
|
||||
ESP_LOGV(TAG, "timeout: activity detected, resetting timeout");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------
|
||||
//---------- handleTimeout -----------
|
||||
//------------------------------------
|
||||
//percentage the duty can vary since last timeout check and still counts as incative
|
||||
//TODO: add this to config
|
||||
float inactivityTolerance = 10;
|
||||
// switch to IDLE when no activity (prevent accidential movement)
|
||||
// notify "power still on" when in IDLE for a very long time (prevent battery drain when forgotten to turn off)
|
||||
// this function has to be run repeatedly (can be slow interval)
|
||||
#define TIMEOUT_POWER_STILL_ON_BEEP_INTERVAL_MS 5 * 60 * 1000 // beep every 5 minutes for someone to notice
|
||||
#define TIMEOUT_POWER_STILL_ON_BATTERY_THRESHOLD_PERCENT 96 // only notify/beep when below certain percentage (prevent beeping when connected to charger)
|
||||
// note: timeout durations are configured in config.cpp
|
||||
void controlledArmchair::handleTimeout()
|
||||
{
|
||||
uint32_t noActivityDurationMs = esp_log_timestamp() - timestamp_lastActivity;
|
||||
// log current inactivity and configured timeouts
|
||||
ESP_LOGD(TAG, "timeout check: last activity %dmin and %ds ago - timeout IDLE after %ds - notify after power on after %dh",
|
||||
noActivityDurationMs / 1000 / 60,
|
||||
noActivityDurationMs / 1000 % 60,
|
||||
config.timeoutSwitchToIdleMs / 1000,
|
||||
config.timeoutNotifyPowerStillOnMs / 1000 / 60 / 60);
|
||||
|
||||
//local function that checks whether two values differ more than a given tolerance
|
||||
bool validateActivity(float dutyOld, float dutyNow, float tolerance){
|
||||
float dutyDelta = dutyNow - dutyOld;
|
||||
if (fabs(dutyDelta) < tolerance) {
|
||||
return false; //no significant activity detected
|
||||
} else {
|
||||
return true; //there was activity
|
||||
// -- timeout switch to IDLE --
|
||||
// timeout to IDLE when not idling already
|
||||
if (mode != controlMode_t::IDLE && noActivityDurationMs > config.timeoutSwitchToIdleMs)
|
||||
{
|
||||
ESP_LOGW(TAG, "timeout check: [TIMEOUT], no activity for more than %ds -> switch to IDLE", config.timeoutSwitchToIdleMs / 1000);
|
||||
changeMode(controlMode_t::IDLE);
|
||||
//TODO switch to previous status-screen when activity detected
|
||||
}
|
||||
}
|
||||
|
||||
//function that evaluates whether there is no activity/change on the motor duty for a certain time. If so, a switch to IDLE is issued. - has to be run repeatedly in a slow interval
|
||||
void controlledArmchair::handleTimeout(){
|
||||
//check for timeout only when not idling already
|
||||
if (mode != controlMode_t::IDLE) {
|
||||
//get current duty from controlled motor objects
|
||||
float dutyLeftNow = motorLeft->getStatus().duty;
|
||||
float dutyRightNow = motorRight->getStatus().duty;
|
||||
|
||||
//activity detected on any of the two motors
|
||||
if (validateActivity(dutyLeft_lastActivity, dutyLeftNow, inactivityTolerance)
|
||||
|| validateActivity(dutyRight_lastActivity, dutyRightNow, inactivityTolerance)
|
||||
){
|
||||
ESP_LOGD(TAG, "timeout check: [activity] detected since last check -> reset");
|
||||
//reset last duty and timestamp
|
||||
dutyLeft_lastActivity = dutyLeftNow;
|
||||
dutyRight_lastActivity = dutyRightNow;
|
||||
resetTimeout();
|
||||
}
|
||||
//no activity on any motor and msTimeout exceeded
|
||||
else if (esp_log_timestamp() - timestamp_lastActivity > config.timeoutMs){
|
||||
ESP_LOGI(TAG, "timeout check: [TIMEOUT], no activity for more than %.ds -> switch to idle", config.timeoutMs/1000);
|
||||
//toggle to idle mode
|
||||
toggleIdle();
|
||||
}
|
||||
else {
|
||||
ESP_LOGD(TAG, "timeout check: [inactive], last activity %.1f s ago, timeout after %d s", (float)(esp_log_timestamp() - timestamp_lastActivity)/1000, config.timeoutMs/1000);
|
||||
// -- timeout notify "forgot to turn off" --
|
||||
// repeatedly notify via buzzer when in IDLE for a very long time to prevent battery drain ("forgot to turn off")
|
||||
// also battery charge-level has to be below certain threshold to prevent beeping in case connected to charger
|
||||
// note: ignores user input while in IDLE (e.g. encoder rotation)
|
||||
else if ((esp_log_timestamp() - timestamp_lastModeChange) > config.timeoutNotifyPowerStillOnMs && getBatteryPercent() < TIMEOUT_POWER_STILL_ON_BATTERY_THRESHOLD_PERCENT)
|
||||
{
|
||||
// beep in certain intervals
|
||||
if ((esp_log_timestamp() - timestamp_lastTimeoutBeep) > TIMEOUT_POWER_STILL_ON_BEEP_INTERVAL_MS)
|
||||
{
|
||||
ESP_LOGW(TAG, "timeout: [TIMEOUT] in IDLE since %.3f hours -> beeping", (float)(esp_log_timestamp() - timestamp_lastModeChange) / 1000 / 60 / 60);
|
||||
// TODO dont beep at certain time ranges (e.g. at night)
|
||||
timestamp_lastTimeoutBeep = esp_log_timestamp();
|
||||
buzzer->beep(6, 100, 50);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -374,8 +384,6 @@ void controlledArmchair::handleTimeout(){
|
||||
//-----------------------------------
|
||||
//function to change to a specified control mode
|
||||
void controlledArmchair::changeMode(controlMode_t modeNew) {
|
||||
//reset timeout timer
|
||||
resetTimeout();
|
||||
|
||||
//exit if target mode is already active
|
||||
if (mode == modeNew) {
|
||||
@ -385,6 +393,8 @@ void controlledArmchair::changeMode(controlMode_t modeNew) {
|
||||
|
||||
//copy previous mode
|
||||
modePrevious = mode;
|
||||
//store time changed (needed for timeout)
|
||||
timestamp_lastModeChange = esp_log_timestamp();
|
||||
|
||||
ESP_LOGW(TAG, "=== changing mode from %s to %s ===", controlModeStr[(int)mode], controlModeStr[(int)modeNew]);
|
||||
|
||||
@ -403,6 +413,11 @@ void controlledArmchair::changeMode(controlMode_t modeNew) {
|
||||
buzzer->beep(1,200,100);
|
||||
break;
|
||||
|
||||
case controlMode_t::HTTP:
|
||||
ESP_LOGW(TAG, "switching from HTTP mode -> stopping wifi-ap");
|
||||
wifi_stop_ap();
|
||||
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...
|
||||
@ -448,9 +463,11 @@ void controlledArmchair::changeMode(controlMode_t modeNew) {
|
||||
ESP_LOGW(TAG, "switching to IDLE mode: turning both motors off, beep");
|
||||
idleBothMotors();
|
||||
buzzer->beep(1, 900, 0);
|
||||
#ifdef JOYSTICK_LOG_IN_IDLE
|
||||
esp_log_level_set("evaluatedJoystick", ESP_LOG_DEBUG);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case controlMode_t::HTTP:
|
||||
ESP_LOGW(TAG, "switching to HTTP mode -> starting wifi-ap");
|
||||
wifi_start_ap();
|
||||
break;
|
||||
|
||||
case controlMode_t::ADJUST_CHAIR:
|
||||
@ -540,9 +557,9 @@ void controlledArmchair::toggleMode(controlMode_t modePrimary){
|
||||
|
||||
|
||||
|
||||
//-------------------------------
|
||||
//------ loadDecelDuration ------
|
||||
//-------------------------------
|
||||
//-----------------------------
|
||||
//-------- loadMaxDuty --------
|
||||
//-----------------------------
|
||||
// update local config value when maxDuty is stored in nvs
|
||||
void controlledArmchair::loadMaxDuty(void)
|
||||
{
|
||||
|
@ -27,8 +27,8 @@ extern const char* controlModeStr[9];
|
||||
typedef struct control_config_t {
|
||||
controlMode_t defaultMode; //default mode after startup and toggling IDLE
|
||||
//timeout options
|
||||
uint32_t timeoutMs; //time of inactivity after which the mode gets switched to IDLE
|
||||
float timeoutTolerancePer; //percentage the duty can vary between timeout checks considered still inactive
|
||||
uint32_t timeoutSwitchToIdleMs; //time of inactivity after which the mode gets switched to IDLE
|
||||
uint32_t timeoutNotifyPowerStillOnMs;
|
||||
} control_config_t;
|
||||
|
||||
|
||||
@ -96,6 +96,8 @@ class controlledArmchair {
|
||||
void setMaxDuty(float maxDutyNew) { writeMaxDuty(maxDutyNew); };
|
||||
float getMaxDuty() const {return joystickGenerateCommands_config.maxDuty; };
|
||||
|
||||
uint32_t getInactivityDurationMs() {return esp_log_timestamp() - timestamp_lastActivity;};
|
||||
|
||||
private:
|
||||
|
||||
//--- functions ---
|
||||
@ -169,10 +171,10 @@ class controlledArmchair {
|
||||
//variable for slow loop
|
||||
uint32_t timestamp_SlowLoopLastRun = 0;
|
||||
|
||||
//variables for detecting timeout (switch to idle, after inactivity)
|
||||
float dutyLeft_lastActivity = 0;
|
||||
float dutyRight_lastActivity = 0;
|
||||
//variables for detecting timeout (switch to idle, or notify "forgot to turn off" after inactivity
|
||||
uint32_t timestamp_lastModeChange = 0;
|
||||
uint32_t timestamp_lastActivity = 0;
|
||||
uint32_t timestamp_lastTimeoutBeep = 0;
|
||||
};
|
||||
|
||||
|
||||
|
@ -12,7 +12,16 @@ extern "C"{
|
||||
#define STARTUP_MSG_TIMEOUT 2000
|
||||
#define ADC_BATT_VOLTAGE ADC1_CHANNEL_6
|
||||
#define BAT_CELL_COUNT 7
|
||||
// continously vary display contrast from 0 to 250 in OVERVIEW status screen
|
||||
//#define BRIGHTNESS_TEST
|
||||
|
||||
// if display and driver support hardware scrolling the SCREENSAVER status-screen will be smoother:
|
||||
//#define HARDWARE_SCROLL_AVAILABLE
|
||||
|
||||
|
||||
//=== variables ===
|
||||
// every function can access the display configuration from config.cpp
|
||||
static display_config_t displayConfig;
|
||||
|
||||
|
||||
//--------------------------
|
||||
@ -61,7 +70,10 @@ void display_init(display_config_t config){
|
||||
ssd1306_init(&dev, config.width, config.height, config.offsetX);
|
||||
|
||||
ssd1306_clear_screen(&dev, false);
|
||||
ssd1306_contrast(&dev, config.contrast);
|
||||
ssd1306_contrast(&dev, config.contrastNormal);
|
||||
|
||||
//store configuration locally (e.g. for accessing timeouts)
|
||||
displayConfig = config;
|
||||
}
|
||||
|
||||
|
||||
@ -233,8 +245,8 @@ float getBatteryPercent()
|
||||
//#############################
|
||||
//shows overview on entire display:
|
||||
//Battery percentage, voltage, current, mode, rpm, speed
|
||||
#define STATUS_SCREEN_OVERVIEW_UPDATE_INTERVAL 500
|
||||
void showStatusScreenOverview(display_task_parameters_t * objects)
|
||||
#define STATUS_SCREEN_OVERVIEW_UPDATE_INTERVAL 400
|
||||
void showStatusScreenOverview(display_task_parameters_t *objects)
|
||||
{
|
||||
//-- battery percentage --
|
||||
// TODO update when no load (currentsensors = ~0A) only
|
||||
@ -263,6 +275,17 @@ void showStatusScreenOverview(display_task_parameters_t * objects)
|
||||
objects->speedLeft->getRpm(),
|
||||
objects->speedRight->getRpm());
|
||||
vTaskDelay(STATUS_SCREEN_OVERVIEW_UPDATE_INTERVAL / portTICK_PERIOD_MS);
|
||||
|
||||
//-- brightness test --
|
||||
#ifdef BRIGHTNESS_TEST
|
||||
// continously vary brightness/contrast for testing
|
||||
displayConfig.contrastNormal += 10;
|
||||
if (displayConfig.contrastNormal > 255)
|
||||
displayConfig.contrastNormal = 0;
|
||||
ssd1306_contrast(&dev, displayConfig.contrastNormal);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
ESP_LOGW(TAG, "TEST BRIGHTNESS, setting to %d", displayConfig.contrastNormal);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -315,8 +338,6 @@ void showStatusScreenJoystick(display_task_parameters_t * objects)
|
||||
#define STATUS_SCREEN_MOTORS_UPDATE_INTERVAL 150
|
||||
void showStatusScreenMotors(display_task_parameters_t *objects)
|
||||
{
|
||||
// print all joystick data
|
||||
joystickData_t data = objects->joystick->getData();
|
||||
displayTextLine(&dev, 0, true, false, "%-4.0fW ", fabs(objects->motorLeft->getCurrentA()) * getBatteryVoltage());
|
||||
displayTextLine(&dev, 3, true, false, "%-4.0fW ", fabs(objects->motorRight->getCurrentA()) * getBatteryVoltage());
|
||||
//displayTextLine(&dev, 0, true, false, "L:%02.0f%%", objects->motorLeft->getStatus().duty);
|
||||
@ -331,6 +352,71 @@ void showStatusScreenMotors(display_task_parameters_t *objects)
|
||||
}
|
||||
|
||||
|
||||
// ################################
|
||||
// #### showScreen Screensaver ####
|
||||
// ################################
|
||||
// show inactivity duration and battery perventage scrolling across screen the entire screen to prevent burn in
|
||||
#define STATUS_SCREEN_SCREENSAVER_DELAY_NEXT_LINE_MS 10 * 1000
|
||||
#define STATUS_SCREEN_SCREENSAVER_UPDATE_INTERVAL 500
|
||||
#define DISPLAY_HORIZONTAL_CHARACTER_COUNT 16
|
||||
#define DISPLAY_VERTICAL_LINE_COUNT 8
|
||||
void showStatusScreenScreensaver(display_task_parameters_t *objects)
|
||||
{
|
||||
//-- variables for line rotation --
|
||||
static int msPassed = 0;
|
||||
static int currentLine = 0;
|
||||
static bool lineChanging = false;
|
||||
// clear display once when rotating to next line
|
||||
if (lineChanging)
|
||||
{
|
||||
ssd1306_clear_screen(&dev, false);
|
||||
lineChanging = false;
|
||||
}
|
||||
//-- print 2 lines scrolling horizontally --
|
||||
#ifdef HARDWARE_SCROLL_AVAILABLE // when display supports hardware scrolling -> only the content has to be updated
|
||||
// note: scrolling is enabled at screen change (display_selectStatusPage())
|
||||
// update text every iteration to prevent empty screen at start
|
||||
displayTextLine(&dev, currentLine, false, false, "IDLE since:");
|
||||
displayTextLine(&dev, currentLine + 1, false, false, "%.1fh, B:%02.0f%%",
|
||||
(float)objects->control->getInactivityDurationMs() / 1000 / 60 / 60,
|
||||
getBatteryPercent());
|
||||
// note: scrolling is disabled at screen change (display_selectStatusPage())
|
||||
#else // custom implementation to scroll the text 1 character to the right every iteration (also wraps over the end to beginning)
|
||||
static int offset = DISPLAY_HORIZONTAL_CHARACTER_COUNT;
|
||||
char buf1[64], buf2[64];
|
||||
// scroll text left to right (taken window of the string moves to the left => offset 16->0, 16->0 ...)
|
||||
offset -= 1;
|
||||
if (offset < 0)
|
||||
offset = DISPLAY_HORIZONTAL_CHARACTER_COUNT - 1; // 0 = no crop -> start over with crop
|
||||
// note: these strings have to be symetrical and 2x display character count long
|
||||
snprintf(buf1, 64, "IDLE since: IDLE since: ");
|
||||
snprintf(buf2, 64, "%.1fh, B:%02.0f%% %.1fh, B:%02.0f%% ",
|
||||
(float)objects->control->getInactivityDurationMs() / 1000 / 60 / 60,
|
||||
getBatteryPercent(),
|
||||
(float)objects->control->getInactivityDurationMs() / 1000 / 60 / 60,
|
||||
getBatteryPercent());
|
||||
// print strings on display while limiting to certain window (ignore certain count of characters at start)
|
||||
displayTextLine(&dev, currentLine, false, false, "%s", buf1 + offset);
|
||||
displayTextLine(&dev, currentLine + 1, false, false, "%s", buf2 + offset);
|
||||
#endif
|
||||
//-- handle line rotation --
|
||||
// to not block the display task for several seconds returning every e.g. 500ms here
|
||||
// -> ensures detection of activity (exit condition) in task loop is handled regularly
|
||||
if (msPassed > STATUS_SCREEN_SCREENSAVER_DELAY_NEXT_LINE_MS) // switch to next line is due
|
||||
{
|
||||
msPassed = 0; // rest seconds count
|
||||
// increment / rotate to next line
|
||||
if (++currentLine >= DISPLAY_VERTICAL_LINE_COUNT - 1) // rotate to next line
|
||||
currentLine = 0;
|
||||
lineChanging = true; // clear screen in next run
|
||||
}
|
||||
//-- wait update interval --
|
||||
// wait and increment passed time after each run
|
||||
vTaskDelay(STATUS_SCREEN_SCREENSAVER_UPDATE_INTERVAL / portTICK_PERIOD_MS);
|
||||
msPassed += STATUS_SCREEN_SCREENSAVER_UPDATE_INTERVAL;
|
||||
}
|
||||
|
||||
|
||||
//########################
|
||||
//#### showStartupMsg ####
|
||||
//########################
|
||||
@ -353,16 +439,44 @@ void showStartupMsg(){
|
||||
//============================
|
||||
//===== selectStatusPage =====
|
||||
//============================
|
||||
void display_selectStatusPage(displayStatusPage_t newStatusPage){
|
||||
void display_selectStatusPage(displayStatusPage_t newStatusPage)
|
||||
{
|
||||
//-- run commands when switching FROM certain mode --
|
||||
switch (selectedStatusPage)
|
||||
{
|
||||
#ifdef HARDWARE_SCROLL_AVAILABLE
|
||||
case STATUS_SCREEN_SCREENSAVER:
|
||||
ssd1306_hardware_scroll(&dev, SCROLL_STOP); // disable scrolling when exiting screensaver
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ESP_LOGW(TAG, "switching statusPage from %d to %d", (int)selectedStatusPage, (int)newStatusPage);
|
||||
selectedStatusPage = newStatusPage;
|
||||
|
||||
//-- run commands when switching TO certain mode --
|
||||
switch (selectedStatusPage)
|
||||
{
|
||||
case STATUS_SCREEN_SCREENSAVER:
|
||||
ssd1306_clear_screen(&dev, false); // clear screen when switching
|
||||
#ifdef HARDWARE_SCROLL_AVAILABLE
|
||||
ssd1306_hardware_scroll(&dev, SCROLL_RIGHT);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============================
|
||||
//======= display task =======
|
||||
//============================
|
||||
// TODO: separate task for each loop?
|
||||
|
||||
void display_task(void *pvParameters)
|
||||
{
|
||||
ESP_LOGW(TAG, "Initializing display and starting handle loop");
|
||||
@ -403,6 +517,47 @@ void display_task(void *pvParameters)
|
||||
case STATUS_SCREEN_MOTORS:
|
||||
showStatusScreenMotors(objects);
|
||||
break;
|
||||
case STATUS_SCREEN_SCREENSAVER:
|
||||
showStatusScreenScreensaver(objects);
|
||||
break;
|
||||
}
|
||||
|
||||
//--- handle timeouts ---
|
||||
uint32_t inactiveMs = objects->control->getInactivityDurationMs();
|
||||
//-- screensaver --
|
||||
// handle switch to screensaver when no user input for a long time
|
||||
if (inactiveMs > displayConfig.timeoutSwitchToScreensaverMs) // timeout - switch to screensaver is due
|
||||
{
|
||||
if (selectedStatusPage != STATUS_SCREEN_SCREENSAVER){ // switch/log only once at change
|
||||
ESP_LOGW(TAG, "no activity for more than %d min, switching to screensaver", inactiveMs / 1000 / 60);
|
||||
display_selectStatusPage(STATUS_SCREEN_SCREENSAVER);
|
||||
}
|
||||
}
|
||||
else if (selectedStatusPage == STATUS_SCREEN_SCREENSAVER) // exit screensaver when there was recent activity
|
||||
{
|
||||
ESP_LOGW(TAG, "recent activity detected, disabling screensaver");
|
||||
display_selectStatusPage(STATUS_SCREEN_OVERVIEW);
|
||||
}
|
||||
|
||||
//-- reduce brightness --
|
||||
// handle brightness reduction when no user input for some time
|
||||
static bool brightnessIsReduced = false;
|
||||
if (inactiveMs > displayConfig.timeoutReduceContrastMs) // threshold exceeded - reduction of brightness is due
|
||||
{
|
||||
if (!brightnessIsReduced) //change / log only once at change
|
||||
{
|
||||
// reduce display brightness (less burn in)
|
||||
ESP_LOGW(TAG, "no activity for more than %d min, reducing display brightness to %d/255", inactiveMs / 1000 / 60, displayConfig.contrastReduced);
|
||||
ssd1306_contrast(&dev, displayConfig.contrastReduced);
|
||||
brightnessIsReduced = true;
|
||||
}
|
||||
}
|
||||
else if (brightnessIsReduced) // threshold not exceeded anymore, but still reduced
|
||||
{
|
||||
// increase display brighness again
|
||||
ESP_LOGW(TAG, "recent activity detected, increasing brightness again");
|
||||
ssd1306_contrast(&dev, displayConfig.contrastNormal);
|
||||
brightnessIsReduced = false;
|
||||
}
|
||||
}
|
||||
// TODO add pages and menus
|
||||
|
@ -22,6 +22,7 @@ extern "C" {
|
||||
|
||||
// configuration for initializing display (passed to task as well)
|
||||
typedef struct display_config_t {
|
||||
// initialization
|
||||
gpio_num_t gpio_scl;
|
||||
gpio_num_t gpio_sda;
|
||||
int gpio_reset; // negative number means reset pin is not connected or not used
|
||||
@ -29,7 +30,11 @@ typedef struct display_config_t {
|
||||
int height;
|
||||
int offsetX;
|
||||
bool flip;
|
||||
int contrast;
|
||||
// display-task
|
||||
int contrastNormal;
|
||||
int contrastReduced;
|
||||
uint32_t timeoutReduceContrastMs;
|
||||
uint32_t timeoutSwitchToScreensaverMs;
|
||||
} display_config_t;
|
||||
|
||||
|
||||
@ -49,11 +54,14 @@ typedef struct display_task_parameters_t {
|
||||
|
||||
|
||||
// enum for selecting the currently shown status page (display content when not in MENU mode)
|
||||
typedef enum displayStatusPage_t {STATUS_SCREEN_OVERVIEW=0, STATUS_SCREEN_SPEED, STATUS_SCREEN_JOYSTICK, STATUS_SCREEN_MOTORS} displayStatusPage_t;
|
||||
typedef enum displayStatusPage_t {STATUS_SCREEN_OVERVIEW=0, STATUS_SCREEN_SPEED, STATUS_SCREEN_JOYSTICK, STATUS_SCREEN_MOTORS, STATUS_SCREEN_SCREENSAVER} displayStatusPage_t;
|
||||
|
||||
// get precise battery voltage (using lookup table)
|
||||
float getBatteryVoltage();
|
||||
|
||||
// get battery charge level in percent (using lookup table as discharge curve)
|
||||
float getBatteryPercent();
|
||||
|
||||
// function to select one of the defined status screens which are shown on display when not in MENU mode
|
||||
void display_selectStatusPage(displayStatusPage_t newStatusPage);
|
||||
|
||||
|
@ -27,7 +27,6 @@ extern "C"
|
||||
#include "motorctl.hpp"
|
||||
|
||||
//folder single_board
|
||||
#include "config.hpp"
|
||||
#include "control.hpp"
|
||||
#include "button.hpp"
|
||||
#include "display.hpp"
|
||||
@ -108,7 +107,6 @@ nvs_handle_t nvsHandle;
|
||||
//=================================
|
||||
//initialize spi flash filesystem (used for webserver)
|
||||
void init_spiffs(){
|
||||
ESP_LOGW(TAG, "initializing spiffs...");
|
||||
esp_vfs_spiffs_conf_t esp_vfs_spiffs_conf = {
|
||||
.base_path = "/spiffs",
|
||||
.partition_label = NULL,
|
||||
@ -195,35 +193,29 @@ extern "C" void app_main(void) {
|
||||
gpio_set_direction(GPIO_NUM_17, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(GPIO_NUM_17, 1);
|
||||
|
||||
//--- initialize nvs-flash and netif (needed for wifi) ---
|
||||
ESP_LOGW(TAG,"initializing wifi...");
|
||||
wifi_initNvs_initNetif();
|
||||
//--- initialize nvs-flash and netif ---
|
||||
ESP_LOGW(TAG,"initializing NVS...");
|
||||
wifi_initNvs(); //needed for wifi and persistent config variables
|
||||
ESP_LOGW(TAG,"initializing NETIF...");
|
||||
wifi_initNetif(); // needed for wifi
|
||||
|
||||
//--- initialize spiffs ---
|
||||
init_spiffs();
|
||||
ESP_LOGW(TAG, "initializing SPIFFS...");
|
||||
init_spiffs(); // used by httpd server
|
||||
|
||||
//--- initialize and start wifi ---
|
||||
ESP_LOGW(TAG,"starting wifi...");
|
||||
//wifi_init_client(); //connect to existing wifi
|
||||
wifi_init_ap(); //start access point
|
||||
ESP_LOGD(TAG,"done starting wifi");
|
||||
// Note: now started only when switching to HTTP mode in control.cpp
|
||||
// ESP_LOGW(TAG,"starting wifi...");
|
||||
// wifi_start_client(); //connect to existing wifi (dropped)
|
||||
// wifi_start_ap(); //start access point
|
||||
|
||||
//--- initialize encoder ---
|
||||
const QueueHandle_t encoderQueue = encoder_init(&encoder_config);
|
||||
|
||||
//--- initialize nvs-flash --- (for persistant config values)
|
||||
ESP_LOGW(TAG, "initializing nvs-flash...");
|
||||
esp_err_t err = nvs_flash_init();
|
||||
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND)
|
||||
{
|
||||
ESP_LOGE(TAG, "NVS truncated -> deleting flash");
|
||||
// Retry nvs_flash_init
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
err = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(err);
|
||||
//--- open nvs-flash ---
|
||||
err = nvs_open("storage", NVS_READWRITE, &nvsHandle);
|
||||
// note: nvs already initialized in wifi_initNvs()
|
||||
ESP_LOGW(TAG, "opening NVS-handle...");
|
||||
esp_err_t err = nvs_open("storage", NVS_READWRITE, &nvsHandle); // this handle is passed to all tasks for accessing nvs
|
||||
if (err != ESP_OK)
|
||||
ESP_LOGE(TAG, "Error (%s) opening NVS handle!\n", esp_err_to_name(err));
|
||||
|
||||
|
@ -11,7 +11,6 @@ extern "C"{
|
||||
|
||||
#include "menu.hpp"
|
||||
#include "encoder.hpp"
|
||||
#include "config.hpp"
|
||||
#include "motorctl.hpp"
|
||||
|
||||
|
||||
@ -105,7 +104,7 @@ void item_calibrateJoystick_action(display_task_parameters_t *objects, SSD1306_t
|
||||
// save and next when button clicked, exit when long pressed
|
||||
if (xQueueReceive(objects->encoderQueue, &event, CALIBRATE_JOYSTICK_UPDATE_INTERVAL / portTICK_PERIOD_MS))
|
||||
{
|
||||
objects->control->resetTimeout();
|
||||
objects->control->resetTimeout(); // user input -> reset switch to IDLE timeout
|
||||
switch (event.type)
|
||||
{
|
||||
case RE_ET_BTN_CLICKED:
|
||||
@ -215,7 +214,7 @@ void item_debugJoystick_action(display_task_parameters_t * objects, SSD1306_t *
|
||||
// exit when button pressed
|
||||
if (xQueueReceive(objects->encoderQueue, &event, DEBUG_JOYSTICK_UPDATE_INTERVAL / portTICK_PERIOD_MS))
|
||||
{
|
||||
objects->control->resetTimeout();
|
||||
objects->control->resetTimeout(); // user input -> reset switch to IDLE timeout
|
||||
switch (event.type)
|
||||
{
|
||||
case RE_ET_BTN_CLICKED:
|
||||
@ -700,7 +699,7 @@ void handleMenu(display_task_parameters_t * objects, SSD1306_t *display)
|
||||
{
|
||||
// reset menu- and control-timeout on any encoder event
|
||||
lastActivity = esp_log_timestamp();
|
||||
objects->control->resetTimeout();
|
||||
objects->control->resetTimeout(); // user input -> reset switch to IDLE timeout
|
||||
switch (event.type)
|
||||
{
|
||||
case RE_ET_CHANGED:
|
||||
@ -771,7 +770,7 @@ void handleMenu(display_task_parameters_t * objects, SSD1306_t *display)
|
||||
// wait for encoder event
|
||||
if (xQueueReceive(objects->encoderQueue, &event, QUEUE_TIMEOUT / portTICK_PERIOD_MS))
|
||||
{
|
||||
objects->control->resetTimeout();
|
||||
objects->control->resetTimeout(); // user input -> reset switch to IDLE timeout
|
||||
switch (event.type)
|
||||
{
|
||||
case RE_ET_CHANGED:
|
||||
@ -811,7 +810,7 @@ void handleMenu(display_task_parameters_t * objects, SSD1306_t *display)
|
||||
}
|
||||
// reset menu- and control-timeout on any encoder event
|
||||
lastActivity = esp_log_timestamp();
|
||||
objects->control->resetTimeout();
|
||||
objects->control->resetTimeout(); // user input -> reset switch to IDLE timeout
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -21,26 +21,45 @@ static const char *TAG = "wifi";
|
||||
static esp_event_handler_instance_t instance_any_id;
|
||||
|
||||
|
||||
//============================================
|
||||
//============ init nvs and netif ============
|
||||
//============================================
|
||||
//initialize nvs-flash and netif (needed for both AP and CLIENT)
|
||||
//##########################################
|
||||
//############ common functions ############
|
||||
//##########################################
|
||||
|
||||
//============================
|
||||
//========= init nvs =========
|
||||
//============================
|
||||
//initialize nvs-flash (needed for both AP and CLIENT)
|
||||
//has to be run once at startup
|
||||
void wifi_initNvs_initNetif(){
|
||||
void wifi_initNvs(){
|
||||
//Initialize NVS (needed for wifi)
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
esp_err_t err = nvs_flash_init();
|
||||
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND)
|
||||
{
|
||||
ESP_LOGE(TAG, "NVS truncated -> deleting flash");
|
||||
// Retry nvs_flash_init
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
err = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(err);
|
||||
}
|
||||
|
||||
|
||||
//==============================
|
||||
//========= init netif =========
|
||||
//==============================
|
||||
//initialize netif (needed for both AP and CLIENT)
|
||||
//has to be run once at startup
|
||||
void wifi_initNetif(){
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
}
|
||||
|
||||
|
||||
//===========================================
|
||||
//============ init access point ============
|
||||
//===========================================
|
||||
|
||||
|
||||
//############################################
|
||||
//############### access point ###############
|
||||
//############################################
|
||||
|
||||
//--------------------------------------------
|
||||
//------ configuration / declarations --------
|
||||
@ -66,10 +85,12 @@ static void wifi_event_handler_ap(void* arg, esp_event_base_t event_base,
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------
|
||||
//------ init ap --------
|
||||
//-----------------------
|
||||
void wifi_init_ap(void)
|
||||
|
||||
|
||||
//========================
|
||||
//====== start AP ========
|
||||
//========================
|
||||
void wifi_start_ap(void)
|
||||
{
|
||||
ap = esp_netif_create_default_wifi_ap();
|
||||
|
||||
@ -107,9 +128,9 @@ void wifi_init_ap(void)
|
||||
|
||||
|
||||
//=============================
|
||||
//========= deinit AP =========
|
||||
//========== stop AP ==========
|
||||
//=============================
|
||||
void wifi_deinit_ap(void)
|
||||
void wifi_stop_ap(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id));
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id));
|
||||
@ -123,9 +144,9 @@ void wifi_deinit_ap(void)
|
||||
|
||||
|
||||
|
||||
//===========================================
|
||||
//=============== init client ===============
|
||||
//===========================================
|
||||
//##########################################
|
||||
//################# client #################
|
||||
//##########################################
|
||||
|
||||
//--------------------------------------------
|
||||
//------ configuration / declarations --------
|
||||
@ -168,10 +189,13 @@ static void event_handler(void* arg, esp_event_base_t event_base,
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||
}
|
||||
}
|
||||
//---------------------------
|
||||
//------ init client --------
|
||||
//---------------------------
|
||||
void wifi_init_client(void)
|
||||
|
||||
|
||||
|
||||
//===========================
|
||||
//====== init client ========
|
||||
//===========================
|
||||
void wifi_start_client(void)
|
||||
{
|
||||
s_wifi_event_group = xEventGroupCreate();
|
||||
sta = esp_netif_create_default_wifi_sta();
|
||||
@ -249,10 +273,10 @@ void wifi_init_client(void)
|
||||
|
||||
|
||||
|
||||
//=================================
|
||||
//========= deinit client =========
|
||||
//=================================
|
||||
void wifi_deinit_client(void)
|
||||
//===============================
|
||||
//========= stop client =========
|
||||
//===============================
|
||||
void wifi_stop_client(void)
|
||||
{
|
||||
/* The event will not be processed after unregister */
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip));
|
||||
|
@ -3,20 +3,20 @@
|
||||
//TODO: currently wifi names and passwords are configured in wifi.c -> move this to config?
|
||||
|
||||
//initialize nvs-flash and netif (needed for both AP and CLIENT)
|
||||
//has to be run once at startup
|
||||
//Note: this cant be put in wifi_init functions because this may not be in deinit functions
|
||||
void wifi_initNvs_initNetif();
|
||||
//both functions have to be run once at startup
|
||||
void wifi_initNvs();
|
||||
void wifi_initNetif();
|
||||
|
||||
|
||||
//function to start an access point
|
||||
void wifi_init_ap(void);
|
||||
//function to disable/deinit access point
|
||||
void wifi_deinit_ap(void);
|
||||
//function to start an access point (config in wifi.c)
|
||||
void wifi_start_ap(void);
|
||||
//function to disable/stop access point
|
||||
void wifi_stop_ap(void);
|
||||
|
||||
//function to connect to existing wifi network
|
||||
void wifi_init_client(void);
|
||||
//function to connect to existing wifi network (config in wifi.c)
|
||||
void wifi_start_client(void);
|
||||
//function to disable/deinit client
|
||||
void wifi_deinit_client(void);
|
||||
void wifi_stop_client(void);
|
||||
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user