- add static type to all local variables in every source file so the scope of each variable is limited to that file. This prevents conflicting variable names with other source file (e.g. 'state' variable in vfd.cpp) - simplify encoder concept wrap all used functions from rotary_encoder.h library in custom encoder.hpp file -> only one file has to be included where encoder is used -> global variable 'encoder' is not necessary anymore -> reduces duplicate code for length calculation - update all files where encoder functions where used accordingly
170 lines
4.4 KiB
C++
170 lines
4.4 KiB
C++
#include "cutter.hpp"
|
|
|
|
const char* cutter_stateStr[5] = {"IDLE", "START", "CUTTING", "CANCELED", "TIMEOUT"}; //define strings for logging the state
|
|
|
|
|
|
//---------------------------
|
|
//----- local functions -----
|
|
//---------------------------
|
|
//declare local functions
|
|
void setState(cutter_state_t stateNew);
|
|
bool checkTimeout();
|
|
|
|
|
|
|
|
//---------------------------
|
|
//----- local variables -----
|
|
//---------------------------
|
|
static cutter_state_t cutter_state = cutter_state_t::IDLE;
|
|
static uint32_t timestamp_turnedOn;
|
|
static uint32_t msTimeout = 3000;
|
|
static const char *TAG = "cutter"; //tag for logging
|
|
|
|
|
|
|
|
//=========================
|
|
//========= start =========
|
|
//=========================
|
|
void cutter_start(){
|
|
setState(cutter_state_t::START);
|
|
//starts motor on state change
|
|
}
|
|
|
|
|
|
|
|
//========================
|
|
//========= stop =========
|
|
//========================
|
|
void cutter_stop(){
|
|
if(cutter_state != cutter_state_t::IDLE){
|
|
setState(cutter_state_t::CANCELED);
|
|
}
|
|
//starts motor on state change
|
|
}
|
|
|
|
|
|
|
|
//===========================
|
|
//===== cutter_getState =====
|
|
//===========================
|
|
cutter_state_t cutter_getState(){
|
|
return cutter_state;
|
|
}
|
|
|
|
|
|
|
|
//============================
|
|
//===== cutter_isRunning =====
|
|
//============================
|
|
bool cutter_isRunning(){
|
|
if (cutter_state == cutter_state_t::START
|
|
|| cutter_state == cutter_state_t::CUTTING) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//---------------------------
|
|
//-------- setState ---------
|
|
//---------------------------
|
|
//local function for changing state, taking corresponding actions and sending log output
|
|
void setState(cutter_state_t stateNew){
|
|
//only proceed and send log output when state or direction actually changed
|
|
if ( cutter_state == stateNew) {
|
|
//already at target state -> do nothing
|
|
return;
|
|
}
|
|
|
|
//log old and new state
|
|
ESP_LOGI(TAG, "CHANGING state from: %s",cutter_stateStr[(int)cutter_state]);
|
|
ESP_LOGI(TAG, "CHANGING state to: %s",cutter_stateStr[(int)stateNew]);
|
|
//update stored state
|
|
cutter_state = stateNew;
|
|
|
|
switch(stateNew){
|
|
case cutter_state_t::IDLE:
|
|
case cutter_state_t::TIMEOUT:
|
|
case cutter_state_t::CANCELED:
|
|
//--- turn motor off ---
|
|
gpio_set_level(GPIO_RELAY, 0);
|
|
break;
|
|
|
|
case cutter_state_t::START:
|
|
case cutter_state_t::CUTTING:
|
|
//--- turn motor on ---
|
|
gpio_set_level(GPIO_RELAY, 1);
|
|
//update state, timestamp
|
|
timestamp_turnedOn = esp_log_timestamp();
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//--------------------------
|
|
//------ checkTimeout ------
|
|
//--------------------------
|
|
//local function that checks for timeout
|
|
bool checkTimeout(){
|
|
if (esp_log_timestamp() - timestamp_turnedOn > msTimeout){
|
|
setState(cutter_state_t::TIMEOUT);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//========================
|
|
//======== handle ========
|
|
//========================
|
|
//function that handles the cutter logic -> has to be run repeatedly
|
|
void cutter_handle(){
|
|
//handle evaluated switch (position switch)
|
|
SW_CUTTER_POS.handle();
|
|
//TODO add custom thresholds once at initialization?
|
|
//SW_CUTTER_POS.minOnMs = 10;
|
|
//SW_CUTTER_POS.minOffMs = 10;
|
|
|
|
|
|
switch(cutter_state){
|
|
case cutter_state_t::IDLE:
|
|
case cutter_state_t::TIMEOUT:
|
|
case cutter_state_t::CANCELED:
|
|
//wait for state change via cutter_start();
|
|
break;
|
|
|
|
case cutter_state_t::START:
|
|
//--- moved away from idle position ---
|
|
//if (gpio_get_level(GPIO_CUTTER_POS_SW) == 0){ //contact closed
|
|
if (SW_CUTTER_POS.state == true) { //contact closed -> not at idle pos
|
|
setState(cutter_state_t::CUTTING);
|
|
}
|
|
//--- timeout ---
|
|
else {
|
|
checkTimeout();
|
|
}
|
|
|
|
break;
|
|
|
|
case cutter_state_t::CUTTING:
|
|
//--- idle position reached ---
|
|
//if (gpio_get_level(GPIO_CUTTER_POS_SW) == 1){ //contact not closed
|
|
//TODO: add min on duration
|
|
if (SW_CUTTER_POS.state == false) { //contact open -> at idle pos
|
|
setState(cutter_state_t::IDLE);
|
|
}
|
|
//--- timeout ---
|
|
else {
|
|
checkTimeout();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|