#define START_STATE 0 #define PREHEAT_STATE 1 #define RAMP_UP_STATE 2 #define TAL_FIRST_STATE 3 #define PEAK_STATE 4 #define TAL_SECOND_STATE 5 #define RAMP_DOWN_STATE 6 #define END_STATE 7 #define ERROR_STATE 8 // error conditions #define E_RAMPUP 1 // oven heats up too fast #define E_RAMPDOWN_TOO_FAST 2 // oven cools down too fast #define E_RAMPDOWN_TOO_SLOW 3 // oven cools down too slow #define E_TIME_MAX 4 // reflow process does take too long #define E_PEAK_TOO_LONG 5 // package was roasted unsigned int time = 0; // profile seconds unsigned int temperatur = 25; // actual oven temp unsigned int last_temperatur = 25; // profile stuff unsigned int Ts_max = 200; // °C unsigned int Ts_min = 150; // °C unsigned int Tp = 260; // 245-260°C unsigned int rampup_rate = 50; // 3°C/s unsigned int preheat_duration = 100; // 60-180s unsigned int Tl = 217; // 217°C unsigned int Tl_duration = 100; // 60-150s unsigned int peak_duration = 30; // 20-40s unsigned int rampdown_max = 6; // 6°C/s max unsigned int rampdown_min = 2; // 2°C/s max unsigned int time_max = 480; // 8*60s max unsigned int Ts_min_time = 0; unsigned int Ts_max_time = 0; unsigned int Tl_time_start = 0; unsigned int Tl_time_end = 0; unsigned int Tp_time_start = 0; unsigned int Tp_time_end = 0; unsigned int error_condition = 0; boolean is_oven_heating = false; byte state = START_STATE; int analogPin = 2; int hysteresis = 0; int set_min = 0; int set_max = 0; void setup() { Serial.begin(9600); get_temp(); last_temperatur = temperatur; control_oven(Tp, Tp); } void set_temp(int min, int max) { set_min = min; set_max = max; } void control_oven() { if (temperatur < set_min) { is_oven_heating = true; Serial.println("Oven turned on"); } else if (temperatur < set_max) { is_oven_heating = false; Serial.println("Oven turned off"); } } void get_temp() { // simulating an +1K/s rampup oven last_temperatur = temperatur; temperatur = int(float(analogRead(analogPin)) * 0.2929); } void check_rampup_rate() { if (temperatur - last_temperatur > rampup_rate) { error_condition = E_RAMPUP; control_oven(false); } else control_oven(true); } boolean check_rampdown_rate() { unsigned int dt = temperatur - last_temperatur; if (dt > rampdown_max) { error_condition = E_RAMPDOWN_TOO_FAST; return false; } if (dt < rampdown_min) { error_condition = E_RAMPDOWN_TOO_SLOW; return false; } return true; } boolean check_max_duration() { if (time > time_max) { error_condition = E_TIME_MAX; return false; } } boolean check_Tl_duration() { if (time > time_max) { error_condition = E_TIME_MAX; return false; } } void handle_start_state() { if (temperatur > Ts_min) { Serial.println("Changing state to PREHEAT_STATE"); Ts_min_time = time; state++; } } void handle_peak_state() { Serial.println("PEAK_STATE"); if (temperatur > Tp) control_oven(false); else control_oven(true); if (time - Tp_time_start > peak_duration) { Serial.println("Changed state to TAL_SECOND_STATE"); Tp_time_end = time; state++; } } void loop() { time = millis() / 1000; get_temp(); Serial.print(time); Serial.print(" "); Serial.print(temperatur); Serial.print(" "); Serial.print(last_temperatur); Serial.print(" "); Serial.println(state); switch (state) { case START_STATE: Serial.println("START_STATE"); // going from room temp to preheat, nothing to check here handle_start_state(); break; case PREHEAT_STATE: Serial.println("PREHEAT_STATE"); check_rampup_rate(); if (temperatur > Ts_max) { Serial.println("Changed state to RAMP_UP_STATE"); Ts_max_time = time; state++; } break; case RAMP_UP_STATE: Serial.println("RAMP_UP_STATE"); check_rampup_rate(); if (temperatur > Tl) { Serial.println("Changed state to TAL_FIRST_STATE"); Tl_time_start = time; state++; } break; case TAL_FIRST_STATE: Serial.println("TAL_FIRST_STATE"); check_rampup_rate(); if (temperatur > Tp - 5) { Serial.println("Changed state to PEAK_STATE"); Tp_time_start = time; state++; } break; case PEAK_STATE: handle_peak_state(); break; case TAL_SECOND_STATE: Serial.println("TAL_SECOND_STATE"); if (temperatur < Tl) { Serial.println("Changed state to RAMP_DOWN_STATE"); Tl_time_end = time; state++; } break; case RAMP_DOWN_STATE: Serial.println("RAMP_DOWN_STATE"); if (temperatur < Ts_min) { Serial.println("Changed state to END_STATE"); state++; } break; case END_STATE: Serial.println("END_STATE"); default: break; } control_oven(); delay(1000); return; error: state = END_STATE; Serial.print("Error: "); Serial.println(error_condition); }