Updated v10 Adding max temps hysteresys Working on configuration menu
authorNathael Pajani <nathael.pajani@ed3l.fr>
Fri, 12 Jun 2020 23:31:56 +0000 (01:31 +0200)
committerNathael Pajani <nathael.pajani@ed3l.fr>
Tue, 8 Nov 2022 11:07:29 +0000 (12:07 +0100)
v10/.version
v10/Makefile
v10/config.c
v10/config.h
v10/interface.c
v10/main.c
v10/version.h

index 7facc89..e1617e8 100644 (file)
@@ -1 +1 @@
-36
+57
index 4c5c637..4813728 100644 (file)
@@ -14,9 +14,10 @@ endif
 
 .PHONY: $(NAME).bin
 $(NAME).bin:
-       @$(shell ../../../update_version.sh && touch interface.c)
        @make -C ../../.. ${PRINT_DIRECTORY} NAME=$(NAME) MODULE=$(MODULE) apps/$(MODULE)/$(NAME)/$@
 
 clean mrproper:
        @make -C ../../.. ${PRINT_DIRECTORY} $@
 
+temp:
+       @$(shell ../../../update_version.sh && touch interface.c)
index 976dd95..fd10a18 100644 (file)
@@ -233,6 +233,7 @@ void read_internal_config(void)
        conf = get_user_info();
        memcpy(&sc_conf, conf, sizeof(struct scialys_config));
        if (sc_conf.config_ok != CONFIG_OK) {
+               uprintf(UART0, "User config read from flash does not have magic : 0x%04x.\n", sc_conf.config_ok);
                memset(&sc_conf, 0, sizeof(struct scialys_config));
        }
        /* Checksum */
@@ -243,10 +244,12 @@ void read_internal_config(void)
        if (sum != 0) {
                /* Checksum error : erase config in order to start with a default one */
                memset(&sc_conf, 0, sizeof(struct scialys_config));
+               uprintf(UART0, "User config read from flash has bad checksum.\n");
        }
        /* Config version error ? */
        if (sc_conf.conf_version != CONFIG_VERSION) {
                sc_conf.config_ok = 0;
+               uprintf(UART0, "User config read from flash has bad config version : %d.\n", sc_conf.conf_version);
        }
 }
 
@@ -256,6 +259,7 @@ int user_flash_update(void)
        uint8_t* mem = NULL;
        int ret = 0;
        uint8_t sum = 0, i = 0;
+       uint32_t size = 0;
 
        /* Compute and store checksum */
        sc_conf.checksum = 0;
@@ -271,28 +275,36 @@ int user_flash_update(void)
                uprintf(UART0, "User config update error: %d\n", ret);
                return -1;
        }
-       ret = iap_copy_ram_to_flash((uint32_t)get_user_info(), (uint32_t)&sc_conf, sizeof(struct scialys_config));
+       size = ((sizeof(struct scialys_config) + 3) & ~0x03);
+       ret = iap_copy_ram_to_flash((uint32_t)get_user_info(), (uint32_t)&sc_conf, size);
        if (ret != 0) {
                uprintf(UART0, "User config update error: %d\n", ret);
                return -2;
        }
+       uprintf(UART0, "Scialys module user config update done\n");
        return 0;
 }
 
 
 /* Maximum power which can be used from the external (paid) power source, specified in kW or kVA */
-#define  EXT_SOURCE_POWER_LIMIT  6
+#define  GRID_POWER_LIMIT  6
+
+#define SOURCE_POWER_MAX 3000 /* in Watt */
+
+#define LOAD_POWER_MAX   2700 /* in Watt */
 
 /* mA prod value above which the system will not enter forced mode, waiting for home
  * to stop using power in order to start automatic heating */
-#define SUNNY_DAYS_PROD_VALUE 3000
+uint32_t sunny_days_prod_value = 0;
+
+#define MAX_TEMP_CONFIG (80 * 100)  /* 80 °C */
 
-/* If temperature falls bellow FORCE_HEATER_TEMP value, we enter forced heater mode, until
+/* If temperature falls bellow ENTER_FORCE_HEATER_TEMP value, we enter forced heater mode, until
  *    TARGET_FORCED_HEATER_TEMP is reached.
  * When in forced heater mode, the heater is controlled to heat at FORCED_MODE_VALUE which
  *    is between 0 and 100.
  */
-#define FORCE_HEATER_TEMP  (30 * 100) /* 30 °C */
+#define ENTER_FORCE_HEATER_TEMP  (30 * 100) /* 30 °C */
 #define TARGET_FORCED_HEATER_TEMP (50 * 100) /* 50 °C */
 #define FORCED_MODE_VALUE  100 /* A fraction of 100 */
 /* Delay before automatic forced heating */
@@ -312,28 +324,23 @@ int user_flash_update(void)
 #define MANUAL_TYPE_TARGET  2
 #define DEFAULT_MANUAL_FORCE_TYPE MANUAL_TYPE_TARGET 
 
-
-/* Read main configuration - or set to default one */
-void read_scialys_main_config(void)
+void check_config(void)
 {
-       read_internal_config();
-       /* Check that config read from flash is OK */
-       if (sc_conf.config_ok == CONFIG_OK) {
-               uprintf(UART0, "Internal config read OK\n");
-               return;
-       }
        /* If config version error (old config) then only update new fields */
        switch (sc_conf.conf_version) {
                /* Do not change order.
                 * Do not add breaks.
                 */
                default:
+               case 0x00:
                        /* Set base default config */
                        uprintf(UART0, "Fallback to default config\n");
-                       sc_conf.ext_source_power_limit = EXT_SOURCE_POWER_LIMIT;
-                       sc_conf.sunny_days_prod_value = SUNNY_DAYS_PROD_VALUE;
-                       sc_conf.force_heater_temp = FORCE_HEATER_TEMP;
-                       sc_conf.target_forced_heater_temp = TARGET_FORCED_HEATER_TEMP;
+                       sc_conf.grid_power_limit = GRID_POWER_LIMIT;
+                       sc_conf.source_power_max = SOURCE_POWER_MAX;
+                       sc_conf.load_power_max = LOAD_POWER_MAX;
+                       sc_conf.conf_max_temp = MAX_TEMP_CONFIG;
+                       sc_conf.enter_force_heater_temp = ENTER_FORCE_HEATER_TEMP;
+                       sc_conf.auto_forced_target_heater_temp = TARGET_FORCED_HEATER_TEMP;
                        sc_conf.auto_forced_mode_value = FORCED_MODE_VALUE;
                        sc_conf.forced_heater_delay = FORCED_HEATER_DELAY;
                        sc_conf.forced_heater_duration = FORCED_HEATER_DURATION;
@@ -348,6 +355,22 @@ void read_scialys_main_config(void)
                        sc_conf.conf_version = CONFIG_VERSION;
                        sc_conf.config_ok = CONFIG_OK;
        }
+
+       /* Update sunny_days_prod_value (Watt to mA) */
+       sunny_days_prod_value = (((uint32_t)(sc_conf.load_power_max / 3) * 1000) / 230);
+}
+
+/* Read main configuration - or set to default one */
+void read_scialys_main_config(void)
+{
+       read_internal_config();
+       /* Check that config read from flash is OK */
+       if (sc_conf.config_ok == CONFIG_OK) {
+               uprintf(UART0, "Internal config read OK\n");
+               return;
+       }
+       /* Check that it is up to date */
+       check_config();
 }
 
 
@@ -411,6 +434,7 @@ uint8_t power_board_present = 0;
 int external_config(uint32_t uart)
 {
        int ret = 0;
+       int retcode = 0;
 
        /* uSD card */
        uSD_config((struct pio *)&uSD_cs, SSP_BUS_0);
@@ -429,13 +453,14 @@ int external_config(uint32_t uart)
        if (ret != 0) {
                uprintf(uart, "Temp config error on power board: %d\n", ret);
                power_board_present = 0;
-               return -1;
-       }
-       ret = tmp101_sensor_set_continuous_conversion(&tmp101_sensor_power);
-       if (ret != 0) {
-               uprintf(uart, "Temp config error on power board: %d\n", ret);
-               power_board_present = 0;
-               return -2;
+               retcode -= 1;
+       } else {
+               ret = tmp101_sensor_set_continuous_conversion(&tmp101_sensor_power);
+               if (ret != 0) {
+                       uprintf(uart, "Temp config error on power board: %d\n", ret);
+                       power_board_present = 0;
+                       retcode -= 2;
+               }
        }
 
        /* TMP101 sensor config on display board */
@@ -443,11 +468,13 @@ int external_config(uint32_t uart)
        if (ret != 0) {
                uprintf(uart, "Temp config error on display board: %d\n", ret);
                interface_board_present = 0;
+               retcode -= 4;
        } else {
                ret = tmp101_sensor_set_continuous_conversion(&tmp101_sensor_display);
                if (ret != 0) {
                        uprintf(uart, "Temp config error on display board: %d\n", ret);
                        interface_board_present = 0;
+                       retcode -= 8;
                } else {
                        interface_board_present = 1;
                }
@@ -457,9 +484,9 @@ int external_config(uint32_t uart)
        if (interface_board_present == 1) {
                ret = interface_config(uart);
                if (ret != 0) {
-                       return -3;
+                       retcode -= 16;
                }
        }
 
-       return 0;
+       return retcode;
 }
index 67eb71f..2ef3e5c 100644 (file)
@@ -35,7 +35,6 @@
 
 #include "extdrv/status_led.h"
 #include "extdrv/max31855_thermocouple.h"
-#include "extdrv/ws2812.h"
 
 #include "lib/stdio.h"
 
  * Default values are defined within config.c
  *
  * Meaning of fields :
- * ext_source_power_limit :
- *   Maximum power which can be used from the external (paid) power source, specified in kW/h
+ * grid_power_limit :
+ *   Maximum power which can be used from the external (paid) power source, specified in kWatt
  * sunny_days_prod_value :
  *   in milli Amps
- * force_heater_temp :
+ * enter_force_heater_temp :
+ *   temperature bellow which the system enters auto forced heating mode
  *   degrees centigrade
- * target_forced_heater_temp :
+ * auto_forced_target_heater_temp :
  *   
  * auto_forced_mode_value :
  *   
 struct scialys_config {
        uint8_t conf_version;
        uint8_t checksum;
-       uint16_t ext_source_power_limit; /* specified in kW/h */
-       uint16_t sunny_days_prod_value;  /* in milli Amps */
-       uint16_t force_heater_temp;  /* degrees centigrade */
-       uint16_t target_forced_heater_temp;
-       uint16_t auto_forced_mode_value;
+       /* Config limits */
+       uint16_t grid_power_limit; /* specified in kWatt */
+       uint16_t source_power_max; /* specified in Watt */
+       uint16_t load_power_max; /* specified in Watt */
+       uint16_t conf_max_temp; /* degrees centigrade (0 - 90°C) */
+       uint16_t load_type; /* LOAD_TYPE_AC or LOAD_TYPE_DC */
+       uint16_t force_command_value; /* % : 0 - 100 */
+       /* Manual Force limits */
+       uint16_t enter_force_heater_temp;  /* degrees centigrade (0 - 90°C) */
+       uint16_t auto_forced_target_heater_temp; /* degrees centigrade (0 - 90°C) */
+       uint16_t auto_forced_mode_value; /* % : 0 - 100 */
        uint16_t forced_heater_delay;
        uint16_t forced_heater_duration;
-       uint16_t manual_forced_mode_value;
-       uint16_t manual_target_heater_temp;
+       uint16_t manual_forced_mode_value; /* % : 0 - 100 */
+       uint16_t manual_target_heater_temp; /* degrees centigrade (0 - 90°C) */
        uint16_t manual_activation_duration;
-       uint8_t manual_force_type;
-       uint8_t never_force;
+       uint8_t manual_force_type; /* Off, Min, Max */
+       uint8_t never_force; /* 0 or 1 */
+       /* Other */
        uint16_t config_ok;
 } __attribute__((packed));
 
 extern struct scialys_config sc_conf;
+extern uint32_t sunny_days_prod_value;
+
+/* Check that current config is valid */
+void check_config(void);
 
 /* Read main configuration from internal user flash - or set to default one */
 void read_scialys_main_config(void);
index 3ebc2da..c3da842 100644 (file)
@@ -154,6 +154,14 @@ void button_callback(uint32_t gpio)
        }
 }
 
+#define SCIALYS_WS2812_NB_LEDS 2
+uint8_t ws2812_leds_data[SCIALYS_WS2812_NB_LEDS * 3];
+struct ws2812_conf ws2812_leds = {
+    .nb_leds = SCIALYS_WS2812_NB_LEDS,
+    .led_data = ws2812_leds_data,
+    .inverted = 0,
+};
+
 int interface_config(uint32_t uart)
 {
        /* Buttons inputs on front panel */
@@ -165,7 +173,7 @@ int interface_config(uint32_t uart)
        set_gpio_callback(button_callback, &button_ok, EDGE_RISING);
 
        /* WS2812B Leds on display board */
-       ws2812_config(&ws2812_data_out_pin);
+       ws2812_config(&ws2812_leds, &ws2812_data_out_pin);
 
        /* Configure and start display */
        config_gpio(&oled_reset, 0, GPIO_DIR_OUT, 1); /* Release reset signal */
@@ -173,8 +181,8 @@ int interface_config(uint32_t uart)
        erase_screen_content();
        ssd130x_display_full_screen(&display);
 
-       ws2812_set_pixel(0, 0x05, 0x15, 0x08);
-       ws2812_send_frame(0);
+       ws2812_set_pixel(&ws2812_leds, 0, 0x05, 0x15, 0x08);
+       ws2812_send_frame(&ws2812_leds, 0);
 
        uprintf(uart, "Interface config OK\n");
 
@@ -196,53 +204,57 @@ volatile int manual_activation_request = 0;
 
 enum menu_list {
        MAIN_MENU,
-       MANUAL_MODE,
+       FORCE_MODE,
        DATE_CONFIG,
        LIMITS,
-       FUNCTIONS,
-       TEST_MODE,
+       RESET_CONFIG,
        SAVE_CONFIG,
+       TEST_MODE,
        NB_MENU, /* This one must be the last */
 };
 static const char* menu_titles[] = {
        [MAIN_MENU] = "Menu principal",
-       [MANUAL_MODE] = "Marche Forcee",
+       [FORCE_MODE] = "Marche Forcee",
        [DATE_CONFIG] = "Regl. Heure",
-       [LIMITS] = "Limites",
-       [FUNCTIONS] = "Reglages",
-       [TEST_MODE] = "Test mode",
+       [LIMITS] = "Regl. Limites",
        [SAVE_CONFIG] = "Save config",
+       [RESET_CONFIG] = "Reset config",
+       [TEST_MODE] = "Test mode",
 };
 static uint8_t current_menu = MAIN_MENU;
-static uint8_t current_entry = MANUAL_MODE;
+static uint8_t current_entry = FORCE_MODE;
 
-enum func_menu_list {
-       FUNC_LOAD_TYPE,
-       FUNC_CMD_TYPE,
-       FUNC_NB_MENU, /* This one must be the last */
+enum force_mode_list {
+       MANUAL_FORCE_MODE,
+       AUTO_FORCE_MODE,
+       FORCE_NB_MENU, /* This one must be the last */
 };
-static const char* func_modes_titles[] = {
-       [FUNC_LOAD_TYPE] = "Load Type",
-       [FUNC_CMD_TYPE] = "CMD type",
+static const char* force_modes_titles[] = {
+       [MANUAL_FORCE_MODE] = "Manuelle",
+       [AUTO_FORCE_MODE] = "Automatique",
 };
-static uint8_t func_cur_menu = FUNC_LOAD_TYPE;
-static uint8_t func_cur_entry = FUNC_LOAD_TYPE;
+static uint8_t force_cur_menu = MANUAL_FORCE_MODE;
+static uint8_t force_cur_entry = MANUAL_FORCE_MODE;
 
 enum limits_menu_list {
-       TEMP_FORCED_START,
-       TEMP_FORCED_TARGET,
+       TEMP_MAX,
+       PMAX_GRID,
+       PMAX_PROD,
+       PMAX_CONSO,
+       LOAD_TYPE,
        FORCED_MODE_VAL,
-       SUNNY_DAY_VALUE,
        LIM_NB_MENU, /* This one must be the last */
 };
 static const char* limits_modes_titles[] = {
-       [TEMP_FORCED_START] = "Water Min",
-       [TEMP_FORCED_TARGET] = "Water Target",
+       [TEMP_MAX] = "Temp Max",
+       [PMAX_GRID] = "Pmax Abon.",
+       [PMAX_PROD] = "Pmax Prod.",
+       [PMAX_CONSO] = "P Charge",
+       [LOAD_TYPE] = "Type Charge",
        [FORCED_MODE_VAL] = "Force Val",
-       [SUNNY_DAY_VALUE] = "Sun Prod",
 };
-static uint8_t limits_cur_menu = TEMP_FORCED_START;
-static uint8_t limits_cur_entry = TEMP_FORCED_START;
+static uint8_t limits_cur_menu = TEMP_MAX;
+static uint8_t limits_cur_entry = TEMP_MAX;
 
 enum test_menu_list {
        TEST_FAN,
@@ -287,9 +299,9 @@ void config_interface_handle(void)
                                int i = 0;
                                for (i = 1; i < NB_MENU; i++) {
                                        if (i != current_entry) {
-                                               display_line(i + 1, 3, menu_titles[i]);
+                                               display_line(i + 1, 2, menu_titles[i]);
                                        } else {
-                                               snprintf(line, DISP_LLEN, " ->%s", menu_titles[i]);
+                                               snprintf(line, DISP_LLEN, " >%s", menu_titles[i]);
                                                display_line(i + 1, 0, line);
                                        }
                                }
@@ -316,12 +328,12 @@ void config_interface_handle(void)
                case DATE_CONFIG: {
                                static uint8_t date_idx = 0;
                                struct rtc_time now;
-                               snprintf(line, DISP_LLEN, "^");
+                               snprintf(line, DISP_LLEN, "%c", 0x60);
                                display_line(3, 6 + (date_idx * 3), line);
                                rtc_pcf85363_time_read(&rtc_conf, &now);
                                snprintf(line, DISP_LLEN, "%02xh%02x:%02x", now.hour, now.min, now.sec);
                                display_line(4, 6, line);
-                               snprintf(line, DISP_LLEN, "V");
+                               snprintf(line, DISP_LLEN, "%c", 0x7F);
                                display_line(5, 6 + (date_idx * 3), line);
                                if ((button & BUTTON_RIGHT) && (date_idx < 2)) {
                                        date_idx++;
@@ -364,7 +376,7 @@ void config_interface_handle(void)
                                                if (i != limits_cur_entry) {
                                                        display_line(i + 2, 3, limits_modes_titles[i]);
                                                } else {
-                                                       snprintf(line, DISP_LLEN, " ->%s", limits_modes_titles[i]);
+                                                       snprintf(line, DISP_LLEN, "  >%s", limits_modes_titles[i]);
                                                        display_line(i + 2, 0, line);
                                                }
                                        }
@@ -387,34 +399,78 @@ void config_interface_handle(void)
                                                sub_menu_level = 0;
                                                current_menu = MAIN_MENU;
                                        }
-                               } else {
+                               } else { /* sub_menu_level == 2 */
+                                       display_line(1, 1, limits_modes_titles[limits_cur_menu]);
+                                       switch (limits_cur_menu) {
+                                               case TEMP_MAX:
+                                                       snprintf(line, DISP_LLEN, "          %c", 0x60);
+                                                       display_line(3, 1, line);
+                                                       snprintf(line, DISP_LLEN, "Abs. max: %d %cC", sc_conf.conf_max_temp / 100, 0x24);
+                                                       display_line(4, 1, line);
+                                                       snprintf(line, DISP_LLEN, "          %c", 0x7f);
+                                                       display_line(5, 1, line);
+                                                       if (button & BUTTON_UP) {
+                                                               if (sc_conf.conf_max_temp <= 8500) {
+                                                                       sc_conf.conf_max_temp += 500;
+                                                               } else {
+                                                                       sc_conf.conf_max_temp = 9000;
+                                                               }
+                                                       }
+                                                       if (button & BUTTON_DOWN) {
+                                                               if (sc_conf.conf_max_temp > 500) {
+                                                                       sc_conf.conf_max_temp -= 500;
+                                                               } else {
+                                                                       sc_conf.conf_max_temp = 0;
+                                                               }
+                                                       }
+                                                       if (button & BUTTON_LEFT) {
+                                                               sub_menu_level = 1;
+                                                       }
+                                                       if (button & BUTTON_OK) {
+                                                               sub_menu_level = 0;
+                                                               current_menu = MAIN_MENU;
+                                                       }
+                                                       break;
+                                               case FORCED_MODE_VAL:
+                                                       break;
+                                               case PMAX_GRID:
+                                                       /* remember to update max_intensity */
+                                                       break;
+                                               case PMAX_PROD:
+                                                       /* remember to update sunny_days_prod_value */
+                                                       break;
+                                               case PMAX_CONSO:
+                                                       break;
+                                               case LOAD_TYPE:
+                                                       break;
+                                       }
                                }
                        }
                        break;
-               case FUNCTIONS: {
+               case FORCE_MODE: {
                                if (sub_menu_level == 1) {
                                        int i = 0;
-                                       for (i = 0; i < FUNC_NB_MENU; i++) {
-                                               if (i != func_cur_entry) {
-                                                       display_line(i + 2, 3, func_modes_titles[i]);
+                                       for (i = 0; i < FORCE_NB_MENU; i++) {
+                                               if (i != force_cur_entry) {
+                                                       display_line(i + 2, 3, force_modes_titles[i]);
                                                } else {
-                                                       snprintf(line, DISP_LLEN, " ->%s", func_modes_titles[i]);
+                                                       snprintf(line, DISP_LLEN, " ->%s", force_modes_titles[i]);
                                                        display_line(i + 2, 0, line);
                                                }
                                        }
                                        if (button & BUTTON_UP) {
-                                               func_cur_entry -= 1;
+                                               force_cur_entry -= 1;
                                        }
                                        if (button & BUTTON_DOWN) {
-                                               func_cur_entry += 1;
+                                               force_cur_entry += 1;
                                        }
-                                       if (func_cur_entry >= FUNC_NB_MENU) {
-                                               func_cur_entry = 0;
-                                       } else if (func_cur_entry == 0xFF) {
-                                               func_cur_entry = FUNC_NB_MENU - 1;
+                                       if (force_cur_entry >= FORCE_NB_MENU) {
+                                               force_cur_entry = 0;
+                                       } else if (force_cur_entry == 0xFF) {
+                                               force_cur_entry = FORCE_NB_MENU - 1;
                                        }
                                        if (button & (BUTTON_OK | BUTTON_RIGHT)) {
-                                               func_cur_menu = func_cur_entry;
+                                               force_cur_menu = force_cur_entry;
                                                sub_menu_level = 2;
                                        }
                                        if (button & BUTTON_LEFT) {
@@ -465,7 +521,7 @@ void config_interface_handle(void)
                                                        if (force_cmd >= 0) {
                                                                force_cmd = -1;
                                                        } else {
-                                                               force_cmd = 0;
+                                                               force_cmd = 50;
                                                        }
                                                default:
                                                        break;
@@ -478,12 +534,55 @@ void config_interface_handle(void)
                        }
                        break;
                case SAVE_CONFIG: {
-                               user_flash_update();
+                               snprintf(line, DISP_LLEN, "Sauver config ?");
+                               display_line(2, 1, line);
+                               snprintf(line, DISP_LLEN, "Valider = OK");
+                               display_line(5, 1, line);
+                               snprintf(line, DISP_LLEN, "Gauche = Annul");
+                               display_line(6, 1, line);
+                               if (button & BUTTON_LEFT) {
+                                       sub_menu_level = 0;
+                                       current_menu = MAIN_MENU;
+                               }
+                               if (button & BUTTON_OK) {
+                                       int ret = 0;
+                                       erase_screen_content();
+                                       snprintf(line, DISP_LLEN, "Saving ...");
+                                       display_line(4, 2, line);
+                                       ssd130x_display_full_screen(&display);
+                                       ret = user_flash_update();
+                                       uprintf(UART0, "\nFlash update from menu: %d\n", ret);
+                                       msleep(1500);
+                                       sub_menu_level = 0;
+                                       current_menu = MAIN_MENU;
+                               }
+                       }
+                       break;
+               case RESET_CONFIG: {
+                               snprintf(line, DISP_LLEN, "Efface Config ?");
+                               display_line(2, 1, line);
+                               snprintf(line, DISP_LLEN, "Valider = OK");
+                               display_line(5, 1, line);
+                               snprintf(line, DISP_LLEN, "Gauche = Annul");
+                               display_line(6, 1, line);
+                               if (button & BUTTON_LEFT) {
+                                       sub_menu_level = 0;
+                                       current_menu = MAIN_MENU;
+                               }
+                               if (button & BUTTON_OK) {
+                                       erase_screen_content();
+                                       snprintf(line, DISP_LLEN, "Chargement ...");
+                                       display_line(4, 8, line);
+                                       ssd130x_display_full_screen(&display);
+                                       sc_conf.conf_version = 0x00;
+                                       check_config();
+                                       uprintf(UART0, "\nSystem defaults reloaded from menu\n");
+                                       msleep(500);
+                                       sub_menu_level = 0;
+                                       current_menu = MAIN_MENU;
+                               }
                        }
                        break;
-               case MANUAL_MODE:
-                       manual_activation_request = -1;
-                       /* Fallback */
                default:
                        interface_mode = MODE_RUN;
                        current_menu = MAIN_MENU;
@@ -548,7 +647,7 @@ void interface_update(char heat_mode)
                display_line(0, 0, line);
 
                /* Display info */
-               snprintf(line, DISP_LLEN, "Water:% 2d.%03d %cC", (water_centi_degrees / 100), (abs_centi % 100), 0x1F);
+               snprintf(line, DISP_LLEN, "Water:% 2d.%03d %cC", (water_centi_degrees / 100), (abs_centi % 100), 0x24);
                display_line(2, 0, line);
                snprintf(line, DISP_LLEN, "Prod :% 2d,%03dA", (solar_prod_value / 1000), ((solar_prod_value % 1000) / 10));
                display_line(3, 0, line);
@@ -565,9 +664,9 @@ void interface_update(char heat_mode)
 
                /* Update RGB leds */
                /* FIXME : use for error signal */
-               ws2812_set_pixel(0, (home_conso_value / 2000), (solar_prod_value / 2000), 0);
-               ws2812_set_pixel(1, 0, 0, command_val);
-               ws2812_send_frame(0);
+               ws2812_set_pixel(&ws2812_leds, 0, (home_conso_value / 2000), (solar_prod_value / 2000), 0);
+               ws2812_set_pixel(&ws2812_leds, 1, 0, 0, command_val);
+               ws2812_send_frame(&ws2812_leds, 0);
        } else {
                /* Config mode. Mode entered by button action, which implies that interface board is present. */
                config_interface_handle();
index 81d81e1..173a17e 100644 (file)
@@ -45,7 +45,7 @@
 #define T_MULT  (3600 * 1000 / DEC_PERIOD)
 
 /* Max water temperature. Internal protection which cannot be overriden by configuration */
-#define MAX_WATER_TEMP (90 * 100)  /* Hundredth of degrees C : 90°C */
+#define ABSOLUTE_MAX_WATER_TEMP (90 * 100)  /* Hundredth of degrees C : 90°C */
 /* Internal system max temperature : turn off heating when reached */
 #define MAX_INTERNAL_TEMP (80 * 10) /* Tenth of degrees C : 80°C */
 
@@ -78,8 +78,13 @@ enum modes {
 
 /* Water and internaltemperature */
 int water_centi_degrees = 0;
-int deci_degrees_power = 0;
-int deci_degrees_disp = 0;
+
+/* Set to ABSOLUTE_MAX_WATER_TEMP - 1.5°C when enbling max temp hysteresis */
+int max_temp_hysteresys = 0;
+
+/* Internal temperatures */
+int deci_degrees_power = 0; /* Power board sensor */
+int deci_degrees_disp = 0; /* Display board sensor */
 
 /* Value in mA computed upon startup from config ext_source_power_limit */
 static int32_t max_intensity = 0;
@@ -258,10 +263,19 @@ void handle_cmd_update(uint32_t curent_tick)
                goto cmd_update_end;
        }
 
-       /* Water max temperature protection */
-       if (water_centi_degrees > MAX_WATER_TEMP) {
+       /* 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); /* still 1.5°C */
+               }
                goto cmd_update_end;
+       } else if (water_centi_degrees < max_temp_hysteresys) {
+               /* Remove Hysteresys */
+               max_temp_hysteresys = ABSOLUTE_MAX_WATER_TEMP;
        }
 
        /* Forced over-voltage protection or test mode */
@@ -393,14 +407,14 @@ void mode_update(uint32_t unused)
        mode = heat;
 
        /* Need to enter Forced heating mode ? */
-       if (water_centi_degrees < sc_conf.force_heater_temp) {
+       if (water_centi_degrees < sc_conf.enter_force_heater_temp) {
                if (forced_heater_mode == 0) {
                        msg = "Water temp low, entering forced mode\n";
                        forced_heater_mode = 1;
                }
                status_led(red_on);
                mode = forced;
-       } else if ((water_centi_degrees > sc_conf.target_forced_heater_temp) && (forced_heater_mode == 1)) {
+       } else if ((water_centi_degrees > sc_conf.auto_forced_target_heater_temp) && (forced_heater_mode == 1)) {
                status_led(red_off);
                msg = "Water temp OK, forced mode exit\n";
                forced_heater_mode = 0;
@@ -408,7 +422,7 @@ void mode_update(uint32_t unused)
        }
 
        /* Do not force if there is a lot of sun, it may be enough to heat again soon */
-       if ((solar_prod_value > sc_conf.sunny_days_prod_value) && (forced_heater_mode == 1)) {
+       if ((solar_prod_value > sunny_days_prod_value) && (forced_heater_mode == 1)) {
                mode = delayed_heat_prod;
                forced_heater_mode = 0;
        }
@@ -550,13 +564,16 @@ int main(void)
        board_io_config();
        modules_config();
        external_config(UART0);
+
        read_scialys_main_config();
-       /* Compute max_intensity from config ext_source_power_limit.
-        *   ext_source_power_limit is in kVA, max_intensity in mA */
-       max_intensity = sc_conf.ext_source_power_limit * 1000 * 1000 / 230;
+       /* Compute max_intensity from config grid_power_limit.
+        *   grid_power_limit is in kVA, max_intensity in mA */
+       max_intensity = sc_conf.grid_power_limit * 1000 * 1000 / 230;
+
        scialys_systick_and_timers_config();
 
-       uprintf(UART0, "System setup complete. %d\n", -max_intensity);
+       uprintf(UART0, "System setup complete.\n");
+       uprintf(UART0, "Max intensity: %d\n", max_intensity);
        msleep(500);
        status_led(green_only);
 
@@ -591,16 +608,28 @@ int main(void)
                }
 
                /* Update water tank temperature */
+               #define WTA_NB_VAL 8 /* Choose a multiple of 2 */
+               #define WTA_SHIFT  3 /* Set shift according to WTA_NB_VAL */
                if (1) {
-                       int ret = 0, old_water_temp = 0;
-                       old_water_temp = water_centi_degrees;
-                       /* Get thermocouple value */
+                       static int water_centi_average[WTA_NB_VAL];
+                       static int wta_idx = 0;
+                       int ret = 0, i = 0;
+                       /* Get thermocouple value, store in table only if valid */
                        ret = max31855_sensor_read(&thermocouple, NULL, &water_centi_degrees);
                        if (ret != 0) {
                                uprintf(UART0, "Water Temp read error : %d\n", ret);
-                               /* Do not act upon iinvalid temp value */
-                               water_centi_degrees = old_water_temp;
+                       } else {
+                               water_centi_average[wta_idx++] = water_centi_degrees;
+                               if (wta_idx >= WTA_NB_VAL) {
+                                       wta_idx = 0;
+                               }
+                       }
+                       water_centi_degrees = 0;
+                       /* Average water tank temperature */
+                       for (i = 0; i < WTA_NB_VAL; i++) {
+                               water_centi_degrees += water_centi_average[i];
                        }
+                       water_centi_degrees >>= WTA_SHIFT;
                }
 
                /* Update current mode */
index 7eeaa2b..949853a 100644 (file)
@@ -1,3 +1,3 @@
 #define MODULE_VERSION_STR  "v0.10"
 #define SOFT_VERSION_STR  "T"
-#define COMPILE_VERSION "36"
+#define COMPILE_VERSION "57"