Merge branch 'project-structure' into dev - objects in heap
Almost all objects are stored in heap and passed to tasks via pointers now, thus eliminating global variables and making the code more understandable
This commit is contained in:
commit
dab6a437c0
@ -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,59 @@
|
||||
#include "config.hpp"
|
||||
// NOTE: this file is included in main.cpp only.
|
||||
// outsourced all configuration related functions and structures to this file:
|
||||
|
||||
//===================================
|
||||
//======= motor configuration =======
|
||||
//===================================
|
||||
extern "C"
|
||||
{
|
||||
#include "esp_log.h"
|
||||
}
|
||||
#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"
|
||||
#include "display.hpp"
|
||||
#include "encoder.h"
|
||||
|
||||
//==================================
|
||||
//======== 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 +62,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 +75,147 @@ 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 ===
|
||||
//============================
|
||||
fan_config_t configCooling = {
|
||||
//----------------------------
|
||||
//--- configure fan contol ---
|
||||
//----------------------------
|
||||
fan_config_t configFans = {
|
||||
.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);
|
||||
//-------------------------
|
||||
//-------- display --------
|
||||
//-------------------------
|
||||
display_config_t display_config {
|
||||
.gpio_scl = GPIO_NUM_22,
|
||||
.gpio_sda = GPIO_NUM_23,
|
||||
.gpio_reset = GPIO_NUM_15,
|
||||
.width = 128,
|
||||
.height = 64,
|
||||
.offsetX = 2,
|
||||
.flip = false,
|
||||
.contrast = 0xff, //max: 255
|
||||
};
|
||||
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");
|
||||
|
||||
|
||||
|
||||
//-------------------------
|
||||
//-------- encoder --------
|
||||
//-------------------------
|
||||
//configure rotary encoder (next to joystick)
|
||||
rotary_encoder_t encoder_config = {
|
||||
.pin_a = GPIO_NUM_25,
|
||||
.pin_b = GPIO_NUM_26,
|
||||
.pin_btn = GPIO_NUM_27,
|
||||
.code = 1,
|
||||
.store = 0, //encoder count
|
||||
.index = 0,
|
||||
.btn_pressed_time_us = 20000,
|
||||
.btn_state = RE_BTN_RELEASED //default state
|
||||
};
|
@ -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;
|
||||
|
@ -8,15 +8,6 @@ extern "C"{
|
||||
|
||||
|
||||
|
||||
//==== display config ====
|
||||
#define I2C_INTERFACE y
|
||||
#define SCL_GPIO 22
|
||||
#define SDA_GPIO 23
|
||||
#define RESET_GPIO 15 // FIXME remove this
|
||||
// the following options are set in menuconfig: (see sdkconfig)
|
||||
// #define CONFIG_OFFSETX 2 //note: the larger display (actual 130x64) needs 2 pixel offset (prevents bugged column)
|
||||
// #define CONFIG_I2C_PORT_0 y
|
||||
|
||||
//=== content config ===
|
||||
#define STARTUP_MSG_TIMEOUT 2000
|
||||
#define ADC_BATT_VOLTAGE ADC1_CHANNEL_6
|
||||
@ -55,22 +46,21 @@ static const char * TAG = "display";
|
||||
//==== display_init ====
|
||||
//======================
|
||||
//note CONFIG_OFFSETX is used (from menuconfig)
|
||||
void display_init(){
|
||||
void display_init(display_config_t config){
|
||||
adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); //max voltage
|
||||
ESP_LOGW("display", "INTERFACE is i2c");
|
||||
ESP_LOGW("display", "SDA_GPIO=%d",SDA_GPIO);
|
||||
ESP_LOGW("display", "SCL_GPIO=%d",SCL_GPIO);
|
||||
ESP_LOGW("display", "RESET_GPIO=%d",RESET_GPIO);
|
||||
i2c_master_init(&dev, SDA_GPIO, SCL_GPIO, RESET_GPIO);
|
||||
#if FLIP
|
||||
dev._flip = true;
|
||||
ESP_LOGW("display", "Flip upside down");
|
||||
#endif
|
||||
ESP_LOGI("display", "Panel is 128x64");
|
||||
ssd1306_init(&dev, 128, 64);
|
||||
ESP_LOGW(TAG, "Initializing Display...");
|
||||
ESP_LOGI(TAG, "config: sda=%d, sdl=%d, reset=%d, offset=%d, flip=%d, size: %dx%d",
|
||||
config.gpio_sda, config.gpio_scl, config.gpio_reset, config.offsetX, config.flip, config.width, config.height);
|
||||
|
||||
i2c_master_init(&dev, config.gpio_sda, config.gpio_scl, config.gpio_reset);
|
||||
if (config.flip) {
|
||||
dev._flip = true;
|
||||
ESP_LOGW(TAG, "Flip upside down");
|
||||
}
|
||||
ssd1306_init(&dev, config.width, config.height, config.offsetX);
|
||||
|
||||
ssd1306_clear_screen(&dev, false);
|
||||
ssd1306_contrast(&dev, 0xff);
|
||||
ssd1306_contrast(&dev, config.contrast);
|
||||
}
|
||||
|
||||
|
||||
@ -204,7 +194,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 +204,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,8 +254,12 @@ void showStartupMsg(){
|
||||
|
||||
void display_task(void *pvParameters)
|
||||
{
|
||||
ESP_LOGW(TAG, "Initializing display and starting handle loop");
|
||||
//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();
|
||||
display_init(objects->displayConfig);
|
||||
// TODO check if successfully initialized
|
||||
|
||||
// show startup message
|
||||
@ -276,14 +270,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,36 @@ extern "C" {
|
||||
#include "font8x8_basic.h"
|
||||
}
|
||||
|
||||
#include "config.hpp"
|
||||
|
||||
#include "joystick.hpp"
|
||||
#include "control.hpp"
|
||||
#include "speedsensor.hpp"
|
||||
|
||||
// configuration for initializing display (passed to task as well)
|
||||
typedef struct display_config_t {
|
||||
gpio_num_t gpio_scl;
|
||||
gpio_num_t gpio_sda;
|
||||
gpio_num_t gpio_reset;
|
||||
int width;
|
||||
int height;
|
||||
int offsetX;
|
||||
bool flip;
|
||||
int contrast;
|
||||
} display_config_t;
|
||||
|
||||
|
||||
// struct with variables passed to task from main()
|
||||
typedef struct display_task_parameters_t {
|
||||
display_config_t displayConfig;
|
||||
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
|
||||
|
@ -17,33 +17,23 @@ extern "C"
|
||||
//------- variables -------
|
||||
//-------------------------
|
||||
static const char * TAG = "encoder";
|
||||
uint16_t encoderCount;
|
||||
rotary_encoder_btn_state_t encoderButtonState = {};
|
||||
//global event queue:
|
||||
QueueHandle_t encoderQueue = NULL;
|
||||
|
||||
//encoder config
|
||||
rotary_encoder_t encoderConfig = {
|
||||
.pin_a = PIN_A,
|
||||
.pin_b = PIN_B,
|
||||
.pin_btn = PIN_BUTTON,
|
||||
.code = 1,
|
||||
.store = encoderCount,
|
||||
.index = 0,
|
||||
.btn_pressed_time_us = 20000,
|
||||
.btn_state = encoderButtonState
|
||||
};
|
||||
|
||||
|
||||
|
||||
//==================================
|
||||
//========== 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(rotary_encoder_t * encoderConfig)
|
||||
{
|
||||
QueueHandle_t encoderQueue = xQueueCreate(QUEUE_SIZE, sizeof(rotary_encoder_event_t));
|
||||
rotary_encoder_init(encoderQueue);
|
||||
rotary_encoder_add(&encoderConfig);
|
||||
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 +42,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)) {
|
||||
|
@ -6,15 +6,12 @@ extern "C" {
|
||||
|
||||
//config
|
||||
#define QUEUE_SIZE 10
|
||||
#define PIN_A GPIO_NUM_25
|
||||
#define PIN_B GPIO_NUM_26
|
||||
#define PIN_BUTTON GPIO_NUM_27
|
||||
|
||||
//global encoder queue
|
||||
extern QueueHandle_t encoderQueue;
|
||||
//init encoder with pointer to encoder config
|
||||
QueueHandle_t encoder_init(rotary_encoder_t * encoderConfig);
|
||||
|
||||
//init encoder with config in encoder.cpp
|
||||
void encoder_init();
|
||||
|
||||
//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);
|
@ -12,6 +12,28 @@ extern "C"
|
||||
static const char * TAG = "fan-control";
|
||||
|
||||
|
||||
//=======================================
|
||||
//============== fan task ===============
|
||||
//=======================================
|
||||
//task that controlls fans for cooling the drivers
|
||||
//turns fan on/off depending on motor duty history
|
||||
void task_fans( void * task_fans_parameters ){
|
||||
//get configuration struct from task parameter
|
||||
task_fans_parameters_t *objects = (task_fans_parameters_t *)task_fans_parameters;
|
||||
|
||||
//create fan instances with config defined in config.cpp
|
||||
ESP_LOGI(TAG, "Initializing fans and starting fan handle loop");
|
||||
controlledFan fan(objects->fan_config, objects->motorLeft, objects->motorRight);
|
||||
|
||||
//repeatedly run fan handle function in a slow loop
|
||||
while(1){
|
||||
fan.handle();
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------
|
||||
//-------- constructor --------
|
||||
//-----------------------------
|
||||
|
@ -16,7 +16,22 @@ typedef struct fan_config_t {
|
||||
uint32_t minOnMs;
|
||||
uint32_t minOffMs;
|
||||
uint32_t turnOffDelayMs;
|
||||
} fan_config;
|
||||
} fan_config_t;
|
||||
|
||||
|
||||
// struct with variables passed to task from main
|
||||
typedef struct task_fans_parameters_t {
|
||||
fan_config_t fan_config;
|
||||
controlledMotor * motorLeft;
|
||||
controlledMotor * motorRight;
|
||||
} task_fans_parameters_t;
|
||||
|
||||
|
||||
//====================================
|
||||
//========== motorctl task ===========
|
||||
//====================================
|
||||
//note: pointer to task_fans_parameters_t has to be passed as task-parameter (config, motor objects)
|
||||
void task_fans( void * task_fans_parameters );
|
||||
|
||||
|
||||
|
||||
|
@ -1,6 +1,3 @@
|
||||
#include "hal/uart_types.h"
|
||||
#include "motordrivers.hpp"
|
||||
#include "types.hpp"
|
||||
extern "C"
|
||||
{
|
||||
#include <stdio.h>
|
||||
@ -14,107 +11,100 @@ extern "C"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_spiffs.h"
|
||||
|
||||
#include "driver/ledc.h"
|
||||
|
||||
//custom C files
|
||||
#include "wifi.h"
|
||||
}
|
||||
|
||||
#include <new>
|
||||
|
||||
//custom C++ files
|
||||
//folder common
|
||||
#include "uart_common.hpp"
|
||||
#include "motordrivers.hpp"
|
||||
#include "http.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"
|
||||
|
||||
//tag for logging
|
||||
//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;
|
||||
|
||||
// TODO initialize driver in createOjects like everything else
|
||||
// (as in 6e9b3d96d96947c53188be1dec421bd7ff87478e)
|
||||
// issue with laggy encoder wenn calling methods via pointer though
|
||||
//sabertooth2x60a *sabertoothDriver;
|
||||
sabertooth2x60a sabertoothDriver(sabertoothConfig);
|
||||
|
||||
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)
|
||||
{
|
||||
//TODO why encoder lag when call via pointer?
|
||||
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 =============
|
||||
//======================================
|
||||
//TODO: move the task creation to buzzer class (buzzer.cpp)
|
||||
//e.g. only have function buzzer.createTask() in app_main
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=======================================
|
||||
//============== fan task ===============
|
||||
//=======================================
|
||||
//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);
|
||||
//repeatedly run fan handle function in a slow loop
|
||||
while(1){
|
||||
fan.handle();
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=================================
|
||||
//========== init spiffs ==========
|
||||
//=================================
|
||||
//initialize spi flash filesystem (used for webserver)
|
||||
void init_spiffs(){
|
||||
ESP_LOGI(TAG, "init spiffs");
|
||||
ESP_LOGW(TAG, "initializing spiffs...");
|
||||
esp_vfs_spiffs_conf_t esp_vfs_spiffs_conf = {
|
||||
.base_path = "/spiffs",
|
||||
.partition_label = NULL,
|
||||
@ -132,31 +122,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 from config.cpp
|
||||
motorLeft = new controlledMotor(setLeftFunc, configMotorControlLeft);
|
||||
motorRight = new controlledMotor(setRightFunc, configMotorControlRight);
|
||||
|
||||
// create speedsensor instances
|
||||
// with configurations from config.cpp
|
||||
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 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");
|
||||
|
||||
// create control object (control.hpp)
|
||||
// with configuration from config.cpp
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -166,75 +179,108 @@ void setLoglevels(void){
|
||||
//=========== app_main ============
|
||||
//=================================
|
||||
extern "C" void app_main(void) {
|
||||
//enable 5V volate regulator
|
||||
ESP_LOGW(TAG, "===== BOOT (pre main) Completed =====\n");
|
||||
|
||||
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();
|
||||
|
||||
// init encoder
|
||||
//--- initialize encoder ---
|
||||
encoder_init();
|
||||
// now global encoderQueue providing all encoder events is available
|
||||
|
||||
//----------------------------------------------
|
||||
//--- 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);
|
||||
|
||||
//------------------------------
|
||||
//--- create task for buzzer ---
|
||||
//------------------------------
|
||||
xTaskCreate(&task_buzzer, "task_buzzer", 2048, NULL, 2, NULL);
|
||||
|
||||
//-------------------------------
|
||||
//--- 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);
|
||||
|
||||
//------------------------------
|
||||
//--- 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);
|
||||
|
||||
//-----------------------------------
|
||||
//--- create task for fan control ---
|
||||
//-----------------------------------
|
||||
//task that evaluates and processes the button input and runs the configured commands
|
||||
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);
|
||||
|
||||
|
||||
//beep at startup
|
||||
buzzer.beep(3, 70, 50);
|
||||
|
||||
//--- initialize nvs-flash and netif (needed for wifi) ---
|
||||
ESP_LOGW(TAG,"initializing 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...");
|
||||
ESP_LOGW(TAG,"starting wifi...");
|
||||
//wifi_init_client(); //connect to existing wifi
|
||||
wifi_init_ap(); //start access point
|
||||
ESP_LOGI(TAG,"done starting wifi");
|
||||
ESP_LOGD(TAG,"done starting wifi");
|
||||
|
||||
//--- initialize encoder ---
|
||||
const QueueHandle_t encoderQueue = encoder_init(&encoder_config);
|
||||
|
||||
printf("\n");
|
||||
|
||||
|
||||
|
||||
//--- create all objects ---
|
||||
ESP_LOGW(TAG, "===== CREATING SHARED OBJECTS =====");
|
||||
|
||||
//initialize sabertooth object in STACK (due to performance issues in heap)
|
||||
///sabertoothDriver = static_cast<sabertooth2x60a*>(alloca(sizeof(sabertooth2x60a)));
|
||||
///new (sabertoothDriver) sabertooth2x60a(sabertoothConfig);
|
||||
|
||||
//create all class instances used below in HEAP
|
||||
createObjects();
|
||||
|
||||
printf("\n");
|
||||
|
||||
|
||||
|
||||
//--- 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
|
||||
task_motorctl_parameters_t motorctl_param = {motorLeft, motorRight};
|
||||
xTaskCreate(&task_motorctl, "task_motor-control", 2*4096, &motorctl_param, 6, NULL);
|
||||
|
||||
//------------------------------
|
||||
//--- create task for buzzer ---
|
||||
//------------------------------
|
||||
//task that processes queued beeps
|
||||
//note: pointer to shard object 'buzzer' is passed as task parameter:
|
||||
xTaskCreate(&task_buzzer, "task_buzzer", 2048, buzzer, 2, NULL);
|
||||
|
||||
//-------------------------------
|
||||
//--- create task for control ---
|
||||
//-------------------------------
|
||||
//task that generates motor commands depending on the current mode and sends those to motorctl task
|
||||
//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 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, 3, NULL);
|
||||
|
||||
//-----------------------------------
|
||||
//--- create task for fan control ---
|
||||
//-----------------------------------
|
||||
//task that controls cooling fans of the motor driver
|
||||
task_fans_parameters_t fans_param = {configFans, motorLeft, motorRight};
|
||||
xTaskCreate(&task_fans, "task_fans", 2048, &fans_param, 1, NULL);
|
||||
|
||||
//-----------------------------------
|
||||
//----- create task for display -----
|
||||
//-----------------------------------
|
||||
////task that handles the display (show stats, handle menu in 'MENU' mode)
|
||||
display_task_parameters_t display_param = {display_config, control, joystick, encoderQueue, motorLeft, motorRight, speedLeft, speedRight, buzzer};
|
||||
xTaskCreate(&display_task, "display_task", 3*2048, &display_param, 3, NULL);
|
||||
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS); //wait for all tasks to finish initializing
|
||||
printf("\n");
|
||||
|
||||
|
||||
|
||||
//--- startup finished ---
|
||||
ESP_LOGW(TAG, "===== STARTUP FINISHED =====\n");
|
||||
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,15 +289,17 @@ 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);
|
||||
|
||||
|
||||
|
||||
//--- main loop ---
|
||||
//does nothing except for testing things
|
||||
while(1){
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
vTaskDelay(portMAX_DELAY);
|
||||
//vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
|
||||
//---------------------------------
|
||||
//-------- TESTING section --------
|
||||
//---------------------------------
|
||||
|
@ -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
|
||||
|
||||
#
|
||||
|
@ -2,6 +2,19 @@
|
||||
|
||||
static const char *TAG_BUZZER = "buzzer";
|
||||
|
||||
//======================================
|
||||
//============ buzzer task =============
|
||||
//======================================
|
||||
// Task that repeatedly handles the buzzer object (process Queued beeps)
|
||||
void task_buzzer(void * param_buzzerObject){
|
||||
ESP_LOGI("task_buzzer", "Start of buzzer task...");
|
||||
buzzer_t * buzzer = (buzzer_t *)param_buzzerObject;
|
||||
//run function that waits for a beep events to arrive in the queue
|
||||
//and processes them
|
||||
buzzer->processQueue();
|
||||
}
|
||||
|
||||
|
||||
//============================
|
||||
//========== init ============
|
||||
//============================
|
||||
|
@ -53,4 +53,9 @@ class buzzer_t {
|
||||
};
|
||||
|
||||
|
||||
|
||||
//======================================
|
||||
//============ buzzer task =============
|
||||
//======================================
|
||||
// Task that repeatedly handles the buzzer object (process Queued beeps)
|
||||
// Note: pointer to globally initialized buzzer object has to be passed as task-parameter
|
||||
void task_buzzer(void * param_buzzerObject);
|
@ -48,6 +48,7 @@ void cControlledRest::init()
|
||||
// both relays off initially
|
||||
gpio_set_level(gpio_down, 0);
|
||||
gpio_set_level(gpio_up, 0);
|
||||
state = REST_OFF;
|
||||
}
|
||||
|
||||
|
||||
@ -105,7 +106,10 @@ void controlChairAdjustment(joystickData_t data, cControlledRest * legRest, cCon
|
||||
//leg rest (x-axis)
|
||||
if (data.x > stickThreshold) legRest->setState(REST_UP);
|
||||
else if (data.x < -stickThreshold) legRest->setState(REST_DOWN);
|
||||
else legRest->setState(REST_OFF);
|
||||
|
||||
//back rest (y-axis)
|
||||
if (data.y > stickThreshold) backRest->setState(REST_UP);
|
||||
else if (data.y < -stickThreshold) backRest->setState(REST_DOWN);
|
||||
else backRest->setState(REST_OFF);
|
||||
}
|
||||
|
@ -17,12 +17,12 @@ extern const char* restStateStr[];
|
||||
//class that controls 2 relays powering a motor that moves a rest of the armchair up or down
|
||||
//2 instances will be created one for back and one for leg rest
|
||||
class cControlledRest {
|
||||
public:
|
||||
cControlledRest(gpio_num_t gpio_up, gpio_num_t gpio_down, const char * name);
|
||||
public:
|
||||
cControlledRest(gpio_num_t gpio_up, gpio_num_t gpio_down, const char *name);
|
||||
void setState(restState_t targetState);
|
||||
void stop();
|
||||
|
||||
private:
|
||||
private:
|
||||
void init();
|
||||
|
||||
char name[32];
|
||||
|
@ -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(15 / 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");
|
||||
|
||||
}
|
||||
|
||||
|
@ -64,8 +64,8 @@ class controlledMotor {
|
||||
float currentMax;
|
||||
float currentNow;
|
||||
|
||||
float dutyTarget;
|
||||
float dutyNow;
|
||||
float dutyTarget = 0;
|
||||
float dutyNow = 0;
|
||||
float dutyIncrementAccel;
|
||||
float dutyIncrementDecel;
|
||||
float dutyDelta;
|
||||
@ -74,7 +74,7 @@ class controlledMotor {
|
||||
uint32_t msFadeDecel;
|
||||
|
||||
uint32_t ramp;
|
||||
int64_t timestampLastRunUs;
|
||||
int64_t timestampLastRunUs = 0;
|
||||
|
||||
bool deadTimeWaiting = false;
|
||||
uint32_t timestampsModeLastActive[4] = {};
|
||||
@ -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 );
|
||||
|
||||
|
@ -7,6 +7,9 @@
|
||||
static const char* TAG = "speedSensor";
|
||||
|
||||
|
||||
//initialize ISR only once (for multiple instances)
|
||||
bool speedSensor::isrIsInitialized = false;
|
||||
|
||||
|
||||
uint32_t min(uint32_t a, uint32_t b){
|
||||
if (a>b) return b;
|
||||
@ -84,11 +87,8 @@ void IRAM_ATTR onEncoderChange(void* arg) {
|
||||
speedSensor::speedSensor(speedSensor_config_t config_f){
|
||||
//copy config
|
||||
config = config_f;
|
||||
//note: currently gets initialized at first method call
|
||||
//this prevents crash due to too early initialization at boot
|
||||
//TODO: create global objects later after boot
|
||||
//init gpio and ISR
|
||||
//init();
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
@ -102,15 +102,16 @@ void speedSensor::init() {
|
||||
gpio_pad_select_gpio(config.gpioPin);
|
||||
gpio_set_direction(config.gpioPin, GPIO_MODE_INPUT);
|
||||
gpio_set_pull_mode(config.gpioPin, GPIO_PULLUP_ONLY);
|
||||
ESP_LOGW(TAG, "%s, configured gpio-pin %d", config.logName, (int)config.gpioPin);
|
||||
|
||||
//configure interrupt
|
||||
gpio_set_intr_type(config.gpioPin, GPIO_INTR_ANYEDGE);
|
||||
gpio_install_isr_service(0);
|
||||
if (!isrIsInitialized) {
|
||||
gpio_install_isr_service(0);
|
||||
isrIsInitialized = true;
|
||||
ESP_LOGW(TAG, "Initialized ISR service");
|
||||
}
|
||||
gpio_isr_handler_add(config.gpioPin, onEncoderChange, this);
|
||||
ESP_LOGW(TAG, "%s, configured interrupt", config.logName);
|
||||
|
||||
isInitialized = true;
|
||||
ESP_LOGW(TAG, "[%s], configured gpio-pin %d and interrupt routine", config.logName, (int)config.gpioPin);
|
||||
}
|
||||
|
||||
|
||||
@ -121,8 +122,6 @@ void speedSensor::init() {
|
||||
//==========================
|
||||
//get rotational speed in revolutions per minute
|
||||
float speedSensor::getRpm(){
|
||||
//check if initialized
|
||||
if (!isInitialized) init();
|
||||
uint32_t timeElapsed = esp_timer_get_time() - lastEdgeTime;
|
||||
//timeout (standstill)
|
||||
//TODO variable timeout considering config.degreePerGroup
|
||||
|
@ -24,8 +24,8 @@ class speedSensor {
|
||||
public:
|
||||
//constructor
|
||||
speedSensor(speedSensor_config_t config);
|
||||
//initializes gpio pin and configures interrupt
|
||||
void init();
|
||||
// initializes gpio pin, configures and starts interrupt
|
||||
void init();
|
||||
|
||||
//negative values = reverse direction
|
||||
//positive values = forward direction
|
||||
@ -35,8 +35,7 @@ public:
|
||||
|
||||
//1=forward, -1=reverse
|
||||
int direction;
|
||||
|
||||
//variables for handling the encoder
|
||||
//variables for handling the encoder (public because ISR needs access)
|
||||
speedSensor_config_t config;
|
||||
int prevState = 0;
|
||||
uint64_t pulseDurations[3] = {};
|
||||
@ -44,10 +43,9 @@ public:
|
||||
uint8_t pulseCounter = 0;
|
||||
int debugCount = 0;
|
||||
double currentRpm = 0;
|
||||
bool isInitialized = false;
|
||||
|
||||
private:
|
||||
|
||||
static bool isrIsInitialized; // default false due to static
|
||||
};
|
||||
|
||||
|
||||
|
@ -12,6 +12,7 @@ extern "C"
|
||||
//====== struct/type declarations ======
|
||||
//=======================================
|
||||
//global structs and types that need to be available for all boards
|
||||
//this file is necessary to prevent dependency loop between motordrivers.hpp and motorctl.hpp since
|
||||
|
||||
|
||||
//===============================
|
||||
|
@ -17,8 +17,10 @@ typedef union out_column_t {
|
||||
uint8_t u8[4];
|
||||
} PACK8 out_column_t;
|
||||
|
||||
void ssd1306_init(SSD1306_t * dev, int width, int height)
|
||||
//void ssd1306_init(SSD1306_t * dev, int width, int height, int offsetX) //original
|
||||
void ssd1306_init(SSD1306_t * dev, int width, int height, int offsetX)
|
||||
{
|
||||
dev->_offsetX = offsetX;
|
||||
if (dev->_address == SPIAddress) {
|
||||
spi_init(dev, width, height);
|
||||
} else {
|
||||
|
@ -98,6 +98,7 @@ typedef struct {
|
||||
int _scDirection;
|
||||
PAGE_t _page[8];
|
||||
bool _flip;
|
||||
int _offsetX; //added offset here instead of using macro variable
|
||||
} SSD1306_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -105,7 +106,7 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
void ssd1306_init(SSD1306_t * dev, int width, int height);
|
||||
void ssd1306_init(SSD1306_t * dev, int width, int height, int offsetX);
|
||||
int ssd1306_get_width(SSD1306_t * dev);
|
||||
int ssd1306_get_height(SSD1306_t * dev);
|
||||
int ssd1306_get_pages(SSD1306_t * dev);
|
||||
@ -128,6 +129,7 @@ void _ssd1306_pixel(SSD1306_t * dev, int xpos, int ypos, bool invert);
|
||||
void _ssd1306_line(SSD1306_t * dev, int x1, int y1, int x2, int y2, bool invert);
|
||||
void ssd1306_invert(uint8_t *buf, size_t blen);
|
||||
void ssd1306_flip(uint8_t *buf, size_t blen);
|
||||
void ssd1306_setOffset(SSD1306_t * dev, int offset);
|
||||
uint8_t ssd1306_copy_bit(uint8_t src, int srcBits, uint8_t dst, int dstBits);
|
||||
uint8_t ssd1306_rotate_byte(uint8_t ch1);
|
||||
void ssd1306_fadeout(SSD1306_t * dev);
|
||||
|
@ -112,7 +112,8 @@ void i2c_display_image(SSD1306_t * dev, int page, int seg, uint8_t * images, int
|
||||
if (page >= dev->_pages) return;
|
||||
if (seg >= dev->_width) return;
|
||||
|
||||
int _seg = seg + CONFIG_OFFSETX;
|
||||
//int _seg = seg + CONFIG_OFFSETX; //original
|
||||
int _seg = seg + dev->_offsetX;
|
||||
uint8_t columLow = _seg & 0x0F;
|
||||
uint8_t columHigh = (_seg >> 4) & 0x0F;
|
||||
|
||||
|
@ -158,7 +158,8 @@ void spi_display_image(SSD1306_t * dev, int page, int seg, uint8_t * images, int
|
||||
if (page >= dev->_pages) return;
|
||||
if (seg >= dev->_width) return;
|
||||
|
||||
int _seg = seg + CONFIG_OFFSETX;
|
||||
//int _seg = seg + CONFIG_OFFSETX; //original
|
||||
int _seg = seg + dev->_offsetX;
|
||||
uint8_t columLow = _seg & 0x0F;
|
||||
uint8_t columHigh = (_seg >> 4) & 0x0F;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user