@@ -170,27 +170,29 @@ void update_temp() {
HAL_SPI_Receive(&hspi1, rxdatah, 1, 100);
HAL_SPI_Receive(&hspi1, rxdatal, 1, 100);
// Release CS
HAL_GPIO_WritePin(MAX_CS, 1);
// Assemble data array into one var
uint16_t temp_pre = rxdatal[0] | (rxdatah[0]<<8);
if(temp_pre & 0b0000000000000010) {
ssd1306_clearscreen();
ssd1306_DrawString("Fatal Error", 3, 35);
//ssd1306_DrawString("Fatal Error", 3, 35);
HAL_Delay(100);
state = STATE_TC_ERROR;
temp = 0;
temp_frac = 0;
}
else if(temp_pre & 0b0000000000000001 && !ignore_tc_error) {
state_resume = state;
else
{
if(state == STATE_TC_ERROR)
state = state_resume;
@@ -222,35 +224,36 @@ void update_temp() {
temp_frac = temp % 100;
temp /= 100;
// Use Celsius values
temp = temp_pre * signint;
// Print temp to cdc
/*
CDC_Transmit_FS("Temp: ", 6);
char tempstr[6];
zitoa(temp, tempstr);
CDC_Transmit_FS(tempstr, sizeof(tempstr));
CDC_Transmit_FS("\r\n", 2);
*/
// PID implementation
// TODO: Make struct that has the last_temp and i_state in it, pass by ref. Make struct that has other input values maybe.
int16_t last_pid_temp = 0;
uint8_t last_pid_temp_frac = 0;
int16_t i_state = 0;
int16_t update_pid(uint16_t k_p, uint16_t k_i, uint16_t k_d, int16_t temp, uint8_t temp_frac, int16_t setpoint)
// Calculate instantaneous error
@@ -342,34 +345,24 @@ void process()
HAL_GPIO_WritePin(SSR_PIN, 1);
last_ssr_on = ticks;
// Kill SSR after elapsed period less than SSR_PERIOD
if(ticks - last_ssr_on > ssr_output || ssr_output == 0)
HAL_GPIO_WritePin(SSR_PIN, 0);
void draw_setpoint() {
char tempstr[3];
itoa_fp(temp, temp_frac, tempstr);
ssd1306_DrawStringBig(" ", 3, 0);
ssd1306_DrawStringBig(tempstr, 3, 0);
ssd1306_DrawStringBig(">", 3, 74);
itoa(setpoint, tempstr, 10);
ssd1306_DrawStringBig(" ", 3, 90);
ssd1306_DrawStringBig(tempstr, 3, 90);
uint8_t goto_mode = 2;
// State machine
uint8_t sw_btn_last = 0;
uint8_t sw_up_last = 0;
uint8_t sw_down_last = 0;
uint8_t sw_left_last = 0;
uint8_t sw_right_last = 0;
#define SW_BTN_PRESSED (sw_btn_last == 0 && sw_btn == 1) // rising edge on buttonpress
#define SW_UP_PRESSED (sw_up_last == 0 && sw_up == 1)
@@ -441,24 +434,53 @@ int16_t last_temp = 21245;
/// freaking multiple setpoint support ///
uint8_t step_duration[10] = {0,0,0,0,0,0,0,0,0,0};
int16_t step_setpoint[10] = {0,0,0,0,0,0,0,0,0,0};
uint8_t final_setpoint = 0;
// Multiple screens to set setpoint and duration on each screen
// press center to go to the next one, and press left or right or something to confirm
// When executing, complete on time AND(?) temperature. Maybe allow switching to OR via settings
////////////////////////////////////////////////////////////////////////////////////////////////
uint8_t trigger_drawsetpoint = 1;
int32_t temp_last = 43002;
int32_t setpoint_last = 10023;
// FIXME: need to do this when switching modes too
if(temp != temp_last || trigger_drawsetpoint) {
if(trigger_drawsetpoint)
if(setpoint != setpoint_last || trigger_drawsetpoint) {
trigger_drawsetpoint = 0;
setpoint_last = setpoint;
temp_last = temp;
void machine()
uint8_t last_state = state;
uint8_t temp_changed = temp != last_temp;
last_temp = temp;
uint8_t sw_btn = !HAL_GPIO_ReadPin(SW_BTN);
uint8_t sw_up = !HAL_GPIO_ReadPin(SW_UP);
uint8_t sw_down = !HAL_GPIO_ReadPin(SW_DOWN);
uint8_t sw_left = !HAL_GPIO_ReadPin(SW_LEFT);
uint8_t sw_right = !HAL_GPIO_ReadPin(SW_RIGHT);
@@ -758,24 +780,25 @@ void machine()
} break;
case STATE_PREHEAT_BREW:
// Write text to OLED
// [ therm : preheating brew ]
// [ 30 => 120 C ]
ssd1306_DrawString("Preheating...", 0, 0);
//ssd1306_drawlogo();
draw_setpoint();
pid_enabled = 1;
setpoint = setpoint_brew;
// Button handler
if(SW_BTN_PRESSED) {
save_setpoints(); // TODO: Check for mod
state = STATE_IDLE;
else {
user_input(&setpoint_brew);
@@ -890,24 +913,25 @@ void machine()
default:
pid_enabled = 0;
if(last_state != state) {
// Clear screen on state change
goto_mode = 2;
trigger_drawsetpoint = 1;
// Last buttonpress
sw_btn_last = sw_btn;
sw_up_last = sw_up;
sw_down_last = sw_down;
sw_left_last = sw_left;
sw_right_last = sw_right;
Status change: