*************************************************************************** */
+#include "lib/utils.h"
#include "config.h"
#include "interface.h"
#include "time.h"
#include "uSD.h"
-#define MODULE_VERSION 0x0A
+#define MODULE_VERSION 0x0A
#define MODULE_NAME "Scialys uC"
/* This multiplier is used for all durations and delays which are stored in number of hours */
#define T_MULT (3600 * 1000 / DEC_PERIOD)
-/* Max water temperature. Internal protection which cannot be overriden by configuration */
-#define ABSOLUTE_MAX_WATER_TEMP (90 * 100) /* Hundredth of degrees C : 90°C */
+/* Max water temperature. Internal protection which cannot be overriden by configuration
+ * Note that configuration should not allow temperature above 90°C */
+#define ABSOLUTE_MAX_WATER_TEMP (92 * 100) /* Hundredth of degrees C : 92°C */
-/* Number of main loops during which we keep the mosfets ON in order to keep them safe */
-#define OVERVOLTAGE_PROTECTION_CYCLES 100
-/* Flags and counters */
-uint8_t forced_heater_mode = 0; /* Flag only */
+/* Flags and counters for forced modes */
+uint8_t forced_heater_mode = 0; /* Flag and force type (enum force_types) */
+uint8_t manual_activation_request = 0; /* Flag */
+uint16_t forced_target_temp = 0;
uint32_t forced_heater_delay = 0; /* Flag and counter */
-uint32_t forced_heater_time = 0; /* Flag and counter */
-uint8_t manual_forced_heater = 0; /* Flag only */
-int manual_activation_request = 0; /* Flag and counter */
+uint32_t forced_heater_duration = 0; /* Flag and counter */
+uint8_t forced_cmd_val = 0;
+
+/* Error flags */
int8_t internal_temp_error_shutdown = 0; /* Flag and error code */
uint8_t external_disable = 0; /* Flag only */
uint8_t mosfet_temp_shutdown = 0; /* Flag only */
mode_forced = 'F', /* Auto Forced heating */
mode_manual = 'M', /* Manual Forced heating */
mode_delayed_heat_prod = 'P', /* Pause */
- mode_overprod = 'O', /* Over production, try to start other loads */
mode_temp_OK = 'T', /* Max temperature reached */
mode_overvoltage = 'V', /* Overvoltage detected */
mode_overtemp = 'H', /* Mosfet over-temperature detected */
};
+/* Current running mode */
+volatile char mode = mode_heat;
+volatile char old_mode = mode_heat;
+
/* Water temperature */
int water_centi_degrees = 0;
/***************************************************************************** */
-/* Decrementer for forced heating modes timers */
+/* Decrementer
+ * - decrease forced heating modes timers
+ * - decrease overvoltage protection timer
+ */
void handle_dec_request(uint32_t curent_tick)
{
- /* Manual forced mode */
- if (manual_activation_request > 0) {
- manual_activation_request--;
- }
- /* Automatic forced mode */
- if (forced_heater_mode == 1) {
+ /* Forced mode */
+ if (forced_heater_mode > FORCE_TYPE_OFF) {
if (forced_heater_delay > 0) {
forced_heater_delay--;
} else {
- if (forced_heater_time > 0) {
- forced_heater_time--;
+ if (forced_heater_duration > 0) {
+ forced_heater_duration--;
}
}
}
+ /* Update Over-Voltage information to exit over-voltage protection mode */
+ if (overvoltage > 0) {
+ uint8_t ov_tmp = (gpio_read(overvoltage_pin) ? 1 : 0);
+ if (ov_tmp == 0) {
+ overvoltage--;
+ }
+ }
}
/***************************************************************************** */
/* AC control */
-volatile int act_cmd = 0; /* Start off */
+/* Handle the power command */
+volatile uint8_t act_cmd = 0; /* Start off */
+volatile uint8_t command_val = 0; /* Value displayed on interface */
+
+extern uint32_t power_delay[101];
+volatile uint32_t zc_cnt = 0;
void set_ctrl_duty_cycle(uint8_t value)
{
}
}
-void ac_switch_on(uint32_t flags)
+/* Over-voltage protection */
+/* Number of DEC_PERIOD during which we keep the mosfets ON in order to keep them safe */
+#define OVERVOLTAGE_PROTECTION_CYCLES 100
+#define PROTECTION_CMD_VAL 100
+void overvoltage_protect(uint32_t gpio)
{
- gpio_clear(ac_ctrl);
+ gpio_clear(ac_ctrl); /* Turn mosfets ON */
+ timer_stop(LPC_TIMER_32B1); /* Stop mosfets timer */
+ set_ctrl_duty_cycle(PROTECTION_CMD_VAL); /* Update "actual command" */
+ overvoltage = OVERVOLTAGE_PROTECTION_CYCLES;
+ gpio_set(fan_ctrl); /* Turn on FAN immediatly */
+ /* Change current working mode */
+ old_mode = mode;
+ mode = mode_overvoltage;
}
-extern uint32_t power_delay[101];
-volatile uint32_t zc_cnt = 0;
+/* Used as timer callback to turn ON mosfets */
+void ac_switch_on(uint32_t flags)
+{
+ gpio_clear(ac_ctrl);
+}
-/*
- * Zero crossing handler (either detected or fake one)
+/* Zero crossing handler (either detected or fake one)
* If command is at 100%, only set (keep ?) Mosfets ON (gpio_clear)
* Else, start with mosfets OFF, in order not to have to break established current.
- * FIXME : If U and I not in sync, we should sync to I nul, not V nul.
+ * FIXME : If U and I not in sync, we should sync to I nul, not U nul.
*/
void zero_cross(uint32_t unused)
{
}
-
-/* Handle the power command */
-volatile uint8_t command_val = 0;
-int8_t old_cmd = 0; /* Used to store cmd value when entering over-voltage protection mode */
+/***************************************************************************** */
+/* Update current command depending on current mode and power production and consumption */
#define FAN_COUNTER_START_VAL (15 * 1000)
-static uint16_t fan_on = 0;
-uint8_t force_fan = 0;
+volatile uint16_t fan_on = 0;
+volatile uint8_t force_fan = 0;
extern uint8_t test_force_fan; /* Request to force fan ON from test menu */
-#define PROTECTION_CMD_VAL 100
-static uint8_t linky_disable = 0;
+volatile uint8_t linky_test = 0;
#define CMD_UP_DELAY_RESET_VALUE 3
void handle_cmd_update(uint32_t curent_tick)
{
static uint8_t cmd_up_delay = CMD_UP_DELAY_RESET_VALUE;
int delta = solar_prod_value - home_conso_value;
- /* Forced over-voltage protection or test mode */
- if (overvoltage != 0) {
- cmd = PROTECTION_CMD_VAL;
- goto cmd_update_end;
- } else if (old_cmd != -1) {
- /* Get back to normal after over-voltage protection */
- cmd = old_cmd;
- old_cmd = -1;
- }
-
- /* Reset force_fan to current test value */
- force_fan = test_force_fan;
-
- /* Mosfet temperature limit reached, turn ON all mosfets to prevent internal damage of board */
- if (mosfet_temp_shutdown == 1) {
- cmd = PROTECTION_CMD_VAL;
- force_fan = 1;
- goto cmd_update_end;
- }
-
- /* Water max temperature protection with hysteresys */
- if ((water_centi_degrees > ABSOLUTE_MAX_WATER_TEMP) ||
- (water_centi_degrees > sc_conf.conf_max_temp) ||
- (water_centi_degrees > max_temp_hysteresys)) {
- cmd = 0;
- max_temp_hysteresys = (ABSOLUTE_MAX_WATER_TEMP - 150); /* 1.5 °C */
- if (max_temp_hysteresys > sc_conf.conf_max_temp) {
- max_temp_hysteresys = (sc_conf.conf_max_temp - 150); /* 1.5 °C */
- }
- goto cmd_update_end;
- } else if (water_centi_degrees < max_temp_hysteresys) {
- /* Remove Hysteresys */
- max_temp_hysteresys = ABSOLUTE_MAX_WATER_TEMP;
- }
-
- /* Unable to read internal temperature or temperature above max internal temp : turn off heating */
- if (internal_temp_error_shutdown < 0) {
- cmd = 0;
- force_fan = 1;
- goto cmd_update_end;
- }
-
/* Which is the current mode ? */
- if (forced_heater_mode == 1) {
- /* Forced heating mode */
- if ((forced_heater_delay == 0) && (forced_heater_time > 0)) {
- cmd = sc_conf.auto_forced_mode_value;
- goto cmd_update_limited_end;
- }
- if (manual_forced_heater > 0) {
- cmd = sc_conf.manual_forced_mode_value;
- goto cmd_update_limited_end;
- }
- /* Entering forced heating mode from temperature getting below threshold,
- * wait some delay before effective forced heating */
- if (forced_heater_time == 0) {
- forced_heater_delay = sc_conf.auto_forced_heater_delay * T_MULT;
- forced_heater_time = forced_heater_delay + (sc_conf.auto_forced_heater_duration * T_MULT);
- }
- }
- if (delta < -1280) {
- /* Much more power used than produced */
- if (cmd > 10) {
- cmd -= 10;
- } else {
- cmd = 0;
- }
- } else if (delta < -64) {
- /* More power used than produced */
- if (cmd > 0) {
- cmd--;
- }
- } else if (delta > 1280) {
- /* Much more production than used power */
- if (cmd <= 98) {
- cmd += 2;
- } else {
- cmd = 100;
- }
- } else if (delta > 192) {
- /* More production, but do not rise too quickly when getting close
- * to balance to prevent oscilations */
- if (cmd_up_delay > 0) {
- cmd_up_delay--;
- } else {
- cmd_up_delay = CMD_UP_DELAY_RESET_VALUE;
- if (cmd < 100) {
- cmd++;
+ switch (mode) {
+ case mode_overvoltage:
+ /* End over-voltage protection ? */
+ if (overvoltage == 0) {
+ mode = old_mode;
+ } else {
+ cmd = PROTECTION_CMD_VAL;
}
- }
- }
-
-cmd_update_limited_end:
- command_val = cmd;
- /* Limit external power used when in force mode ! */
- if (delta < -max_intensity) {
- cmd = 0;
- linky_disable |= 16;
- if ((forced_heater_delay == 0) && (forced_heater_time > 0)) {
- /* Wait for 100 * 100ms (10s) before trying to heat again */
- forced_heater_delay = 100;
- }
- if (manual_forced_heater > 0) {
- /* Re-increment by one the delay */
- manual_activation_request++;
- }
- }
- /* Test for Linky - FIXME */
-#if 0
- linky_disable = 0;
- if ((cmd > 48) && (cmd < 100)) {
- if (water_centi_degrees > (50 * 100)) {
- if (delta > 6000) {
- linky_disable = 2;
- cmd = 100;
+ break;
+ case mode_overtemp:
+ /* End over-temperature protection ? */
+ if ((mosfet_temp_shutdown == 0) && (internal_temp_error_shutdown >= 0)) {
+ mode = old_mode;
} else {
- linky_disable = 4;
- cmd = 48;
+ cmd = 0;
+ force_fan = 1;
}
- } else {
- linky_disable = 8;
- cmd = 100;
- }
+ break;
+ case mode_manual:
+ case mode_forced:
+ /* Forced heating mode */
+ if ((forced_heater_delay == 0) && (forced_heater_duration > 0)) {
+ /* Limit external power used when in force mode ! */
+ if (delta >= 0) {
+ cmd = forced_cmd_val;
+ } else if (delta < -max_intensity) {
+ if (cmd >= 10) {
+ cmd -= 10;
+ } else {
+ cmd = 0;
+ }
+ } else if (cmd < forced_cmd_val) {
+ if (cmd == 0) {
+ /* Start with a high enough value to avoid triggering overvoltage protection */
+ cmd = min(forced_cmd_val, 40);
+ } else {
+ cmd++;
+ }
+ }
+ break;
+ }
+ /* FALTHROUGH : automatic force delay period, try to use what is available anyway */
+ case mode_ext_disable:
+ case mode_delayed_heat_prod:
+ /* automatic force disabled due to current production, try to use what is available */
+ case mode_heat:
+ /* Set load power according to extra power production */
+ if (delta < -1280) {
+ /* Much more power used than produced */
+ if (cmd > 10) {
+ cmd -= 10;
+ } else {
+ cmd = 0;
+ }
+ } else if (delta < -64) {
+ /* More power used than produced */
+ if (cmd > 0) {
+ cmd--;
+ }
+ } else if (delta > 1280) {
+ /* Much more production than used power */
+ if (cmd == 0) {
+ /* Start with a high enough value to avoid triggering overvoltage protection */
+ cmd = 40;
+ } else if (cmd <= 98) {
+ cmd += 2;
+ } else {
+ cmd = 100;
+ }
+ } else if (delta > 192) {
+ /* More production, but do not rise too quickly when getting close
+ * to balance to prevent oscilations */
+ if (cmd_up_delay > 0) {
+ cmd_up_delay--;
+ } else {
+ cmd_up_delay = CMD_UP_DELAY_RESET_VALUE;
+ if (cmd < 100) {
+ cmd++;
+ }
+ }
+ }
+ break;
+ case mode_temp_OK:
+ default:
+ cmd = 0;
+ break;
}
-#endif
-cmd_update_end:
+ /* Reset force_fan to current test value */
+ force_fan |= test_force_fan;
/* Update FAN command (start or stop FAN) */
- if ((cmd > 0) || (force_fan == 1)) {
+ if ((cmd > 0) || force_fan) {
fan_on = FAN_COUNTER_START_VAL;
gpio_set(fan_ctrl);
} else {
gpio_clear(fan_ctrl);
}
}
- //command_val = cmd;
+
+#if 0
+ /* Test for Linky - FIXME */
+ linky_test = 0;
+ if ((cmd > 48) && (cmd < 100)) {
+ if (water_centi_degrees > (50 * 100)) {
+ linky_test = 2;
+ cmd = 48;
+ } else {
+ linky_test = 4;
+ cmd = 100;
+ }
+ }
+#endif
+
+ /* Store command for display */
+ command_val = cmd;
/* Set Control Output duty cycle */
set_ctrl_duty_cycle(cmd);
}
-/* Over-voltage protection */
-void overvoltage_protect(uint32_t gpio)
-{
- gpio_clear(ac_ctrl); /* Turn mosfets ON */
- timer_stop(LPC_TIMER_32B1); /* Stop mosfets timer */
- set_ctrl_duty_cycle(PROTECTION_CMD_VAL); /* Update "actual command" */
- overvoltage = OVERVOLTAGE_PROTECTION_CYCLES;
- gpio_set(fan_ctrl); /* Turn on FAN immediatly */
- old_cmd = command_val; /* Save current command value (to be restored after overvoltage protection */
-}
-
+/***************************************************************************** */
/* Update current working mode depending on environnement */
-volatile char mode = mode_heat; /* Debug info */
+
+/* There's three possible scenario and a few limits which define the command value.
+ * Possible scenario by order of priority :
+ * - Manual forced mode :
+ * This mode is entered when the user presses the "OK" button on the interface when the interface
+ * is in mode "run", which sets manual_activation_request to 1
+ * This mode lasts for as much as sc_conf.manual_activation_duration (hours) or until
+ * sc_conf.manual_target_heater_temp is reached
+ * Which target is used depends on sc_conf.manual_force_type.
+ * In this mode, heating is made at sc_conf.manual_forced_mode_value, unless local energy
+ * consumption goes beyond sc_conf.grid_power_limit
+ * - Automatic force mode :
+ * This mode is entered when the water temperature goes below sc_conf.enter_forced_mode_temp
+ * This mode lasts for as much as sc_conf.auto_forced_heater_duration (hours) or until
+ * sc_conf.auto_forced_target_heater_temp is reached
+ * Which target is used depends on sc_conf.auto_force_type.
+ * In this mode, heating starts only after a delay of sc_conf.auto_forced_heater_delay (hours) in
+ * order to wait for possible automatic heating from the local energy produced. This is usefull to
+ * prevent heating while another appliance is being used for a short time, or right after the
+ * morning showers while the local energy production system may produce enough energy during the
+ * day to come.
+ * Automatic heating can happen during the delay period, and in this case automatic force mode is
+ * only delayed further if sc_conf.source_has_power_ok is reached by the local energy production
+ * and exited only if sc_conf.auto_forced_target_heater_temp is reached by the water temperature.
+ * In this mode, heating is made at sc_conf.auto_forced_mode_value unless local energy
+ * consumption goes beyond sc_conf.grid_power_limit
+ * - Automatic heating :
+ * In this mode (which is the main purpose of this module) heating is controlled by the difference
+ * between local energy production and local energy consumption.
+ *
+ * Limits :
+ * - Water temperature :
+ * There are two "software" temperature limits and one "hardware" limit.
+ * The hardware limit comes from the water tank heating system and cannot be overriden.
+ * It is unkown and irrelevant to this algorithm. It is the only real "security" limit.
+ * The two other limits are software ones : one hard-coded upper limit of 90°C which is not
+ * advertised to the user, and one configurable through sc_conf.conf_max_temp.
+ * Reching these limits should stop heating completely, unless there's an overvoltage condition.
+ * - External disable switch :
+ */
+
volatile char* msg = NULL;
void mode_update(void)
{
- /* Default mode : try to heat the water tank */
- mode = mode_heat;
-
- /* Need to enter Forced heating mode ? */
- if ((water_centi_degrees < sc_conf.enter_forced_mode_temp) && (sc_conf.auto_force_type != FORCE_TYPE_OFF)) {
- if (forced_heater_mode == 0) {
- msg = "Water temp low, entering forced mode\n";
- forced_heater_mode = 1;
- }
- status_led(red_on);
- mode = mode_forced;
- } else if (forced_heater_mode == 1) {
- int exit_forced = 0;
- /* End of forced heating ? (target reached) ? */
- switch (sc_conf.auto_force_type) {
- case FORCE_TYPE_TIMER:
- case FORCE_TYPE_TARGET:
- if (water_centi_degrees > sc_conf.auto_forced_target_heater_temp) {
- exit_forced = 1;
- }
- break;
- case FORCE_TYPE_MIN:
- if (water_centi_degrees > sc_conf.auto_forced_target_heater_temp) {
- exit_forced = 1;
- }
- case FORCE_TYPE_MAX:
- if (water_centi_degrees > sc_conf.auto_forced_target_heater_temp) {
- exit_forced = 1;
- }
- }
- if (exit_forced == 1) {
- status_led(red_off);
- msg = "Water temp OK, forced mode exit\n";
- forced_heater_mode = 0;
- mode = mode_temp_OK;
- } else {
- mode = mode_forced;
- }
+ /* Check protections first */
+ if ((mode == mode_overvoltage) || (mode == mode_overtemp)) {
+ return;
}
-
- /* Do not force if there is a lot of sun, it may be enough to heat again soon
- * 'sunny_days_prod_value' is computed from 'sc_conf.source_has_power_ok'
- */
- if ((solar_prod_value > sunny_days_prod_value) && (forced_heater_mode == 1)) {
- mode = mode_delayed_heat_prod;
- forced_heater_mode = 0;
+ /* Mosfet temperature limit reached or internal temperature above max internal temp */
+ if ((mosfet_temp_shutdown != 0) || (internal_temp_error_shutdown < 0)) {
+ old_mode = mode;
+ mode = mode_overtemp;
+ return;
}
- /* Do not force heating if disabled by external command */
- external_disable = (gpio_read(ext_disable_in_pin) ? 0 : 1); /* Invert : input is pulled low when external disable is ON */
- if ((external_disable == 1) && (forced_heater_mode != 0)) {
- forced_heater_mode = 0;
- mode = mode_ext_disable;
- msg = "Forced mode disabled by external input\n";
+ /* Water temperature reached config limit ? */
+ if (water_centi_degrees >= sc_conf.conf_max_temp) {
+ mode = mode_temp_OK; /* Max temperature reached */
+ return;
}
- /* Get Over-Temperature information */
- mosfet_temp_shutdown = (gpio_read(overtemperature_pin) ? 0 : 1); /* Invert : Temp switch is NC type */
- if (mosfet_temp_shutdown != 0) {
- mode = mode_overtemp;
- }
+ /* Default mode : try to heat the water tank */
+ mode = mode_heat;
- /* Update Over-Voltage information - Only used to exit over-voltage protection mode */
- if (overvoltage > 0) {
- uint8_t ov_tmp = (gpio_read(overvoltage_pin) ? 1 : 0);
- if (ov_tmp == 0) {
- overvoltage--;
- }
- mode = mode_overvoltage;
+ /* Did the user request a forced heating ? */
+ if (manual_activation_request == 1) {
+ msg = "Entering manual forced mode\n";
+ forced_heater_mode = sc_conf.manual_force_type;
+ forced_target_temp = sc_conf.manual_target_heater_temp;
+ forced_heater_duration = sc_conf.manual_activation_duration * T_MULT;
+ forced_cmd_val = sc_conf.manual_forced_mode_value;
+ forced_heater_delay = 0;
+ manual_activation_request = 2;
}
- if (sc_conf.never_force == 1) {
- forced_heater_mode = 0;
+ /* Do we need automatic forced heating ? */
+ if ((forced_heater_mode == FORCE_TYPE_OFF) && (water_centi_degrees < sc_conf.enter_forced_mode_temp)) {
+ forced_heater_mode = sc_conf.auto_force_type;
+ if (forced_heater_mode != FORCE_TYPE_OFF) {
+ msg = "Water temp low, entering forced mode\n";
+ forced_target_temp = sc_conf.auto_forced_target_heater_temp;
+ forced_heater_duration = sc_conf.auto_forced_heater_duration * T_MULT;
+ forced_cmd_val = sc_conf.auto_forced_mode_value;
+ forced_heater_delay = sc_conf.auto_forced_heater_delay * T_MULT;
+ }
}
- /* Did the user request a forced heating ? */
- if (manual_activation_request != 0) {
- forced_heater_mode = 1;
- mode = mode_manual;
- if (manual_activation_request == -1) {
- msg = "Entering manual forced mode\n";
- manual_activation_request = sc_conf.manual_activation_duration * T_MULT;
- manual_forced_heater = 1;
+ /* Handle specific cases when forced heating is ON */
+ if (forced_heater_mode != FORCE_TYPE_OFF) {
+ int exit_forced = 0; /* Need to reach 2 to exit forced heating */
+ /* End of forced heating ? (target reached) ? */
+ if (water_centi_degrees > forced_target_temp) {
+ if ((forced_heater_mode == FORCE_TYPE_MIN) || (forced_heater_mode == FORCE_TYPE_TARGET)) {
+ msg = "Water temp OK, forced mode exit\n";
+ exit_forced = 2;
+ } else {
+ exit_forced = 1;
+ }
+ }
+ if (forced_heater_duration == 0) {
+ if ((forced_heater_mode == FORCE_TYPE_MIN) || (forced_heater_mode == FORCE_TYPE_TIMER)) {
+ msg = "Water heating timer elapsed, forced mode exit\n";
+ exit_forced = 2;
+ } else {
+ exit_forced++;
+ }
}
- if (manual_activation_request < 10) {
- msg = "Leaving manual forced mode\n";
+ if (exit_forced >= 2) {
+ /* Exit condition reached */
+ forced_heater_mode = FORCE_TYPE_OFF;
manual_activation_request = 0;
+ mode = mode_heat;
+ } else {
+ if (manual_activation_request == 2) {
+ mode = mode_manual;
+ } else if (solar_prod_value > sunny_days_prod_value) {
+ /* Do not force if there is a lot of sun, it may be enough to heat again soon
+ * 'sunny_days_prod_value' is computed from 'sc_conf.source_has_power_ok'
+ */
+ mode = mode_delayed_heat_prod;
+ if (forced_heater_delay < 100) {
+ forced_heater_delay = 100; /* FIXME : add some time (N * DEC_PERIOD) to the delay value */
+ }
+ } else {
+ mode = mode_forced;
+ }
+ }
+ /* Do not force heating if disabled by external command */
+ if (external_disable == 1) {
+ forced_heater_mode = FORCE_TYPE_OFF;
+ mode = mode_ext_disable;
+ msg = "Forced mode disabled by external input\n";
+ }
+ /* Do not force heating if disabled by configuration */
+ if (sc_conf.never_force == 1) {
+ forced_heater_mode = FORCE_TYPE_OFF;
+ mode = mode_heat;
+ msg = "Forced mode disabled by configuration\n";
}
- }
-
- /* Command at 100% and still more production than energy used ? */
- if ((command_val == 100) && (solar_prod_value > home_conso_value)) {
- mode = mode_overprod;
}
}
/* Each flag is set if seen once within the interval */
data.flags |= (fan_on ? 1 : 0) | (force_fan << 1);
- data.flags |= (((internal_temp_error_shutdown < 0) ? 1 : 0) << 2);
- data.flags |= (mosfet_temp_shutdown << 3) | (overvoltage << 4);
+ data.flags |= ((internal_temp_error_shutdown < 0) ? (0x01 << 2) : 0);
+ data.flags |= (mosfet_temp_shutdown << 3);
+ data.flags |= ((overvoltage > 0) ? (0x01 << 4) : 0);
data.flags |= (external_disable << 5);
data.flags |= (forced_heater_mode << 6) | (manual_activation_request << 7);
data.deci_degrees_disp = data.deci_degrees_disp / nb_val;
data.load_power_lowest = data.load_power_lowest / nb_val;
data.load_power_highest = data.load_power_highest / nb_val;
- /* Add "fixed ones */
+ /* Add "fixed" ones */
data.command_val = command_val;
data.act_cmd = act_cmd;
data.mode = mode;
}
}
+/* Send data on UEXT communication port for slave module or communication extention */
void slave_send_data(void)
{
static struct scialys_data data;
comm_tx(&data);
}
+
/***************************************************************************** */
int main(void)
{
scialys_systick_and_timers_config();
+ /* Changing load type is not allowed without turning the module off, so checking outside of main loop is OK */
+ if (sc_conf.load_type == LOAD_TYPE_DC) {
+ add_systick_callback(zero_cross_detect, 20);
+ }
+
uprintf(UART0, "System setup complete.\n");
msleep(100);
status_led(green_only);
while (1) {
/* Feed the dog */
- if ((solar_prod_value != 0) && (home_conso_value != 0)) {
+ if ((solar_prod_value != 0) && (home_conso_value != 0) && (water_centi_degrees < ABSOLUTE_MAX_WATER_TEMP)) {
watchdog_feed();
}
/* Update water tank temperature */
water_centi_degrees = water_temp_update(UART0);
+ /* Get Over-Temperature information */
+ mosfet_temp_shutdown = (gpio_read(overtemperature_pin) ? 0 : 1); /* Invert : Temp switch is NC type */
+
+ /* Read external disable pin */
+ external_disable = (gpio_read(ext_disable_in_pin) ? 0 : 1); /* Invert : input is pulled low when external disable is ON */
+
/* Update current mode */
mode_update();
/* Display */
/* only update twice per second */
cur_tick = systick_get_tick_count();
- if ((cur_tick < last_tick_update) || ((~0 - last_tick_update) < 500)) {
- /* simple tick wrapping handling */
+ /* simple tick wrapping handling */
+ if (cur_tick < last_tick_update) {
last_tick_update = 0;
}
if (cur_tick > (last_tick_update + 500)) {
/* Data Log */
if (1) {
- external_disable |= linky_disable;
+ external_disable |= linky_test;
uprintf(UART0, "#%c:%d:%d:%d:%d:%d:%d:",
mode, loop++, solar_prod_value, home_conso_value,
water_centi_degrees, deci_degrees_power, deci_degrees_disp);