Outsource currentsensor, motorctl, motordrivers to common/
since board_single uses mostly the same code as board_control and board_motorctl several files are outsorced to common folder to prevent dupliate code and different versions
This commit is contained in:
parent
ee5bad53ee
commit
13b896accb
@ -1,11 +1,8 @@
|
||||
idf_component_register(
|
||||
SRCS
|
||||
"main.cpp"
|
||||
"motordrivers.cpp"
|
||||
"motorctl.cpp"
|
||||
"config.cpp"
|
||||
"fan.cpp"
|
||||
"currentsensor.cpp"
|
||||
"uart.cpp"
|
||||
INCLUDE_DIRS
|
||||
"."
|
||||
|
@ -5,4 +5,5 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(armchair)
|
||||
set(EXTRA_COMPONENT_DIRS "../components ../common")
|
||||
project(armchair-singleBoard)
|
||||
|
@ -1,18 +1,13 @@
|
||||
idf_component_register(
|
||||
SRCS
|
||||
"main.cpp"
|
||||
"motordrivers.cpp"
|
||||
"motorctl.cpp"
|
||||
"config.cpp"
|
||||
"joystick.cpp"
|
||||
"buzzer.cpp"
|
||||
"control.cpp"
|
||||
"button.cpp"
|
||||
"fan.cpp"
|
||||
"wifi.c"
|
||||
"http.cpp"
|
||||
"auto.cpp"
|
||||
"currentsensor.cpp"
|
||||
INCLUDE_DIRS
|
||||
"."
|
||||
)
|
||||
|
@ -1,95 +0,0 @@
|
||||
#include "buzzer.hpp"
|
||||
#include "config.hpp"
|
||||
|
||||
static const char *TAG_BUZZER = "buzzer";
|
||||
|
||||
//============================
|
||||
//========== init ============
|
||||
//============================
|
||||
//define gpio pin as output, initialize queue
|
||||
void buzzer_t::init(){
|
||||
//define buzzer pin as output
|
||||
gpio_pad_select_gpio(gpio_pin);
|
||||
gpio_set_direction(gpio_pin, GPIO_MODE_OUTPUT);
|
||||
//create queue
|
||||
beepQueue = xQueueCreate( 20, sizeof( struct beepEntry ) );
|
||||
}
|
||||
|
||||
|
||||
//=============================
|
||||
//======== constructor ========
|
||||
//=============================
|
||||
//copy provided config parameters to private variables, run init function
|
||||
buzzer_t::buzzer_t(gpio_num_t gpio_pin_f, uint16_t msGap_f){
|
||||
ESP_LOGI(TAG_BUZZER, "Initializing buzzer");
|
||||
//copy configuration parameters to variables
|
||||
gpio_pin = gpio_pin_f;
|
||||
msGap = msGap_f;
|
||||
//run init function to initialize gpio and queue
|
||||
init();
|
||||
};
|
||||
|
||||
|
||||
//============================
|
||||
//=========== beep ===========
|
||||
//============================
|
||||
//function to add a beep command to the queue
|
||||
void buzzer_t::beep(uint8_t count, uint16_t msOn, uint16_t msOff){
|
||||
//create entry struct with provided data
|
||||
struct beepEntry entryInsert = {
|
||||
count = count,
|
||||
msOn = msOn,
|
||||
msOff = msOff
|
||||
};
|
||||
|
||||
// Send a pointer to a struct AMessage object. Don't block if the
|
||||
// queue is already full.
|
||||
//struct beepEntry *entryInsertPointer;
|
||||
//entryInsertPointer = &entryInsertData;
|
||||
ESP_LOGW(TAG_BUZZER, "Inserted object to queue - count=%d, msOn=%d, msOff=%d", entryInsert.count, entryInsert.msOn, entryInsert.msOff);
|
||||
//xQueueGenericSend( beepQueue, ( void * ) &entryInsertPointer, ( TickType_t ) 0, queueSEND_TO_BACK );
|
||||
xQueueSend( beepQueue, ( void * )&entryInsert, ( TickType_t ) 0 );
|
||||
}
|
||||
|
||||
|
||||
//==============================
|
||||
//======== processQueue ========
|
||||
//==============================
|
||||
void buzzer_t::processQueue(){
|
||||
//struct for receiving incomming events
|
||||
struct beepEntry entryRead = { };
|
||||
|
||||
//loop forever
|
||||
while(1){
|
||||
ESP_LOGD(TAG_BUZZER, "processQueue: waiting for beep command");
|
||||
|
||||
//if queue is ready
|
||||
if( beepQueue != 0 )
|
||||
{
|
||||
// wait for a queue entry to be available indefinetely if INCLUDE_vTaskSuspend is enabled in the FreeRTOS config
|
||||
// otherwise waits for at least 7 weeks
|
||||
if( xQueueReceive( beepQueue, &entryRead, portMAX_DELAY ) )
|
||||
{
|
||||
ESP_LOGW(TAG_BUZZER, "Read entry from queue: count=%d, msOn=%d, msOff=%d", entryRead.count, entryRead.msOn, entryRead.msOff);
|
||||
|
||||
//beep requested count with requested delays
|
||||
for (int i = entryRead.count; i--;){
|
||||
//turn on
|
||||
ESP_LOGD(TAG_BUZZER, "turning buzzer on");
|
||||
gpio_set_level(gpio_pin, 1);
|
||||
vTaskDelay(entryRead.msOn / portTICK_PERIOD_MS);
|
||||
//turn off
|
||||
ESP_LOGD(TAG_BUZZER, "turning buzzer off");
|
||||
gpio_set_level(gpio_pin, 0);
|
||||
vTaskDelay(entryRead.msOff / portTICK_PERIOD_MS);
|
||||
}
|
||||
//wait for minimum gap between beep events
|
||||
vTaskDelay(msGap / portTICK_PERIOD_MS);
|
||||
}
|
||||
}else{ //wait for queue to become available
|
||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,56 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
}
|
||||
|
||||
#include "freertos/queue.h"
|
||||
|
||||
|
||||
|
||||
//===================================
|
||||
//========= buzzer_t class ==========
|
||||
//===================================
|
||||
//class which blinks a gpio pin for the provided count and durations.
|
||||
//- 'processQueue' has to be run in a separate task
|
||||
//- uses a queue to queue up multiple beep commands
|
||||
class buzzer_t {
|
||||
public:
|
||||
//--- constructor ---
|
||||
buzzer_t(gpio_num_t gpio_pin_f, uint16_t msGap_f = 200);
|
||||
|
||||
//--- functions ---
|
||||
void processQueue(); //has to be run once in a separate task, waits for and processes queued events
|
||||
void beep(uint8_t count, uint16_t msOn, uint16_t msOff);
|
||||
//void clear(); (TODO - not implemented yet)
|
||||
//void createTask(); (TODO - not implemented yet)
|
||||
|
||||
//--- variables ---
|
||||
uint16_t msGap; //gap between beep entries (when multiple queued)
|
||||
|
||||
private:
|
||||
//--- functions ---
|
||||
void init();
|
||||
|
||||
//--- variables ---
|
||||
gpio_num_t gpio_pin;
|
||||
|
||||
struct beepEntry {
|
||||
uint8_t count;
|
||||
uint16_t msOn;
|
||||
uint16_t msOff;
|
||||
};
|
||||
|
||||
//queue for queueing up multiple events while one is still processing
|
||||
QueueHandle_t beepQueue = NULL;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,75 +0,0 @@
|
||||
extern "C" {
|
||||
#include "hal/timer_types.h"
|
||||
#include "esp_log.h"
|
||||
}
|
||||
|
||||
#include "currentsensor.hpp"
|
||||
|
||||
//tag for logging
|
||||
static const char * TAG = "current-sensors";
|
||||
|
||||
|
||||
|
||||
//--------------------------
|
||||
//------- getVoltage -------
|
||||
//--------------------------
|
||||
//local function to get average voltage from adc
|
||||
float getVoltage(adc1_channel_t adc, uint32_t samples){
|
||||
//measure voltage
|
||||
int measure = 0;
|
||||
for (int j=0; j<samples; j++){
|
||||
measure += adc1_get_raw(adc);
|
||||
ets_delay_us(50);
|
||||
}
|
||||
return (float)measure / samples / 4096 * 3.3;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============================
|
||||
//======== constructor ========
|
||||
//=============================
|
||||
currentSensor::currentSensor (adc1_channel_t adcChannel_f, float ratedCurrent_f){
|
||||
//copy config
|
||||
adcChannel = adcChannel_f;
|
||||
ratedCurrent = ratedCurrent_f;
|
||||
//init adc
|
||||
adc1_config_width(ADC_WIDTH_BIT_12); //max resolution 4096
|
||||
adc1_config_channel_atten(adcChannel, ADC_ATTEN_DB_11); //max voltage
|
||||
//calibrate
|
||||
calibrateZeroAmpere();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============================
|
||||
//=========== read ===========
|
||||
//============================
|
||||
float currentSensor::read(void){
|
||||
//measure voltage
|
||||
voltage = getVoltage(adcChannel, 30);
|
||||
|
||||
//scale voltage to current
|
||||
if (voltage < centerVoltage){
|
||||
current = (1 - voltage / centerVoltage) * -ratedCurrent;
|
||||
} else if (voltage > centerVoltage){
|
||||
current = (voltage - centerVoltage) / (3.3 - centerVoltage) * ratedCurrent;
|
||||
}else {
|
||||
current = 0;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "read sensor adc=%d: voltage=%.3fV, centerVoltage=%.3fV => current=%.3fA", (int)adcChannel, voltage, centerVoltage, current);
|
||||
return current;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===============================
|
||||
//===== calibrateZeroAmpere =====
|
||||
//===============================
|
||||
void currentSensor::calibrateZeroAmpere(void){
|
||||
//measure voltage
|
||||
float prev = centerVoltage;
|
||||
centerVoltage = getVoltage(adcChannel, 100);
|
||||
ESP_LOGW(TAG, "defined centerVoltage (0A) to %.3f (previous %.3f)", centerVoltage, prev);
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
#include <driver/adc.h>
|
||||
|
||||
//supported current sensor working method:
|
||||
//0V = -ratedCurrent
|
||||
//centerVoltage = 0A
|
||||
//3.3V = ratedCurrent
|
||||
|
||||
class currentSensor{
|
||||
public:
|
||||
currentSensor (adc1_channel_t adcChannel_f, float ratedCurrent);
|
||||
void calibrateZeroAmpere(void); //set current voltage to voltage representing 0A
|
||||
float read(void); //get current ampere
|
||||
private:
|
||||
adc1_channel_t adcChannel;
|
||||
float ratedCurrent;
|
||||
uint32_t measure;
|
||||
float voltage;
|
||||
float current;
|
||||
float centerVoltage = 3.3/2;
|
||||
};
|
@ -1,330 +0,0 @@
|
||||
#include "motorctl.hpp"
|
||||
|
||||
//tag for logging
|
||||
static const char * TAG = "motor-control";
|
||||
|
||||
|
||||
//=============================
|
||||
//======== constructor ========
|
||||
//=============================
|
||||
//constructor, simultaniously initialize instance of motor driver 'motor' and current sensor 'cSensor' with provided config (see below lines after ':')
|
||||
controlledMotor::controlledMotor(single100a_config_t config_driver, motorctl_config_t config_control):
|
||||
motor(config_driver),
|
||||
cSensor(config_control.currentSensor_adc, config_control.currentSensor_ratedCurrent) {
|
||||
//copy parameters for controlling the motor
|
||||
config = config_control;
|
||||
//copy configured default fading durations to actually used variables
|
||||
msFadeAccel = config.msFadeAccel;
|
||||
msFadeDecel = config.msFadeDecel;
|
||||
|
||||
init();
|
||||
//TODO: add currentsensor object here
|
||||
//currentSensor cSensor(config.currentSensor_adc, config.currentSensor_ratedCurrent);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============================
|
||||
//========== init ============
|
||||
//============================
|
||||
void controlledMotor::init(){
|
||||
commandQueue = xQueueCreate( 1, sizeof( struct motorCommand_t ) );
|
||||
//cSensor.calibrateZeroAmpere(); //currently done in currentsensor constructor TODO do this regularly e.g. in idle?
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------
|
||||
//----- fade -----
|
||||
//----------------
|
||||
//local function that fades a variable
|
||||
//- increments a variable (pointer) by given value
|
||||
//- sets to target if already closer than increment
|
||||
//TODO this needs testing
|
||||
void fade(float * dutyNow, float dutyTarget, float dutyIncrement){
|
||||
float dutyDelta = dutyTarget - *dutyNow;
|
||||
if ( fabs(dutyDelta) > fabs(dutyIncrement) ) { //check if already close to target
|
||||
*dutyNow = *dutyNow + dutyIncrement;
|
||||
}
|
||||
//already closer to target than increment
|
||||
else {
|
||||
*dutyNow = dutyTarget;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------
|
||||
//----- getStateFromDuty -----
|
||||
//----------------------------
|
||||
//local function that determines motor the direction from duty range -100 to 100
|
||||
motorstate_t getStateFromDuty(float duty){
|
||||
if(duty > 0) return motorstate_t::FWD;
|
||||
if (duty < 0) return motorstate_t::REV;
|
||||
return motorstate_t::IDLE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==============================
|
||||
//=========== handle ===========
|
||||
//==============================
|
||||
//function that controls the motor driver and handles fading/ramp, current limit and deadtime
|
||||
void controlledMotor::handle(){
|
||||
|
||||
//TODO: History: skip fading when motor was running fast recently / alternatively add rot-speed sensor
|
||||
|
||||
//--- receive commands from queue ---
|
||||
if( xQueueReceive( commandQueue, &commandReceive, ( TickType_t ) 0 ) )
|
||||
{
|
||||
ESP_LOGD(TAG, "Read command from queue: state=%s, duty=%.2f", motorstateStr[(int)commandReceive.state], commandReceive.duty);
|
||||
state = commandReceive.state;
|
||||
dutyTarget = commandReceive.duty;
|
||||
|
||||
//--- convert duty ---
|
||||
//define target duty (-100 to 100) from provided duty and motorstate
|
||||
//this value is more suitable for the fading algorithm
|
||||
switch(commandReceive.state){
|
||||
case motorstate_t::BRAKE:
|
||||
//update state
|
||||
state = motorstate_t::BRAKE;
|
||||
dutyTarget = 0;
|
||||
break;
|
||||
case motorstate_t::IDLE:
|
||||
dutyTarget = 0;
|
||||
break;
|
||||
case motorstate_t::FWD:
|
||||
dutyTarget = fabs(commandReceive.duty);
|
||||
break;
|
||||
case motorstate_t::REV:
|
||||
dutyTarget = - fabs(commandReceive.duty);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--- calculate increment ---
|
||||
//calculate increment for fading UP with passed time since last run and configured fade time
|
||||
int64_t usPassed = esp_timer_get_time() - timestampLastRunUs;
|
||||
if (msFadeAccel > 0){
|
||||
dutyIncrementAccel = ( usPassed / ((float)msFadeAccel * 1000) ) * 100; //TODO define maximum increment - first run after startup (or long) pause can cause a very large increment
|
||||
} else {
|
||||
dutyIncrementAccel = 100;
|
||||
}
|
||||
|
||||
//calculate increment for fading DOWN with passed time since last run and configured fade time
|
||||
if (msFadeDecel > 0){
|
||||
dutyIncrementDecel = ( usPassed / ((float)msFadeDecel * 1000) ) * 100;
|
||||
} else {
|
||||
dutyIncrementDecel = 100;
|
||||
}
|
||||
|
||||
|
||||
//--- BRAKE ---
|
||||
//brake immediately, update state, duty and exit this cycle of handle function
|
||||
if (state == motorstate_t::BRAKE){
|
||||
motor.set(motorstate_t::BRAKE, 0);
|
||||
dutyNow = 0;
|
||||
return; //no need to run the fade algorithm
|
||||
}
|
||||
|
||||
|
||||
//--- calculate difference ---
|
||||
dutyDelta = dutyTarget - dutyNow;
|
||||
//positive: need to increase by that value
|
||||
//negative: need to decrease
|
||||
|
||||
|
||||
//----- FADING -----
|
||||
//fade duty to target (up and down)
|
||||
//TODO: this needs optimization (can be more clear and/or simpler)
|
||||
if (dutyDelta > 0) { //difference positive -> increasing duty (-100 -> 100)
|
||||
if (dutyNow < 0) { //reverse, decelerating
|
||||
fade(&dutyNow, dutyTarget, dutyIncrementDecel);
|
||||
}
|
||||
else if (dutyNow >= 0) { //forward, accelerating
|
||||
fade(&dutyNow, dutyTarget, dutyIncrementAccel);
|
||||
}
|
||||
}
|
||||
else if (dutyDelta < 0) { //difference negative -> decreasing duty (100 -> -100)
|
||||
if (dutyNow <= 0) { //reverse, accelerating
|
||||
fade(&dutyNow, dutyTarget, - dutyIncrementAccel);
|
||||
}
|
||||
else if (dutyNow > 0) { //forward, decelerating
|
||||
fade(&dutyNow, dutyTarget, - dutyIncrementDecel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//----- CURRENT LIMIT -----
|
||||
if ((config.currentLimitEnabled) && (dutyDelta != 0)){
|
||||
currentNow = cSensor.read();
|
||||
if (fabs(currentNow) > config.currentMax){
|
||||
float dutyOld = dutyNow;
|
||||
//adaptive decrement:
|
||||
//Note current exceeded twice -> twice as much decrement: TODO: decrement calc needs finetuning, currently random values
|
||||
dutyIncrementDecel = (currentNow/config.currentMax) * ( usPassed / ((float)msFadeDecel * 1500) ) * 100;
|
||||
float currentLimitDecrement = ( (float)usPassed / ((float)1000 * 1000) ) * 100; //1000ms from 100 to 0
|
||||
if (dutyNow < -currentLimitDecrement) {
|
||||
dutyNow += currentLimitDecrement;
|
||||
} else if (dutyNow > currentLimitDecrement) {
|
||||
dutyNow -= currentLimitDecrement;
|
||||
}
|
||||
ESP_LOGW(TAG, "current limit exceeded! now=%.3fA max=%.1fA => decreased duty from %.3f to %.3f", currentNow, config.currentMax, dutyOld, dutyNow);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--- define new motorstate --- (-100 to 100 => direction)
|
||||
state=getStateFromDuty(dutyNow);
|
||||
|
||||
|
||||
//--- DEAD TIME ----
|
||||
//ensure minimum idle time between direction change to prevent driver overload
|
||||
//FWD -> IDLE -> FWD continue without waiting
|
||||
//FWD -> IDLE -> REV wait for dead-time in IDLE
|
||||
//TODO check when changed only?
|
||||
if ( //not enough time between last direction state
|
||||
( state == motorstate_t::FWD && (esp_log_timestamp() - timestampsModeLastActive[(int)motorstate_t::REV] < config.deadTimeMs))
|
||||
|| (state == motorstate_t::REV && (esp_log_timestamp() - timestampsModeLastActive[(int)motorstate_t::FWD] < config.deadTimeMs))
|
||||
){
|
||||
ESP_LOGD(TAG, "waiting dead-time... dir change %s -> %s", motorstateStr[(int)statePrev], motorstateStr[(int)state]);
|
||||
if (!deadTimeWaiting){ //log start
|
||||
deadTimeWaiting = true;
|
||||
ESP_LOGW(TAG, "starting dead-time... %s -> %s", motorstateStr[(int)statePrev], motorstateStr[(int)state]);
|
||||
}
|
||||
//force IDLE state during wait
|
||||
state = motorstate_t::IDLE;
|
||||
dutyNow = 0;
|
||||
} else {
|
||||
if (deadTimeWaiting){ //log end
|
||||
deadTimeWaiting = false;
|
||||
ESP_LOGW(TAG, "dead-time ended - continue with %s", motorstateStr[(int)state]);
|
||||
}
|
||||
ESP_LOGV(TAG, "deadtime: no change below deadtime detected... dir=%s, duty=%.1f", motorstateStr[(int)state], dutyNow);
|
||||
}
|
||||
|
||||
|
||||
//--- save current actual motorstate and timestamp ---
|
||||
//needed for deadtime
|
||||
timestampsModeLastActive[(int)getStateFromDuty(dutyNow)] = esp_log_timestamp();
|
||||
//(-100 to 100 => direction)
|
||||
statePrev = getStateFromDuty(dutyNow);
|
||||
|
||||
|
||||
//--- apply new target to motor ---
|
||||
motor.set(state, fabs(dutyNow));
|
||||
//note: BRAKE state is handled earlier
|
||||
|
||||
|
||||
//--- update timestamp ---
|
||||
timestampLastRunUs = esp_timer_get_time(); //update timestamp last run with current timestamp in microseconds
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===============================
|
||||
//========== setTarget ==========
|
||||
//===============================
|
||||
//function to set the target mode and duty of a motor
|
||||
//puts the provided command in a queue for the handle function running in another task
|
||||
void controlledMotor::setTarget(motorstate_t state_f, float duty_f){
|
||||
commandSend = {
|
||||
.state = state_f,
|
||||
.duty = duty_f
|
||||
};
|
||||
|
||||
ESP_LOGD(TAG, "Inserted command to queue: state=%s, duty=%.2f", motorstateStr[(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 );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===============================
|
||||
//========== getStatus ==========
|
||||
//===============================
|
||||
//function which returns the current status of the motor in a motorCommand_t struct
|
||||
motorCommand_t controlledMotor::getStatus(){
|
||||
motorCommand_t status = {
|
||||
.state = state,
|
||||
.duty = dutyNow
|
||||
};
|
||||
//TODO: mutex
|
||||
return status;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//===============================
|
||||
//=========== setFade ===========
|
||||
//===============================
|
||||
//function for editing or enabling the fading/ramp of the motor control
|
||||
|
||||
//set/update fading duration/amount
|
||||
void controlledMotor::setFade(fadeType_t fadeType, uint32_t msFadeNew){
|
||||
//TODO: mutex for msFade variable also used in handle function
|
||||
switch(fadeType){
|
||||
case fadeType_t::ACCEL:
|
||||
msFadeAccel = msFadeNew;
|
||||
break;
|
||||
case fadeType_t::DECEL:
|
||||
msFadeDecel = msFadeNew;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//enable (set to default value) or disable fading
|
||||
void controlledMotor::setFade(fadeType_t fadeType, bool enabled){
|
||||
uint32_t msFadeNew = 0; //define new fade time as default disabled
|
||||
if(enabled){ //enable
|
||||
//set to default/configured value
|
||||
switch(fadeType){
|
||||
case fadeType_t::ACCEL:
|
||||
msFadeNew = config.msFadeAccel;
|
||||
break;
|
||||
case fadeType_t::DECEL:
|
||||
msFadeNew = config.msFadeDecel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//apply new Fade value
|
||||
setFade(fadeType, msFadeNew);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==================================
|
||||
//=========== toggleFade ===========
|
||||
//==================================
|
||||
//toggle fading between OFF and default value
|
||||
bool controlledMotor::toggleFade(fadeType_t fadeType){
|
||||
uint32_t msFadeNew = 0;
|
||||
bool enabled = false;
|
||||
switch(fadeType){
|
||||
case fadeType_t::ACCEL:
|
||||
if (msFadeAccel == 0){
|
||||
msFadeNew = config.msFadeAccel;
|
||||
enabled = true;
|
||||
} else {
|
||||
msFadeNew = 0;
|
||||
}
|
||||
break;
|
||||
case fadeType_t::DECEL:
|
||||
if (msFadeDecel == 0){
|
||||
msFadeNew = config.msFadeAccel;
|
||||
enabled = true;
|
||||
} else {
|
||||
msFadeNew = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
//apply new Fade value
|
||||
setFade(fadeType, msFadeNew);
|
||||
|
||||
//return new state (fading enabled/disabled)
|
||||
return enabled;
|
||||
}
|
||||
|
@ -1,104 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_timer.h"
|
||||
}
|
||||
|
||||
#include "motordrivers.hpp"
|
||||
#include "currentsensor.hpp"
|
||||
|
||||
|
||||
//=======================================
|
||||
//====== struct/type declarations ======
|
||||
//=======================================
|
||||
|
||||
//struct for sending command for one motor in the queue
|
||||
struct motorCommand_t {
|
||||
motorstate_t state;
|
||||
float duty;
|
||||
};
|
||||
|
||||
//struct containing commands for two motors
|
||||
typedef struct motorCommands_t {
|
||||
motorCommand_t left;
|
||||
motorCommand_t right;
|
||||
} motorCommands_t;
|
||||
|
||||
//struct with all config parameters for a motor regarding ramp and current limit
|
||||
typedef struct motorctl_config_t {
|
||||
uint32_t msFadeAccel; //acceleration of the motor (ms it takes from 0% to 100%)
|
||||
uint32_t msFadeDecel; //deceleration of the motor (ms it takes from 100% to 0%)
|
||||
bool currentLimitEnabled;
|
||||
adc1_channel_t currentSensor_adc;
|
||||
float currentSensor_ratedCurrent;
|
||||
float currentMax;
|
||||
uint32_t deadTimeMs; //time motor stays in IDLE before direction change
|
||||
} motorctl_config_t;
|
||||
|
||||
//enum fade type (acceleration, deceleration)
|
||||
//e.g. used for specifying which fading should be modified with setFade, togleFade functions
|
||||
enum class fadeType_t {ACCEL, DECEL};
|
||||
|
||||
|
||||
|
||||
//===================================
|
||||
//====== controlledMotor class ======
|
||||
//===================================
|
||||
class controlledMotor {
|
||||
public:
|
||||
//--- functions ---
|
||||
controlledMotor(single100a_config_t config_driver, motorctl_config_t config_control); //constructor with structs for configuring motordriver and parameters for control TODO: add configuration for currentsensor
|
||||
void handle(); //controls motor duty with fade and current limiting feature (has to be run frequently by another task)
|
||||
void setTarget(motorstate_t state_f, float duty_f = 0); //adds target command to queue for handle function
|
||||
motorCommand_t getStatus(); //get current status of the motor (returns struct with state and duty)
|
||||
|
||||
void setFade(fadeType_t fadeType, bool enabled); //enable/disable acceleration or deceleration fading
|
||||
void setFade(fadeType_t fadeType, uint32_t msFadeNew); //set acceleration or deceleration fade time
|
||||
bool toggleFade(fadeType_t fadeType); //toggle acceleration or deceleration on/off
|
||||
|
||||
//TODO set current limit method
|
||||
|
||||
private:
|
||||
//--- functions ---
|
||||
void init(); //creates currentsensor objects, motordriver objects and queue
|
||||
|
||||
//--- objects ---
|
||||
//motor driver
|
||||
single100a motor;
|
||||
//queue for sending commands to the separate task running the handle() function very fast
|
||||
QueueHandle_t commandQueue = NULL;
|
||||
//current sensor
|
||||
currentSensor cSensor;
|
||||
|
||||
//--- variables ---
|
||||
//struct for storing control specific parameters
|
||||
motorctl_config_t config;
|
||||
motorstate_t state = motorstate_t::IDLE;
|
||||
|
||||
float currentMax;
|
||||
float currentNow;
|
||||
|
||||
float dutyTarget;
|
||||
float dutyNow;
|
||||
float dutyIncrementAccel;
|
||||
float dutyIncrementDecel;
|
||||
float dutyDelta;
|
||||
|
||||
uint32_t msFadeAccel;
|
||||
uint32_t msFadeDecel;
|
||||
|
||||
uint32_t ramp;
|
||||
int64_t timestampLastRunUs;
|
||||
|
||||
bool deadTimeWaiting = false;
|
||||
uint32_t timestampsModeLastActive[4] = {};
|
||||
motorstate_t statePrev = motorstate_t::FWD;
|
||||
|
||||
struct motorCommand_t commandReceive = {};
|
||||
struct motorCommand_t commandSend = {};
|
||||
};
|
@ -1,129 +0,0 @@
|
||||
#include "motordrivers.hpp"
|
||||
|
||||
//TODO: move from ledc to mcpwm?
|
||||
//https://docs.espressif.com/projects/esp-idf/en/v4.3/esp32/api-reference/peripherals/mcpwm.html#
|
||||
//https://github.com/espressif/esp-idf/tree/v4.3/examples/peripherals/mcpwm/mcpwm_basic_config
|
||||
|
||||
//Note fade functionality provided by LEDC would be very useful but unfortunately is not usable here because:
|
||||
//"Due to hardware limitations, there is no way to stop a fade before it reaches its target duty."
|
||||
|
||||
//definition of string array to be able to convert state enum to readable string
|
||||
const char* motorstateStr[4] = {"IDLE", "FWD", "REV", "BRAKE"};
|
||||
|
||||
//tag for logging
|
||||
static const char * TAG = "motordriver";
|
||||
|
||||
|
||||
|
||||
//====================================
|
||||
//===== single100a motor driver ======
|
||||
//====================================
|
||||
|
||||
//-----------------------------
|
||||
//-------- constructor --------
|
||||
//-----------------------------
|
||||
//copy provided struct with all configuration and run init function
|
||||
single100a::single100a(single100a_config_t config_f){
|
||||
config = config_f;
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------
|
||||
//---------- init ------------
|
||||
//----------------------------
|
||||
//function to initialize pwm output, gpio pins and calculate maxDuty
|
||||
void single100a::init(){
|
||||
|
||||
//--- configure ledc timer ---
|
||||
ledc_timer_config_t ledc_timer;
|
||||
ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;
|
||||
ledc_timer.timer_num = config.ledc_timer;
|
||||
ledc_timer.duty_resolution = config.resolution; //13bit gives max 5khz freq
|
||||
ledc_timer.freq_hz = config.pwmFreq;
|
||||
ledc_timer.clk_cfg = LEDC_AUTO_CLK;
|
||||
//apply configuration
|
||||
ledc_timer_config(&ledc_timer);
|
||||
|
||||
//--- configure ledc channel ---
|
||||
ledc_channel_config_t ledc_channel;
|
||||
ledc_channel.channel = config.ledc_channel;
|
||||
ledc_channel.duty = 0;
|
||||
ledc_channel.gpio_num = config.gpio_pwm;
|
||||
ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE;
|
||||
ledc_channel.hpoint = 0;
|
||||
ledc_channel.timer_sel = config.ledc_timer;
|
||||
ledc_channel.intr_type = LEDC_INTR_DISABLE;
|
||||
ledc_channel.flags.output_invert = 0; //TODO: add config option to invert the pwm output?
|
||||
//apply configuration
|
||||
ledc_channel_config(&ledc_channel);
|
||||
|
||||
//--- define gpio pins as outputs ---
|
||||
gpio_pad_select_gpio(config.gpio_a);
|
||||
gpio_set_direction(config.gpio_a, GPIO_MODE_OUTPUT);
|
||||
gpio_pad_select_gpio(config.gpio_b);
|
||||
gpio_set_direction(config.gpio_b, GPIO_MODE_OUTPUT);
|
||||
|
||||
//--- calculate max duty according to selected resolution ---
|
||||
dutyMax = pow(2, ledc_timer.duty_resolution) -1;
|
||||
ESP_LOGI(TAG, "initialized single100a driver");
|
||||
ESP_LOGI(TAG, "resolution=%dbit, dutyMax value=%d, resolution=%.4f %%", ledc_timer.duty_resolution, dutyMax, 100/(float)dutyMax);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---------------------------
|
||||
//----------- set -----------
|
||||
//---------------------------
|
||||
//function to put the h-bridge module in the desired state and duty cycle
|
||||
void single100a::set(motorstate_t state_f, float duty_f){
|
||||
|
||||
//scale provided target duty in percent to available resolution for ledc
|
||||
uint32_t dutyScaled;
|
||||
if (duty_f > 100) { //target duty above 100%
|
||||
dutyScaled = dutyMax;
|
||||
} else if (duty_f <= 0) { //target at or below 0%
|
||||
state_f = motorstate_t::IDLE;
|
||||
dutyScaled = 0;
|
||||
} else { //target duty 0-100%
|
||||
//scale duty to available resolution
|
||||
dutyScaled = duty_f / 100 * dutyMax;
|
||||
}
|
||||
|
||||
//put the single100a h-bridge module in the desired state update duty-cycle
|
||||
switch (state_f){
|
||||
case motorstate_t::IDLE:
|
||||
ledc_set_duty(LEDC_HIGH_SPEED_MODE, config.ledc_channel, dutyScaled);
|
||||
ledc_update_duty(LEDC_HIGH_SPEED_MODE, config.ledc_channel);
|
||||
//TODO: to fix bugged state of h-bridge module when idle and start again, maybe try to leave pwm signal on for some time before updating a/b pins?
|
||||
//no brake: (freewheel)
|
||||
//gpio_set_level(config.gpio_a, config.aEnabledPinState);
|
||||
//gpio_set_level(config.gpio_b, !config.bEnabledPinState);
|
||||
gpio_set_level(config.gpio_a, config.aEnabledPinState);
|
||||
gpio_set_level(config.gpio_b, config.bEnabledPinState);
|
||||
break;
|
||||
case motorstate_t::BRAKE:
|
||||
ledc_set_duty(LEDC_HIGH_SPEED_MODE, config.ledc_channel, 0);
|
||||
ledc_update_duty(LEDC_HIGH_SPEED_MODE, config.ledc_channel);
|
||||
//brake:
|
||||
gpio_set_level(config.gpio_a, !config.aEnabledPinState);
|
||||
gpio_set_level(config.gpio_b, !config.bEnabledPinState);
|
||||
break;
|
||||
case motorstate_t::FWD:
|
||||
ledc_set_duty(LEDC_HIGH_SPEED_MODE, config.ledc_channel, dutyScaled);
|
||||
ledc_update_duty(LEDC_HIGH_SPEED_MODE, config.ledc_channel);
|
||||
//forward:
|
||||
gpio_set_level(config.gpio_a, config.aEnabledPinState);
|
||||
gpio_set_level(config.gpio_b, !config.bEnabledPinState);
|
||||
break;
|
||||
case motorstate_t::REV:
|
||||
ledc_set_duty(LEDC_HIGH_SPEED_MODE, config.ledc_channel, dutyScaled);
|
||||
ledc_update_duty(LEDC_HIGH_SPEED_MODE, config.ledc_channel);
|
||||
//reverse:
|
||||
gpio_set_level(config.gpio_a, !config.aEnabledPinState);
|
||||
gpio_set_level(config.gpio_b, config.bEnabledPinState);
|
||||
break;
|
||||
}
|
||||
ESP_LOGD(TAG, "set module to state=%s, duty=%d/%d, duty_input=%.3f%%", motorstateStr[(int)state_f], dutyScaled, dutyMax, duty_f);
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "driver/ledc.h"
|
||||
#include "esp_err.h"
|
||||
}
|
||||
|
||||
#include <cmath>
|
||||
|
||||
|
||||
//====================================
|
||||
//===== single100a motor driver ======
|
||||
//====================================
|
||||
|
||||
//--------------------------------------------
|
||||
//---- struct, enum, variable declarations ---
|
||||
//--------------------------------------------
|
||||
|
||||
//class which controls a motor using a 'single100a' h-bridge module
|
||||
enum class motorstate_t {IDLE, FWD, REV, BRAKE};
|
||||
//definition of string array to be able to convert state enum to readable string (defined in motordrivers.cpp)
|
||||
extern const char* motorstateStr[4];
|
||||
|
||||
//struct with all config parameters for single100a motor driver
|
||||
typedef struct single100a_config_t {
|
||||
gpio_num_t gpio_pwm;
|
||||
gpio_num_t gpio_a;
|
||||
gpio_num_t gpio_b;
|
||||
ledc_timer_t ledc_timer;
|
||||
ledc_channel_t ledc_channel;
|
||||
bool aEnabledPinState;
|
||||
bool bEnabledPinState;
|
||||
ledc_timer_bit_t resolution;
|
||||
int pwmFreq;
|
||||
} single100a_config_t;
|
||||
|
||||
|
||||
|
||||
//--------------------------------
|
||||
//------- single100a class -------
|
||||
//--------------------------------
|
||||
class single100a {
|
||||
public:
|
||||
//--- constructor ---
|
||||
single100a(single100a_config_t config_f); //provide config struct (see above)
|
||||
|
||||
//--- functions ---
|
||||
void set(motorstate_t state, float duty_f = 0); //set mode and duty of the motor (see motorstate_t above)
|
||||
//TODO: add functions to get the current state and duty
|
||||
|
||||
private:
|
||||
//--- functions ---
|
||||
void init(); //initialize pwm and gpio outputs, calculate maxDuty
|
||||
|
||||
//--- variables ---
|
||||
single100a_config_t config;
|
||||
uint32_t dutyMax;
|
||||
motorstate_t state = motorstate_t::IDLE;
|
||||
};
|
@ -1,265 +0,0 @@
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_mac.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#include "wifi.h"
|
||||
|
||||
|
||||
|
||||
//--- variables used for ap and wifi ---
|
||||
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)
|
||||
//has to be run once at startup
|
||||
void wifi_initNvs_initNetif(){
|
||||
//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_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
}
|
||||
|
||||
|
||||
//===========================================
|
||||
//============ init access point ============
|
||||
//===========================================
|
||||
|
||||
//--------------------------------------------
|
||||
//------ configuration / declarations --------
|
||||
//--------------------------------------------
|
||||
#define EXAMPLE_ESP_WIFI_SSID_AP "armchair"
|
||||
#define EXAMPLE_ESP_WIFI_PASS_AP ""
|
||||
#define EXAMPLE_ESP_WIFI_CHANNEL_AP 1
|
||||
#define EXAMPLE_MAX_STA_CONN_AP 4
|
||||
|
||||
static esp_netif_t *ap;
|
||||
|
||||
static void wifi_event_handler_ap(void* arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void* event_data)
|
||||
{
|
||||
if (event_id == WIFI_EVENT_AP_STACONNECTED) {
|
||||
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
|
||||
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
|
||||
MAC2STR(event->mac), event->aid);
|
||||
} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
|
||||
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
|
||||
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
|
||||
MAC2STR(event->mac), event->aid);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------
|
||||
//------ init ap --------
|
||||
//-----------------------
|
||||
void wifi_init_ap(void)
|
||||
{
|
||||
ap = esp_netif_create_default_wifi_ap();
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
|
||||
ESP_EVENT_ANY_ID,
|
||||
&wifi_event_handler_ap,
|
||||
NULL,
|
||||
&instance_any_id));
|
||||
|
||||
wifi_config_t wifi_config = {
|
||||
.ap = {
|
||||
.ssid = EXAMPLE_ESP_WIFI_SSID_AP,
|
||||
.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID_AP),
|
||||
.channel = EXAMPLE_ESP_WIFI_CHANNEL_AP,
|
||||
.password = EXAMPLE_ESP_WIFI_PASS_AP,
|
||||
.max_connection = EXAMPLE_MAX_STA_CONN_AP,
|
||||
.authmode = WIFI_AUTH_WPA_WPA2_PSK
|
||||
},
|
||||
};
|
||||
if (strlen(EXAMPLE_ESP_WIFI_PASS_AP) == 0) {
|
||||
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d",
|
||||
EXAMPLE_ESP_WIFI_SSID_AP, EXAMPLE_ESP_WIFI_PASS_AP, EXAMPLE_ESP_WIFI_CHANNEL_AP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============================
|
||||
//========= deinit AP =========
|
||||
//=============================
|
||||
void wifi_deinit_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));
|
||||
esp_wifi_stop();
|
||||
esp_wifi_deinit();
|
||||
esp_netif_destroy_default_wifi(ap);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===========================================
|
||||
//=============== init client ===============
|
||||
//===========================================
|
||||
|
||||
//--------------------------------------------
|
||||
//------ configuration / declarations --------
|
||||
//--------------------------------------------
|
||||
#define EXAMPLE_ESP_WIFI_SSID_CLIENT "BKA-network"
|
||||
#define EXAMPLE_ESP_WIFI_PASS_CLIENT "airwaveslogitech410"
|
||||
#define EXAMPLE_ESP_MAXIMUM_RETRY_CLIENT 10
|
||||
|
||||
static esp_netif_t *sta;
|
||||
static esp_event_handler_instance_t instance_got_ip;
|
||||
|
||||
/* FreeRTOS event group to signal when we are connected*/
|
||||
static EventGroupHandle_t s_wifi_event_group;
|
||||
|
||||
/* The event group allows multiple bits for each event, but we only care about two events:
|
||||
* - we are connected to the AP with an IP
|
||||
* - we failed to connect after the maximum amount of retries */
|
||||
#define WIFI_CONNECTED_BIT BIT0
|
||||
#define WIFI_FAIL_BIT BIT1
|
||||
|
||||
static int s_retry_num = 0;
|
||||
static void event_handler(void* arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void* event_data)
|
||||
{
|
||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
|
||||
esp_wifi_connect();
|
||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY_CLIENT) {
|
||||
esp_wifi_connect();
|
||||
s_retry_num++;
|
||||
ESP_LOGI(TAG, "retry to connect to the AP");
|
||||
} else {
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
|
||||
}
|
||||
ESP_LOGI(TAG,"connect to the AP fail");
|
||||
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
|
||||
ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
|
||||
s_retry_num = 0;
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||
}
|
||||
}
|
||||
//---------------------------
|
||||
//------ init client --------
|
||||
//---------------------------
|
||||
void wifi_init_client(void)
|
||||
{
|
||||
s_wifi_event_group = xEventGroupCreate();
|
||||
sta = esp_netif_create_default_wifi_sta();
|
||||
|
||||
|
||||
|
||||
//set static ip
|
||||
esp_netif_dhcpc_stop(sta);
|
||||
|
||||
esp_netif_ip_info_t ip_info;
|
||||
IP4_ADDR(&ip_info.ip, 10, 0, 0, 66);
|
||||
IP4_ADDR(&ip_info.gw, 10, 0, 0, 1);
|
||||
IP4_ADDR(&ip_info.netmask, 255, 255, 0, 0);
|
||||
|
||||
esp_netif_set_ip_info(sta, &ip_info);
|
||||
|
||||
|
||||
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
|
||||
ESP_EVENT_ANY_ID,
|
||||
&event_handler,
|
||||
NULL,
|
||||
&instance_any_id));
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
|
||||
IP_EVENT_STA_GOT_IP,
|
||||
&event_handler,
|
||||
NULL,
|
||||
&instance_got_ip));
|
||||
|
||||
wifi_config_t wifi_config = {
|
||||
.sta = {
|
||||
.ssid = EXAMPLE_ESP_WIFI_SSID_CLIENT,
|
||||
.password = EXAMPLE_ESP_WIFI_PASS_CLIENT,
|
||||
/* Setting a password implies station will connect to all security modes including WEP/WPA.
|
||||
* However these modes are deprecated and not advisable to be used. Incase your Access point
|
||||
* doesn't support WPA2, these mode can be enabled by commenting below line */
|
||||
.threshold.authmode = WIFI_AUTH_WPA2_PSK,
|
||||
},
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
|
||||
ESP_ERROR_CHECK(esp_wifi_start() );
|
||||
|
||||
ESP_LOGI(TAG, "wifi_init_sta finished.");
|
||||
|
||||
/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
|
||||
* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
|
||||
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
|
||||
WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
|
||||
pdFALSE,
|
||||
pdFALSE,
|
||||
portMAX_DELAY);
|
||||
|
||||
/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
|
||||
* happened. */
|
||||
if (bits & WIFI_CONNECTED_BIT) {
|
||||
ESP_LOGI(TAG, "connected to ap SSID:%s password:%s",
|
||||
EXAMPLE_ESP_WIFI_SSID_CLIENT, EXAMPLE_ESP_WIFI_PASS_CLIENT);
|
||||
} else if (bits & WIFI_FAIL_BIT) {
|
||||
ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s",
|
||||
EXAMPLE_ESP_WIFI_SSID_CLIENT, EXAMPLE_ESP_WIFI_PASS_CLIENT);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "UNEXPECTED EVENT");
|
||||
}
|
||||
|
||||
// /* 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));
|
||||
// ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id));
|
||||
// vEventGroupDelete(s_wifi_event_group);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=================================
|
||||
//========= deinit client =========
|
||||
//=================================
|
||||
void wifi_deinit_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));
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id));
|
||||
vEventGroupDelete(s_wifi_event_group);
|
||||
esp_wifi_stop();
|
||||
esp_wifi_deinit();
|
||||
esp_netif_destroy_default_wifi(sta);
|
||||
}
|
||||
|
@ -1,22 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
//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();
|
||||
|
||||
|
||||
//function to start an access point
|
||||
void wifi_init_ap(void);
|
||||
//function to disable/deinit access point
|
||||
void wifi_deinit_ap(void);
|
||||
|
||||
//function to connect to existing wifi network
|
||||
void wifi_init_client(void);
|
||||
//function to disable/deinit client
|
||||
void wifi_deinit_client(void);
|
||||
|
||||
|
||||
|
@ -4,6 +4,9 @@ idf_component_register(
|
||||
"buzzer.cpp"
|
||||
"uart_common.cpp"
|
||||
"types.cpp"
|
||||
"motordrivers.cpp"
|
||||
"motorctl.cpp"
|
||||
"currentsensor.cpp"
|
||||
INCLUDE_DIRS
|
||||
"."
|
||||
PRIV_REQUIRES nvs_flash
|
||||
|
Loading…
x
Reference in New Issue
Block a user