forked from electro/esp-irblaster
finalizations
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
menu "Project configuration"
|
||||
|
||||
menu "Pin mapping"
|
||||
config PIN_BUZZER
|
||||
int "Buzzer pin"
|
||||
default 16
|
||||
|
||||
config PIN_LED
|
||||
int "LED pin"
|
||||
default 17
|
||||
|
||||
config PIN_STATUSLED
|
||||
int "Status LED pin"
|
||||
default 20
|
||||
|
||||
config PIN_BLIND
|
||||
int "Blind open pin"
|
||||
default 18
|
||||
|
||||
+16
-44
@@ -16,46 +16,14 @@ struct actuators_status gAct = {
|
||||
.power = 0,
|
||||
};
|
||||
|
||||
static void buzzer_init()
|
||||
{
|
||||
ledc_timer_config_t ledc_timer = {
|
||||
.duty_resolution = LEDC_TIMER_8_BIT, // resolution of PWM duty
|
||||
.freq_hz = 4400, // frequency of PWM signal
|
||||
.speed_mode = LEDC_HIGH_SPEED_MODE, // timer mode
|
||||
.timer_num = LEDC_TIMER_0, // timer index
|
||||
.clk_cfg = LEDC_AUTO_CLK, // Auto select the source clock
|
||||
};
|
||||
// Set configuration of timer0 for high speed channels
|
||||
ledc_timer_config(&ledc_timer);
|
||||
|
||||
ledc_channel_config_t chan = {
|
||||
.channel = LEDC_CHANNEL_0,
|
||||
.duty = 127,
|
||||
.gpio_num = CONFIG_PIN_BUZZER,
|
||||
.speed_mode = LEDC_HIGH_SPEED_MODE,
|
||||
.hpoint = 0,
|
||||
.timer_sel = LEDC_TIMER_0
|
||||
};
|
||||
ledc_channel_config(&chan);
|
||||
}
|
||||
|
||||
void act_buzzer_set(bool on)
|
||||
{
|
||||
if (gAct.buzzer == on) {
|
||||
return;
|
||||
}
|
||||
ESP_LOGI(TAG, "set buzzer %d", on);
|
||||
gAct.buzzer = on;
|
||||
if (on) {
|
||||
ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 127);
|
||||
ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0);
|
||||
} else {
|
||||
ledc_stop(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 0);
|
||||
}
|
||||
}
|
||||
int sPinPwm = 0;
|
||||
int sPinDir = 0;
|
||||
|
||||
static void motor_init()
|
||||
{
|
||||
sPinPwm = (gSettings.swap_pwm_dir ? CONFIG_PIN_DIR : CONFIG_PIN_PWM);
|
||||
sPinDir = (gSettings.swap_pwm_dir ? CONFIG_PIN_PWM : CONFIG_PIN_DIR);
|
||||
|
||||
ledc_timer_config_t ledc_timer = {
|
||||
.duty_resolution = LEDC_TIMER_10_BIT, // resolution of PWM duty
|
||||
.freq_hz = 1000, // frequency of PWM signal
|
||||
@@ -70,7 +38,7 @@ static void motor_init()
|
||||
ledc_channel_config_t chan = {
|
||||
.channel = LEDC_CHANNEL_1,
|
||||
.duty = 512,
|
||||
.gpio_num = CONFIG_PIN_PWM,
|
||||
.gpio_num = sPinPwm,
|
||||
.speed_mode = LEDC_HIGH_SPEED_MODE,
|
||||
.hpoint = 0,
|
||||
.timer_sel = LEDC_TIMER_1,
|
||||
@@ -81,7 +49,7 @@ static void motor_init()
|
||||
// Direction output
|
||||
gpio_config_t ioconf = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = 1 << CONFIG_PIN_DIR,
|
||||
.pin_bit_mask = 1 << sPinDir,
|
||||
};
|
||||
gpio_config(&ioconf);
|
||||
|
||||
@@ -123,7 +91,7 @@ void act_motor_direction_set(enum motor_direction dir)
|
||||
}
|
||||
ESP_LOGI(TAG, "set dir %d", dir);
|
||||
gAct.dir = dir;
|
||||
gpio_set_level(CONFIG_PIN_DIR, (int) dir); // TODO verify polarity
|
||||
gpio_set_level(sPinDir, (int) dir); // TODO verify polarity
|
||||
}
|
||||
|
||||
static void blind_init()
|
||||
@@ -150,7 +118,7 @@ static void led_init()
|
||||
{
|
||||
gpio_config_t ioconf = {
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = 1 << CONFIG_PIN_LED,
|
||||
.pin_bit_mask = (1 << CONFIG_PIN_LED) | (1 << CONFIG_PIN_STATUSLED),
|
||||
};
|
||||
gpio_config(&ioconf);
|
||||
}
|
||||
@@ -165,20 +133,24 @@ void act_led_set(bool on)
|
||||
gpio_set_level(CONFIG_PIN_LED, (int) on); // TODO verify polarity
|
||||
}
|
||||
|
||||
void act_statusled_set(bool on)
|
||||
{
|
||||
gpio_set_level(CONFIG_PIN_STATUSLED, (int) on);
|
||||
}
|
||||
|
||||
void act_init()
|
||||
{
|
||||
buzzer_init();
|
||||
motor_init();
|
||||
blind_init();
|
||||
led_init();
|
||||
}
|
||||
|
||||
int16_t act_temp_in()
|
||||
int16_t act_temp1()
|
||||
{
|
||||
return gTempSensors[0];
|
||||
}
|
||||
|
||||
int16_t act_temp_out()
|
||||
int16_t act_temp2()
|
||||
{
|
||||
return gTempSensors[1];
|
||||
}
|
||||
|
||||
+3
-4
@@ -17,20 +17,19 @@ struct actuators_status {
|
||||
enum motor_direction dir;
|
||||
bool blind;
|
||||
bool led;
|
||||
bool buzzer;
|
||||
uint16_t power;
|
||||
};
|
||||
|
||||
extern struct actuators_status gAct;
|
||||
|
||||
void act_init();
|
||||
void act_buzzer_set(bool on);
|
||||
void act_motor_power_set(uint16_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_temp_in();
|
||||
int16_t act_temp_out();
|
||||
int16_t act_temp1();
|
||||
int16_t act_temp2();
|
||||
|
||||
#endif //FANCTL_ACTUATORS_H
|
||||
|
||||
+21
-2
@@ -35,9 +35,27 @@ void settings_blind_time_set(uint16_t blind_time)
|
||||
|
||||
static void fanctltask(void *dummy) {
|
||||
TickType_t last_wake_time = xTaskGetTickCount();
|
||||
bool statusled = 0;
|
||||
while (1) {
|
||||
act_statusled_set(statusled);
|
||||
statusled ^= 1;
|
||||
//
|
||||
timerCallback();
|
||||
vTaskDelayUntil(&last_wake_time, pdMS_TO_TICKS(1000));
|
||||
|
||||
gState.uptime_secs += 1;
|
||||
if (gState.uptime_secs >= 3600) {
|
||||
gState.uptime_secs = 0;
|
||||
gState.uptime_hours += 1;
|
||||
}
|
||||
|
||||
if ((gState.effective_vent_mode & 6) != 0) {
|
||||
gState.motor_secs += 1;
|
||||
if (gState.motor_secs >= 3600) {
|
||||
gState.motor_secs = 0;
|
||||
gState.motor_hours += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +64,7 @@ void fancontrol_init()
|
||||
gState.set_vent_mode = gSettings.initial_mode;
|
||||
gState.set_power = gSettings.initial_power;
|
||||
|
||||
// this doesnt work
|
||||
// TimerHandle_t hTimer = xTimerCreate("fanctl",
|
||||
// pdMS_TO_TICKS(1000),
|
||||
// pdTRUE,
|
||||
@@ -236,8 +255,8 @@ static void timerCallback()
|
||||
}
|
||||
|
||||
// Measure temperatures
|
||||
int16_t t1 = act_temp_in();
|
||||
int16_t t2 = act_temp_out();
|
||||
int16_t t1 = act_temp1();
|
||||
int16_t t2 = act_temp2();
|
||||
|
||||
gState.t_actual_in = t1;
|
||||
gState.t_actual_out = t2;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
void fancontrol_init();
|
||||
|
||||
/** this is bit-based: IN:OUT:BLIND */
|
||||
enum ventilation_mode {
|
||||
VENT_MODE_OFF = 0,
|
||||
VENT_MODE_FREE = 1,
|
||||
@@ -84,6 +85,13 @@ struct FanControlState {
|
||||
int32_t t1_aggr;
|
||||
int32_t t2_aggr;
|
||||
uint32_t t_aggr_cnt;
|
||||
|
||||
// helper counters that increment hour counters when overflow
|
||||
uint16_t uptime_secs;
|
||||
uint16_t motor_secs;
|
||||
|
||||
uint16_t uptime_hours;
|
||||
uint16_t motor_hours;
|
||||
};
|
||||
|
||||
extern struct FanControlState gState;
|
||||
|
||||
+106
-37
@@ -9,39 +9,64 @@
|
||||
static const char * TAG = "mb";
|
||||
|
||||
Tcpd_t g_mbifc_server = NULL;
|
||||
ModbusSlave_t gModbus;
|
||||
ModbusSlave_t gModbus = {};
|
||||
|
||||
#define IDENT_MAGIC 3333
|
||||
#define REBOOT_MAGIC 0xB007 /* 45063 */
|
||||
#define INPUT_REG_MIRROR_IN_HOLDING_BASE_ADDR 1000
|
||||
|
||||
enum HoldingRegisters {
|
||||
H_IDENT = 0,
|
||||
// Control
|
||||
H_MODE = 1,
|
||||
H_POWER,
|
||||
H_SUMMER,
|
||||
H_INITIAL_MODE,
|
||||
H_INITIAL_POWER,
|
||||
H_RECUP_MODE,
|
||||
H_RECUP_TIME,
|
||||
H_RECUP_TIME_MIN,
|
||||
H_RECUP_TIME_MAX,
|
||||
H_RECUP_FACTOR,
|
||||
H_RAMP_TIME,
|
||||
H_BLIND_TIME,
|
||||
H_MIN_POWER,
|
||||
H_POWER = 2,
|
||||
H_SUMMER_MODE = 3,
|
||||
|
||||
// Settings
|
||||
H_INITIAL_MODE = 10,
|
||||
H_INITIAL_POWER = 11,
|
||||
H_RECUP_MODE = 12,
|
||||
H_RECUP_TIME = 13,
|
||||
H_RECUP_TIME_MIN = 14,
|
||||
H_RECUP_TIME_MAX = 15,
|
||||
H_RECUP_FACTOR = 16,
|
||||
H_MIN_POWER = 17,
|
||||
|
||||
// Hardware settings (don't need to change once set correctly)
|
||||
H_RAMP_TIME = 30,
|
||||
H_BLIND_TIME = 31,
|
||||
H_SWAP_TEMPS = 32,
|
||||
H_SWAP_PWMDIR = 33,
|
||||
|
||||
H_REBOOT = 70,
|
||||
};
|
||||
|
||||
enum InputRegisters {
|
||||
I_RECUP_TIME_IN = 1,
|
||||
I_RECUP_TIME_OUT,
|
||||
I_T_VALIDITY,
|
||||
I_T_IN_INST,
|
||||
I_T_OUT_INST,
|
||||
I_T_INDOOR,
|
||||
I_T_OUTDOOR,
|
||||
I_T_INFLOW,
|
||||
I_T_EXHAUST,
|
||||
I_MODE_INST,
|
||||
I_MOTOR_RAMP,
|
||||
I_BLIND_RAMP,
|
||||
I_T_VALIDITY = 1,
|
||||
I_T_IN_INST = 2,
|
||||
I_T_OUT_INST = 3,
|
||||
I_T_INDOOR = 4,
|
||||
I_T_OUTDOOR = 5,
|
||||
I_T_INFLOW = 6,
|
||||
I_T_EXHAUST = 7,
|
||||
I_RECUP_TIME_IN = 8,
|
||||
I_RECUP_TIME_OUT = 9,
|
||||
|
||||
I_MODE_INST = 20,
|
||||
I_MOTOR_RAMP = 21,
|
||||
I_BLIND_RAMP = 22,
|
||||
I_MOTOR_SECS = 23,
|
||||
I_MOTOR_HOURS = 24,
|
||||
I_UPTIME_SECS = 25,
|
||||
I_UPTIME_HOURS = 26,
|
||||
I_FREE_HEAP_KB = 27,
|
||||
};
|
||||
|
||||
static void restartLater() {
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
/**
|
||||
* Socket read handler
|
||||
*/
|
||||
@@ -74,7 +99,8 @@ void endOfAccess(ModbusSlave_t *ms) {
|
||||
|
||||
ModbusException_t ri(ModbusSlave_t *pSlave, uint16_t ref, uint16_t *pValue) {
|
||||
ESP_LOGD(TAG, "Read input %d", ref);
|
||||
uint16_t scratch = 0;
|
||||
uint16_t scratch16 = 0;
|
||||
uint32_t scratch32 = 0;
|
||||
|
||||
switch (ref) {
|
||||
case I_RECUP_TIME_IN:
|
||||
@@ -84,13 +110,13 @@ ModbusException_t ri(ModbusSlave_t *pSlave, uint16_t ref, uint16_t *pValue) {
|
||||
*pValue = gState.real_recup_time_out;
|
||||
break;
|
||||
case I_T_VALIDITY:
|
||||
scratch |= (int)gState.valid_t_actual_in;
|
||||
scratch |= (int)gState.valid_t_actual_out << 1;
|
||||
scratch |= (int)gState.valid_t_indoor << 2;
|
||||
scratch |= (int)gState.valid_t_outdoor << 3;
|
||||
scratch |= (int)gState.valid_t_inflow << 4;
|
||||
scratch |= (int)gState.valid_t_exhaust << 5;
|
||||
*pValue = scratch;
|
||||
scratch16 |= (int)gState.valid_t_actual_in;
|
||||
scratch16 |= (int)gState.valid_t_actual_out << 1;
|
||||
scratch16 |= (int)gState.valid_t_indoor << 2;
|
||||
scratch16 |= (int)gState.valid_t_outdoor << 3;
|
||||
scratch16 |= (int)gState.valid_t_inflow << 4;
|
||||
scratch16 |= (int)gState.valid_t_exhaust << 5;
|
||||
*pValue = scratch16;
|
||||
break;
|
||||
case I_T_IN_INST:
|
||||
*pValue = gState.t_actual_in;
|
||||
@@ -119,6 +145,25 @@ ModbusException_t ri(ModbusSlave_t *pSlave, uint16_t ref, uint16_t *pValue) {
|
||||
case I_BLIND_RAMP:
|
||||
*pValue = gState.blind_position;
|
||||
break;
|
||||
case I_UPTIME_SECS:
|
||||
*pValue = gState.uptime_secs;
|
||||
break;
|
||||
case I_UPTIME_HOURS:
|
||||
*pValue = gState.uptime_hours;
|
||||
break;
|
||||
case I_MOTOR_SECS:
|
||||
*pValue = gState.motor_secs;
|
||||
break;
|
||||
case I_MOTOR_HOURS:
|
||||
*pValue = gState.motor_hours;
|
||||
break;
|
||||
case I_FREE_HEAP_KB:
|
||||
scratch32 = esp_get_free_heap_size() / 1024;
|
||||
if (scratch32 > UINT16_MAX) {
|
||||
scratch32 = UINT16_MAX;
|
||||
}
|
||||
*pValue = scratch32;
|
||||
break;
|
||||
|
||||
default:
|
||||
return MB_EXCEPTION_ILLEGAL_DATA_ADDRESS;
|
||||
@@ -131,13 +176,16 @@ ModbusException_t rh(ModbusSlave_t *pSlave, uint16_t ref, uint16_t *pValue) {
|
||||
ESP_LOGD(TAG, "Read holding %d", ref);
|
||||
|
||||
switch (ref) {
|
||||
case H_IDENT:
|
||||
*pValue = IDENT_MAGIC;
|
||||
break;
|
||||
case H_MODE:
|
||||
*pValue = (int) gState.set_vent_mode;
|
||||
break;
|
||||
case H_POWER:
|
||||
*pValue = gState.set_power;
|
||||
break;
|
||||
case H_SUMMER:
|
||||
case H_SUMMER_MODE:
|
||||
*pValue = (int) gSettings.summer_mode;
|
||||
break;
|
||||
case H_INITIAL_MODE:
|
||||
@@ -170,10 +218,16 @@ ModbusException_t rh(ModbusSlave_t *pSlave, uint16_t ref, uint16_t *pValue) {
|
||||
case H_MIN_POWER:
|
||||
*pValue = gSettings.min_power;
|
||||
break;
|
||||
case H_SWAP_TEMPS:
|
||||
*pValue = gSettings.swap_temps;
|
||||
break;
|
||||
case H_SWAP_PWMDIR:
|
||||
*pValue = gSettings.swap_pwm_dir;
|
||||
break;
|
||||
default:
|
||||
// inputs are mapped to the holding address space
|
||||
if (ref >= 100) {
|
||||
return ri(pSlave, ref - 100, pValue);
|
||||
if (ref >= INPUT_REG_MIRROR_IN_HOLDING_BASE_ADDR) {
|
||||
return ri(pSlave, ref - INPUT_REG_MIRROR_IN_HOLDING_BASE_ADDR, pValue);
|
||||
}
|
||||
|
||||
return MB_EXCEPTION_ILLEGAL_DATA_ADDRESS;
|
||||
@@ -211,7 +265,7 @@ ModbusException_t wh(ModbusSlave_t *pSlave, uint16_t ref, uint16_t value) {
|
||||
}
|
||||
fan_set_power(value);
|
||||
break;
|
||||
case H_SUMMER:
|
||||
case H_SUMMER_MODE:
|
||||
gSettings.summer_mode = (value != 0);
|
||||
settings_persist(SETTINGS_summer_mode);
|
||||
break;
|
||||
@@ -279,6 +333,21 @@ ModbusException_t wh(ModbusSlave_t *pSlave, uint16_t ref, uint16_t value) {
|
||||
gSettings.min_power = value;
|
||||
settings_persist(SETTINGS_min_power);
|
||||
break;
|
||||
case H_SWAP_TEMPS:
|
||||
gSettings.swap_temps = value;
|
||||
settings_persist(SETTINGS_swap_temps);
|
||||
break;
|
||||
case H_SWAP_PWMDIR:
|
||||
gSettings.swap_temps = value;
|
||||
settings_persist(SETTINGS_swap_pwm_dir);
|
||||
break;
|
||||
case H_REBOOT:
|
||||
if (value == REBOOT_MAGIC) {
|
||||
// if we restart immediately, the modbus req won't finish and master then sends retries
|
||||
// and restarts us again and again
|
||||
xTaskCreate(restartLater, "kill", 2048, NULL, PRIO_HIGH, NULL);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return MB_EXCEPTION_ILLEGAL_DATA_ADDRESS;
|
||||
}
|
||||
|
||||
+12
-7
@@ -6,6 +6,7 @@
|
||||
#include "tasks.h"
|
||||
#include "owb.h"
|
||||
#include "ds18b20.h"
|
||||
#include "settings.h"
|
||||
|
||||
static const char* TAG="1w";
|
||||
|
||||
@@ -54,17 +55,21 @@ int read_onewires(int16_t *a, int16_t *b)
|
||||
DS18B20_ERROR errors[2] = { 0 };
|
||||
|
||||
ds18b20_wait_for_conversion(sDevs[0]);
|
||||
vTaskDelay(pdMS_TO_TICKS(10)); // to be sure its done
|
||||
vTaskDelay(pdMS_TO_TICKS(15)); // to be sure it's done
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
errors[i] = ds18b20_read_temp(sDevs[i], &readings[i]);
|
||||
}
|
||||
|
||||
if (errors[0] != DS18B20_OK || errors[1] != DS18B20_OK) {
|
||||
return -1;
|
||||
}
|
||||
int16_t val1 = (int16_t) roundf(readings[0] * 10);
|
||||
int16_t val2 = (int16_t) roundf(readings[1] * 10);
|
||||
|
||||
*a = (int16_t) roundf(readings[0] * 10);
|
||||
*b = (int16_t) roundf(readings[1] * 10);
|
||||
return 0;
|
||||
if (gSettings.swap_temps) {
|
||||
*a = val2;
|
||||
*b = val1;
|
||||
} else {
|
||||
*a = val1;
|
||||
*b = val2;
|
||||
}
|
||||
return (errors[0] == DS18B20_OK) && (errors[1] != DS18B20_OK);
|
||||
}
|
||||
|
||||
+3
-1
@@ -49,7 +49,9 @@ extern nvs_handle g_nvs_storage;
|
||||
X(uint16_t , initial_mode , , 0 , true , u16 , &) /* rezim po zapnuti napajeni */ \
|
||||
X(uint16_t , initial_power , , 50 , true , u16 , &) /* vychozi vykon */ \
|
||||
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_pwm_dir , , 0 , true , bool , &) /* swap pwm/dir signal */
|
||||
|
||||
enum settings_key_enum {
|
||||
#undef X
|
||||
|
||||
+5
-3
@@ -33,6 +33,11 @@ void app_main(void) {
|
||||
settings_init();
|
||||
settings_load();
|
||||
|
||||
// do it ASAP so the fan maybe doesn't have time to start
|
||||
onewires_setup();
|
||||
act_init();
|
||||
fancontrol_init();
|
||||
|
||||
// Start IDF service for pin change interrupts
|
||||
ESP_ERROR_CHECK(gpio_install_isr_service(0));
|
||||
|
||||
@@ -58,10 +63,7 @@ void app_main(void) {
|
||||
console_setup_uart_stdio();
|
||||
ESP_ERROR_CHECK(console_start_stdio(NULL, NULL));
|
||||
|
||||
onewires_setup();
|
||||
act_init();
|
||||
mbiface_setup();
|
||||
fancontrol_init();
|
||||
|
||||
telnetsrv_start(CONSOLE_TELNET_PORT);
|
||||
ESP_LOGI(TAG, "Startup finished, free heap = %u, cmds %"PRIu32, esp_get_free_heap_size(), console_count_commands());
|
||||
|
||||
Reference in New Issue
Block a user