From 3e317b09fc879d3795d3f5534f2c28aa6658efc1 Mon Sep 17 00:00:00 2001 From: Nathael Pajani Date: Sun, 20 Nov 2022 17:03:33 +0100 Subject: [PATCH] Going on with code cleaning, re-organisation, and fixes --- v10/comm.c | 59 +++++++ v10/comm.h | 35 ++++ v10/config.c | 69 +++++--- v10/config.h | 17 +- v10/interface.c | 9 - v10/main.c | 434 ++++++++++++++++++++++-------------------------- v10/param.c | 2 + v10/sensors.c | 101 +++++++++++ v10/sensors.h | 61 +++++++ v10/time.c | 6 +- 10 files changed, 508 insertions(+), 285 deletions(-) create mode 100644 v10/comm.c create mode 100644 v10/comm.h create mode 100644 v10/sensors.c create mode 100644 v10/sensors.h diff --git a/v10/comm.c b/v10/comm.c new file mode 100644 index 0000000..90e7f3d --- /dev/null +++ b/v10/comm.c @@ -0,0 +1,59 @@ +/**************************************************************************** + * apps/scialys/v10/comm.c + * + * Copyright 2016-2022 Nathael Pajani + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + +#include "core/system.h" +#include "core/systick.h" +#include "core/pio.h" + +#include "drivers/serial.h" +#include "drivers/gpio.h" + +#include "extdrv/status_led.h" + +#include "core/user_information_block.h" +#include "core/iap.h" + +#include "config.h" +#include "interface.h" +#include "time.h" +#include "uSD.h" + + +/***************************************************************************** */ +/* Rx interrupt handler for system configuration over USB */ +void config_rx(uint8_t c) +{ + /* FAN control */ + if (c == 'f') { + gpio_set(fan_ctrl); + } else { + gpio_clear(fan_ctrl); + } +} + + +/* Communication with slave modules over UART1 */ +void comm_rx(uint8_t c) +{ +} + + + diff --git a/v10/comm.h b/v10/comm.h new file mode 100644 index 0000000..beff0e9 --- /dev/null +++ b/v10/comm.h @@ -0,0 +1,35 @@ +/**************************************************************************** + * apps/scialys/v10/comm.h + * + * Copyright 2016-2022 Nathael Pajani + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + +#ifndef COMM_H +#define COMM_H + + +/* Rx interrupt handler for system configuration over USB */ +void config_rx(uint8_t c); + + +/* Communication with slave modules over UART1 */ +void comm_rx(uint8_t c); + + +#endif /* COMM_H */ + diff --git a/v10/config.c b/v10/config.c index 702ea0d..595176f 100644 --- a/v10/config.c +++ b/v10/config.c @@ -1,5 +1,5 @@ /**************************************************************************** - * apps/scialys/v010/config.c + * apps/scialys/v10/config.c * * Copyright 2016-2021 Nathael Pajani * @@ -40,6 +40,7 @@ #include "config.h" #include "interface.h" +#include "comm.h" #include "time.h" #include "uSD.h" @@ -200,6 +201,7 @@ extern void ac_switch_on(uint32_t flags); extern void zero_cross(uint32_t flags); extern void power_track(uint32_t flags); +/* Configure micro-controller internal modules */ void modules_config(void) { uart_on(UART0, 115200, config_rx); @@ -208,7 +210,7 @@ void modules_config(void) ssp_master_on(SSP_BUS_0, LPC_SSP_FRAME_SPI, 8, 4*1000*1000); adc_on(NULL); adc_start_burst_conversion(ADC_MCH(0) | ADC_MCH(1) | ADC_MCH(2), LPC_ADC_SEQ(0)); - /* Configure and start timers */ + /* Activate and configure timers */ /* This one is used to generate the second zero-crossing, which is not seen by the ZC detector */ timer_on(LPC_TIMER_32B0, 0, zero_cross); timer_counter_config(LPC_TIMER_32B0, &ac_timer_conf_zc); @@ -221,6 +223,46 @@ void modules_config(void) } +extern void handle_cmd_update(uint32_t curent_tick); +extern void track_isnail_values(uint32_t curent_tick); +extern void handle_dec_request(uint32_t curent_tick); +/* Period (in ms) of the handler for the command value update */ +#define CMD_UPD_PERIOD 50 +/* Period (in ms) of the handler for the isnail (tores) ADC update + * Do not use a multiple of 10 in order not to be in sync with possible glitchs from the mains + */ +#define ADC_UPD_PERIOD 17 + +/* Add systick callbacks and update and start timers */ +void scialys_systick_and_timers_config(void) +{ + uint32_t clk_cycles_ac_zc = 0; + /* We want 100 Hz (50 Hz but two zero crossings) with 1% granularity */ + clk_cycles_ac_zc = get_main_clock() / (100 * 100); + uprintf(UART0, "clk_cycles_ac_zc: %d\n", clk_cycles_ac_zc); + + /* Configure the fake zero-cross generation timer to 100Hz. + * Do not start it now, it will be started by the first real zero-cross detected in order to + * generate the other half zc (not seen by system due to hardware design) + * Also sarted by config when DC mode is set */ + timer_set_match(LPC_TIMER_32B0, CHAN0, (clk_cycles_ac_zc * 100)); + + /* Configure the power tracking timer. + * 20 points per half sin wave should be enough to get the min and max */ + timer_set_match(LPC_TIMER_16B0, CHAN0, (clk_cycles_ac_zc * 5)); + timer_start(LPC_TIMER_16B0); + + /* Add a systick callback to handle command value update */ + add_systick_callback(handle_cmd_update, CMD_UPD_PERIOD); + + /* Add a systick callback to track ismail values (power consumption and production) */ + add_systick_callback(track_isnail_values, ADC_UPD_PERIOD); + + /* Add a systick callback to handle time counting */ + add_systick_callback(handle_dec_request, DEC_PERIOD); +} + + /***************************************************************************** */ /* External components */ @@ -253,29 +295,6 @@ struct tmp101_sensor_config tmp101_sensor_display = { .resolution = TMP_RES_ELEVEN_BITS, }; -int temp_read(uint32_t uart, int* deci_degrees_disp, int* deci_degrees_power) -{ - int ret = 0; - int conv = 0; - - if (interface_board_present != 0) { - ret = tmp101_sensor_read(&tmp101_sensor_display, NULL, deci_degrees_disp); - if (ret == 0) { - conv |= CONV_DISPLAY_OK; - } else { - uprintf(uart, "TMP101 read error on display board : %d\n", ret); - } - } - if (power_board_present != 0) { - ret = tmp101_sensor_read(&tmp101_sensor_power, NULL, deci_degrees_power); - if (ret == 0) { - conv |= CONV_POWER_OK; - } else { - uprintf(uart, "TMP101 read error on power board : %d\n", ret); - } - } - return conv; -} /* Configure external components */ diff --git a/v10/config.h b/v10/config.h index af8ce21..d97ed99 100644 --- a/v10/config.h +++ b/v10/config.h @@ -39,8 +39,13 @@ #include "lib/stdio.h" +/* Main frequency (core) */ #define SELECTED_FREQ FREQ_SEL_48MHz +/* Period (in ms) of the decrementer handler from the systick interrupt */ +#define DEC_PERIOD 100 + + /***************************************************************************** */ /* Configuration storage */ @@ -196,7 +201,7 @@ void system_init(); void fault_info(const char* name, uint32_t len); -/* Configure modules and main functions */ +/* Configure micro-controller internal modules */ void modules_config(void); /* Configure GPIO for specific board usage */ @@ -205,15 +210,9 @@ void board_io_config(void); /* Configure external components */ int external_components_config(uint32_t uart); +/* Add systick callbacks and update and start timers */ +void scialys_systick_and_timers_config(void); -/***************************************************************************** */ -/* Other parts ... */ - -/* Internal Temperature sensors */ -#define CONV_DISPLAY_OK (0x01 << 0) -#define CONV_POWER_OK (0x01 << 1) -#define CONV_OK (CONV_POWER_OK | CONV_DISPLAY_OK) -int temp_read(uint32_t uart, int* deci_degrees_disp, int* deci_degrees_power); #endif /* CONFIG_H */ diff --git a/v10/interface.c b/v10/interface.c index a053a61..5ccac17 100644 --- a/v10/interface.c +++ b/v10/interface.c @@ -214,7 +214,6 @@ extern uint32_t solar_prod_value; extern uint32_t home_conso_value; extern volatile uint8_t command_val; extern int manual_activation_request; -extern int8_t force_cmd; static int interface_mode = MODE_RUN; @@ -246,14 +245,6 @@ void interface_update(char heat_mode) if (button_pressed & BUTTON_UP) { interface_mode = MODE_CONFIG; } - if (force_cmd >= 0) { - if ((button_pressed & BUTTON_RIGHT) && (force_cmd <= 95)) { - force_cmd += 5; - } - if ((button_pressed & BUTTON_LEFT) && (force_cmd >= 5)) { - force_cmd -= 5; - } - } button_pressed = 0; } diff --git a/v10/main.c b/v10/main.c index 1979da2..efbd226 100644 --- a/v10/main.c +++ b/v10/main.c @@ -36,11 +36,6 @@ /***************************************************************************** */ /* System configuration */ -/* Period (in ms) of the decrementer handler from the systick interrupt */ -#define DEC_PERIOD 100 -/* Period (in ms) of the handler for the command value update */ -#define CMD_UPD_PERIOD 50 -#define ADC_UPD_PERIOD 17 /* This multiplier is used for all durations and delays which are stored in number of hours */ #define T_MULT (3600 * 1000 / DEC_PERIOD) @@ -53,20 +48,17 @@ #define OVERVOLTAGE_PROTECTION_CYCLES 100 -uint8_t forced_heater_mode = 0; /* flag */ -uint32_t forced_heater_delay = 0; -uint32_t forced_heater_time = 0; -uint8_t manual_forced_heater = 0; /* flag */ -int manual_activation_request = 0; - - -uint8_t error_shutdown = 0; /* flag */ - - +/* Flags and counters */ +uint8_t forced_heater_mode = 0; /* Flag only */ +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 */ +uint8_t error_shutdown = 0; /* Flag only */ #define EXTERNAL_DISABLE_FORCE 0 /* Input is pulled low when external disable is ON */ -uint8_t external_disable = 0; -uint8_t temp_shutdown = 0; -uint8_t overvoltage = 0; /* Used to create a delay when overvoltage is detected, +uint8_t external_disable = 0; /* Flag only */ +uint8_t temp_shutdown = 0; /* Flag only */ +uint8_t overvoltage = 0; /* Flag and counter. Used to create a delay when overvoltage is detected, set to OVERVOLTAGE_PROTECTION_CYCLES and decreases to 0 */ enum modes { @@ -79,7 +71,7 @@ enum modes { temp_OK = 'T', /* Max temperature reached */ }; -/* Water and internaltemperature */ +/* Water temperature */ int water_centi_degrees = 0; /* Set to ABSOLUTE_MAX_WATER_TEMP - 1.5°C when enbling max temp hysteresis */ @@ -96,32 +88,17 @@ int32_t max_intensity = 0; struct rtc_time now; -/***************************************************************************** */ -/* Rx interrupt handler for system configuration over USB */ -void config_rx(uint8_t c) -{ - /* FAN control */ - if (c == 'f') { - gpio_set(fan_ctrl); - } else { - gpio_clear(fan_ctrl); - } -} +/***************************************************************************** */ +/* Decrementer for forced heating modes timers */ -/* Communication with slave modules over UART1 */ -void comm_rx(uint8_t c) +void handle_dec_request(uint32_t curent_tick) { -} - - - -/***************************************************************************** */ -/* Decrementer for heating timers */ -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) { if (forced_heater_delay > 0) { forced_heater_delay--; @@ -135,15 +112,19 @@ void handle_dec_request(uint32_t curent_tick) { /***************************************************************************** */ -/* Track power production and usage */ +/* Power Tracking */ -/* Average value computed on last NB_VAL ADC values */ +/* Average value computed on the last "NB_VAL" ADC values */ uint32_t solar_prod_value = 0; uint32_t home_conso_value = 0; #define NB_VAL 4 /* MUST be a power of 2 */ #define NB_SHIFT 2 -static void track_isnail_values(uint32_t flags) +/* + * Track power production and usage + * These are obtained by reading the Tore outputs (i-Snail output through ADC 0 and 1) + */ +void track_isnail_values(uint32_t curent_tick) { static uint8_t idx = 0; static uint16_t solar[NB_VAL]; @@ -179,17 +160,54 @@ static void track_isnail_values(uint32_t flags) home_conso_value = sum_home << (6 - NB_SHIFT); } + +/* + * Track power used by load. + * These are obtained from ACS711 through ADC 2 + * ADC values are between 0 and 1023, no load value is at about 520 + */ +#define TRACK_MAX 1 +#define TRACK_MIN 0 +static volatile uint16_t load_power_highest = 520; +static volatile uint16_t load_power_lowest = 520; + +void power_track(uint32_t flags) +{ + /* Start tracking the higest value */ + static int tracking = TRACK_MAX; + static uint16_t last_value = 0; + uint16_t val = 0; + + /* Get load power usage */ + adc_get_value(&val, LPC_ADC(2)); + + /* Four possibilities : + * tracking max and value increasing : nothing to do + * tracking max and value decreasing : we found the max, store it and change tracking + * tracking min and value decreasing : nothing to do + * tracking min and value increasing : we found the min, store it and change tracking + */ + if (tracking == TRACK_MAX) { + if (last_value > val) { + /* Found max */ + load_power_highest = last_value; + tracking = TRACK_MIN; + } + } else { + if (last_value < val) { + /* Found min */ + load_power_lowest = last_value; + tracking = TRACK_MAX; + } + } + last_value = val; +} + + /***************************************************************************** */ /* AC control */ -volatile uint8_t command_val = 0; volatile int act_cmd = 0; /* Start off */ -int8_t force_cmd = -1; /* Forced command value, for tests */ -int8_t old_cmd = 0; /* Used to store cmd value when entering over-voltage protection mode */ -#define FAN_CNT_START (15 * 1000) -static uint16_t fan_on = 0; -uint8_t force_fan = 0; /* Request to force fan ON from test menu */ - void set_ctrl_duty_cycle(uint8_t value) { @@ -208,31 +226,34 @@ void ac_switch_on(uint32_t flags) gpio_clear(ac_ctrl); } -static uint32_t clk_cycles_ac_zc = 0; + extern uint32_t power_delay[101]; volatile uint32_t zc_cnt = 0; +/* + * 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. + */ void zero_cross(uint32_t unused) { uint32_t delay = 0; zc_cnt++; + /* Command at 100% ? set Mosfets ON and return. */ if (act_cmd == 100) { gpio_clear(ac_ctrl); return; } + /* Set Mosfet OFF */ gpio_set(ac_ctrl); + /* Command at 0% ? leave Mosfets OFF (do not start timer) and return. */ if (act_cmd == 0) { return; } /* Set timer to trigger ac out ON at given delay */ - if (0) { - /* Time based delay */ - delay = clk_cycles_ac_zc * (100 - act_cmd); - } else { - /* Power based delay */ - delay = power_delay[100 - act_cmd]; - } + delay = power_delay[100 - act_cmd]; timer_set_match(LPC_TIMER_32B1, CHAN0, delay); timer_restart(LPC_TIMER_32B1); } @@ -240,11 +261,22 @@ void zero_cross(uint32_t unused) /* This one is used to synchronize to the real zero-crossing detection, if any. */ void zero_cross_detect(uint32_t unused) { + /* Prepare to generate the fake second zero crossing */ timer_restart(LPC_TIMER_32B0); + /* And call zero cross handler for this one */ zero_cross(0); } + + /* 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 */ +#define FAN_COUNTER_START_VAL (15 * 1000) +static uint16_t fan_on = 0; +uint8_t force_fan = 0; /* Request to force fan ON from test menu */ +#define PROTECTION_CMD_VAL 100 + static uint8_t linky_disable = 0; #define CMD_UP_DELAY_RESET_VALUE 3 void handle_cmd_update(uint32_t curent_tick) @@ -253,11 +285,14 @@ 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; - /* Unable to read internal temperature : turn off heating */ - if (error_shutdown == 1) { - cmd = 0; - force_fan = 1; + /* 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; } /* Water max temperature protection with hysteresys */ @@ -275,14 +310,11 @@ void handle_cmd_update(uint32_t curent_tick) max_temp_hysteresys = ABSOLUTE_MAX_WATER_TEMP; } - /* Forced over-voltage protection or test mode */ - if (force_cmd != -1) { - cmd = force_cmd; + /* Unable to read internal temperature : turn off heating */ + if ((temp_shutdown == 1) || (error_shutdown == 1)) { + cmd = 0; + force_fan = 1; goto cmd_update_end; - } else if (old_cmd != -1) { - /* Get back to normal after over-voltage protection */ - cmd = old_cmd; - old_cmd = -1; } /* Which is the current mode ? */ @@ -370,8 +402,9 @@ cmd_update_limited_end: } cmd_update_end: + /* Update FAN command (start or stop FAN) */ if ((cmd > 0) || (force_fan == 1)) { - fan_on = FAN_CNT_START; + fan_on = FAN_COUNTER_START_VAL; gpio_set(fan_ctrl); } else { if (fan_on > 0) { @@ -388,40 +421,53 @@ cmd_update_end: /* Over-voltage protection */ void overvoltage_protect(uint32_t gpio) { - gpio_clear(ac_ctrl); - timer_stop(LPC_TIMER_32B1); - set_ctrl_duty_cycle(100); - force_cmd = 100; + gpio_clear(ac_ctrl); /* Turn mosfets ON */ + timer_stop(LPC_TIMER_32B1); /* Stop mosfets timer */ + set_ctrl_duty_cycle(100); /* Update "actual command" */ overvoltage = OVERVOLTAGE_PROTECTION_CYCLES; - gpio_set(fan_ctrl); - old_cmd = command_val; + 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 = heat; /* Debug info */ volatile char* msg = NULL; -void mode_update(uint32_t unused) +void mode_update(void) { /* Default mode : try to heat the water tank */ mode = heat; /* Need to enter Forced heating mode ? */ - if (water_centi_degrees < sc_conf.enter_forced_mode_temp) { + 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 = forced; - } 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; - mode = temp_OK; + } 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: + case FORCE_TYPE_MIN: + case FORCE_TYPE_MAX: + if ((water_centi_degrees > sc_conf.auto_forced_target_heater_temp) && ()) { + } + } + if (exit_forced == 1) { + status_led(red_off); + msg = "Water temp OK, forced mode exit\n"; + forced_heater_mode = 0; + mode = temp_OK; + } } - /* Do not force if there is a lot of sun, it may be enough to heat again soon */ + /* 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 = delayed_heat_prod; forced_heater_mode = 0; @@ -434,16 +480,14 @@ void mode_update(uint32_t unused) mode = ext_disable; msg = "Forced mode disabled by external input\n"; } - /* Get Over-Voltage or Over-Temperature information */ + + /* Get Over-Temperature information */ temp_shutdown = (gpio_read(overtemperature_pin) ? 0 : 1); + /* Update Over-Voltage information */ if (overvoltage > 0) { uint8_t ov_tmp = (gpio_read(overvoltage_pin) ? 0 : 1); if (ov_tmp == 0) { overvoltage--; - if (overvoltage == 0) { - /* Get back to normal */ - force_cmd = -1; - } } } @@ -473,84 +517,75 @@ void mode_update(uint32_t unused) } /***************************************************************************** */ -/* Power tracking - load part */ -/* ADC values are between 0 and 1023, no load value is at about 520 */ -#define TRACK_MAX 1 -#define TRACK_MIN 0 -static volatile uint16_t load_power_highest = 520; -static volatile uint16_t load_power_lowest = 520; -void power_track(uint32_t flags) +/* Add a false zero-cross, but make sure to do it only once and only if we are not AC powered */ +void DC_switch_start(void) { - /* Start tracking the higest value */ - static int tracking = TRACK_MAX; - static uint16_t last_value = 0; - uint16_t val = 0; - - /* Get load power usage */ - adc_get_value(&val, LPC_ADC(2)); - - /* Four possibilities : - * tracking max and value increasing : nothing to do - * tracking max and value decreasing : we found the max, store it and change tracking - * tracking min and value decreasing : nothing to do - * tracking min and value increasing : we found the min, store it and change tracking - */ - if (tracking == TRACK_MAX) { - if (last_value > val) { - /* Found max */ - load_power_highest = last_value; - tracking = TRACK_MIN; - } + static int already_done = 0; + if ((already_done == 0) && (zc_cnt == 0)) { + int ret = add_systick_callback(zero_cross, 10); /* 2 zero-crossing at 50Hz -> 100Hz -> 10ms */ + uprintf(UART0, "Entering forced DC mode on systick callback %d\n", ret); + already_done = 1; } else { - if (last_value < val) { - /* Found min */ - load_power_lowest = last_value; - tracking = TRACK_MAX; - } + uprintf(UART0, "DC forced mode not available. On: %d, Zc: %d\n", already_done, zc_cnt); } - last_value = val; } /***************************************************************************** */ -void scialys_systick_and_timers_config(void) +void update_internal_temp(void) { - /* We want 100 Hz (50 Hz but two zero crossings) with 1% granularity */ - clk_cycles_ac_zc = get_main_clock() / (100 * 100); - uprintf(UART0, "clk_cycles_ac_zc: %d\n", clk_cycles_ac_zc); - - /* Configure the fake zero-cross generation timer to 100Hz. - * Do not start it now, it will be started by the first real zero-cross detected in order to - * generate the other half zc (not seen by system due to hardware design) - * Also sarted by config when DC mode is set */ - timer_set_match(LPC_TIMER_32B0, CHAN0, (clk_cycles_ac_zc * 100)); - - /* Configure the power tracking timer. - * 20 points per half sin wave should be enough to get the min and max */ - timer_set_match(LPC_TIMER_16B0, CHAN0, (clk_cycles_ac_zc * 5)); - timer_start(LPC_TIMER_16B0); + /* Get internal temperatures */ + ret = temp_read(UART0, &deci_degrees_disp, &deci_degrees_power); + if (ret != CONV_OK) { + force_fan = 1; + } + /* Internal temperature protection */ + if ((deci_degrees_power > MAX_INTERNAL_TEMP) || (deci_degrees_disp > MAX_INTERNAL_TEMP)) { + error_shutdown = 1; + uprintf(UART0, "Error shutdown !\n"); + } else if ((deci_degrees_power < ((MAX_INTERNAL_TEMP) / 2)) && + (deci_degrees_disp < ((MAX_INTERNAL_TEMP) / 2))) { + error_shutdown = 0; + } +} - /* Add a systick callback to handle command value update */ - add_systick_callback(handle_cmd_update, CMD_UPD_PERIOD); - /* Add a systick callback to track ismail values (power consumption and production) */ - add_systick_callback(track_isnail_values, ADC_UPD_PERIOD); +/* Store data on uSD once every N seconds. + * Note : Once every second requires about 1Go per year. + */ +#define NB_SEC_STORE 5 +void store_data(uint32_t cur_tick) +{ + static uint32_t last_tick_store = 0; + static struct sd_data_blob data; + static uint8_t nb_val = 0; - /* Add a systick callback to handle time counting */ - add_systick_callback(handle_dec_request, DEC_PERIOD); -} + if (nb_val == 0) { + memset(&data, 0, sizeof(struct sd_data_blob)); + } + /* simple tick wrapping handling */ + if ((cur_tick < last_tick_store) || ((~0 - last_tick_store) < (NB_SEC_STORE * 1000))) { + last_tick_store = 0; + } -/* Add a false zero-cross, but make sure to do it only once and only if we are not AC powered */ -void DC_switch_start(void) -{ - static int already_done = 0; - if ((already_done == 0) && (zc_cnt == 0)) { - int ret = add_systick_callback(zero_cross, 10); /* 2 zero-crossing at 50Hz -> 100Hz -> 10ms */ - uprintf(UART0, "Entering forced DC mode on systick callback %d\n", ret); - already_done = 1; - } else { - uprintf(UART0, "DC forced mode already ON: %d/%d\n", already_done, zc_cnt); + /* Each flag is set if seen once within the interval */ + data.flags |= (fan_on ? 1 : 0) | (force_fan << 1); + data.flags |= (error_shutdown << 2) | (temp_shutdown << 3) | (overvoltage << 4); + data.flags |= (external_disable << 5); + data.flags |= (forced_heater_mode << 6) | (manual_activation_request << 7); + + /* Add current value to the storage value */ + /* FIXME */ + nb_val++; + + if (cur_tick > (last_tick_store + (NB_SEC_STORE * 1000))) { + /* Divide by the number of values */ + /* FIXME */ + scialys_uSD_append_data(&data); + uprintf(UART0, "Saved 5s data\n"); + nb_val = 0; + last_tick_store = cur_tick; } } @@ -563,7 +598,6 @@ int main(void) /* Order is important here */ system_init(); - msleep(800); /* Required for uSD to stabilise before SPI is setup .... */ board_io_config(); modules_config(); external_components_config(UART0); @@ -573,67 +607,23 @@ int main(void) scialys_systick_and_timers_config(); uprintf(UART0, "System setup complete.\n"); - uprintf(UART0, "Max intensity: %d\n", max_intensity); - msleep(500); + msleep(100); status_led(green_only); while (1) { /* Feed the dog */ - if ((solar_prod_value != 0) && (home_conso_value != 0) && - (solar_prod_value < 45000) && (home_conso_value < 45000) ) { - /* FIXME : Make max solar prod and home conso a parameter */ + if ((solar_prod_value != 0) && (home_conso_value != 0)) { watchdog_feed(); } /* Update internal temperatures */ - if (1) { - /* Get internal temperatures */ - ret = temp_read(UART0, &deci_degrees_disp, &deci_degrees_power); - if (ret != CONV_OK) { - if ((ret & CONV_POWER_OK) == 0) { - force_fan = 1; - } - if ((ret & CONV_DISPLAY_OK) == 0) { - force_fan = 1; - } - } - /* Internal temperature protection */ - if ((deci_degrees_power > MAX_INTERNAL_TEMP) || (deci_degrees_disp > MAX_INTERNAL_TEMP)) { - error_shutdown = 1; - uprintf(UART0, "Error shutdown !\n"); - } else if ((deci_degrees_power < ((MAX_INTERNAL_TEMP) / 2)) && - (deci_degrees_disp < ((MAX_INTERNAL_TEMP) / 2))) { - error_shutdown = 0; - } - } + update_internal_temp(); /* 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) { - 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); - } 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; - } + water_centi_degrees = water_temp_update(); /* Update current mode */ - mode_update(0); + mode_update(); /* Display */ /* only update twice per second */ @@ -647,42 +637,8 @@ int main(void) last_tick_update = cur_tick; } - /* Store data on uSD once every N seconds. - * Note : Once every second requires about 1Go per year. - */ - #define NB_SEC_STORE 5 - if (1) { - static uint32_t last_tick_store = 0; - static struct sd_data_blob data; - static uint8_t nb_val = 0; - - if (nb_val == 0) { - memset(&data, 0, sizeof(struct sd_data_blob)); - } - /* simple tick wrapping handling */ - if ((cur_tick < last_tick_store) || ((~0 - last_tick_store) < (NB_SEC_STORE * 1000))) { - last_tick_store = 0; - } - - /* Each flag is set if seen once within the interval */ - data.flags |= (fan_on ? 1 : 0) | (force_fan << 1); - data.flags |= (error_shutdown << 2) | (temp_shutdown << 3) | (overvoltage << 4); - data.flags |= (external_disable << 5); - data.flags |= (forced_heater_mode << 6) | (manual_activation_request << 7); - - /* Add current value to the storage value */ - /* FIXME */ - nb_val++; - - if (cur_tick > (last_tick_store + (NB_SEC_STORE * 1000))) { - /* Divide by the number of values */ - /* FIXME */ - scialys_uSD_append_data(&data); - uprintf(UART0, "Saved 5s data\n"); - nb_val = 0; - last_tick_store = cur_tick; - } - } + /* Store data on uSD once every N seconds. */ + store_data(cur_tick); /* Debug */ if (1) { diff --git a/v10/param.c b/v10/param.c index afdba75..3466277 100644 --- a/v10/param.c +++ b/v10/param.c @@ -350,6 +350,7 @@ int config_interface_handle(void) sc_conf.grid_power_limit = 36; } } + /* This one is used in main loop after computation */ update_max_intensity(); BUTTONS_ACTS_DEFAULT(); break; @@ -385,6 +386,7 @@ int config_interface_handle(void) sc_conf.source_has_power_ok = 36000; } } + /* This one is used in main loop after computation */ update_sunny_days_prod_value(); BUTTONS_ACTS_DEFAULT(); break; diff --git a/v10/sensors.c b/v10/sensors.c new file mode 100644 index 0000000..18c17ea --- /dev/null +++ b/v10/sensors.c @@ -0,0 +1,101 @@ +/**************************************************************************** + * apps/scialys/v10/sensors.c + * + * Copyright 2016-2022 Nathael Pajani + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + +#include "core/system.h" +#include "core/systick.h" +#include "core/pio.h" + +#include "drivers/gpio.h" +#include "drivers/i2c.h" +#include "drivers/adc.h" +#include "drivers/ssp.h" + +#include "extdrv/tmp101_temp_sensor.h" +#include "extdrv/max31855_thermocouple.h" + +#include "config.h" +#include "sensors.h" + + +/***************************************************************************** */ +/* External components */ + +extern uint8_t interface_board_present ; +extern uint8_t power_board_present; + +int temp_read(uint32_t uart, int* deci_degrees_disp, int* deci_degrees_power) +{ + int ret = 0; + int conv = 0; + + if (interface_board_present != 0) { + ret = tmp101_sensor_read(&tmp101_sensor_display, NULL, deci_degrees_disp); + if (ret == 0) { + conv |= CONV_DISPLAY_OK; + } else { + uprintf(uart, "TMP101 read error on display board : %d\n", ret); + } + } + if (power_board_present != 0) { + ret = tmp101_sensor_read(&tmp101_sensor_power, NULL, deci_degrees_power); + if (ret == 0) { + conv |= CONV_POWER_OK; + } else { + uprintf(uart, "TMP101 read error on power board : %d\n", ret); + } + } + return conv; +} + + +/***************************************************************************** */ +/* Update water tank temperature */ + + +int water_temp_update(void) +{ + static int water_centi_average[WTA_NB_VAL]; + static int wta_idx = 0; + int water_centi_degrees = 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); + } 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; /* Division */ + + return water_centi_degrees; +} + + + diff --git a/v10/sensors.h b/v10/sensors.h new file mode 100644 index 0000000..6786be3 --- /dev/null +++ b/v10/sensors.h @@ -0,0 +1,61 @@ +/**************************************************************************** + * apps/scialys/v10/sensors.h + * + * Copyright 2016-2021 Nathael Pajani + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + +#ifndef SENSORS_H +#define SENSORS_H + +#include "core/system.h" +#include "core/systick.h" +#include "core/pio.h" + +#include "drivers/serial.h" +#include "drivers/gpio.h" +#include "drivers/i2c.h" +#include "drivers/adc.h" +#include "drivers/ssp.h" +#include "drivers/timers.h" + +#include "extdrv/status_led.h" +#include "extdrv/max31855_thermocouple.h" + +#include "lib/stdio.h" + + + +/***************************************************************************** */ +/* Internal Temperature sensors */ + +#define CONV_DISPLAY_OK (0x01 << 0) +#define CONV_POWER_OK (0x01 << 1) +#define CONV_OK (CONV_POWER_OK | CONV_DISPLAY_OK) +int temp_read(uint32_t uart, int* deci_degrees_disp, int* deci_degrees_power); + + +/***************************************************************************** */ +/* 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 */ +int water_temp_update(void); + + + +#endif /* SENSORS_H */ + diff --git a/v10/time.c b/v10/time.c index 5259dcd..da5e1d0 100644 --- a/v10/time.c +++ b/v10/time.c @@ -39,9 +39,9 @@ struct rtc_pcf85363a_config rtc_conf = { }; /* Oldest acceptable time in RTC. BCD coded. */ const struct rtc_time oldest = { - .year = 0x21, - .month = 0x04, - .day = 0x24, + .year = 0x22, + .month = 0x11, + .day = 0x10, .hour = 0x13, .min = 0x37, }; -- 2.43.0