3-phase PV router
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1
23
24static_assert(__cplusplus >= 201703L, "**** Please define 'gnu++17' in 'platform.txt' ! ****");
25static_assert(__cplusplus >= 201703L, "See also : https://github.com/FredM67/PVRouter-3-phase/blob/main/Mk2_3phase_RFdatalog_temp/Readme.md");
26
27#include <Arduino.h> // may not be needed, but it's probably a good idea to include this
28
29#include "config.h"
30
31// In this sketch, the ADC is free-running with a cycle time of ~104uS.
32
33#include "calibration.h"
34#include "processing.h"
35#include "shared_var.h"
36#include "types.h"
37#include "utils.h"
38#include "utils_relay.h"
39#include "validation.h"
40#include "main.h"
41
42// -------------- general global variables -----------------
43//
44// Some of these variables are used in multiple blocks so cannot be static.
45// For integer maths, some variables need to be 'int32_t'
46//
47
65{
66 if constexpr (OVERRIDE_PIN_PRESENT)
67 {
68 const auto pinState{ getPinState(forcePin) };
69
70#ifdef ENABLE_DEBUG
71 static uint8_t previousState{ HIGH };
72 if (previousState != pinState)
73 {
74 DBUGLN(!pinState ? F("Trigger override!") : F("End override!"));
75 }
76
77 previousState = pinState;
78#endif
79
80 for (auto &bOverrideLoad : Shared::b_overrideLoadOn)
81 {
82 bOverrideLoad = !pinState;
83 }
84
85 return !pinState;
86 }
87 else
88 {
89 return false;
90 }
91}
92
108{
109 if constexpr (DIVERSION_PIN_PRESENT)
110 {
111 const auto pinState{ getPinState(diversionPin) };
112
113#ifdef ENABLE_DEBUG
114 static auto previousState{ HIGH };
115 if (previousState != pinState)
116 {
117 DBUGLN(!pinState ? F("Trigger diversion OFF!") : F("End diversion OFF!"));
118 }
119
120 previousState = pinState;
121#endif
122
124 }
125}
126
141{
143
144 // waits till the priorities have been rotated from inside the ISR
145 do
146 {
147 delay(10);
148 } while (Shared::b_reOrderLoads);
149
150 // prints the (new) load priorities
152}
153
171bool proceedLoadPrioritiesAndOverridingDualTariff(const int16_t &currentTemperature_x100)
172{
173 constexpr int16_t iTemperatureThreshold_x100{ iTemperatureThreshold * 100 };
174 static bool pinOffPeakState{ HIGH };
175 const auto pinNewState{ getPinState(dualTariffPin) };
176
177 if (pinOffPeakState && !pinNewState)
178 {
179 // we start off-peak period
180 DBUGLN(F("Change to off-peak period!"));
181
182 ul_TimeOffPeak = millis();
183
184 if constexpr (PRIORITY_ROTATION == RotationModes::AUTO)
185 {
187 }
188 }
189 else
190 {
191 const auto ulElapsedTime{ static_cast< uint32_t >(millis() - ul_TimeOffPeak) };
192 const auto pinState{ getPinState(forcePin) };
193
194 for (uint8_t i = 0; i < NO_OF_DUMPLOADS; ++i)
195 {
196 // for each load, if we're inside off-peak period and within the 'force period', trigger the ISR to turn the load ON
197 if (!pinOffPeakState && !pinNewState && (ulElapsedTime >= rg_OffsetForce[i][0]) && (ulElapsedTime < rg_OffsetForce[i][1]))
198 {
199 Shared::b_overrideLoadOn[i] = !pinState || (currentTemperature_x100 <= iTemperatureThreshold_x100);
200 }
201 else
202 {
203 Shared::b_overrideLoadOn[i] = !pinState;
204 }
205 }
206 }
207 // end of off-peak period
208 if (!pinOffPeakState && pinNewState)
209 {
210 DBUGLN(F("Change to peak period!"));
211 }
212
213 pinOffPeakState = pinNewState;
214
215 return (LOW == pinOffPeakState);
216}
217
236bool proceedLoadPrioritiesAndOverriding(const int16_t &currentTemperature_x100)
237{
238 if constexpr (DUAL_TARIFF)
239 {
240 return proceedLoadPrioritiesAndOverridingDualTariff(currentTemperature_x100);
241 }
242
243 if constexpr (EMONESP_CONTROL)
244 {
245 static uint8_t pinRotationState{ HIGH };
246 const auto pinNewState{ getPinState(rotationPin) };
247
248 if (pinRotationState && !pinNewState)
249 {
250 DBUGLN(F("Trigger rotation!"));
251
253 }
254 pinRotationState = pinNewState;
255 }
256 else if constexpr (PRIORITY_ROTATION == RotationModes::AUTO)
257 {
259 {
261
263 }
264 }
265
266 if constexpr (OVERRIDE_PIN_PRESENT)
267 {
268 const auto pinState{ getPinState(forcePin) };
269
270 for (auto &bOverrideLoad : Shared::b_overrideLoadOn)
271 {
272 bOverrideLoad = !pinState;
273 }
274 }
275
276 return false;
277}
278
296void setup()
297{
298 delay(initialDelay); // allows time to open the Serial Monitor
299
300 DEBUG_PORT.begin(9600);
301 Serial.begin(9600, SERIAL_OUTPUT_TYPE == SerialOutputType::IoT ? SERIAL_7E1 : SERIAL_8N1); // initialize Serial interface, Do NOT set greater than 9600
302
303 // On start, always display config info in the serial monitor
305
306 // initializes all loads to OFF at startup
308
310
311 if constexpr (TEMP_SENSOR_PRESENT)
312 {
313 temperatureSensing.initTemperatureSensors();
314 }
315
316 DBUG(F(">>free RAM = "));
317 DBUGLN(freeRam()); // a useful value to keep an eye on
318 DBUGLN(F("----"));
319}
320
335{
336 tx_data.power = 0;
337 for (uint8_t phase = 0; phase < NO_OF_PHASES; ++phase)
338 {
340 tx_data.power_L[phase] *= -1;
341
342 tx_data.power += tx_data.power_L[phase];
343
344 if constexpr (DATALOG_PERIOD_IN_SECONDS > 10)
345 {
346 tx_data.Vrms_L_x100[phase] = static_cast< uint32_t >((100U << 2) * f_voltageCal[phase] * sqrt(Shared::copyOf_sum_Vsquared[phase] / Shared::copyOf_sampleSetsDuringThisDatalogPeriod));
347 }
348 else
349 {
350 tx_data.Vrms_L_x100[phase] = static_cast< uint32_t >(100U * f_voltageCal[phase] * sqrt(Shared::copyOf_sum_Vsquared[phase] / Shared::copyOf_sampleSetsDuringThisDatalogPeriod));
351 }
352 }
353}
354
372{
373 uint8_t idx{ temperatureSensing.get_size() };
374 do
375 {
376 auto tmp = temperatureSensing.readTemperature(--idx);
377
378 // if read temperature is 85 and the delta with previous is greater than 5, skip the value
379 if (8500 == tmp && (abs(tmp - tx_data.temperature_x100[idx]) > 500))
380 {
382 }
383
384 tx_data.temperature_x100[idx] = tmp;
385 } while (idx);
386
387 temperatureSensing.requestTemperatures(); // for use next time around
388}
389
408void handlePerSecondTasks(bool &bOffPeak, int16_t &iTemperature_x100)
409{
411 {
413 }
414
415 if constexpr (WATCHDOG_PIN_PRESENT)
416 {
418 }
419
421
422 if (!forceFullPower())
423 {
424 bOffPeak = proceedLoadPrioritiesAndOverriding(iTemperature_x100); // called every second
425 }
426
427 if constexpr (RELAY_DIVERSION)
428 {
429 relays.inc_duration();
430 relays.proceed_relays();
431 }
432}
433
449void loop()
450{
451 static uint8_t perSecondTimer{ 0 };
452 static bool bOffPeak{ false };
453 static int16_t iTemperature_x100{ 0 };
454
455 if (Shared::b_newMainsCycle) // flag is set after every pair of ADC conversions
456 {
457 Shared::b_newMainsCycle = false; // reset the flag
458 ++perSecondTimer;
459
460 if (perSecondTimer >= SUPPLY_FREQUENCY)
461 {
462 perSecondTimer = 0;
463 handlePerSecondTasks(bOffPeak, iTemperature_x100);
464 }
465 }
466
468 {
470
472
473 if constexpr (RELAY_DIVERSION)
474 {
475 relays.update_average(tx_data.power);
476 }
477
478 if constexpr (TEMP_SENSOR_PRESENT)
479 {
481 }
482
483 sendResults(bOffPeak);
484 }
485} // end of loop()
Calibration values definition.
constexpr float f_voltageCal[NO_OF_PHASES]
Definition calibration.h:51
constexpr float f_powerCal[NO_OF_PHASES]
Definition calibration.h:34
Configuration values to be set by the end-user.
constexpr bool RELAY_DIVERSION
Definition config.h:40
constexpr bool OVERRIDE_PIN_PRESENT
Definition config.h:37
constexpr uint32_t ROTATION_AFTER_SECONDS
Definition config.h:105
constexpr uint8_t dualTariffPin
Definition config.h:85
constexpr TemperatureSensing temperatureSensing
Definition config.h:98
constexpr uint8_t forcePin
Definition config.h:88
constexpr RelayEngine relays
Definition config.h:91
constexpr bool DUAL_TARIFF
Definition config.h:41
constexpr uint8_t diversionPin
Definition config.h:86
constexpr SerialOutputType SERIAL_OUTPUT_TYPE
Definition config.h:27
constexpr bool EMONESP_CONTROL
Definition config.h:34
constexpr uint8_t NO_OF_DUMPLOADS
Definition config.h:32
constexpr bool TEMP_SENSOR_PRESENT
Definition config.h:42
constexpr int16_t iTemperatureThreshold
Definition config.h:96
constexpr bool WATCHDOG_PIN_PRESENT
Definition config.h:39
constexpr bool DIVERSION_PIN_PRESENT
Definition config.h:35
constexpr uint8_t rotationPin
Definition config.h:87
constexpr uint8_t watchDogPin
Definition config.h:89
constexpr uint8_t DATALOG_PERIOD_IN_SECONDS
constexpr uint8_t NO_OF_PHASES
constexpr uint8_t SUPPLY_FREQUENCY
constexpr int16_t DEVICE_DISCONNECTED_RAW
Definition constants.h:27
#define DBUGLN(...)
Definition debug.h:97
#define DBUG(...)
Definition debug.h:96
uint32_t ul_TimeOffPeak
Definition dualtariff.h:62
constexpr auto rg_OffsetForce
Definition dualtariff.h:64
uint8_t i
void updatePowerAndVoltageData()
Updates power and voltage data for all phases.
Definition main.cpp:334
void handlePerSecondTasks(bool &bOffPeak, int16_t &iTemperature_x100)
Handles tasks that need to be executed every second.
Definition main.cpp:408
bool proceedLoadPrioritiesAndOverridingDualTariff(const int16_t &currentTemperature_x100)
Handles load priorities and overriding during dual tariff periods.
Definition main.cpp:171
void checkDiversionOnOff()
Checks and updates the diversion state based on the diversion pin.
Definition main.cpp:107
bool forceFullPower()
Forces all loads to full power if the override pin is active.
Definition main.cpp:64
void proceedRotation()
Proceeds with load priority rotation.
Definition main.cpp:140
bool proceedLoadPrioritiesAndOverriding(const int16_t &currentTemperature_x100)
Handles load priorities and overriding logic.
Definition main.cpp:236
void sendResults(bool bOffPeak)
Prints or sends telemetry data logs based on the selected output format.
Definition utils.h:423
void logLoadPriorities()
Prints the load priorities to the Serial output.
Definition utils.h:464
void loop()
Main processor loop.
Definition main.cpp:449
void setup()
Called once during startup.
Definition main.cpp:296
void printConfiguration()
Print the configuration during startup.
Definition utils.h:47
void initializeProcessing()
Initializes the processing engine, including ports, load states, and ADC setup.
void processTemperatureData()
Processes temperature data from DS18B20 sensors.
Definition main.cpp:371
Header file for the main application.
volatile bool EDD_isIdle
Definition shared_var.h:16
volatile int32_t copyOf_sum_Vsquared[NO_OF_PHASES]
Definition shared_var.h:23
volatile bool b_datalogEventPending
Definition shared_var.h:10
volatile bool b_overrideLoadOn[NO_OF_DUMPLOADS]
Definition shared_var.h:12
volatile bool b_reOrderLoads
Definition shared_var.h:13
volatile uint16_t copyOf_sampleSetsDuringThisDatalogPeriod
Definition shared_var.h:26
volatile int32_t copyOf_sumP_atSupplyPoint[NO_OF_PHASES]
Definition shared_var.h:22
volatile uint16_t absenceOfDivertedEnergyCountInSeconds
Definition shared_var.h:17
volatile bool b_newMainsCycle
Definition shared_var.h:11
volatile bool b_diversionEnabled
Definition shared_var.h:14
Public functions/variables of processing engine.
constexpr uint16_t initialDelay
Definition processing.h:26
PayloadTx_struct< NO_OF_PHASES > tx_data
Definition processing.h:32
Some basics classes/types.
Some utility functions.
int freeRam()
Get the available RAM during setup.
Definition utils.h:489
constexpr bool getPinState(uint8_t pin)
Get the Pin State.
Definition utils_pins.h:194
constexpr void togglePin(uint8_t pin)
Toggle the specified pin.
Definition utils_pins.h:89
Some utility functions for the relay output feature.
Compile-time validations.