Compare commits

...

4 Commits

  1. 11
      README.md
  2. 8
      main/actuators.c
  3. 10
      main/actuators.h
  4. 170
      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_MIN = 14, // na teplotu - spodni 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_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)
H_RAMP_TIME = 30, // doba rozbehu nebo zastaveni motoru
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
I_T_VALIDITY = 1,
I_T_IN_INST = 2,
I_T_IN_INST = 2, // teplota x100 (C)
I_T_OUT_INST = 3,
I_T_INDOOR = 4,
I_T_OUTDOOR = 5,

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

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

@ -13,13 +13,15 @@
const char *TAG = "fc";
#define UNIDIR_T_MEAS_PERIOD 15 /* s */
#define UNIDIR_T_MEAS_PERIOD 60
struct FanControlState gState = {};
static void timerCallback();
static void invalidate_temps();
static float absf(float f);
void settings_blind_time_set(uint16_t blind_time)
{
// if the blind is surely at the end
@ -85,13 +87,39 @@ static const char * vent_mode_labels[] = {
[VENT_MODE_RECUP] = "RECUP",
};
static const char * recup_mode_labels[] = {
[RECUP_MODE_TIME] = "TIME",
[RECUP_MODE_TEMP] = "TEMP",
};
//static const char * recup_mode_labels[] = {
// [RECUP_MODE_TIME] = "TIME",
// [RECUP_MODE_TEMP] = "TEMP",
//};
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
if (gAct.blind) {
if (gState.blind_position < gSettings.blind_time) {
@ -115,7 +143,9 @@ static void timerCallback()
gState.ramp++;
}
}
gState.run_time++;
if (gState.run_time < 0xFFFF) {
gState.run_time++;
}
} else {
if (gState.ramp > 0) {
gState.ramp--;
@ -141,7 +171,8 @@ static void timerCallback()
if (gState.blind_position >= gSettings.blind_time) {
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;
}
break;
@ -151,7 +182,7 @@ static void timerCallback()
if (gState.blind_position >= gSettings.blind_time) {
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;
}
break;
@ -164,53 +195,49 @@ static void timerCallback()
// Stop condition
bool do_switch = false;
// TODO questionable logic, verify
// vyfukovaci strana trubice, libovona strana
if (gState.real_direction == MOTOR_DIR_IN) {
if (gState.t_actual_in <= gSettings.t_in_min || gState.t_actual_in >= gSettings.t_in_max) {
ESP_LOGW(TAG, "Temp limit reached, change dir!");
do_switch = true;
}
}
if (gSettings.recup_mode == RECUP_MODE_TIME) {
do_switch = gState.run_time >= gSettings.recup_time;
} else if (gState.run_time >= gSettings.max_recup_time) {
do_switch = true;
float t_output = gState.real_direction == MOTOR_DIR_OUT ? gState.t_actual_out : gState.t_actual_in;
float t_input = gState.real_direction == MOTOR_DIR_IN ? gState.t_actual_out : gState.t_actual_in;
float delta = absf(t_input - t_output);
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 {
// 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) {
if (gState.valid_t_indoor && gState.valid_t_exhaust && gState.valid_t_outdoor) {
delta = gState.t_indoor - gState.t_exhaust;
allow_temp_switch = true;
}
} else {
// IN
if (gState.valid_t_inflow && gState.valid_t_indoor && gState.valid_t_outdoor) {
delta = gState.t_inflow - gState.t_outdoor;
allow_temp_switch = true;
}
if (delta < gSettings.t_stopdelta_out) {
ESP_LOGW(TAG, "OUT stop delta reached, change dir!");
do_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) {
ESP_LOGW(TAG, "Recup time elapsed, change dir!");
do_switch = true;
}
} else {
if (gState.run_time >= gSettings.max_recup_time) {
ESP_LOGW(TAG, "Max time elapsed, change dir!");
// 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 (allow_temp_switch) {
if (gSettings.summer_mode) {
if (ideal_delta < 0) {
// warmer outside, trying to keep cool in
if (delta >= stop_delta) {
do_switch = true;
}
if (speed < gSettings.t_stop_speed) {
ESP_LOGW(TAG, "Near-equilibrium reached, change dir!");
do_switch = true;
}
// colder outside - no stopping (will run to max recup time)
} else {
if (ideal_delta > 0) {
// colder outside, trying to keep warmth in
if (delta <= stop_delta) {
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;
}
// 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) {
switch (gState.real_direction) {
case MOTOR_DIR_IN:
@ -273,29 +291,33 @@ static void timerCallback()
}
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",
vent_mode_labels[gState.set_vent_mode], vent_mode_labels[gState.effective_vent_mode], vent_mode_labels[gState.instantaneous_vent_mode],
"%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.instantaneous_vent_mode],
gState.blind_position,
gState.run_time,
gAct.power,
gState.t_indoor,
gState.valid_t_indoor ? "" : "!",
gState.t_outdoor,
gState.valid_t_outdoor ? "" : "!",
gState.t_inflow,
gState.valid_t_inflow ? "" : "!",
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 ? "" : "!"
gState.t_indoor, gState.valid_t_indoor ? "" : "!",
gState.t_outdoor, gState.valid_t_outdoor ? "" : "!",
gState.t_inflow, gState.valid_t_inflow ? "" : "!",
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)
{
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) {
return;
@ -323,7 +345,7 @@ static void invalidate_temps()
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);

@ -27,13 +27,14 @@ enum recup_mode {
RECUP_MODE_TEMP = 1,
};
#define NUM_PREVIOUS_T_INS 5
struct FanControlState {
/**
* 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;
perc_t set_power;
/**
* 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_out;
int16_t t_indoor;
int16_t t_outdoor;
int16_t t_inflow;
int16_t t_exhaust;
cels_t t_indoor;
cels_t t_outdoor;
cels_t t_inflow;
cels_t t_exhaust;
int16_t t_actual_in;
int16_t t_actual_out;
uint16_t tempSerial;
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;
uint16_t real_recup_time_out;
secs_t real_recup_time_in;
secs_t real_recup_time_out;
// Private
/**
@ -73,27 +77,27 @@ 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;
secs_t blind_position;
/**
* 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.
*/
uint16_t ramp;
secs_t ramp;
// helper counters that increment hour counters when overflow
uint16_t uptime_secs;
uint16_t motor_secs;
secs_t uptime_secs;
hours_t motor_secs;
uint16_t uptime_hours;
uint16_t motor_hours;
secs_t uptime_hours;
hours_t motor_hours;
};
extern struct FanControlState gState;
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

@ -1,4 +1,5 @@
#include <esp_log.h>
#include <math.h>
#include "mbiface.h"
#include "socket_server.h"
#include "tasks.h"
@ -29,8 +30,13 @@ enum HoldingRegisters {
H_RECUP_TIME = 13,
H_RECUP_TIME_MIN = 14,
H_RECUP_TIME_MAX = 15,
H_RECUP_FACTOR = 16,
// H_RECUP_FACTOR = 16,
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)
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) {
ESP_LOGD(TAG, "Read input %d", ref);
uint16_t scratch16 = 0;
@ -119,22 +133,22 @@ ModbusException_t ri(ModbusSlave_t *pSlave, uint16_t ref, uint16_t *pValue) {
*pValue = scratch16;
break;
case I_T_IN_INST:
*pValue = gState.t_actual_in;
*pValue = cels2reg(gState.t_actual_in);
break;
case I_T_OUT_INST:
*pValue = gState.t_actual_out;
*pValue = cels2reg(gState.t_actual_out);
break;
case I_T_INDOOR:
*pValue = gState.t_indoor;
*pValue = cels2reg(gState.t_indoor);
break;
case I_T_OUTDOOR:
*pValue = gState.t_outdoor;
*pValue = cels2reg(gState.t_outdoor);
break;
case I_T_INFLOW:
*pValue = gState.t_inflow;
*pValue = cels2reg(gState.t_inflow);
break;
case I_T_EXHAUST:
*pValue = gState.t_exhaust;
*pValue = cels2reg(gState.t_exhaust);
break;
case I_MODE_INST:
*pValue = gState.instantaneous_vent_mode;
@ -166,7 +180,9 @@ ModbusException_t ri(ModbusSlave_t *pSlave, uint16_t ref, uint16_t *pValue) {
break;
default:
return MB_EXCEPTION_ILLEGAL_DATA_ADDRESS;
// this allows Bridge reading
return 0;
//return MB_EXCEPTION_ILLEGAL_DATA_ADDRESS;
}
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:
*pValue = gSettings.max_recup_time;
break;
case H_RECUP_FACTOR:
*pValue = gSettings.recup_factor;
// case H_RECUP_FACTOR:
// *pValue = gSettings.recup_factor;
// break;
case H_T_IN_MIN:
*pValue = cels2reg(gSettings.t_in_min);
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:
*pValue = gSettings.ramp_time;
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 MB_EXCEPTION_ILLEGAL_DATA_ADDRESS;
return 0;
//return MB_EXCEPTION_ILLEGAL_DATA_ADDRESS;
}
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) {
ESP_LOGD(TAG, "Write holding %d := %02x", ref, value);
float f;
switch (ref) {
case H_MODE:
@ -311,13 +346,49 @@ ModbusException_t wh(ModbusSlave_t *pSlave, uint16_t ref, uint16_t value) {
gSettings.max_recup_time = value;
settings_persist(SETTINGS_max_recup_time);
break;
case H_RECUP_FACTOR:
if (value > 100) {
// case H_RECUP_FACTOR:
// 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;
}
gSettings.t_stopdelta_in = f;
settings_persist(SETTINGS_t_stopdelta_in);
break;
case H_T_STOPDELTA_OUT:
f = reg2cels(value);
if (f < 0) {
return MB_EXCEPTION_ILLEGAL_DATA_VALUE;
}
gSettings.recup_factor = value;
settings_persist(SETTINGS_recup_factor);
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:
gSettings.ramp_time = value;
settings_persist(SETTINGS_ramp_time);

@ -7,6 +7,7 @@
#include "owb.h"
#include "ds18b20.h"
#include "settings.h"
#include "recup_types.h"
static const char* TAG="1w";
@ -14,18 +15,20 @@ static owb_rmt_driver_info s_rmt_driver_info[2] = {};
static OneWireBus * sBuses[2] = {};
static DS18B20_Info *sDevs[2] = {};
volatile int16_t gTempSensors[2] = {};
volatile float gTempSensors[2] = {};
volatile bool tempSensorsOk = false;
volatile uint16_t gTempsSerial = 0;
static void owtask(void *dummy) {
while (1) {
int16_t a = 0, b = 0;
cels_t a = 0, b = 0;
int rv = read_onewires(&a, &b);
tempSensorsOk = (rv == 0);
ESP_LOGI(TAG, "t1 %d, t2 %d Cx10", a, b);
gTempSensors[0] = a;
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);
}
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++) {
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]);
}
int16_t val1 = (int16_t) roundf(readings[0] * 10);
int16_t val2 = (int16_t) roundf(readings[1] * 10);
cels_t val1 = (cels_t) readings[0];
cels_t val2 = (cels_t) readings[1];
if (gSettings.swap_temps) {
*a = val2;

@ -6,12 +6,14 @@
#define ONEWIRES_H
#include <stdint.h>
#include "recup_types.h"
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 uint16_t gTempsSerial;
#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;
};
#if 0
/** 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) {
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);
}
#endif
/** 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) {

@ -41,7 +41,6 @@ extern nvs_handle g_nvs_storage;
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_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 , max_recup_time , , 180 , true , u16 , &) /* seconds */ \
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(bool , summer_mode , , 0 , true , bool , &) /* rezim po zapnuti napajeni */ \
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 {
#undef X

Loading…
Cancel
Save