convert all temp measurements to float, add newtypes for units

fix-tempmode
Ondřej Hruška 2 years ago
parent ebc4f7b165
commit 01b94ff604
  1. 4
      main/actuators.c
  2. 9
      main/actuators.h
  3. 98
      main/fancontrol.c
  4. 34
      main/fancontrol.h
  5. 22
      main/mbiface.c
  6. 13
      main/onewires.c
  7. 5
      main/onewires.h
  8. 15
      main/recup_types.h

@ -145,12 +145,12 @@ 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];
}

@ -7,6 +7,7 @@
#include <stdbool.h>
#include <stdint.h>
#include "recup_types.h"
enum motor_direction {
MOTOR_DIR_IN = 0,
@ -17,19 +18,19 @@ 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();
#endif //FANCTL_ACTUATORS_H

@ -13,7 +13,7 @@
const char *TAG = "fc";
#define UNIDIR_T_MEAS_PERIOD 15 /* s */
#define UNIDIR_T_MEAS_PERIOD 60
struct FanControlState gState = {};
static void timerCallback();
@ -85,10 +85,10 @@ 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()
{
@ -115,7 +115,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 +143,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 +154,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,54 +167,14 @@ static void timerCallback()
// Stop condition
bool do_switch = false;
// TODO questionable logic, verify
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;
} 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;
}
if (gState.run_time >= gSettings.max_recup_time) {
// Max time elapsed, switch even if the condition was not reached
do_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;
}
}
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 (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;
}
}
// 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)
}
// TODO
}
}
@ -243,8 +206,8 @@ static void timerCallback()
}
// Measure temperatures
int16_t t1 = act_temp1();
int16_t t2 = act_temp2();
cels_t t1 = act_temp1();
cels_t t2 = act_temp2();
gState.t_actual_in = t1;
gState.t_actual_out = t2;
@ -273,29 +236,24 @@ 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 ? "" : "!"
);
}
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 +281,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);

@ -33,7 +33,7 @@ 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 +49,16 @@ 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;
cels_t t_actual_in;
cels_t t_actual_out;
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 +73,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"
@ -97,6 +98,8 @@ void endOfAccess(ModbusSlave_t *ms) {
//
}
#define cels2reg(cels) ((uint16_t) roundf((cels) * 100))
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 +122,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 +169,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;
@ -230,7 +235,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;

@ -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,18 @@ 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;
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;
ESP_LOGI(TAG, "t1 %.2f, t2 %.2f C", a, b);
}
}
@ -45,7 +46,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 +62,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,13 @@
#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;
#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
Loading…
Cancel
Save