Compare commits

..

4 Commits

  1. 11
      README.md
  2. 8
      main/actuators.c
  3. 10
      main/actuators.h
  4. 156
      main/fancontrol.c
  5. 38
      main/fancontrol.h
  6. 101
      main/mbiface.c
  7. 15
      main/onewires.c
  8. 6
      main/onewires.h
  9. 15
      main/recup_types.h
  10. 2
      main/settings.c
  11. 10
      main/settings.h

@ -29,9 +29,16 @@ H_RECUP_MODE = 12, // 0=na cas, 1=na teplotu (experimentalni)
H_RECUP_TIME = 13, // pokud na cas, pak toho je cas rekuperace H_RECUP_TIME = 13, // pokud na cas, pak toho je cas rekuperace
H_RECUP_TIME_MIN = 14, // na teplotu - spodni limit H_RECUP_TIME_MIN = 14, // na teplotu - spodni limit
H_RECUP_TIME_MAX = 15, // na teplotu - horni limit H_RECUP_TIME_MAX = 15, // na teplotu - horni limit
H_RECUP_FACTOR = 16, // na teplotu - faktor, 80% = foukej dokud delta teplot neklesne o 80% // 16 - reserved
H_MIN_POWER = 17, // min povoleny vykon motoru H_MIN_POWER = 17, // min povoleny vykon motoru
H_T_IN_MIN = 18,
H_T_IN_MAX = 19,
// these don't work in summer mode:
H_T_STOPDELTA_IN = 20,
H_T_STOPDELTA_OUT = 21,
H_T_STOP_SPEED = 22,
// Hardware settings (don't need to change once set correctly) // Hardware settings (don't need to change once set correctly)
H_RAMP_TIME = 30, // doba rozbehu nebo zastaveni motoru H_RAMP_TIME = 30, // doba rozbehu nebo zastaveni motoru
H_BLIND_TIME = 31, // doba otevreni roletky H_BLIND_TIME = 31, // doba otevreni roletky
@ -51,7 +58,7 @@ Je take zrcadleno v holding mape s ofsetem 1000 (read-only)
// napr. 3 = jsou platne jen T_{IN,OUT}_INST // napr. 3 = jsou platne jen T_{IN,OUT}_INST
I_T_VALIDITY = 1, I_T_VALIDITY = 1,
I_T_IN_INST = 2, I_T_IN_INST = 2, // teplota x100 (C)
I_T_OUT_INST = 3, I_T_OUT_INST = 3,
I_T_INDOOR = 4, I_T_INDOOR = 4,
I_T_OUTDOOR = 5, I_T_OUTDOOR = 5,

@ -145,12 +145,16 @@ void act_init()
led_init(); led_init();
} }
int16_t act_temp1() cels_t act_temp1()
{ {
return gTempSensors[0]; return gTempSensors[0];
} }
int16_t act_temp2() cels_t act_temp2()
{ {
return gTempSensors[1]; return gTempSensors[1];
} }
uint16_t act_temps_serial() {
return gTempsSerial;
}

@ -7,6 +7,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "recup_types.h"
enum motor_direction { enum motor_direction {
MOTOR_DIR_IN = 0, MOTOR_DIR_IN = 0,
@ -17,19 +18,20 @@ struct actuators_status {
enum motor_direction dir; enum motor_direction dir;
bool blind; bool blind;
bool led; bool led;
uint16_t power; perc_t power;
}; };
extern struct actuators_status gAct; extern struct actuators_status gAct;
void act_init(); void act_init();
void act_motor_power_set(uint16_t perc); void act_motor_power_set(perc_t perc);
void act_motor_direction_set(enum motor_direction dir); 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);
void act_statusled_set(bool on); void act_statusled_set(bool on);
int16_t act_temp1(); cels_t act_temp1();
int16_t act_temp2(); cels_t act_temp2();
uint16_t act_temps_serial();
#endif //FANCTL_ACTUATORS_H #endif //FANCTL_ACTUATORS_H

@ -13,13 +13,15 @@
const char *TAG = "fc"; const char *TAG = "fc";
#define UNIDIR_T_MEAS_PERIOD 15 /* s */ #define UNIDIR_T_MEAS_PERIOD 60
struct FanControlState gState = {}; struct FanControlState gState = {};
static void timerCallback(); static void timerCallback();
static void invalidate_temps(); static void invalidate_temps();
static float absf(float f);
void settings_blind_time_set(uint16_t blind_time) void settings_blind_time_set(uint16_t blind_time)
{ {
// if the blind is surely at the end // if the blind is surely at the end
@ -85,13 +87,39 @@ static const char * vent_mode_labels[] = {
[VENT_MODE_RECUP] = "RECUP", [VENT_MODE_RECUP] = "RECUP",
}; };
static const char * recup_mode_labels[] = { //static const char * recup_mode_labels[] = {
[RECUP_MODE_TIME] = "TIME", // [RECUP_MODE_TIME] = "TIME",
[RECUP_MODE_TEMP] = "TEMP", // [RECUP_MODE_TEMP] = "TEMP",
}; //};
static void timerCallback() static void timerCallback()
{ {
// Measure temperatures
cels_t tin = act_temp1();
cels_t tout = act_temp2();
uint16_t old_tempSerial = gState.tempSerial;
// float old_tin = gState.t_actual_in;
// float old_tout = gState.t_actual_out;
gState.tempSerial = act_temps_serial();
gState.t_actual_in = tin;
gState.t_actual_out = tout;
gState.valid_t_actual_in = gState.valid_t_actual_out = tempSensorsOk;
if (gState.tempSerial != old_tempSerial) {
// measuring speed of temp change
for (int i = NUM_PREVIOUS_T_INS - 1; i > 0; i--) {
gState.previous_t_ins[i] = gState.previous_t_ins[i - 1];
}
if (gState.real_direction == MOTOR_DIR_IN) {
gState.previous_t_ins[0] = tin;
} else {
gState.previous_t_ins[0] = tout;
}
}
// posun rolety // posun rolety
if (gAct.blind) { if (gAct.blind) {
if (gState.blind_position < gSettings.blind_time) { if (gState.blind_position < gSettings.blind_time) {
@ -115,7 +143,9 @@ static void timerCallback()
gState.ramp++; gState.ramp++;
} }
} }
if (gState.run_time < 0xFFFF) {
gState.run_time++; gState.run_time++;
}
} else { } else {
if (gState.ramp > 0) { if (gState.ramp > 0) {
gState.ramp--; gState.ramp--;
@ -141,7 +171,8 @@ static void timerCallback()
if (gState.blind_position >= gSettings.blind_time) { if (gState.blind_position >= gSettings.blind_time) {
act_motor_power_set(gState.set_power); act_motor_power_set(gState.set_power);
} }
if (gState.ramp >= gSettings.ramp_time * 2) { // some time is needed before the temperature means anything
if (gState.run_time >= UNIDIR_T_MEAS_PERIOD) {
end_temp_meas = true; end_temp_meas = true;
} }
break; break;
@ -151,7 +182,7 @@ static void timerCallback()
if (gState.blind_position >= gSettings.blind_time) { if (gState.blind_position >= gSettings.blind_time) {
act_motor_power_set(gState.set_power); act_motor_power_set(gState.set_power);
} }
if (gState.ramp >= gSettings.ramp_time * 2) { if (gState.run_time >= UNIDIR_T_MEAS_PERIOD) {
end_temp_meas = true; end_temp_meas = true;
} }
break; break;
@ -164,54 +195,50 @@ static void timerCallback()
// Stop condition // Stop condition
bool do_switch = false; bool do_switch = false;
// TODO questionable logic, verify // vyfukovaci strana trubice, libovona strana
if (gState.real_direction == MOTOR_DIR_IN) {
if (gSettings.recup_mode == RECUP_MODE_TIME) { if (gState.t_actual_in <= gSettings.t_in_min || gState.t_actual_in >= gSettings.t_in_max) {
do_switch = gState.run_time >= gSettings.recup_time; ESP_LOGW(TAG, "Temp limit reached, change dir!");
} else if (gState.run_time >= gSettings.max_recup_time) {
do_switch = true; do_switch = true;
} else { }
// temp-based switching - magic(tm) }
// Delta = IN - OUT
const int16_t ideal_delta = gState.t_indoor - gState.t_outdoor;
int16_t stop_delta = ((int32_t) ideal_delta
* (int32_t) (100 - gSettings.recup_factor)) / 100;
int16_t delta = 0;
bool allow_temp_switch = false;
if (gState.real_direction == MOTOR_DIR_OUT) { float t_output = gState.real_direction == MOTOR_DIR_OUT ? gState.t_actual_out : gState.t_actual_in;
if (gState.valid_t_indoor && gState.valid_t_exhaust && gState.valid_t_outdoor) { float t_input = gState.real_direction == MOTOR_DIR_IN ? gState.t_actual_out : gState.t_actual_in;
delta = gState.t_indoor - gState.t_exhaust; float delta = absf(t_input - t_output);
allow_temp_switch = true;
if (gState.real_direction == MOTOR_DIR_IN) {
if (delta < gSettings.t_stopdelta_in) {
ESP_LOGW(TAG, "IN stop delta reached, change dir!");
do_switch = true;
} }
} else { } else {
// IN if (delta < gSettings.t_stopdelta_out) {
if (gState.valid_t_inflow && gState.valid_t_indoor && gState.valid_t_outdoor) { ESP_LOGW(TAG, "OUT stop delta reached, change dir!");
delta = gState.t_inflow - gState.t_outdoor; do_switch = true;
allow_temp_switch = true;
} }
} }
ESP_LOGI(TAG, "Delta now %d, max %d, stop %d (RF %d%%), allow_switch %d Cx10", delta, ideal_delta, stop_delta, gSettings.recup_factor, allow_temp_switch); if (gSettings.recup_mode == RECUP_MODE_TIME) {
if (gState.run_time >= gSettings.recup_time) {
if (allow_temp_switch) { ESP_LOGW(TAG, "Recup time elapsed, change dir!");
if (gSettings.summer_mode) {
if (ideal_delta < 0) {
// warmer outside, trying to keep cool in
if (delta >= stop_delta) {
do_switch = true; do_switch = true;
} }
}
// colder outside - no stopping (will run to max recup time)
} else { } else {
if (ideal_delta > 0) { if (gState.run_time >= gSettings.max_recup_time) {
// colder outside, trying to keep warmth in ESP_LOGW(TAG, "Max time elapsed, change dir!");
if (delta <= stop_delta) { // Max time elapsed, switch even if the condition was not reached
do_switch = true;
} else {
if (!gSettings.summer_mode) {
// expecting some change in temps
float speed = absf(gState.previous_t_ins[NUM_PREVIOUS_T_INS - 1] - gState.previous_t_ins[0]) / (float)NUM_PREVIOUS_T_INS;
if (speed < gSettings.t_stop_speed) {
ESP_LOGW(TAG, "Near-equilibrium reached, change dir!");
do_switch = true; do_switch = true;
} }
} }
// warmer outside - no stopping (will run to max recup time)
}
} }
} }
@ -242,15 +269,6 @@ static void timerCallback()
gState.instantaneous_vent_mode = gState.effective_vent_mode; gState.instantaneous_vent_mode = gState.effective_vent_mode;
} }
// Measure temperatures
int16_t t1 = act_temp1();
int16_t t2 = act_temp2();
gState.t_actual_in = t1;
gState.t_actual_out = t2;
gState.valid_t_actual_in = gState.valid_t_actual_out = tempSensorsOk;
if (end_temp_meas) { if (end_temp_meas) {
switch (gState.real_direction) { switch (gState.real_direction) {
case MOTOR_DIR_IN: case MOTOR_DIR_IN:
@ -273,29 +291,33 @@ static void timerCallback()
} }
ESP_LOGI(TAG, ESP_LOGI(TAG,
"%s (ef %s, inst %s), rt %ds %d%%m, Tid %d%s, Tod %d%s, Tit %d%s, Teh %d%s, T1 %d%s, T2 %d%s Cx10", "%s (%s), B%ds, M%ds, %d%%, Tid %.2f%s, Tod %.2f%s, Tit %.2f%s, Teh %.2f%s, T1 %.2f%s, T2 %.2f%s C",
vent_mode_labels[gState.set_vent_mode], vent_mode_labels[gState.effective_vent_mode], vent_mode_labels[gState.instantaneous_vent_mode], vent_mode_labels[gState.set_vent_mode], vent_mode_labels[gState.instantaneous_vent_mode],
gState.blind_position,
gState.run_time, gState.run_time,
gAct.power, gAct.power,
gState.t_indoor, gState.t_indoor, gState.valid_t_indoor ? "" : "!",
gState.valid_t_indoor ? "" : "!", gState.t_outdoor, gState.valid_t_outdoor ? "" : "!",
gState.t_outdoor, gState.t_inflow, gState.valid_t_inflow ? "" : "!",
gState.valid_t_outdoor ? "" : "!", gState.t_exhaust, gState.valid_t_exhaust ? "" : "!",
gState.t_inflow, gState.t_actual_in, gState.valid_t_actual_in ? "" : "!",
gState.valid_t_inflow ? "" : "!", gState.t_actual_out, gState.valid_t_actual_out ? "" : "!"
gState.t_exhaust,
gState.valid_t_exhaust ? "" : "!",
gState.t_actual_in,
gState.valid_t_actual_in ? "" : "!",
gState.t_actual_out,
gState.valid_t_actual_out ? "" : "!"
); );
} }
static float absf(float f)
{
if (f < 0) {
return -f;
} else {
return f;
}
}
void fan_set_vent_mode(enum ventilation_mode mode) void fan_set_vent_mode(enum ventilation_mode mode)
{ {
ESP_LOGI(TAG, "Set vent mode = %d", mode); ESP_LOGI(TAG, "Set vent mode = %s", vent_mode_labels[mode]);
if (mode == gState.set_vent_mode) { if (mode == gState.set_vent_mode) {
return; return;
@ -323,7 +345,7 @@ static void invalidate_temps()
gState.valid_t_actual_out = false; gState.valid_t_actual_out = false;
} }
void fan_set_power(uint16_t power) void fan_set_power(perc_t power)
{ {
ESP_LOGI(TAG, "Set power = %d%%", power); ESP_LOGI(TAG, "Set power = %d%%", power);

@ -27,13 +27,14 @@ enum recup_mode {
RECUP_MODE_TEMP = 1, RECUP_MODE_TEMP = 1,
}; };
#define NUM_PREVIOUS_T_INS 5
struct FanControlState { struct FanControlState {
/** /**
* 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. * This value stays unchanged even if stopped, unlike gAct.power which reflects the actual output.
*/ */
uint16_t set_power; perc_t set_power;
/** /**
* rezim ventilace. Use fan_set_vent_mode() to change it! * rezim ventilace. Use fan_set_vent_mode() to change it!
*/ */
@ -49,16 +50,19 @@ struct FanControlState {
bool valid_t_actual_in; bool valid_t_actual_in;
bool valid_t_actual_out; bool valid_t_actual_out;
int16_t t_indoor; cels_t t_indoor;
int16_t t_outdoor; cels_t t_outdoor;
int16_t t_inflow; cels_t t_inflow;
int16_t t_exhaust; cels_t t_exhaust;
int16_t t_actual_in; uint16_t tempSerial;
int16_t t_actual_out; cels_t t_actual_in;
cels_t t_actual_out;
// buffer used to calculate the current temp change speed
cels_t previous_t_ins[NUM_PREVIOUS_T_INS];
uint16_t real_recup_time_in; secs_t real_recup_time_in;
uint16_t real_recup_time_out; secs_t real_recup_time_out;
// Private // Private
/** /**
@ -73,27 +77,27 @@ struct FanControlState {
* Poloha roletky, 0<->blind_time, inkrement/dekrement 1 za sekundu. * Poloha roletky, 0<->blind_time, inkrement/dekrement 1 za sekundu.
* Pri zmene blind_time se musi hodnota aktualizovat, pokud je na doraze nebo za. * Pri zmene blind_time se musi hodnota aktualizovat, pokud je na doraze nebo za.
*/ */
uint16_t blind_position; secs_t blind_position;
/** /**
* Cas chodu motoru v aktualnim smeru, inkrement 1 za sekundu. * Cas chodu motoru v aktualnim smeru, inkrement 1 za sekundu.
*/ */
uint16_t run_time; secs_t run_time;
/** /**
* "stav chodu motoru". 0=stop, ramp_time = jede. * "stav chodu motoru". 0=stop, ramp_time = jede.
*/ */
uint16_t ramp; secs_t ramp;
// helper counters that increment hour counters when overflow // helper counters that increment hour counters when overflow
uint16_t uptime_secs; secs_t uptime_secs;
uint16_t motor_secs; hours_t motor_secs;
uint16_t uptime_hours; secs_t uptime_hours;
uint16_t motor_hours; hours_t motor_hours;
}; };
extern struct FanControlState gState; extern struct FanControlState gState;
void fan_set_vent_mode(enum ventilation_mode mode); void fan_set_vent_mode(enum ventilation_mode mode);
void fan_set_power(uint16_t power); void fan_set_power(perc_t power);
#endif //FANCTL_FANCONTROL_H #endif //FANCTL_FANCONTROL_H

@ -1,4 +1,5 @@
#include <esp_log.h> #include <esp_log.h>
#include <math.h>
#include "mbiface.h" #include "mbiface.h"
#include "socket_server.h" #include "socket_server.h"
#include "tasks.h" #include "tasks.h"
@ -29,8 +30,13 @@ enum HoldingRegisters {
H_RECUP_TIME = 13, H_RECUP_TIME = 13,
H_RECUP_TIME_MIN = 14, H_RECUP_TIME_MIN = 14,
H_RECUP_TIME_MAX = 15, H_RECUP_TIME_MAX = 15,
H_RECUP_FACTOR = 16, // H_RECUP_FACTOR = 16,
H_MIN_POWER = 17, H_MIN_POWER = 17,
H_T_IN_MIN = 18,
H_T_IN_MAX = 19,
H_T_STOPDELTA_IN = 20,
H_T_STOPDELTA_OUT = 21,
H_T_STOP_SPEED = 22,
// Hardware settings (don't need to change once set correctly) // Hardware settings (don't need to change once set correctly)
H_RAMP_TIME = 30, H_RAMP_TIME = 30,
@ -97,6 +103,14 @@ void endOfAccess(ModbusSlave_t *ms) {
// //
} }
union ui16 {
uint16_t u;
uint16_t i;
};
#define cels2reg(cels) (((union ui16) { .i = ((int16_t) roundf((cels) * 100.0f)) }).u)
#define reg2cels(regv) (((float) ((union ui16) { .u = (regv) }).i) / 100.0f)
ModbusException_t ri(ModbusSlave_t *pSlave, uint16_t ref, uint16_t *pValue) { ModbusException_t ri(ModbusSlave_t *pSlave, uint16_t ref, uint16_t *pValue) {
ESP_LOGD(TAG, "Read input %d", ref); ESP_LOGD(TAG, "Read input %d", ref);
uint16_t scratch16 = 0; uint16_t scratch16 = 0;
@ -119,22 +133,22 @@ ModbusException_t ri(ModbusSlave_t *pSlave, uint16_t ref, uint16_t *pValue) {
*pValue = scratch16; *pValue = scratch16;
break; break;
case I_T_IN_INST: case I_T_IN_INST:
*pValue = gState.t_actual_in; *pValue = cels2reg(gState.t_actual_in);
break; break;
case I_T_OUT_INST: case I_T_OUT_INST:
*pValue = gState.t_actual_out; *pValue = cels2reg(gState.t_actual_out);
break; break;
case I_T_INDOOR: case I_T_INDOOR:
*pValue = gState.t_indoor; *pValue = cels2reg(gState.t_indoor);
break; break;
case I_T_OUTDOOR: case I_T_OUTDOOR:
*pValue = gState.t_outdoor; *pValue = cels2reg(gState.t_outdoor);
break; break;
case I_T_INFLOW: case I_T_INFLOW:
*pValue = gState.t_inflow; *pValue = cels2reg(gState.t_inflow);
break; break;
case I_T_EXHAUST: case I_T_EXHAUST:
*pValue = gState.t_exhaust; *pValue = cels2reg(gState.t_exhaust);
break; break;
case I_MODE_INST: case I_MODE_INST:
*pValue = gState.instantaneous_vent_mode; *pValue = gState.instantaneous_vent_mode;
@ -166,7 +180,9 @@ ModbusException_t ri(ModbusSlave_t *pSlave, uint16_t ref, uint16_t *pValue) {
break; break;
default: default:
return MB_EXCEPTION_ILLEGAL_DATA_ADDRESS; // this allows Bridge reading
return 0;
//return MB_EXCEPTION_ILLEGAL_DATA_ADDRESS;
} }
return MB_EXCEPTION_OK; return MB_EXCEPTION_OK;
@ -206,9 +222,26 @@ ModbusException_t rh(ModbusSlave_t *pSlave, uint16_t ref, uint16_t *pValue) {
case H_RECUP_TIME_MAX: case H_RECUP_TIME_MAX:
*pValue = gSettings.max_recup_time; *pValue = gSettings.max_recup_time;
break; break;
case H_RECUP_FACTOR: // case H_RECUP_FACTOR:
*pValue = gSettings.recup_factor; // *pValue = gSettings.recup_factor;
// break;
case H_T_IN_MIN:
*pValue = cels2reg(gSettings.t_in_min);
break; break;
case H_T_IN_MAX:
*pValue = cels2reg(gSettings.t_in_max);
break;
case H_T_STOPDELTA_IN:
*pValue = cels2reg(gSettings.t_stopdelta_in);
break;
case H_T_STOPDELTA_OUT:
*pValue = cels2reg(gSettings.t_stopdelta_out);
break;
case H_T_STOP_SPEED:
*pValue = cels2reg(gSettings.t_stop_speed);
break;
case H_RAMP_TIME: case H_RAMP_TIME:
*pValue = gSettings.ramp_time; *pValue = gSettings.ramp_time;
break; break;
@ -230,7 +263,8 @@ ModbusException_t rh(ModbusSlave_t *pSlave, uint16_t ref, uint16_t *pValue) {
return ri(pSlave, ref - INPUT_REG_MIRROR_IN_HOLDING_BASE_ADDR, pValue); return ri(pSlave, ref - INPUT_REG_MIRROR_IN_HOLDING_BASE_ADDR, pValue);
} }
return MB_EXCEPTION_ILLEGAL_DATA_ADDRESS; return 0;
//return MB_EXCEPTION_ILLEGAL_DATA_ADDRESS;
} }
return MB_EXCEPTION_OK; return MB_EXCEPTION_OK;
@ -251,6 +285,7 @@ static bool is_valid_vent_mode(int value) {
ModbusException_t wh(ModbusSlave_t *pSlave, uint16_t ref, uint16_t value) { ModbusException_t wh(ModbusSlave_t *pSlave, uint16_t ref, uint16_t value) {
ESP_LOGD(TAG, "Write holding %d := %02x", ref, value); ESP_LOGD(TAG, "Write holding %d := %02x", ref, value);
float f;
switch (ref) { switch (ref) {
case H_MODE: case H_MODE:
@ -311,13 +346,49 @@ ModbusException_t wh(ModbusSlave_t *pSlave, uint16_t ref, uint16_t value) {
gSettings.max_recup_time = value; gSettings.max_recup_time = value;
settings_persist(SETTINGS_max_recup_time); settings_persist(SETTINGS_max_recup_time);
break; break;
case H_RECUP_FACTOR: // case H_RECUP_FACTOR:
if (value > 100) { // if (value > 100) {
// return MB_EXCEPTION_ILLEGAL_DATA_VALUE;
// }
// gSettings.recup_factor = value;
// settings_persist(SETTINGS_recup_factor);
// break;
case H_T_IN_MIN:
f = reg2cels(value);
gSettings.t_in_min = f;
settings_persist(SETTINGS_t_in_min);
break;
case H_T_IN_MAX:
f = reg2cels(value);
gSettings.t_in_max = f;
settings_persist(SETTINGS_t_in_max);
break;
case H_T_STOPDELTA_IN:
f = reg2cels(value);
if (f < 0) {
return MB_EXCEPTION_ILLEGAL_DATA_VALUE; return MB_EXCEPTION_ILLEGAL_DATA_VALUE;
} }
gSettings.recup_factor = value; gSettings.t_stopdelta_in = f;
settings_persist(SETTINGS_recup_factor); settings_persist(SETTINGS_t_stopdelta_in);
break; break;
case H_T_STOPDELTA_OUT:
f = reg2cels(value);
if (f < 0) {
return MB_EXCEPTION_ILLEGAL_DATA_VALUE;
}
gSettings.t_stopdelta_out = f;
settings_persist(SETTINGS_t_stopdelta_out);
break;
case H_T_STOP_SPEED:
f = reg2cels(value);
if (f < 0) {
return MB_EXCEPTION_ILLEGAL_DATA_VALUE;
}
gSettings.t_stop_speed = f;
settings_persist(SETTINGS_t_stop_speed);
break;
case H_RAMP_TIME: case H_RAMP_TIME:
gSettings.ramp_time = value; gSettings.ramp_time = value;
settings_persist(SETTINGS_ramp_time); settings_persist(SETTINGS_ramp_time);

@ -7,6 +7,7 @@
#include "owb.h" #include "owb.h"
#include "ds18b20.h" #include "ds18b20.h"
#include "settings.h" #include "settings.h"
#include "recup_types.h"
static const char* TAG="1w"; static const char* TAG="1w";
@ -14,18 +15,20 @@ static owb_rmt_driver_info s_rmt_driver_info[2] = {};
static OneWireBus * sBuses[2] = {}; static OneWireBus * sBuses[2] = {};
static DS18B20_Info *sDevs[2] = {}; static DS18B20_Info *sDevs[2] = {};
volatile int16_t gTempSensors[2] = {}; volatile float gTempSensors[2] = {};
volatile bool tempSensorsOk = false; volatile bool tempSensorsOk = false;
volatile uint16_t gTempsSerial = 0;
static void owtask(void *dummy) { static void owtask(void *dummy) {
while (1) { while (1) {
int16_t a = 0, b = 0; cels_t a = 0, b = 0;
int rv = read_onewires(&a, &b); int rv = read_onewires(&a, &b);
tempSensorsOk = (rv == 0); tempSensorsOk = (rv == 0);
ESP_LOGI(TAG, "t1 %d, t2 %d Cx10", a, b);
gTempSensors[0] = a; gTempSensors[0] = a;
gTempSensors[1] = b; gTempSensors[1] = b;
gTempsSerial++;
ESP_LOGI(TAG, "t1 %.2f, t2 %.2f C", a, b);
} }
} }
@ -45,7 +48,7 @@ void onewires_setup()
xTaskCreate(owtask, "1w", ONEWIRES_TASK_STACK, NULL, ONEWIRES_TASK_PRIO, NULL); xTaskCreate(owtask, "1w", ONEWIRES_TASK_STACK, NULL, ONEWIRES_TASK_PRIO, NULL);
} }
int read_onewires(int16_t *a, int16_t *b) int read_onewires(cels_t *a, cels_t *b)
{ {
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
ds18b20_convert_all(sBuses[i]); ds18b20_convert_all(sBuses[i]);
@ -61,8 +64,8 @@ int read_onewires(int16_t *a, int16_t *b)
errors[i] = ds18b20_read_temp(sDevs[i], &readings[i]); errors[i] = ds18b20_read_temp(sDevs[i], &readings[i]);
} }
int16_t val1 = (int16_t) roundf(readings[0] * 10); cels_t val1 = (cels_t) readings[0];
int16_t val2 = (int16_t) roundf(readings[1] * 10); cels_t val2 = (cels_t) readings[1];
if (gSettings.swap_temps) { if (gSettings.swap_temps) {
*a = val2; *a = val2;

@ -6,12 +6,14 @@
#define ONEWIRES_H #define ONEWIRES_H
#include <stdint.h> #include <stdint.h>
#include "recup_types.h"
void onewires_setup(); void onewires_setup();
int read_onewires(int16_t *a, int16_t *b); int read_onewires(cels_t *a, cels_t *b);
extern volatile int16_t gTempSensors[2]; extern volatile cels_t gTempSensors[2];
extern volatile bool tempSensorsOk; extern volatile bool tempSensorsOk;
extern volatile uint16_t gTempsSerial;
#endif //ONEWIRES_H #endif //ONEWIRES_H

@ -0,0 +1,15 @@
/**
* Commonly used types
*/
#ifndef REKUPERATOR_RECUP_TYPES_H
#define REKUPERATOR_RECUP_TYPES_H
#include <stdint.h>
typedef float cels_t;
typedef uint16_t perc_t;
typedef uint16_t secs_t;
typedef uint16_t hours_t;
#endif //REKUPERATOR_RECUP_TYPES_H

@ -37,7 +37,6 @@ 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;
@ -61,7 +60,6 @@ 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) {

@ -41,7 +41,6 @@ extern nvs_handle g_nvs_storage;
X(uint32_t , static_dns , , 0x08080808 , true , u32 , &) /* 8.8.8.8 */ \ X(uint32_t , static_dns , , 0x08080808 , true , u32 , &) /* 8.8.8.8 */ \
X(uint16_t , recup_mode , , 0 , true , u16 , &) /* recuperator control mode - 0=time, 1=min time+temp equilibrium */ \ X(uint16_t , recup_mode , , 0 , true , u16 , &) /* recuperator control mode - 0=time, 1=min time+temp equilibrium */ \
X(uint16_t , recup_time , , 60 , true , u16 , &) /* seconds */ \ X(uint16_t , recup_time , , 60 , true , u16 , &) /* seconds */ \
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 , , 180 , true , u16 , &) /* seconds */ \ X(uint16_t , max_recup_time , , 180 , true , u16 , &) /* seconds */ \
X(uint16_t , ramp_time , , 6 , true , u16 , &) /* cas rozjezdu nebo zastaveni motoru (s) */ \ X(uint16_t , ramp_time , , 6 , true , u16 , &) /* cas rozjezdu nebo zastaveni motoru (s) */ \
@ -51,7 +50,14 @@ extern nvs_handle g_nvs_storage;
X(uint16_t , min_power , , 5 , true , u16 , &) /* min power % */ \ X(uint16_t , min_power , , 5 , true , u16 , &) /* min power % */ \
X(bool , summer_mode , , 0 , true , bool , &) /* rezim po zapnuti napajeni */ \ X(bool , summer_mode , , 0 , true , bool , &) /* rezim po zapnuti napajeni */ \
X(bool , swap_temps , , 0 , true , bool , &) /* swap t0/t1 */ \ X(bool , swap_temps , , 0 , true , bool , &) /* swap t0/t1 */ \
X(bool , swap_pwm_dir , , 0 , true , bool , &) /* swap pwm/dir signal */ X(bool , swap_pwm_dir , , 0 , true , bool , &) /* swap pwm/dir signal */ \
X(float , t_in_min , , 10 , true , f32 , &) /* minimalni teplota do mistnosti */ \
X(float , t_in_max , , 27 , true , f32 , &) /* maximalni teplota do mistnosti */ \
X(float , t_stopdelta_in , , 3 , true , f32 , &) /* delta when recuperation stops in IN mode */ \
X(float , t_stopdelta_out , , 1 , true , f32 , &) /* delta when recuperation stops in OUT mode */ \
X(float , t_stop_speed , , 0.025 , true , f32 , &) /* zastav rekuperaci, pokud zmena teploty na vystupni strane roste/klesa pomaleji nez X/sec */
// X(uint16_t , recup_factor , , 80 , true , u16 , &) /* perc */
enum settings_key_enum { enum settings_key_enum {
#undef X #undef X

Loading…
Cancel
Save