From 2cedcb712a912e6b8146575270173b376745a1b1 Mon Sep 17 00:00:00 2001 From: Thomas Kolb Date: Sat, 22 Apr 2023 20:02:16 +0200 Subject: [PATCH] Implement heater control This change controls a GPIO on the expansion connector depending on the surrounding temperature. If external temperature is too low for charging, the GPIO is set high, else it is set low. In combination with the new LNSC-2420-Addon board this allows to switch on a high-power heater connected directly to the solar panels whenever the temperature is too low to charge the battery. Once the temperature becomes high enough again, the heater is switched off and the battery is charged instead. --- src/addon_io.c | 35 +++++++++++++++++++++++++++++++++++ src/addon_io.h | 14 ++++++++++++++ src/charge_control.c | 7 +++++++ src/pinout.h | 10 ++++++++++ 4 files changed, 66 insertions(+) create mode 100644 src/addon_io.c create mode 100644 src/addon_io.h diff --git a/src/addon_io.c b/src/addon_io.c new file mode 100644 index 0000000..39befcc --- /dev/null +++ b/src/addon_io.c @@ -0,0 +1,35 @@ +#include + +#include "pinout.h" + +#include "addon_io.h" + +static const uint32_t OUTPUT_LIST[2] = {ADDON_ISO_IO_OUT1, ADDON_ISO_IO_OUT2}; + +void addon_io_init(void) +{ + // Isolated outputs configuration: output, initially low = off + gpio_clear(ADDON_ISO_IO_PORT, ADDON_ISO_IO_OUT1 | ADDON_ISO_IO_OUT2); + gpio_mode_setup(ADDON_ISO_IO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, ADDON_ISO_IO_OUT1 | ADDON_ISO_IO_OUT2); + + // Isolated inputs configuration: input, no pull resistors + gpio_mode_setup(ADDON_ISO_IO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, ADDON_ISO_IO_IN); +} + + +void addon_io_iso_out_on(uint8_t idx) +{ + gpio_set(ADDON_ISO_IO_PORT, OUTPUT_LIST[idx]); +} + + +void addon_io_iso_out_off(uint8_t idx) +{ + gpio_clear(ADDON_ISO_IO_PORT, OUTPUT_LIST[idx]); +} + + +bool addon_io_read_iso_in(void) +{ + return gpio_get(ADDON_ISO_IO_PORT, ADDON_ISO_IO_IN) != 0; +} diff --git a/src/addon_io.h b/src/addon_io.h new file mode 100644 index 0000000..511fcc5 --- /dev/null +++ b/src/addon_io.h @@ -0,0 +1,14 @@ +#ifndef ADDON_IO_H +#define ADDON_IO_H + +#include +#include + +void addon_io_init(void); + +void addon_io_iso_out_on(uint8_t idx); +void addon_io_iso_out_off(uint8_t idx); + +bool addon_io_read_iso_in(void); + +#endif // ADDON_IO_H diff --git a/src/charge_control.c b/src/charge_control.c index e1898e8..117bfd5 100644 --- a/src/charge_control.c +++ b/src/charge_control.c @@ -8,6 +8,7 @@ #include "charge_pump.h" #include "rs485.h" #include "flash_config.h" +#include "addon_io.h" #include "charge_control.h" @@ -243,12 +244,18 @@ static void solar_fsm_update(uint64_t uptime_ms, struct MeasurementResult *meas) case CHARGE_LOW_EXTERNAL_TEMPERATURE: if(charge_state_entered) { power_switch_solar_off(); + + // switch on the heater via the isolated I/O addon board + addon_io_iso_out_on(0); } // this state can only be entered if the BMP280 measurement is valid, so // no need to check it again here. if(bmp280_get_temperature() > external_temperature_recovery) { charge_state = CHARGE_WAIT_CHARGEPUMP; + + // switch the heater off again when this state is left + addon_io_iso_out_off(0); break; } break; diff --git a/src/pinout.h b/src/pinout.h index 84a24eb..d1893e7 100644 --- a/src/pinout.h +++ b/src/pinout.h @@ -43,6 +43,8 @@ #define RS485_TX_PIN GPIO6 #define RS485_RX_PIN GPIO7 +/*** Expansion connector signals ***/ + /* BMP280 I²C */ #define BMP280_I2C_PORT GPIOA @@ -50,4 +52,12 @@ #define BMP280_I2C_SCL GPIO9 #define BMP280_I2C_SDA GPIO10 +/* Isolated inputs and outputs on I/O addon board */ + +#define ADDON_ISO_IO_PORT GPIOA + +#define ADDON_ISO_IO_OUT1 GPIO5 +#define ADDON_ISO_IO_OUT2 GPIO6 +#define ADDON_ISO_IO_IN GPIO7 + #endif // PINOUT_H