diff --git a/main/fancontrol.c b/main/fancontrol.c index 06b6cdb..365b070 100644 --- a/main/fancontrol.c +++ b/main/fancontrol.c @@ -8,9 +8,11 @@ #include "settings.h" #include "actuators.h" +#define UNIDIR_T_MEAS_PERIOD 15 /* s */ struct FanControlState gState = {}; static void timerCallback(TimerHandle_t xTimer); +static void invalidate_temps(); void settings_blind_time_set(uint16_t blind_time) { bool nadoraz = (gState.blind_position >= gSettings.blind_time) || (gState.blind_position >= blind_time); @@ -25,7 +27,7 @@ void settings_blind_time_set(uint16_t blind_time) { } void fancontrol_init() { - gState.vent_mode = gSettings.initial_mode; + gState.set_vent_mode = gSettings.initial_mode; gState.set_power = gSettings.initial_power; xTimerCreate("fanctl", @@ -69,7 +71,9 @@ static void timerCallback(TimerHandle_t xTimer) { } } - switch (gState.vent_mode) { + bool end_temp_meas = false; + + switch (gState.effective_vent_mode) { case VENT_MODE_OFF: act_motor_power_set(0); act_blind_set(0); @@ -84,6 +88,9 @@ static void timerCallback(TimerHandle_t xTimer) { if (gState.blind_position >= gSettings.blind_time) { act_motor_power_set(gState.set_power); } + if (gState.t_aggr_cnt > UNIDIR_T_MEAS_PERIOD) { + end_temp_meas = true; + } break; case VENT_MODE_IN: act_motor_direction_set(MOTOR_DIR_IN); @@ -91,6 +98,9 @@ static void timerCallback(TimerHandle_t xTimer) { if (gState.blind_position >= gSettings.blind_time) { act_motor_power_set(gState.set_power); } + if (gState.t_aggr_cnt > UNIDIR_T_MEAS_PERIOD) { + end_temp_meas = true; + } break; case VENT_MODE_RECUP: act_blind_set(1); @@ -103,6 +113,7 @@ static void timerCallback(TimerHandle_t xTimer) { // zmena smeru gState.run_time = 0; act_motor_direction_set(1 - gAct.dir); + end_temp_meas = true; } } } @@ -110,23 +121,94 @@ static void timerCallback(TimerHandle_t xTimer) { break; } - if (gAct.dir == gState.real_direction && gState.ramp >= gSettings.ramp_time) { - // Measure temperatures - int16_t t1 = 200; - int16_t t2 = 200; // TODO - - gState.t_actual_1 = t1; - gState.t_actual_2 = t2; + if (gState.effective_vent_mode == VENT_MODE_RECUP) { + if (gState.real_direction == MOTOR_DIR_OUT) { + gState.instantaneous_vent_mode = VENT_MODE_OUT; + } else { + gState.instantaneous_vent_mode = VENT_MODE_IN; + } + } else { + gState.instantaneous_vent_mode = gState.effective_vent_mode; + } + if (end_temp_meas) { + uint16_t t1 = (uint16_t) (gState.t1_aggr / gState.t_aggr_cnt); + uint16_t t2 = (uint16_t) (gState.t2_aggr / gState.t_aggr_cnt); switch (gState.real_direction) { case MOTOR_DIR_IN: gState.t_outdoor = t2; gState.t_intake = t1; + gState.valid_t_outdoor = gState.valid_t_intake = true; + if (gState.effective_vent_mode == VENT_MODE_IN) { + gState.valid_t_indoor = gState.valid_t_exhaust = false; + } break; case MOTOR_DIR_OUT: gState.t_indoor = t1; gState.t_exhaust = t2; + gState.valid_t_indoor = gState.valid_t_exhaust = true; + if (gState.effective_vent_mode == VENT_MODE_OUT) { + gState.valid_t_outdoor = gState.valid_t_intake = false; + } break; } + gState.t1_aggr = gState.t2_aggr = gState.t_aggr_cnt = 0; + } + + if (gState.effective_vent_mode == VENT_MODE_IN + || gState.effective_vent_mode == VENT_MODE_OUT + || gState.effective_vent_mode == VENT_MODE_RECUP) { + // Measure temperatures + int16_t t1 = 200; + int16_t t2 = 190; // TODO + + gState.t_actual_1 = t1; + gState.t_actual_2 = t2; + + gState.valid_t_actual_1 = gState.valid_t_actual_2 = true; + + if (gAct.dir == gState.real_direction + && gState.ramp >= gSettings.ramp_time) { + gState.t1_aggr += t1; + gState.t2_aggr += t2; + gState.t_aggr_cnt++; + } + } else { + gState.valid_t_actual_1 = gState.valid_t_actual_2 = false; + } +} + +void fan_set_vent_mode(enum ventilation_mode mode) { + if (mode == gState.set_vent_mode) { + return; + } + + gState.set_vent_mode = mode; + gState.t1_aggr = gState.t2_aggr = gState.t_aggr_cnt = 0; + if (gState.set_power != 0) { + gState.effective_vent_mode = mode; + } + + if (mode == VENT_MODE_OFF || mode == VENT_MODE_FREE) { + invalidate_temps(); } } + +static void invalidate_temps() { + gState.valid_t_indoor = false; + gState.valid_t_outdoor = false; + gState.valid_t_intake = false; + gState.valid_t_exhaust = false; + gState.valid_t_actual_1 = false; + gState.valid_t_actual_2 = false; +} + +void fan_set_power(uint16_t power) { + gState.set_power = power; + if (power == 0) { + gState.effective_vent_mode = VENT_MODE_OFF; + invalidate_temps(); + } else { + gState.effective_vent_mode = gState.set_vent_mode; + } +} \ No newline at end of file diff --git a/main/fancontrol.h b/main/fancontrol.h index c3b6dc1..32bce03 100644 --- a/main/fancontrol.h +++ b/main/fancontrol.h @@ -20,30 +20,24 @@ enum ventilation_mode { struct FanControlState { /** - * Poloha roletky, 0<->blind_time, inkrement/dekrement 1 za sekundu. - * Pri zmene blind_time se musi hodnota aktualizovat, pokud je na doraze nebo za. - */ - uint16_t blind_position; - /** - * Power requested trough register or as the default value + * Power requested trough register or as the default value. + * This value stays unchanged even if stopped, unlike gAct.power which reflects the actual output. */ uint16_t set_power; /** - * Cas chodu motoru v aktualnim smeru, inkrement 1 za sekundu. - */ - uint16_t run_time; - /** - * "stav chodu motoru". 0=stop, ramp_time = jede. - */ - uint16_t ramp; - /** - * skutecny aktualni pohyb motoru (zustava stejny, dokud ramp time nedosahne nuly) - */ - enum motor_direction real_direction; - /** - * rezim ventilace + * rezim ventilace. Use fan_set_vent_mode() to change it! */ - enum ventilation_mode vent_mode; + enum ventilation_mode set_vent_mode; + /** Status for the register */ + enum ventilation_mode instantaneous_vent_mode; + + /* sensors */ + bool valid_t_indoor; + bool valid_t_outdoor; + bool valid_t_intake; + bool valid_t_exhaust; + bool valid_t_actual_1; + bool valid_t_actual_2; uint16_t t_indoor; uint16_t t_outdoor; @@ -52,8 +46,37 @@ struct FanControlState { uint16_t t_actual_1; uint16_t t_actual_2; + + // Private + /** + * like vent_mode, but if power is 0, becomes OFF + */ + enum ventilation_mode effective_vent_mode; + /** + * skutecny aktualni pohyb motoru (zustava stejny, dokud ramp time nedosahne nuly) + */ + enum motor_direction real_direction; + /** + * Poloha roletky, 0<->blind_time, inkrement/dekrement 1 za sekundu. + * Pri zmene blind_time se musi hodnota aktualizovat, pokud je na doraze nebo za. + */ + uint16_t blind_position; + /** + * Cas chodu motoru v aktualnim smeru, inkrement 1 za sekundu. + */ + uint16_t run_time; + /** + * "stav chodu motoru". 0=stop, ramp_time = jede. + */ + uint16_t ramp; + uint32_t t1_aggr; + uint32_t t2_aggr; + uint32_t t_aggr_cnt; }; extern struct FanControlState gState; +void fan_set_vent_mode(enum ventilation_mode mode); +void fan_set_power(uint16_t power); + #endif //FANCTL_FANCONTROL_H