Skip to content

Commit

Permalink
Implement Deep-Sleep
Browse files Browse the repository at this point in the history
On Suspend timeout initiate MCU deep-sleep
  • Loading branch information
vortigont committed May 20, 2024
1 parent c4be839 commit a988b29
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 31 deletions.
4 changes: 2 additions & 2 deletions ESPIron/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
#define BUTTON_ACTION GPIO_NUM_0 // middle push-button
#define BUTTON_INCR GPIO_NUM_2 // incrementer “+” push-button
#define BUTTON_DECR GPIO_NUM_4 // decrementer “-” push-button
#define HEATER_PIN 5 // heater MOSFET PWM control 加热器MOSFET PWM控制
#define HEATER_PIN GPIO_NUM_5 // heater MOSFET PWM control 加热器MOSFET PWM控制
#define SH1107_RST_PIN 7 // display reset pin

// CH224K USB PD chip pins connection
// https://components101.com/sites/default/files/component_datasheet/WCH_CH224K_ENG.pdf
#define PD_CFG_0 16
Expand All @@ -34,7 +35,6 @@
// Heater PWM parameters
#define HEATER_CHANNEL LEDC_CHANNEL_2 // PWM channel
#define HEATER_FREQ 200 // PWM frequency
//#define HEATER_HIGHFREQ 1000 // PWM frequency for 20V/50% PWM mode
#define HEATER_RES LEDC_TIMER_8_BIT // PWM resolution

// Default temperature control value (recommended soldering temperature: 300~380°C)
Expand Down
5 changes: 3 additions & 2 deletions ESPIron/evtloop.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,10 @@ enum class iron_t:int32_t {
stateWorking = 300,
stateStandby, // iron controller switched to 'Standby' mode
stateIdle,
stateSuspend,
stateSuspend, // switch to suspend mode
stateWakeUp, // WakeUp from suspend mode
stateBoost, // iron controller switched to 'Boost' mode, parameter uint32_t - seconds left to disable boost mode
stateSetup,
stateSetup, // enter in menu confgiration mode
stateNoTip,
tipEject, // sent by heater when it looses the tip sense
tipInsert, // sent by heater when detect tip sensor
Expand Down
15 changes: 15 additions & 0 deletions ESPIron/hid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,21 @@ void IronHID::init(){
// initialize screen
_init_screen();

// subscribe to notification events
if (!_evt_ntfy_handler){
esp_event_handler_instance_register_with(
evt::get_hndlr(),
IRON_VISET,
e2int( iron_t::stateSuspend ), // I need only 'suspend' for now
// notification on suspend
[](void* self, esp_event_base_t base, int32_t id, void* data) { u8g2.sleepOn(); }, // suspend display
this,
&_evt_ntfy_handler
);

}


// enable middle button
_btn.enable();
// enable 'encoder' buttons
Expand Down
8 changes: 7 additions & 1 deletion ESPIron/hid.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,10 @@ class IronHID {
std::mutex _mtx;

// event handler
esp_event_handler_instance_t _evt_viset_handler = nullptr;
esp_event_handler_instance_t _evt_viset_handler{nullptr};

// event handler
esp_event_handler_instance_t _evt_ntfy_handler{nullptr};

// action button
GPIOButton<ESPEventPolicy> _btn;
Expand All @@ -117,6 +120,9 @@ class IronHID {

void _viset_render();

// process Iron notification events
void _notify_handler();

public:
// c-tor
IronHID() : _encdr(BUTTON_DECR, BUTTON_INCR, LOW), _btn(BUTTON_ACTION, LOW) {};
Expand Down
74 changes: 65 additions & 9 deletions ESPIron/ironcontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,43 @@
*/

#include "ironcontroller.hpp"
#include "main.h"
#include "esp_sleep.h"
#include "driver/rtc_io.h"
#include "log.h"
#include "Arduino.h" // needed for Serial

#define MODE_TIMER_PERIOD 1000
#define DEEPSLEEP_DELAY 3000

using namespace evt;

/**
* @brief initiate deep-sleep suspend
*
*/
void deep_sleep(TimerHandle_t h){
LOGI(T_IRON, printf, "Enabling EXT0 wakeup on GPIO:%d\n", BUTTON_ACTION);
esp_sleep_enable_ext0_wakeup(BUTTON_ACTION, 0); // wake on action key press

// Configure pullup/downs via RTCIO to tie wakeup pins to inactive level during deepsleep.
rtc_gpio_pullup_en(BUTTON_ACTION);
rtc_gpio_pulldown_dis(BUTTON_ACTION);

// I'm not sure about Iron's schematics if it's FET Gate/PWM pin is pulled properly to ensure FET is closed on MCU suspend,
// so I will do set proper pull from MCU as well
if (HEATER_INVERT){
rtc_gpio_pullup_en(HEATER_PIN);
rtc_gpio_pulldown_dis(HEATER_PIN);
} else {
rtc_gpio_pullup_dis(HEATER_PIN);
rtc_gpio_pulldown_en(HEATER_PIN);
}

// enter deep sleep
esp_deep_sleep_start();
}


IronController::~IronController(){
// unsubscribe from event bus
if (_evt_sensor_handler){
Expand All @@ -34,6 +64,10 @@ IronController::~IronController(){
esp_event_handler_instance_unregister_with(evt::get_hndlr(), IRON_GET_EVT, ESP_EVENT_ANY_ID, _evt_req_handler);
_evt_req_handler = nullptr;
}

if (_tmr_mode)
xTimerStop(_tmr_mode, portMAX_DELAY );

}

void IronController::init(){
Expand All @@ -57,7 +91,7 @@ void IronController::init(){
[](TimerHandle_t h) { static_cast<IronController*>(pvTimerGetTimerID(h))->_mode_switcher(); }
);
if (_tmr_mode)
xTimerStart( _tmr_mode, pdMS_TO_TICKS(10) );
xTimerStart( _tmr_mode, portMAX_DELAY );
}

// event bus subscriptions
Expand Down Expand Up @@ -93,6 +127,7 @@ void IronController::_mode_switcher(){
case ironState_t::standby : {
if (pdTICKS_TO_MS(xTaskGetTickCount()) - pdTICKS_TO_MS(_xTicks.motion) > _timeout.idle){
_state = ironState_t::idle;
_xTicks.idle = xTaskGetTickCount();
LOGI(T_CTRL, printf, "Engage idle mode due to idle timeout of %u ms\n", _timeout.idle);
// notify other componets that we are switching to 'idle' mode
EVT_POST(IRON_NOTIFY, e2int(iron_t::stateIdle));
Expand All @@ -101,18 +136,30 @@ void IronController::_mode_switcher(){
_state = ironState_t::working;
LOGI(T_CTRL, println, "cancel Standby mode");
// notify other componets that we are switching to 'work' mode
EVT_POST_DATA(IRON_SET_EVT, e2int(iron_t::heaterTargetT), &_temp.working, sizeof(_temp.working));
EVT_POST(IRON_NOTIFY, e2int(iron_t::stateWorking));
EVT_POST_DATA(IRON_SET_EVT, e2int(iron_t::heaterTargetT), &_temp.working, sizeof(_temp.working));
}
return;
}

case ironState_t::suspend : {
if (pdTICKS_TO_MS(xTaskGetTickCount()) - pdTICKS_TO_MS(_xTicks.motion) > _timeout.suspend){
case ironState_t::idle : {
if (pdTICKS_TO_MS(xTaskGetTickCount()) - pdTICKS_TO_MS(_xTicks.idle) > _timeout.suspend){
_state = ironState_t::suspend;
LOGI(T_CTRL, printf, "Engage suspend mode due to suspend timeout of %u ms\n", _timeout.suspend);
// notify other componets that we are switching to 'idle' mode
// stop modeswitcher timer, in suspend mode I won't change anything until keypress event will bring device back
if (_tmr_mode)
xTimerStop(_tmr_mode, portMAX_DELAY );
// notify other components that we are switching to 'suspend' mode
EVT_POST(IRON_NOTIFY, e2int(iron_t::stateSuspend));
// give some time for other components to prepare for deep sleep, then suspend the controller
TimerHandle_t timer = xTimerCreate(NULL,
pdMS_TO_TICKS(DEEPSLEEP_DELAY),
pdFALSE,
nullptr,
deep_sleep
);
if (timer)
xTimerStart( timer, portMAX_DELAY );
}
return;
}
Expand Down Expand Up @@ -165,7 +212,6 @@ void IronController::_evt_commands(esp_event_base_t base, int32_t id, void* data
switch (_state){
case ironState_t::idle :
case ironState_t::standby :
case ironState_t::suspend :
// switch to working mode
_state = ironState_t::working;
// reset motion timer
Expand All @@ -181,10 +227,22 @@ void IronController::_evt_commands(esp_event_base_t base, int32_t id, void* data
case ironState_t::working :
// switch to idle mode
_state = ironState_t::idle;
// reset idle timer
_xTicks.idle = xTaskGetTickCount();
// notify other components
LOGI(T_CTRL, println, "switch to Idle mode");
EVT_POST(IRON_NOTIFY, e2int(iron_t::stateIdle));
break;
/*
// iron was suspended, wake up
case ironState_t::suspend :
_state = ironState_t::idle;
// reset idle timer
_xTicks.idle = xTaskGetTickCount();
// start mode switcher timer
if (_tmr_mode) xTimerStart( _tmr_mode, portMAX_DELAY );
break;
*/
}
break;
}
Expand Down Expand Up @@ -266,5 +324,3 @@ void IronController::_evt_reqs(esp_event_base_t base, int32_t id, void* data){
}
}

// An instance of IronController
IronController espIron;
33 changes: 16 additions & 17 deletions ESPIron/ironcontroller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,13 @@ class IronController {
// last time motion was detected
TickType_t motion;
TickType_t boost;
TickType_t idle;
};

public:
IronTimeouts _timeout;
Temperatures _temp;
TickStamps _xTicks;

private:

// current iron mode
ironState_t _state{ironState_t::idle};

Expand Down Expand Up @@ -71,18 +69,6 @@ class IronController {
// req commands events executor
void _evt_reqs(esp_event_base_t base, int32_t id, void* data);

/**
* @brief save current timeout values to NVS
*
*/
void _saveTimeouts(){ nvs_blob_write(T_IRON, T_timeouts, static_cast<void*>(&_timeout), sizeof(IronTimeouts)); };

/**
* @brief save current temperature values to NVS
*
*/
void _saveTemp(){ nvs_blob_write(T_IRON, T_temperatures, static_cast<void*>(&_timeout), sizeof(IronTimeouts)); };

public:
~IronController();

Expand All @@ -99,6 +85,19 @@ class IronController {

// get internal temperatures configuration
const Temperatures& getTemperatures() const { return _temp; }
};

extern IronController espIron;
private:
/**
* @brief save current timeout values to NVS
*
*/
void _saveTimeouts(){ nvs_blob_write(T_IRON, T_timeouts, static_cast<void*>(&_timeout), sizeof(IronTimeouts)); };

/**
* @brief save current temperature values to NVS
*
*/
void _saveTemp(){ nvs_blob_write(T_IRON, T_temperatures, static_cast<void*>(&_timeout), sizeof(IronTimeouts)); };


};
3 changes: 3 additions & 0 deletions ESPIron/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ QC3Control QC(QC_DP_PIN, QC_DM_PIN);
FirmwareMSC MSC_Update;
#endif

// An instance of IronController
IronController espIron;

#ifndef DEVELOP_MODE
// Iron tip heater object
TipHeater heater(HEATER_PIN, HEATER_CHANNEL, HEATER_INVERT);
Expand Down

0 comments on commit a988b29

Please sign in to comment.