#include "oven_control.h" #include #include #include "profile.h" //Pin assignments for SainSmart LCD Keypad Shield LiquidCrystal _lcd(8, 9, 4, 5, 6, 7); DFR_Key _keypad; Profile _profile; OvenCtl::OvenCtl() { time = 0; temperature = 25; last_temperature = 25; actual_dt = 0; // timestamps of event beginnings/ends Ts_time_start = 0; Ts_time_end = 0; Tl_time_start = 0; Tl_time_end = 0; Tp_time_start = 0; Tp_time_end = 0; // thermostat set_min = 0; set_max = 0; set_dt_min = 0; set_dt_max = 0; state = 0; error_condition = 0; is_oven_heating = false; // ui stuff led_on = false; disable_checks = true; lcd = &_lcd; keypad = &_keypad; profile = &_profile; lcd->begin(16, 2); } void OvenCtl::send_state() { Serial.write(time); Serial.write(temperature); Serial.write(last_temperature); Serial.write(state); Serial.write(error_condition); } void OvenCtl::send_config() { int tmp; for (int i=0;i < PI_END; i++) { tmp = profile->data[i]; Serial.write(tmp & 0xff); Serial.write((tmp >> 8 ) & 0xff); } // Serial.print("\n"); } void OvenCtl::handle_states() { if (state > 0) time++; get_temp(); check_dt(); // if (!error_condition) { // print_debug(); // } // else { // set_error_state(); // } // switch (state) { case CONFIG_STATE: if (profile->handle_config_state(lcd, keypad)) set_start_state(); break; case START_STATE: handle_start_state(); break; case PREHEAT_STATE: handle_preheat_state(); break; case RAMP_UP_STATE: handle_ramp_up_state(); break; case TAL_FIRST_STATE: handle_tal_first_state(); break; case PEAK_STATE: handle_peak_state(); break; case TAL_SECOND_STATE: Tl_time_end = time; handle_tal_second_state(); break; case RAMP_DOWN_STATE: handle_ramp_down_state(); break; case END_STATE: handle_end_state(); break; case ERROR_STATE: handle_error_state(); break; default: break; } control_oven(); if (state > 0) { print_status(); send_state(); delay(1000); } } void OvenCtl::print_profile_state() { } void OvenCtl::print_status() { String tmp("T: "); if (time < 10) tmp += "00"; else if (time < 100) tmp += "0"; tmp += time; tmp += " Tmp: "; if (temperature < 10) tmp += "00"; else if (temperature < 100) tmp += "0"; tmp += temperature; lcd->setCursor(0, 0); lcd->print(tmp); tmp = "Profile: "; tmp += state; tmp += "/"; tmp += END_STATE; lcd->setCursor(0, 1); lcd->print(tmp); lcd->setCursor(13, 1); if (is_oven_heating) lcd->print("on "); else lcd->print("off"); } void OvenCtl::control_oven() { if (temperature < set_min && !is_oven_heating) { is_oven_heating = true; Serial.println("Oven turned on"); } else if (temperature > set_min && is_oven_heating) { is_oven_heating = false; Serial.println("Oven turned off"); } } void OvenCtl::set_temp(int min, int max, int dt_min, int dt_max) { set_min = min; set_max = max; set_dt_min = dt_min; set_dt_max = dt_max; } void OvenCtl::get_temp() { last_temperature = temperature; temperature = int(float(analogRead(2)) * 0.2929); actual_dt = temperature - last_temperature; } void OvenCtl::check_dt() { if (disable_checks) return; if (actual_dt > set_dt_max) { error_condition |= E_DT_MAX; } if (actual_dt < set_dt_min) { error_condition |= E_DT_MIN; } } void OvenCtl::check_max_duration() { if (disable_checks) return; Serial.println(time); if (time > profile->data[PI_TIME_MAX]) { error_condition |= E_TIME_MAX; } Serial.println(time); } void OvenCtl::check_Ts_duration_min() { if (disable_checks) return; Tl_time_end = time; if (time - Tl_time_start < profile->data[PI_TL_DURATION_MIN]) { error_condition |= E_TL_TOO_SHORT; } } void OvenCtl::check_Ts_duration_max() { if (disable_checks) return; if (time - Ts_time_start > profile->data[PI_TL_DURATION_MAX]) { error_condition |= E_TS_TOO_LONG; } } void OvenCtl::check_Tl_duration_min() { if (disable_checks) return; Tl_time_end = time; if (time - Tl_time_start < profile->data[PI_TL_DURATION_MIN]) { error_condition |= E_TL_TOO_SHORT; } } void OvenCtl::check_Tl_duration_max() { if (disable_checks) return; if (time - Tl_time_start > profile->data[PI_TL_DURATION_MAX]) { error_condition |= E_TL_TOO_LONG; } } void OvenCtl::check_Tp_duration_min() { Tp_time_end = time; if (time - Tp_time_start < profile->data[PI_TP_DURATION_MIN]) { error_condition |= E_TP_TOO_SHORT; } } void OvenCtl::check_Tp_duration_max() { if (disable_checks) return; if (time - Tp_time_start > profile->data[PI_TP_DURATION_MAX]) { error_condition |= E_TP_TOO_LONG; } } void OvenCtl::set_config_state() { send_config(); profile->print_config_state_0(lcd); } void OvenCtl::set_start_state() { led_on = false; digitalWrite(13, LOW); error_condition = 0; state = START_STATE; get_temp(); last_temperature = temperature; actual_dt = temperature - last_temperature; set_temp(profile->data[PI_TP]-5, profile->data[PI_TP], 0, profile->data[PI_RAMP_UP_MAX]); lcd->clear(); } void OvenCtl::set_preheat_state() { Serial.println("Changing state to PREHEAT_STATE"); state++; } void OvenCtl::set_ramp_up_state() { Serial.println("Changed state to RAMP_UP_STATE"); state++; } void OvenCtl::set_tal_first_state() { Serial.println("Changed state to TAL_FIRST_STATE"); state++; } void OvenCtl::set_peak_state() { Serial.println("Changed state to PEAK_STATE"); state++; } void OvenCtl::set_tal_second_state() { Serial.println("Changed state to TAL_SECOND_STATE"); set_temp(25, 25, -3, -6); state++; } void OvenCtl::set_ramp_down_state() { Serial.println("Changed state to RAMP_DOWN_STATE"); state++; } void OvenCtl::set_end_state() { Serial.println("Changed state to END_STATE"); state++; } void OvenCtl::set_error_state() { if (state != ERROR_STATE) { Serial.println("Changed state to ERROR_STATE"); set_temp(0, 0, 0, 0); state = ERROR_STATE; } } void OvenCtl::handle_config_state() { if (profile->handle_config_state(lcd, keypad)) state++; } void OvenCtl::handle_start_state() { check_max_duration(); Serial.println(time); if (temperature > profile->data[PI_TS_MIN]) { Ts_time_start = time; set_preheat_state(); } } void OvenCtl::handle_preheat_state() { check_Ts_duration_max(); check_max_duration(); if (temperature > profile->data[PI_TS_MAX]) { check_Ts_duration_min(); set_ramp_up_state(); } } void OvenCtl::handle_ramp_up_state() { check_max_duration(); if (temperature > profile->data[PI_TL]) { Tl_time_start = time; set_tal_first_state(); } } void OvenCtl::handle_tal_first_state() { check_max_duration(); check_Tl_duration_max(); if (temperature > profile->data[PI_TP] - 5) { Tp_time_start = time; set_peak_state(); } } void OvenCtl::handle_peak_state() { check_Tl_duration_max(); check_Tp_duration_max(); if (time - Tp_time_start > profile->data[PI_TP_DURATION_MAX]) { check_Tp_duration_min(); set_tal_second_state(); } } void OvenCtl::handle_tal_second_state() { check_Tl_duration_max(); if (temperature < profile->data[PI_TL]) { check_Tl_duration_min(); set_ramp_down_state(); } } void OvenCtl::handle_ramp_down_state() { if (temperature < profile->data[PI_TS_MIN]) { set_end_state(); } } void OvenCtl::handle_end_state() { // while(true) { // continue; // } } void OvenCtl::handle_error_state() { if (led_on) { digitalWrite(13, LOW); led_on = false; } else { digitalWrite(13, HIGH); led_on = true; } // if (error_condition & E_DT_MIN) // Serial.println(PSTR("Error: delta °K/second too low")); // if (error_condition & E_DT_MAX) // Serial.println("Error: delta °K/second too big"); // if (error_condition & E_TIME_MAX) // Serial.println("Error: reflow process does take too long"); // if (error_condition & E_TS_TOO_SHORT) // Serial.println("Error: heatup duration was too short"); // if (error_condition & E_TS_TOO_LONG) // Serial.println("Error: heatup duration was too long"); // if (error_condition & E_TL_TOO_SHORT) // Serial.println("Error: temperature above liquidus duration was too short"); // if (error_condition & E_TL_TOO_LONG) // Serial.println("Error: temperature above liquidus duration was too long"); // if (error_condition & E_TP_TOO_LONG) // Serial.println("Error: peak temperature duration was too short"); // if (error_condition & E_TP_TOO_SHORT) // Serial.println("Error: peak temperature duration was too long"); }