From 9854dd0c86e0e406e1018430175a260989c263b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Metrich?= <45318189+FredM67@users.noreply.github.com> Date: Fri, 5 May 2023 22:38:58 +0200 Subject: [PATCH] More code for relay diversion --- Mk2_3phase_RFdatalog_temp/config.h | 19 +-- Mk2_3phase_RFdatalog_temp/config_system.h | 29 ++++ Mk2_3phase_RFdatalog_temp/main.cpp | 14 +- Mk2_3phase_RFdatalog_temp/movingAvg.h | 2 +- Mk2_3phase_RFdatalog_temp/processing.cpp | 3 +- Mk2_3phase_RFdatalog_temp/processing.h | 4 - Mk2_3phase_RFdatalog_temp/utils.h | 150 ------------------- Mk2_3phase_RFdatalog_temp/utils_pins.h | 167 ++++++++++++++++++++++ Mk2_3phase_RFdatalog_temp/utils_relay.h | 57 ++++++-- Mk2_3phase_RFdatalog_temp/validation.h | 2 +- 10 files changed, 260 insertions(+), 187 deletions(-) create mode 100644 Mk2_3phase_RFdatalog_temp/config_system.h create mode 100644 Mk2_3phase_RFdatalog_temp/utils_pins.h diff --git a/Mk2_3phase_RFdatalog_temp/config.h b/Mk2_3phase_RFdatalog_temp/config.h index 839bda3e..7baefe24 100644 --- a/Mk2_3phase_RFdatalog_temp/config.h +++ b/Mk2_3phase_RFdatalog_temp/config.h @@ -24,6 +24,7 @@ //#define SERIALOUT ///< Uncomment if a wired serial connection is used //-------------------------------------------------------------------------------------------------- +#include "config_system.h" #include "debug.h" #include "types.h" @@ -50,7 +51,7 @@ inline constexpr bool OVERRIDE_PIN_PRESENT{ false }; /**< set #endif inline constexpr bool WATCHDOG_PIN_PRESENT{ false }; /**< set it to 'true' if there's a watch led */ -inline constexpr bool RELAY_DIVERSION{ false }; /**< set it to 'true' if a relay is used for diversion */ +inline constexpr bool RELAY_DIVERSION{ false }; /**< set it to 'true' if a relay is used for diversion */ inline constexpr bool DUAL_TARIFF{ false }; /**< set it to 'true' if there's a dual tariff each day AND the router is connected to the billing meter */ // ----------- Pinout assignments ----------- @@ -83,7 +84,7 @@ inline constexpr uint8_t watchDogPin{ 0xff }; /**< inline constexpr uint8_t tempSensorPin{ 0xff }; /**< for 3-phase PCB, sensor pin */ -inline constexpr relayConfig relay_Config; /**< config for relay diversion, see class definition for defaults */ +inline relayOutput relay_Output{ relayPin }; /**< config for relay diversion, see class definition for defaults */ inline constexpr uint8_t ul_OFF_PEAK_DURATION{ 8 }; /**< Duration of the off-peak period in hours */ inline constexpr pairForceLoad rg_ForceLoad[NO_OF_DUMPLOADS]{ { -3, 2 } }; /**< force config for load #1 ONLY for dual tariff */ @@ -96,19 +97,7 @@ inline constexpr DeviceAddress sensorAddrs[]{ { 0x28, 0xBE, 0x41, 0x6B, 0x09, 0x { 0x28, 0x59, 0x1F, 0x6A, 0x09, 0x00, 0x00, 0xB0 }, { 0x28, 0x1B, 0xD7, 0x6A, 0x09, 0x00, 0x00, 0xB7 } }; /**< list of temperature sensor Addresses */ -//-------------------------------------------------------------------------------------------------- -// for users with zero-export profile, this value will be negative -inline constexpr int16_t REQUIRED_EXPORT_IN_WATTS{ 20 }; /**< when set to a negative value, this acts as a PV generator */ - -//-------------------------------------------------------------------------------------------------- -// other system constants, should match most of installations -inline constexpr uint8_t SUPPLY_FREQUENCY{ 50 }; /**< number of cycles/s of the grid power supply */ - -inline constexpr uint8_t DATALOG_PERIOD_IN_SECONDS{ 5 }; /**< Period of datalogging in seconds */ -inline constexpr uint16_t DATALOG_PERIOD_IN_MAINS_CYCLES{ DATALOG_PERIOD_IN_SECONDS * SUPPLY_FREQUENCY }; /**< Period of datalogging in cycles */ -//-------------------------------------------------------------------------------------------------- - -inline constexpr uint32_t ROTATION_AFTER_CYCLES{ 8UL * 3600UL * SUPPLY_FREQUENCY }; /**< rotates load priorities after this period of inactivity */ +inline constexpr uint32_t ROTATION_AFTER_CYCLES{ 8UL * 3600UL * SUPPLY_FREQUENCY }; /**< rotates load priorities after this period of inactivity */ /* -------------------------------------- RF configuration (for the RFM12B module) diff --git a/Mk2_3phase_RFdatalog_temp/config_system.h b/Mk2_3phase_RFdatalog_temp/config_system.h new file mode 100644 index 00000000..001fa4b0 --- /dev/null +++ b/Mk2_3phase_RFdatalog_temp/config_system.h @@ -0,0 +1,29 @@ +/** + * @file config_system.h + * @author Frédéric Metrich (frederic.metrich@live.fr) + * @brief Basic configuration values to be set by the end-user + * @version 0.1 + * @date 2023-05-05 + * + * @copyright Copyright (c) 2023 + * + */ + +#ifndef __CONFIG_SYSTEM_H__ +#define __CONFIG_SYSTEM_H__ + +#include + +//-------------------------------------------------------------------------------------------------- +// for users with zero-export profile, this value will be negative +inline constexpr int16_t REQUIRED_EXPORT_IN_WATTS{ 20 }; /**< when set to a negative value, this acts as a PV generator */ + +//-------------------------------------------------------------------------------------------------- +// other system constants, should match most of installations +inline constexpr uint8_t SUPPLY_FREQUENCY{ 50 }; /**< number of cycles/s of the grid power supply */ + +inline constexpr uint8_t DATALOG_PERIOD_IN_SECONDS{ 5 }; /**< Period of datalogging in seconds */ +inline constexpr uint16_t DATALOG_PERIOD_IN_MAINS_CYCLES{ DATALOG_PERIOD_IN_SECONDS * SUPPLY_FREQUENCY }; /**< Period of datalogging in cycles */ +//-------------------------------------------------------------------------------------------------- + +#endif // __CONFIG_SYSTEM_H__ diff --git a/Mk2_3phase_RFdatalog_temp/main.cpp b/Mk2_3phase_RFdatalog_temp/main.cpp index 4ad2fb2d..083c7933 100644 --- a/Mk2_3phase_RFdatalog_temp/main.cpp +++ b/Mk2_3phase_RFdatalog_temp/main.cpp @@ -35,6 +35,7 @@ static_assert(__cplusplus >= 201703L, "See also : https://github.com/FredM67/PVR #include "processing.h" #include "types.h" #include "utils.h" +#include "utils_relay.h" #include "validation.h" // -------------- general global variables ----------------- @@ -353,7 +354,7 @@ void loop() static bool bOffPeak{ false }; static int16_t iTemperature_x100{ 0 }; - if (b_newMainsCycle) // flag is set after every pair of ADC conversions + if (b_newMainsCycle) // flag is set after every pair of ADC conversions { b_newMainsCycle = false; // reset the flag ++perSecondTimer; @@ -373,6 +374,12 @@ void loop() { bOffPeak = proceedLoadPrioritiesAndOverriding(iTemperature_x100); // called every second } + + if constexpr (RELAY_DIVERSION) + { + relay_Output.inc_duration(); + relay_Output.proceed_relay(); + } } } @@ -396,6 +403,11 @@ void loop() { tx_data.Vrms_L_x100[phase] = static_cast< int32_t >(100 * f_voltageCal[phase] * sqrt(copyOf_sum_Vsquared[phase] / copyOf_sampleSetsDuringThisDatalogPeriod)); } + + if constexpr (RELAY_DIVERSION) + { + relay_Output.update_average(tx_data.power); + } } if constexpr (TEMP_SENSOR_PRESENT) diff --git a/Mk2_3phase_RFdatalog_temp/movingAvg.h b/Mk2_3phase_RFdatalog_temp/movingAvg.h index 64c2aeca..38db479c 100644 --- a/Mk2_3phase_RFdatalog_temp/movingAvg.h +++ b/Mk2_3phase_RFdatalog_temp/movingAvg.h @@ -80,7 +80,7 @@ class movingAvg private: uint8_t _idx{ 0 }; - typename conditional< is_floating_point< T >::value, T, int32_t >::type _sum; + typename conditional< is_floating_point< T >::value, T, int32_t >::type _sum{ 0 }; T _ar[N]{}; }; diff --git a/Mk2_3phase_RFdatalog_temp/processing.cpp b/Mk2_3phase_RFdatalog_temp/processing.cpp index 7e8533b9..361a7b59 100644 --- a/Mk2_3phase_RFdatalog_temp/processing.cpp +++ b/Mk2_3phase_RFdatalog_temp/processing.cpp @@ -13,7 +13,8 @@ #include "calibration.h" #include "processing.h" -#include "utils.h" +#include "utils_pins.h" +#include "dualtariff.h" /*! * @defgroup TimeCritical Time critical functions Group diff --git a/Mk2_3phase_RFdatalog_temp/processing.h b/Mk2_3phase_RFdatalog_temp/processing.h index a631094e..c58451ad 100644 --- a/Mk2_3phase_RFdatalog_temp/processing.h +++ b/Mk2_3phase_RFdatalog_temp/processing.h @@ -14,8 +14,6 @@ #include "config.h" -#include "movingAvg.h" - // analogue input pins inline constexpr uint8_t sensorV[NO_OF_PHASES]{ 0, 2, 4 }; /**< for 3-phase PCB, voltage measurement for each phase */ inline constexpr uint8_t sensorI[NO_OF_PHASES]{ 1, 3, 5 }; /**< for 3-phase PCB, current measurement for each phase */ @@ -47,8 +45,6 @@ inline volatile uint8_t copyOf_lowestNoOfSampleSetsPerMainsCycle; /**< */ inline volatile uint16_t copyOf_sampleSetsDuringThisDatalogPeriod; /**< copy of for counting the sample sets during each datalogging period */ inline volatile uint16_t copyOf_countLoadON[NO_OF_DUMPLOADS]; /**< copy of number of cycle the load was ON (over 1 datalog period) */ -inline volatile movingAvg< int16_t, DATALOG_PERIOD_IN_MAINS_CYCLES > sliding_Average; - #ifdef TEMP_ENABLED inline PayloadTx_struct< NO_OF_PHASES, size(sensorAddrs) > tx_data; /**< logging data */ #else diff --git a/Mk2_3phase_RFdatalog_temp/utils.h b/Mk2_3phase_RFdatalog_temp/utils.h index 85093016..d122bb90 100644 --- a/Mk2_3phase_RFdatalog_temp/utils.h +++ b/Mk2_3phase_RFdatalog_temp/utils.h @@ -20,156 +20,6 @@ #include "utils_rf.h" #include "utils_temp.h" -inline void togglePin(const uint8_t pin) __attribute__((always_inline)); - -inline void setPinON(const uint8_t pin) __attribute__((always_inline)); -inline void setPinsON(const uint16_t pins) __attribute__((always_inline)); - -inline void setPinOFF(const uint8_t pin) __attribute__((always_inline)); -inline void setPinsOFF(const uint16_t pins) __attribute__((always_inline)); - -inline bool getPinState(const uint8_t pin) __attribute__((always_inline)); - -/** - * @brief Set the specified bit to 1 - * - * @tparam T Type of the variable - * @param _dest Integer variable to modify - * @param bit Bit to set in _dest - */ -template< typename T > constexpr void bit_set(T& _dest, const uint8_t bit) -{ - _dest |= (T)0x01 << bit; -} - -/** - * @brief Read the specified bit - * - * @tparam T Type of the variable - * @param _src Integer variable to read - * @param bit Bit to read in _src - * @return constexpr uint8_t - */ -template< typename T > constexpr uint8_t bit_read(const T& _src, const uint8_t bit) -{ - return (_src >> bit) & (T)0x01; -} - -/** - * @brief Clear the specified bit - * - * @tparam T Type of the variable - * @param _dest Integer variable to modify - * @param bit Bit to clear in _src - * @return constexpr uint8_t - */ -template< typename T > constexpr uint8_t bit_clear(T& _dest, const uint8_t bit) -{ - return _dest &= ~((T)0x01 << bit); -} - -/** - * @brief Toggle the specified pin - * - */ -void togglePin(const uint8_t pin) -{ - if (pin < 8) - { - bit_set(PIND, pin); - } - else - { - bit_set(PINB, pin - 8); - } -} - -/** - * @brief Set the Pin state for the specified pin - * - * @param pin pin to change [2..13] - * @param bState state to be set - */ -inline void setPinState(const uint8_t pin, const bool bState) -{ - if (bState) - { - setPinON(pin); - } - else - { - setPinOFF(pin); - } -} - -/** - * @brief Set the Pin state to ON for the specified pin - * - * @param pin pin to change [2..13] - */ -inline void setPinON(const uint8_t pin) -{ - if (pin < 8) - { - bit_set(PORTD, pin); - } - else - { - bit_set(PORTB, pin - 8); - } -} - -/** - * @brief Set the Pins state to ON - * - * @param pins The pins to change - */ -inline void setPinsON(const uint16_t pins) -{ - PORTD |= lowByte(pins); - PORTB |= highByte(pins); -} - -/** - * @brief Set the Pin state to OFF for the specified pin - * - * @param pin pin to change [2..13] - */ -inline void setPinOFF(const uint8_t pin) -{ - if (pin < 8) - { - bit_clear(PORTD, pin); - } - else - { - bit_clear(PORTB, pin - 8); - } -} - -/** - * @brief Set the Pins state to OFF - * - * @param pins The pins to change - */ -inline void setPinsOFF(const uint16_t pins) -{ - PORTD &= ~lowByte(pins); - PORTB &= ~highByte(pins); -} - -/** - * @brief Get the Pin State - * - * @param pin The pin to read - * @return true if HIGH - * @return false if LOW - */ -inline bool getPinState(const uint8_t pin) -{ - return (pin < 8) ? bitRead(PIND, pin) : bitRead(PINB, pin - 8); -} - /** * @brief Print the configuration during start * diff --git a/Mk2_3phase_RFdatalog_temp/utils_pins.h b/Mk2_3phase_RFdatalog_temp/utils_pins.h new file mode 100644 index 00000000..bebeff0f --- /dev/null +++ b/Mk2_3phase_RFdatalog_temp/utils_pins.h @@ -0,0 +1,167 @@ +/** + * @file utils_pins.h + * @author Frédéric Metrich (frederic.metrich@live.fr) + * @brief Some utility functions for pins manipulation + * @version 0.1 + * @date 2023-05-05 + * + * @copyright Copyright (c) 2023 + * + */ + +#ifndef __UTILS_PINS_H__ +#define __UTILS_PINS_H__ + +#include + +inline void togglePin(const uint8_t pin) __attribute__((always_inline)); + +inline void setPinON(const uint8_t pin) __attribute__((always_inline)); +inline void setPinsON(const uint16_t pins) __attribute__((always_inline)); + +inline void setPinOFF(const uint8_t pin) __attribute__((always_inline)); +inline void setPinsOFF(const uint16_t pins) __attribute__((always_inline)); + +inline bool getPinState(const uint8_t pin) __attribute__((always_inline)); + +/** + * @brief Set the specified bit to 1 + * + * @tparam T Type of the variable + * @param _dest Integer variable to modify + * @param bit Bit to set in _dest + */ +template< typename T > constexpr void bit_set(T& _dest, const uint8_t bit) +{ + _dest |= (T)0x01 << bit; +} + +/** + * @brief Read the specified bit + * + * @tparam T Type of the variable + * @param _src Integer variable to read + * @param bit Bit to read in _src + * @return constexpr uint8_t + */ +template< typename T > constexpr uint8_t bit_read(const T& _src, const uint8_t bit) +{ + return (_src >> bit) & (T)0x01; +} + +/** + * @brief Clear the specified bit + * + * @tparam T Type of the variable + * @param _dest Integer variable to modify + * @param bit Bit to clear in _src + * @return constexpr uint8_t + */ +template< typename T > constexpr uint8_t bit_clear(T& _dest, const uint8_t bit) +{ + return _dest &= ~((T)0x01 << bit); +} + +/** + * @brief Toggle the specified pin + * + */ +void togglePin(const uint8_t pin) +{ + if (pin < 8) + { + bit_set(PIND, pin); + } + else + { + bit_set(PINB, pin - 8); + } +} + +/** + * @brief Set the Pin state for the specified pin + * + * @param pin pin to change [2..13] + * @param bState state to be set + */ +inline void setPinState(const uint8_t pin, const bool bState) +{ + if (bState) + { + setPinON(pin); + } + else + { + setPinOFF(pin); + } +} + +/** + * @brief Set the Pin state to ON for the specified pin + * + * @param pin pin to change [2..13] + */ +inline void setPinON(const uint8_t pin) +{ + if (pin < 8) + { + bit_set(PORTD, pin); + } + else + { + bit_set(PORTB, pin - 8); + } +} + +/** + * @brief Set the Pins state to ON + * + * @param pins The pins to change + */ +inline void setPinsON(const uint16_t pins) +{ + PORTD |= lowByte(pins); + PORTB |= highByte(pins); +} + +/** + * @brief Set the Pin state to OFF for the specified pin + * + * @param pin pin to change [2..13] + */ +inline void setPinOFF(const uint8_t pin) +{ + if (pin < 8) + { + bit_clear(PORTD, pin); + } + else + { + bit_clear(PORTB, pin - 8); + } +} + +/** + * @brief Set the Pins state to OFF + * + * @param pins The pins to change + */ +inline void setPinsOFF(const uint16_t pins) +{ + PORTD &= ~lowByte(pins); + PORTB &= ~highByte(pins); +} + +/** + * @brief Get the Pin State + * + * @param pin The pin to read + * @return true if HIGH + * @return false if LOW + */ +inline bool getPinState(const uint8_t pin) +{ + return (pin < 8) ? bitRead(PIND, pin) : bitRead(PINB, pin - 8); +} + +#endif // __UTILS_PINS_H__ diff --git a/Mk2_3phase_RFdatalog_temp/utils_relay.h b/Mk2_3phase_RFdatalog_temp/utils_relay.h index 14a9f6d5..8cad2fcd 100644 --- a/Mk2_3phase_RFdatalog_temp/utils_relay.h +++ b/Mk2_3phase_RFdatalog_temp/utils_relay.h @@ -14,36 +14,52 @@ #include "types.h" +#include "config_system.h" +#include "movingAvg.h" +#include "utils_pins.h" + /** * @brief Config parameters for relay diversion * */ -template< uint8_t T = 1 > class relayConfig +template< uint8_t T = 1 > class relayOutput { public: - constexpr relayConfig() = default; + constexpr relayOutput() = delete; + + /** + * @brief Construct a new relay Config object + * + * @param _relay_pin Control pin for the relay + */ + explicit constexpr relayOutput(uint8_t _relay_pin) + : relay_pin(_relay_pin) + { + } /** * @brief Construct a new relay Config object * + * @param _relay_pin Control pin for the relay * @param _surplusThreshold Surplus threshold to turn relay ON * @param _importThreshold Import threshold to turn relay OFF */ - constexpr relayConfig(int16_t _surplusThreshold, int16_t _importThreshold) - : surplusThreshold(abs(_surplusThreshold)), importThreshold(abs(_importThreshold)) + constexpr relayOutput(uint8_t _relay_pin, int16_t _surplusThreshold, int16_t _importThreshold) + : relay_pin(_relay_pin), surplusThreshold(abs(_surplusThreshold)), importThreshold(abs(_importThreshold)) { } /** * @brief Construct a new relay Config object * + * @param _relay_pin Control pin for the relay * @param _surplusThreshold Surplus threshold to turn relay ON * @param _importThreshold Import threshold to turn relay OFF * @param _minON Minimum duration in minutes to leave relay ON * @param _minOFF Minimum duration in minutes to leave relay OFF */ - constexpr relayConfig(int16_t _surplusThreshold, int16_t _importThreshold, uint16_t _minON, uint16_t _minOFF) - : surplusThreshold(abs(_surplusThreshold)), importThreshold(abs(_importThreshold)), minON(_minON * 60), minOFF(_minOFF * 60) + constexpr relayOutput(uint8_t _relay_pin, int16_t _surplusThreshold, int16_t _importThreshold, uint16_t _minON, uint16_t _minOFF) + : relay_pin(_relay_pin), surplusThreshold(abs(_surplusThreshold)), importThreshold(abs(_importThreshold)), minON(_minON * 60), minOFF(_minOFF * 60) { } @@ -99,10 +115,11 @@ template< uint8_t T = 1 > class relayConfig /** * @brief Proceed with the relay * - * @param currentAvgPower Current sliding average power */ - void proceed_relay(int16_t currentAvgPower) + void proceed_relay() { + const auto currentAvgPower{ sliding_Average.getAverage() }; + if (currentAvgPower > surplusThreshold) { try_turnON(); @@ -113,6 +130,11 @@ template< uint8_t T = 1 > class relayConfig } } + inline static void update_average(int16_t currentPower) + { + sliding_Average.addValue(currentPower); + } + private: /** * @brief Turn ON the relay if the 'time' condition is met @@ -126,6 +148,8 @@ template< uint8_t T = 1 > class relayConfig } if (duration > minOFF) { + setPinON(relay_pin); + relayState = true; duration = 0; } @@ -143,19 +167,24 @@ template< uint8_t T = 1 > class relayConfig } if (duration > minON) { + setPinOFF(relay_pin); + relayState = false; duration = 0; } } private: - int16_t surplusThreshold{ 1000 }; /**< Surplus threshold to turn relay ON */ - int16_t importThreshold{ 200 }; /**< Import threshold to turn relay OFF */ - uint16_t minON{ 5 * 60 }; /**< Minimum duration in seconds the relay is turned ON */ - uint16_t minOFF{ 5 * 60 }; /**< Minimum duration in seconds the relay is turned OFF */ + uint8_t relay_pin{ 0xff }; /**< Pin associated with the relay */ + int16_t surplusThreshold{ 1000 }; /**< Surplus threshold to turn relay ON */ + int16_t importThreshold{ 200 }; /**< Import threshold to turn relay OFF */ + uint16_t minON{ 5 * 60 }; /**< Minimum duration in seconds the relay is turned ON */ + uint16_t minOFF{ 5 * 60 }; /**< Minimum duration in seconds the relay is turned OFF */ + + uint16_t duration{ 0 }; /**< Duration of the current state */ + bool relayState{ false }; /**< State of the relay */ - uint16_t duration{ 0 }; /**< Duration of the current state */ - bool relayState{ false }; /**< State of the relay */ + static inline movingAvg< int16_t, T * 60 / DATALOG_PERIOD_IN_SECONDS > sliding_Average; }; #endif // _UTILS_RELAY_H \ No newline at end of file diff --git a/Mk2_3phase_RFdatalog_temp/validation.h b/Mk2_3phase_RFdatalog_temp/validation.h index 77e2fc33..57029e84 100644 --- a/Mk2_3phase_RFdatalog_temp/validation.h +++ b/Mk2_3phase_RFdatalog_temp/validation.h @@ -12,7 +12,7 @@ #ifndef _VALIDATION_H #define _VALIDATION_H -#include "utils.h" +#include "utils_pins.h" /** * @note All these checks are done by the compiler.