application: extend states and add central management
This commit is contained in:
parent
51cf8b0f95
commit
dde56c996c
228
application.c
228
application.c
|
@ -125,8 +125,39 @@ enum state_e {
|
|||
STATE_SAFE, /**< safe state entered, probably because of an error */
|
||||
STATE_HEAT, /**< simply heat up bed */
|
||||
STATE_COOL, /**< simply cool down bed */
|
||||
STATE_FAN, /**< simply use fan to set to ambient temperature */
|
||||
STATE_PREPARE, /**< heat up for initialisation/first denaturation */
|
||||
STATE_INITIALISATION, /**< first (longer) denaturation phase */
|
||||
STATE_TO_DENATURATION, /**< transition to denaturation phase */
|
||||
STATE_DENATURATION, /**< denaturation phase */
|
||||
STATE_TO_ANNEALING, /**< transition to annealing phase */
|
||||
STATE_ANNEALING, /**< annealing phase */
|
||||
STATE_TO_EXTENSTION, /**< transition to extension phase */
|
||||
STATE_EXTENSION, /**< extension phase */
|
||||
STATE_TO_HOLD, /**< transition to final hold */
|
||||
STATE_HOLD, /**< final hold */
|
||||
} state = STATE_IDLE;
|
||||
|
||||
/** name of the states */
|
||||
const char* state_names[] = {
|
||||
[STATE_IDLE] = "ready",
|
||||
[STATE_SAFE] = "safe",
|
||||
[STATE_HEAT] = "heating",
|
||||
[STATE_COOL] = "cooling",
|
||||
[STATE_FAN] = "fanning",
|
||||
[STATE_PREPARE] = ">initialisation",
|
||||
[STATE_INITIALISATION] = "initialisation",
|
||||
[STATE_TO_DENATURATION] = ">denaturation",
|
||||
[STATE_DENATURATION] = "denaturation",
|
||||
[STATE_TO_ANNEALING] = ">annealing",
|
||||
[STATE_ANNEALING] = "annealing",
|
||||
[STATE_TO_EXTENSTION] = ">extension",
|
||||
[STATE_EXTENSION] = "extension",
|
||||
// there is an optional final extension
|
||||
[STATE_TO_HOLD] = ">final hold",
|
||||
[STATE_HOLD] = "final hold",
|
||||
};
|
||||
|
||||
/** set if an error or anomaly has been encountered */
|
||||
static char* error = NULL;
|
||||
|
||||
|
@ -151,8 +182,6 @@ size_t putc(char c)
|
|||
*/
|
||||
static void safe_state(void)
|
||||
{
|
||||
state = STATE_SAFE; // remember we entered safe state
|
||||
|
||||
// this is the safest configuration of TEC switching (in cooling mode it switches all off, in heating mode it only heats mildly the top part
|
||||
gpio_set(GPIO_PORT(MBLK019_CH26_PIN), GPIO_PIN(MBLK019_CH26_PIN)); // don't sink current (e.g. not powering the opto-coupler/transistor)
|
||||
gpio_set(GPIO_PORT(MBLK019_CH14_PIN), GPIO_PIN(MBLK019_CH14_PIN)); // don't sink current (e.g. not powering the opto-coupler/transistor)
|
||||
|
@ -177,13 +206,9 @@ static void safe_state(void)
|
|||
led_cool_blink = false; // stop blinking LED
|
||||
led_cool_off(); // switch off LED
|
||||
|
||||
oled_text_clear(); // clear screen
|
||||
oled_text_line("safe", 0); // indicate state
|
||||
oled_text_update(); // display text
|
||||
|
||||
if (error) {
|
||||
led_power_blink = false; // start blinking red LED to indicate error
|
||||
oled_text_line("error", 1);
|
||||
oled_text_line("error", 2);
|
||||
oled_text_update();
|
||||
}
|
||||
}
|
||||
|
@ -429,6 +454,155 @@ static void bed_pid(void)
|
|||
tec_power((uint16_t)power); // set power
|
||||
}
|
||||
|
||||
/** set new state
|
||||
* @param[in] new new state to set
|
||||
*/
|
||||
static void set_state(enum state_e new)
|
||||
{
|
||||
if (STATE_SAFE == state && STATE_SAFE != new) {
|
||||
puts("restart controller to exit safe state\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (new) {
|
||||
case STATE_IDLE: // you can go to idle from any state (except safe)
|
||||
tec_power(0); // ensure bed is not powered anymore
|
||||
tec_power_yellow_off(); // disconnect all wires
|
||||
tec_power_orange_off(); // disconnect all wires
|
||||
lid_power(0); // ensure lid is not powered
|
||||
break;
|
||||
case STATE_SAFE: // go to safe state
|
||||
safe_state(); // put all peripherals in safe mode
|
||||
break;
|
||||
case STATE_HEAT:
|
||||
heatsink_fan_on(); // switch fan on
|
||||
tec_power(0); // switch power off before changing mode
|
||||
tec_heat(); // switch to heating mode
|
||||
break;
|
||||
case STATE_COOL:
|
||||
heatsink_fan_on(); // switch fan on
|
||||
tec_power(0); // switch power off before changing mode
|
||||
tec_cool(); // switch to heating mode
|
||||
break;
|
||||
case STATE_FAN:
|
||||
tec_power(0); // ensure bed is not powered anymore
|
||||
tec_power_yellow_off(); // disconnect all wires
|
||||
tec_power_orange_off(); // disconnect all wires
|
||||
lid_power(0); // ensure lid is not powered
|
||||
heatsink_fan_on(); // switch fan on
|
||||
break;
|
||||
case STATE_PREPARE:
|
||||
if (STATE_IDLE == state) { // only allowed from idle state
|
||||
bed_target = 95.0; // set target temperature
|
||||
lid_target = bed_target; // set temperature
|
||||
heatsink_fan_on(); // switch fan on
|
||||
tec_power(0); // switch power off
|
||||
tec_heat(); // switch to heating mode
|
||||
// TODO set unlimited time
|
||||
} else { // transition not allowed
|
||||
set_state(STATE_SAFE);
|
||||
}
|
||||
break;
|
||||
case STATE_INITIALISATION:
|
||||
if (STATE_PREPARE == state) { // only allowed from state
|
||||
// temperature and heating is already set
|
||||
// TODO set time to 5 min
|
||||
} else { // transition not allowed
|
||||
set_state(STATE_SAFE);
|
||||
}
|
||||
break;
|
||||
case STATE_TO_DENATURATION:
|
||||
if (STATE_EXTENSION == state) { // only allowed from state
|
||||
lid_target = 95.0; // set target temperature
|
||||
bed_target = 95.0; // set target temperature
|
||||
// heating is already set
|
||||
// TODO set unlimited time
|
||||
} else { // transition not allowed
|
||||
set_state(STATE_SAFE);
|
||||
}
|
||||
break;
|
||||
case STATE_DENATURATION:
|
||||
if (STATE_TO_DENATURATION == state) { // only allowed from state
|
||||
// temperature and heating is already set
|
||||
// TODO set time to 5 min
|
||||
} else { // transition not allowed
|
||||
set_state(STATE_SAFE);
|
||||
}
|
||||
break;
|
||||
case STATE_TO_ANNEALING:
|
||||
if (STATE_DENATURATION == state) { // only allowed from state
|
||||
bed_target = 45.0; // set target temperature (5 °C below primer)
|
||||
lid_target = bed_target; // same temperature
|
||||
tec_power(0); // switch power off
|
||||
tec_cool(); // switch to cooling mode
|
||||
// TODO set unlimited time
|
||||
} else { // transition not allowed
|
||||
set_state(STATE_SAFE);
|
||||
}
|
||||
break;
|
||||
case STATE_ANNEALING:
|
||||
if (STATE_TO_ANNEALING == state) { // only allowed from state
|
||||
tec_power(0); // switch power off before switching mode
|
||||
tec_heat(); // switch to heating mode
|
||||
// temperature is already set
|
||||
// TODO set time to 30-40 s
|
||||
} else { // transition not allowed
|
||||
set_state(STATE_SAFE);
|
||||
}
|
||||
break;
|
||||
case STATE_TO_EXTENSTION:
|
||||
if (STATE_ANNEALING == state) { // only allowed from state
|
||||
bed_target = 72.0; // set target temperature
|
||||
lid_target = bed_target; // set target temperature
|
||||
// heating is already set
|
||||
// TODO set unlimited time
|
||||
} else { // transition not allowed
|
||||
set_state(STATE_SAFE);
|
||||
}
|
||||
break;
|
||||
case STATE_EXTENSION:
|
||||
if (STATE_TO_EXTENSTION == state) { // only allowed from state
|
||||
// temperature and heating is already set
|
||||
// TODO set time to ~1 min/kb of expected product; 5-10 min on last cycle.
|
||||
} else { // transition not allowed
|
||||
set_state(STATE_SAFE);
|
||||
}
|
||||
break;
|
||||
case STATE_TO_HOLD:
|
||||
if (STATE_EXTENSION == state) { // only allowed from state
|
||||
bed_target = 10.0; // set target temperature (5 °C below primer)
|
||||
lid_target = NAN; // we don't need to heat anymore
|
||||
lid_power(0); // switch power off
|
||||
tec_power(0); // switch power off
|
||||
tec_cool(); // switch to cooling mode
|
||||
// TODO set unlimited time
|
||||
} else { // transition not allowed
|
||||
set_state(STATE_SAFE);
|
||||
}
|
||||
break;
|
||||
case STATE_HOLD:
|
||||
if (STATE_TO_HOLD == state) { // only allowed from state
|
||||
// nothing to do, we just reached the final hold up
|
||||
// TODO set time to 30-40 s
|
||||
} else { // transition not allowed
|
||||
set_state(STATE_SAFE);
|
||||
}
|
||||
break;
|
||||
default: // unknown new state
|
||||
error = "unknown state to set";
|
||||
set_state(STATE_SAFE);
|
||||
break;
|
||||
}
|
||||
|
||||
// display state
|
||||
if (new != state && STATE_SAFE != state) {
|
||||
state = new; // save new state
|
||||
printf("new state: %s\n", state_names[state]); // show new state
|
||||
oled_text_line(state_names[state], 1); // set new state
|
||||
oled_text_update(); // show on display
|
||||
}
|
||||
}
|
||||
|
||||
/** display available commands
|
||||
* @param[in] argument no argument required
|
||||
*/
|
||||
|
@ -467,25 +641,17 @@ static void command_bed_power(void* argument)
|
|||
return;
|
||||
}
|
||||
if (0 == target) { // switch off
|
||||
// turn all off
|
||||
tec_power(0); // switch power off
|
||||
tec_power_yellow_off(); // disconnect 12V from yellow TEC line
|
||||
tec_power_orange_off(); // disconnect 12V from orange TEC line
|
||||
heatsink_fan_off(); // we can switch the fan off now
|
||||
bed_target = 0; // remember we have no target
|
||||
state = STATE_IDLE; // set new state
|
||||
set_state(STATE_IDLE); // set new state
|
||||
} else if (1 == target) { // just use fan
|
||||
bed_target = 0; // remember we have no target
|
||||
set_state(STATE_FAN); // set new state
|
||||
} else if (target > 0) { // heat
|
||||
heatsink_fan_on(); // switch fan on
|
||||
tec_power(0); // switch power off
|
||||
tec_heat(); // switch to heating mode
|
||||
bed_target = target; // remember target
|
||||
state = STATE_HEAT; // set new state
|
||||
set_state(STATE_HEAT); // set new state
|
||||
} else { // cool
|
||||
heatsink_fan_on(); // switch fan on
|
||||
tec_power(0); // switch power off
|
||||
tec_cool(); // switch to heating mode
|
||||
bed_target = -target; // remember target
|
||||
state = STATE_COOL; // set new state
|
||||
set_state(STATE_COOL); // set new state
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -543,24 +709,14 @@ static void command_lid_temperature(void* argument)
|
|||
static void command_safe(void* argument)
|
||||
{
|
||||
(void)argument; // we won't use the argument
|
||||
safe_state();
|
||||
set_state(STATE_SAFE);
|
||||
printf("in safe state\n");
|
||||
}
|
||||
|
||||
static void command_state(void* argument)
|
||||
{
|
||||
(void)argument; // we won't use the argument
|
||||
switch (state) {
|
||||
case STATE_IDLE:
|
||||
puts("idle");
|
||||
break;
|
||||
case STATE_SAFE:
|
||||
puts("safe");
|
||||
break;
|
||||
default:
|
||||
puts("unknown state");
|
||||
break;
|
||||
}
|
||||
puts(state_names[state]);
|
||||
putc('\n');
|
||||
|
||||
if (error) {
|
||||
|
@ -951,7 +1107,7 @@ void main(void)
|
|||
if (oled_text_setup()) { // setup OLED display with default slave address
|
||||
oled_text_clear(); // clear buffer (else last state is displayed)
|
||||
oled_text_line("PCR 3000", 0);
|
||||
oled_text_line("system ready", 1);
|
||||
oled_text_line(state_names[state], 1); // show state
|
||||
oled_text_update();
|
||||
puts("OK\n");
|
||||
} else {
|
||||
|
@ -975,7 +1131,7 @@ void main(void)
|
|||
terminal_setup(); // start terminal
|
||||
|
||||
if (error && STATE_SAFE != state) { // an error has occurred during initialisation
|
||||
safe_state(); // go to safe state
|
||||
set_state(STATE_SAFE); // go to safe state
|
||||
} else {
|
||||
led_power_on(); // indicate user we are ready
|
||||
}
|
||||
|
@ -1078,7 +1234,7 @@ void main(void)
|
|||
error = "heat sink is getting too warm";
|
||||
}
|
||||
if (error) { // an error has occurred
|
||||
safe_state(); // go to safe state
|
||||
set_state(STATE_SAFE); // go to safe state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue