Commit c5a1b903 authored by Philippe Kalaf's avatar Philippe Kalaf

Re-architect to use threads instead of ISR for workers

parent 9a5a2ae2
This diff is collapsed.
......@@ -32,17 +32,15 @@
#define MODE_MANUAL 4
#define MODE_STEAM 5
// Brew states
#define STOPPED 0
#define BREWING 1
#define PRE_INFUSING 2
#define SOFT_STOPPING 3
#define STEAMING 4
// Brew states, will also be used as thread flags
#define STOPPED static_cast<int>(1 << 0)
#define BREWING static_cast<int>(1 << 1)
#define PRE_INFUSING static_cast<int>(1 << 2)
#define SOFT_STOPPING static_cast<int>(1 << 3)
#define STEAMING static_cast<int>(1 << 4)
#define PORTAFILTER_VOLUME 100
//#define TEMP2
/// This is the main class where all brew functions and sensors are handled
class BrewControl
{
......@@ -133,6 +131,8 @@ public:
uint16_t get_last_pulse_count_top();
private:
Mutex _brew_worker_mutex;
// Signal to turn on/off pump
DigitalOut _brew_switch;
......@@ -164,7 +164,7 @@ private:
bool _enable_boiler;
// The shot clock is the time spent brewing
float _shot_clock;
Timer _shot_clock;
// Desired shot time, volume and temperature during a brew
int _target_shot_time;
......@@ -190,10 +190,11 @@ private:
bool _stop_preinfuse;
// Workers
Ticker _brew_ticker;
Thread _brew_worker_thread;
void _brew_worker();
Ticker _boiler_pid_ticker;
void _boiler_pid_worker();
void _stop();
};
......
......@@ -55,10 +55,10 @@ Serial pc(USBTX, USBRX); // tx, rx
C12832_LCD LCD;
// Menu display thread
Thread menu_thread;
Thread menu_thread(osPriorityNormal, 1024);
// mutex to make the lcd lib thread safe
Mutex lcd_mutex;
// mutex for heap between main and menu_handler threads
Mutex heap_mutex;
// Joystick for menu control
InterruptIn Fire(p9); // JS_PUSH
......@@ -172,6 +172,8 @@ const uint8_t conversion_table[9][2] = {
{0, 2}, {1, 2}, {2, 2}
};
#define MAIN_LOOP_PERIOD_MS 500
// takes the params from given menu and give thems to brew control
void set_params(uint8_t menu_id)
{
......@@ -215,7 +217,6 @@ void draw_menu()
uint8_t i, j;
uint8_t state;
string out_s;
lcd_mutex.lock();
// clear screen if required & set
LCD.cls();
LCD.invert(0);
......@@ -229,7 +230,7 @@ void draw_menu()
if (menu_level == L_BREW)
{
// Invert screen while brewing or steaming
if (state)
if (state != STOPPED)
LCD.invert(1);
if (active_menu == M_BREW_MANUAL)
{
......@@ -355,7 +356,36 @@ void draw_menu()
}
LCD.printf("%s", out_s.c_str());
}
lcd_mutex.unlock();
}
void enter_power_save()
{
// let's set ambient temp to keep things cool
brew_control.set_shot_temperature(23);
// turn on LCD power saving
//LCD.power_save(1);
power_save = 1;
menu_level = L_STANDBY;
}
void exit_power_save()
{
power_save = 0;
power_save_timer.reset();
// go back to previously set temperature
set_params(M_BREW_SETTINGS);
// turn off LCD power saving
//LCD.power_save(0);
}
// should get called everytime a power saving reset event happens
void check_power_save()
{
if(power_save)
exit_power_save();
else
power_save_timer.reset();
}
// This thread waits for joystick commands, then sets parameters and then draws the menu
......@@ -364,11 +394,19 @@ void menu_handler()
while(true) {
// wait on joystick action
uint32_t flags = ThisThread::flags_wait_any_for(LEFT | UP | RIGHT | DOWN | FIRE, 500);
if (flags == osFlagsErrorTimeout)
heap_mutex.lock();
// Flags should return osFlagsErrorTimeout but it's returning 0...
if (!flags)
{
draw_menu();
heap_mutex.unlock();
continue;
}
else
{
check_power_save();
}
// fire
if (flags == FIRE) {
......@@ -384,7 +422,7 @@ void menu_handler()
edit_mode = 0;
break;
case L_BREW: // send params to brew control b4 brewing
if(!brew_control.get_state())
if(brew_control.get_state() == STOPPED)
{
// set general settings
set_params(M_BREW_SETTINGS);
......@@ -417,7 +455,7 @@ void menu_handler()
if(active_menu == M_BREW_MANUAL || active_menu == M_BREW_STEAM)
menu_level = L_MENU;
// only exit brew menu if not in brewing mode
else if(!brew_control.get_state())
else if(brew_control.get_state() == STOPPED)
menu_level = L_MENU_SUB;
break;
}
......@@ -484,6 +522,7 @@ void menu_handler()
// draw next menu
draw_menu();
heap_mutex.unlock();
}
}
......@@ -502,64 +541,29 @@ bool check_js_timer()
}
}
void enter_power_save()
{
// let's set ambient temp to keep things cool
brew_control.set_shot_temperature(23);
// turn on LCD power saving
//LCD.power_save(1);
power_save = 1;
menu_level = L_STANDBY;
}
void exit_power_save()
{
power_save = 0;
power_save_timer.reset();
// go back to previously set temperature
set_params(M_BREW_SETTINGS);
// turn off LCD power saving
//LCD.power_save(0);
}
// should get called everytime a power saving reset event happens
void check_power_save()
{
if(power_save)
exit_power_save();
else
power_save_timer.reset();
}
// Joystick ISRs just send signals to unblock menu thread
void cycle_up()
{
check_power_save();
if(check_js_timer())
menu_thread.flags_set(UP);
}
void cycle_down()
{
check_power_save();
if(check_js_timer())
menu_thread.flags_set(DOWN);
}
void cycle_left()
{
check_power_save();
if(check_js_timer())
menu_thread.flags_set(LEFT);
}
void cycle_right()
{
check_power_save();
if(check_js_timer())
menu_thread.flags_set(RIGHT);
}
void fire_away()
{
check_power_save();
if(check_js_timer())
menu_thread.flags_set(FIRE);
}
......@@ -567,6 +571,8 @@ void fire_away()
// print the actual contrast
int main()
{
pc.baud(115200);
// Initialize default mode - 60ml shots
int target_volume = 60;
brew_control.set_shot_volume(target_volume);
......@@ -577,7 +583,6 @@ int main()
// We want to call the menu_handler in another thread
menu_thread.start(callback(menu_handler));
draw_menu();
// Attach joystick ISR callbacks
Up.rise(&cycle_up);
......@@ -592,6 +597,7 @@ int main()
#if 1
if (pc.readable()) {
char c = pc.getc();
heap_mutex.lock();
// Menu navigation from ttyUSB
if(c == 'i')
......@@ -679,6 +685,8 @@ int main()
}
else if (c == '=')
brew_control.toggle_solenoid();
heap_mutex.unlock();
}
/*
pc.printf("%d %.3f ml %.2f bar %.1f C %.1f C %.1f s %.2f ml/s\n",
......@@ -690,15 +698,22 @@ int main()
brew_control.get_current_time(),
brew_control.get_current_flow_rate());
*/
pc.printf("%.1f %.1f %d %d\n", brew_control.get_current_temperature_side(),
pc.printf("%.1f %.1f %d %d\n", brew_control.get_current_temperature_side(),
brew_control.get_current_temperature_top(),
brew_control.get_last_pulse_count_side(),
brew_control.get_last_pulse_count_top()
);
#endif
ThisThread::sleep_for(100); // wait 0.1s
// If there has been no keypress for POWER_SAVE_TIMEOUT_S, go to powersaving mode
if (power_save_timer.read() > POWER_SAVE_TIMEOUT_S)
enter_power_save();
#endif
heap_mutex.lock();
// If there has been no keypress for POWER_SAVE_TIMEOUT_S, go to powersaving mode
if (power_save_timer.read() > POWER_SAVE_TIMEOUT_S)
enter_power_save();
heap_mutex.unlock();
ThisThread::sleep_for(MAIN_LOOP_PERIOD_MS); // wait 0.1s
}
}
https://github.com/ARMmbed/mbed-os/#2fd0c5cfbd83fce62da6308f9d64c0ab64e1f0d6
https://github.com/ARMmbed/mbed-os/#6a0a86538c0b9b2bfcc4583b1e2b7fea8f4e71e9
......@@ -20,6 +20,7 @@
#include "phasecontrol.h"
// estimate of lag caused by ZCD circuit in usec
// measured as per http://espresso-for-geeks.kalaf.net/mod-list/#hw-zero-cross
#define ZCD_DELAY 36
// power frequency half-period in usec
......@@ -127,11 +128,9 @@ uint8_t PhaseControl::get_level()
return _level;
}
void PhaseControl::set_level(int level)
void PhaseControl::set_level(uint8_t level)
{
if (level < 0)
_level = 0;
else if (level > 100)
if (level > 100)
_level = 100;
else
_level = level;
......
......@@ -34,7 +34,7 @@ public:
void level_down(uint8_t value = 1);
void start();
void stop();
void set_level(int level);
void set_level(uint8_t level);
/* debug info
int times[2000][2];
......@@ -45,7 +45,7 @@ private:
void delayed_start();
void delayed_stop();
InterruptIn _zcd;
volatile int _level;
uint8_t _level;
DigitalOut _control_signal;
Timeout _control_timeout;
Timeout _test_timeout;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment