master
Ondřej Hruška 2 years ago
parent 475478aea4
commit 0753dce6b1
  1. 46
      main/actuators.c
  2. 3
      main/actuators.h
  3. 61
      main/fancontrol.c
  4. 6
      main/fancontrol.h
  5. 4
      main/settings.c
  6. 2
      main/settings.h

@ -12,7 +12,8 @@ struct actuators_status gAct = {
.power = 0, .power = 0,
}; };
static void buzzer_init() { static void buzzer_init()
{
ledc_timer_config_t ledc_timer = { ledc_timer_config_t ledc_timer = {
.duty_resolution = LEDC_TIMER_8_BIT, // resolution of PWM duty .duty_resolution = LEDC_TIMER_8_BIT, // resolution of PWM duty
.freq_hz = 4400, // frequency of PWM signal .freq_hz = 4400, // frequency of PWM signal
@ -34,7 +35,8 @@ static void buzzer_init() {
ledc_channel_config(&chan); ledc_channel_config(&chan);
} }
void act_buzzer_set(bool on) { void act_buzzer_set(bool on)
{
gAct.buzzer = on; gAct.buzzer = on;
if (on) { if (on) {
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 127); ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 127);
@ -44,7 +46,8 @@ void act_buzzer_set(bool on) {
} }
} }
static void motor_init() { static void motor_init()
{
ledc_timer_config_t ledc_timer = { ledc_timer_config_t ledc_timer = {
.duty_resolution = LEDC_TIMER_10_BIT, // resolution of PWM duty .duty_resolution = LEDC_TIMER_10_BIT, // resolution of PWM duty
.freq_hz = 1000, // frequency of PWM signal .freq_hz = 1000, // frequency of PWM signal
@ -75,14 +78,15 @@ static void motor_init() {
gpio_config(&ioconf); gpio_config(&ioconf);
} }
void act_motor_power_set(uint16_t perc) { void act_motor_power_set(uint16_t perc)
if (gAct.power == perc) return; {
if (gAct.power == perc) { return; }
if (perc > 0) { if (perc > 0) {
if (perc < gSettings.min_power) { if (perc < gSettings.min_power) {
perc = gSettings.min_power; perc = gSettings.min_power;
} }
gAct.power = perc; gAct.power = perc;
uint16_t duty = (uint16_t) (10.23f * (float)perc); uint16_t duty = (uint16_t) (10.23f * (float) perc);
if (duty > 1023) { if (duty > 1023) {
duty = 1023; duty = 1023;
} }
@ -94,12 +98,14 @@ void act_motor_power_set(uint16_t perc) {
} }
} }
void act_motor_direction_set(enum motor_direction dir) { void act_motor_direction_set(enum motor_direction dir)
{
gAct.dir = dir; gAct.dir = dir;
gpio_set_level(CONFIG_PIN_DIR, (int) dir); // TODO verify polarity gpio_set_level(CONFIG_PIN_DIR, (int) dir); // TODO verify polarity
} }
static void blind_init() { static void blind_init()
{
// Blind output // Blind output
gpio_config_t ioconf = { gpio_config_t ioconf = {
.mode = GPIO_MODE_OUTPUT, .mode = GPIO_MODE_OUTPUT,
@ -108,12 +114,14 @@ static void blind_init() {
gpio_config(&ioconf); gpio_config(&ioconf);
} }
void act_blind_set(bool open) { void act_blind_set(bool open)
{
gAct.blind = open; gAct.blind = open;
gpio_set_level(CONFIG_PIN_BLIND, (int) open); // TODO verify polarity gpio_set_level(CONFIG_PIN_BLIND, (int) open); // TODO verify polarity
} }
static void led_init() { static void led_init()
{
gpio_config_t ioconf = { gpio_config_t ioconf = {
.mode = GPIO_MODE_OUTPUT, .mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1 << CONFIG_PIN_LED, .pin_bit_mask = 1 << CONFIG_PIN_LED,
@ -121,14 +129,28 @@ static void led_init() {
gpio_config(&ioconf); gpio_config(&ioconf);
} }
void act_led_set(bool on) { void act_led_set(bool on)
{
gAct.led = on; gAct.led = on;
gpio_set_level(CONFIG_PIN_LED, (int) on); // TODO verify polarity gpio_set_level(CONFIG_PIN_LED, (int) on); // TODO verify polarity
} }
void act_init() { void act_init()
{
buzzer_init(); buzzer_init();
motor_init(); motor_init();
blind_init(); blind_init();
led_init(); led_init();
} }
int16_t act_temp_in()
{
// TODO
return 200;
}
int16_t act_temp_out()
{
// TODO
return 40;
}

@ -30,4 +30,7 @@ void act_motor_direction_set(enum motor_direction dir);
void act_blind_set(bool open); void act_blind_set(bool open);
void act_led_set(bool on); void act_led_set(bool on);
int16_t act_temp_in();
int16_t act_temp_out();
#endif //FANCTL_ACTUATORS_H #endif //FANCTL_ACTUATORS_H

@ -12,9 +12,11 @@
struct FanControlState gState = {}; struct FanControlState gState = {};
static void timerCallback(TimerHandle_t xTimer); static void timerCallback(TimerHandle_t xTimer);
static void invalidate_temps(); static void invalidate_temps();
void settings_blind_time_set(uint16_t blind_time) { void settings_blind_time_set(uint16_t blind_time)
{
bool nadoraz = (gState.blind_position >= gSettings.blind_time) || (gState.blind_position >= blind_time); bool nadoraz = (gState.blind_position >= gSettings.blind_time) || (gState.blind_position >= blind_time);
gSettings.blind_time = blind_time; gSettings.blind_time = blind_time;
@ -26,7 +28,8 @@ void settings_blind_time_set(uint16_t blind_time) {
settings_persist(SETTINGS_blind_time); settings_persist(SETTINGS_blind_time);
} }
void fancontrol_init() { void fancontrol_init()
{
gState.set_vent_mode = gSettings.initial_mode; gState.set_vent_mode = gSettings.initial_mode;
gState.set_power = gSettings.initial_power; gState.set_power = gSettings.initial_power;
@ -38,7 +41,8 @@ void fancontrol_init() {
} }
static void timerCallback(TimerHandle_t xTimer) { static void timerCallback(TimerHandle_t xTimer)
{
// posun rolety // posun rolety
if (gAct.blind) { if (gAct.blind) {
if (gState.blind_position < gSettings.blind_time) { if (gState.blind_position < gSettings.blind_time) {
@ -119,26 +123,22 @@ static void timerCallback(TimerHandle_t xTimer) {
do_switch = true; do_switch = true;
} else { } else {
// temp-based switching - magic(tm) // temp-based switching - magic(tm)
// Delta = IN - OUT
const int16_t ideal_delta = gState.t_indoor - gState.t_outdoor; const int16_t ideal_delta = gState.t_indoor - gState.t_outdoor;
int16_t delta, stop_delta; int16_t stop_delta = ((int32_t) ideal_delta
* (int32_t) (100 - gSettings.recup_factor)) / 100;
int16_t delta;
bool allow_temp_switch = false; bool allow_temp_switch = false;
if (gState.real_direction == MOTOR_DIR_OUT) { if (gState.real_direction == MOTOR_DIR_OUT) {
delta = gState.t_indoor - gState.t_exhaust;
// 100% factor = nadoraz
stop_delta = ((int32_t)ideal_delta
* (int32_t)(100 - gSettings.recup_factor)) / 100;
// Delta = IN - OUT
if (gState.valid_t_indoor && gState.valid_t_exhaust && gState.valid_t_outdoor) { if (gState.valid_t_indoor && gState.valid_t_exhaust && gState.valid_t_outdoor) {
delta = gState.t_indoor - gState.t_exhaust;
allow_temp_switch = true; allow_temp_switch = true;
} }
} else { } else {
// IN // IN
delta = gState.t_inflow - gState.t_outdoor; if (gState.valid_t_inflow && gState.valid_t_indoor && gState.valid_t_outdoor) {
// 100% factor = nadoraz delta = gState.t_inflow - gState.t_outdoor;
stop_delta = ((int32_t)ideal_delta
* (int32_t)(gSettings.recup_factor)) / 100;
// Delta = IN - OUT
if (gState.valid_t_intake && gState.valid_t_indoor && gState.valid_t_outdoor) {
allow_temp_switch = true; allow_temp_switch = true;
} }
} }
@ -188,13 +188,13 @@ static void timerCallback(TimerHandle_t xTimer) {
if (end_temp_meas) { if (end_temp_meas) {
if (gState.t_aggr_cnt > 0) { if (gState.t_aggr_cnt > 0) {
uint16_t t1 = (uint16_t) (gState.t1_aggr / gState.t_aggr_cnt); int16_t t1 = (int16_t) (gState.t1_aggr / (int32_t)gState.t_aggr_cnt);
uint16_t t2 = (uint16_t) (gState.t2_aggr / gState.t_aggr_cnt); int16_t t2 = (int16_t) (gState.t2_aggr / (int32_t)gState.t_aggr_cnt);
switch (gState.real_direction) { switch (gState.real_direction) {
case MOTOR_DIR_IN: case MOTOR_DIR_IN:
gState.t_outdoor = t2; gState.t_outdoor = t2;
gState.t_inflow = t1; gState.t_inflow = t1;
gState.valid_t_outdoor = gState.valid_t_intake = true; gState.valid_t_outdoor = gState.valid_t_inflow = true;
if (gState.effective_vent_mode == VENT_MODE_IN) { if (gState.effective_vent_mode == VENT_MODE_IN) {
gState.valid_t_indoor = gState.valid_t_exhaust = false; gState.valid_t_indoor = gState.valid_t_exhaust = false;
} }
@ -204,20 +204,21 @@ static void timerCallback(TimerHandle_t xTimer) {
gState.t_exhaust = t2; gState.t_exhaust = t2;
gState.valid_t_indoor = gState.valid_t_exhaust = true; gState.valid_t_indoor = gState.valid_t_exhaust = true;
if (gState.effective_vent_mode == VENT_MODE_OUT) { if (gState.effective_vent_mode == VENT_MODE_OUT) {
gState.valid_t_outdoor = gState.valid_t_intake = false; gState.valid_t_outdoor = gState.valid_t_inflow = false;
} }
break; break;
} }
} }
gState.t1_aggr = gState.t2_aggr = gState.t_aggr_cnt = 0; gState.t1_aggr = gState.t2_aggr = 0;
gState.t_aggr_cnt = 0;
} }
if (gState.effective_vent_mode == VENT_MODE_IN if (gState.effective_vent_mode == VENT_MODE_IN
|| gState.effective_vent_mode == VENT_MODE_OUT || gState.effective_vent_mode == VENT_MODE_OUT
|| gState.effective_vent_mode == VENT_MODE_RECUP) { || gState.effective_vent_mode == VENT_MODE_RECUP) {
// Measure temperatures // Measure temperatures
int16_t t1 = 200; int16_t t1 = act_temp_in();
int16_t t2 = 190; // TODO int16_t t2 = act_temp_out();
gState.t_actual_1 = t1; gState.t_actual_1 = t1;
gState.t_actual_2 = t2; gState.t_actual_2 = t2;
@ -225,7 +226,8 @@ static void timerCallback(TimerHandle_t xTimer) {
gState.valid_t_actual_1 = gState.valid_t_actual_2 = true; gState.valid_t_actual_1 = gState.valid_t_actual_2 = true;
if (gAct.dir == gState.real_direction if (gAct.dir == gState.real_direction
&& gState.ramp >= gSettings.ramp_time) { && gState.ramp >= gSettings.ramp_time)
{
gState.t1_aggr += t1; gState.t1_aggr += t1;
gState.t2_aggr += t2; gState.t2_aggr += t2;
gState.t_aggr_cnt++; gState.t_aggr_cnt++;
@ -235,7 +237,8 @@ static void timerCallback(TimerHandle_t xTimer) {
} }
} }
void fan_set_vent_mode(enum ventilation_mode mode) { void fan_set_vent_mode(enum ventilation_mode mode)
{
if (mode == gState.set_vent_mode) { if (mode == gState.set_vent_mode) {
return; return;
} }
@ -253,16 +256,18 @@ void fan_set_vent_mode(enum ventilation_mode mode) {
} }
} }
static void invalidate_temps() { static void invalidate_temps()
{
gState.valid_t_indoor = false; gState.valid_t_indoor = false;
gState.valid_t_outdoor = false; gState.valid_t_outdoor = false;
gState.valid_t_intake = false; gState.valid_t_inflow = false;
gState.valid_t_exhaust = false; gState.valid_t_exhaust = false;
gState.valid_t_actual_1 = false; gState.valid_t_actual_1 = false;
gState.valid_t_actual_2 = false; gState.valid_t_actual_2 = false;
} }
void fan_set_power(uint16_t power) { void fan_set_power(uint16_t power)
{
gState.set_power = power; gState.set_power = power;
if (power == 0) { if (power == 0) {
gState.effective_vent_mode = VENT_MODE_OFF; gState.effective_vent_mode = VENT_MODE_OFF;
@ -270,4 +275,4 @@ void fan_set_power(uint16_t power) {
} else { } else {
gState.effective_vent_mode = gState.set_vent_mode; gState.effective_vent_mode = gState.set_vent_mode;
} }
} }

@ -43,7 +43,7 @@ struct FanControlState {
/* sensors */ /* sensors */
bool valid_t_indoor; bool valid_t_indoor;
bool valid_t_outdoor; bool valid_t_outdoor;
bool valid_t_intake; bool valid_t_inflow;
bool valid_t_exhaust; bool valid_t_exhaust;
bool valid_t_actual_1; bool valid_t_actual_1;
bool valid_t_actual_2; bool valid_t_actual_2;
@ -78,8 +78,8 @@ struct FanControlState {
* "stav chodu motoru". 0=stop, ramp_time = jede. * "stav chodu motoru". 0=stop, ramp_time = jede.
*/ */
uint16_t ramp; uint16_t ramp;
uint32_t t1_aggr; int32_t t1_aggr;
uint32_t t2_aggr; int32_t t2_aggr;
uint32_t t_aggr_cnt; uint32_t t_aggr_cnt;
}; };

@ -37,6 +37,7 @@ union fu {
uint32_t u; uint32_t u;
}; };
#if 0
/** Read float from NVS. See `nvs_get_u32` for more info. */ /** Read float from NVS. See `nvs_get_u32` for more info. */
static esp_err_t nvs_get_f32 (nvs_handle_t handle, const char* key, float* out_value) { static esp_err_t nvs_get_f32 (nvs_handle_t handle, const char* key, float* out_value) {
uint32_t u = 0; uint32_t u = 0;
@ -60,6 +61,7 @@ static esp_err_t nvs_set_f32 (nvs_handle_t handle, const char* key, float value)
}; };
return nvs_set_u32(handle, key, reinterpret.u); return nvs_set_u32(handle, key, reinterpret.u);
} }
#endif
/** Dummy read from NVS; placeholder for XTABLE entries with manually implemented getters */ /** Dummy read from NVS; placeholder for XTABLE entries with manually implemented getters */
static esp_err_t nvs_get_none(nvs_handle handle, const char* key, void* out_value) { static esp_err_t nvs_get_none(nvs_handle handle, const char* key, void* out_value) {
@ -123,7 +125,7 @@ void settings_load(void)
void settings_persist(enum settings_key_enum what) void settings_persist(enum settings_key_enum what)
{ {
esp_err_t rv; esp_err_t rv;
char name[24]; //char name[24];
#undef NVSCHECK #undef NVSCHECK
#define NVSCHECK(callback) \ #define NVSCHECK(callback) \

@ -44,7 +44,7 @@ extern nvs_handle g_nvs_storage;
X(uint16_t , recup_factor , , 80 , true , u16 , &) /* perc */ \ X(uint16_t , recup_factor , , 80 , true , u16 , &) /* perc */ \
X(uint16_t , min_recup_time , , 30 , true , u16 , &) /* seconds */ \ X(uint16_t , min_recup_time , , 30 , true , u16 , &) /* seconds */ \
X(uint16_t , max_recup_time , , 120 , true , u16 , &) /* seconds */ \ X(uint16_t , max_recup_time , , 120 , true , u16 , &) /* seconds */ \
X(uint16_t , ramp_time , , 3 , true , u16 , &) /* cas rozjezdu nebo zastaveni motoru (s) */ \ X(uint16_t , ramp_time , , 5 , true , u16 , &) /* cas rozjezdu nebo zastaveni motoru (s) */ \
X(uint16_t , blind_time , , 30 , true , u16 , &) /* cas otevreni nebo zavreni rolety (s) */ \ X(uint16_t , blind_time , , 30 , true , u16 , &) /* cas otevreni nebo zavreni rolety (s) */ \
X(uint16_t , initial_mode , , 0 , true , u16 , &) /* rezim po zapnuti napajeni */ \ X(uint16_t , initial_mode , , 0 , true , u16 , &) /* rezim po zapnuti napajeni */ \
X(uint16_t , initial_power , , 100 , true , u16 , &) /* vychozi vykon */ \ X(uint16_t , initial_power , , 100 , true , u16 , &) /* vychozi vykon */ \

Loading…
Cancel
Save