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 "types.h"
36#include "utils.h"
37#include "utils_relay.h"
38#include "validation.h"
39#include "main.h"
40
41// -------------- general global variables -----------------
42//
43// Some of these variables are used in multiple blocks so cannot be static.
44// For integer maths, some variables need to be 'int32_t'
45//
46
64{
65 if constexpr (OVERRIDE_PIN_PRESENT)
66 {
67 const auto pinState{ getPinState(forcePin) };
68
69#ifdef ENABLE_DEBUG
70 static uint8_t previousState{ HIGH };
71 if (previousState != pinState)
72 {
73 DBUGLN(!pinState ? F("Trigger override!") : F("End override!"));
74 }
75
76 previousState = pinState;
77#endif
78
79 for (auto &bOverrideLoad : b_overrideLoadOn)
80 {
81 bOverrideLoad = !pinState;
82 }
83
84 return !pinState;
85 }
86 else
87 {
88 return false;
89 }
90}
91
107{
108 if constexpr (DIVERSION_PIN_PRESENT)
109 {
110 const auto pinState{ getPinState(diversionPin) };
111
112#ifdef ENABLE_DEBUG
113 static auto previousState{ HIGH };
114 if (previousState != pinState)
115 {
116 DBUGLN(!pinState ? F("Trigger diversion OFF!") : F("End diversion OFF!"));
117 }
118
119 previousState = pinState;
120#endif
121
122 b_diversionOff = !pinState;
123 }
124}
125
140{
141 b_reOrderLoads = true;
142
143 // waits till the priorities have been rotated from inside the ISR
144 do
145 {
146 delay(10);
147 } while (b_reOrderLoads);
148
149 // prints the (new) load priorities
151}
152
170bool proceedLoadPrioritiesAndOverridingDualTariff(const int16_t &currentTemperature_x100)
171{
172 constexpr int16_t iTemperatureThreshold_x100{ iTemperatureThreshold * 100 };
173 static bool pinOffPeakState{ HIGH };
174 const auto pinNewState{ getPinState(dualTariffPin) };
175
176 if (pinOffPeakState && !pinNewState)
177 {
178 // we start off-peak period
179 DBUGLN(F("Change to off-peak period!"));
180
181 ul_TimeOffPeak = millis();
182
183 if constexpr (PRIORITY_ROTATION == RotationModes::AUTO)
184 {
186 }
187 }
188 else
189 {
190 const auto ulElapsedTime{ static_cast< uint32_t >(millis() - ul_TimeOffPeak) };
191 const auto pinState{ getPinState(forcePin) };
192
193 for (uint8_t i = 0; i < NO_OF_DUMPLOADS; ++i)
194 {
195 // for each load, if we're inside off-peak period and within the 'force period', trigger the ISR to turn the load ON
196 if (!pinOffPeakState && !pinNewState && (ulElapsedTime >= rg_OffsetForce[i][0]) && (ulElapsedTime < rg_OffsetForce[i][1]))
197 {
198 b_overrideLoadOn[i] = !pinState || (currentTemperature_x100 <= iTemperatureThreshold_x100);
199 }
200 else
201 {
202 b_overrideLoadOn[i] = !pinState;
203 }
204 }
205 }
206 // end of off-peak period
207 if (!pinOffPeakState && pinNewState)
208 {
209 DBUGLN(F("Change to peak period!"));
210 }
211
212 pinOffPeakState = pinNewState;
213
214 return (LOW == pinOffPeakState);
215}
216
235bool proceedLoadPrioritiesAndOverriding(const int16_t &currentTemperature_x100)
236{
237 if constexpr (DUAL_TARIFF)
238 {
239 return proceedLoadPrioritiesAndOverridingDualTariff(currentTemperature_x100);
240 }
241
242 if constexpr (EMONESP_CONTROL)
243 {
244 static uint8_t pinRotationState{ HIGH };
245 const auto pinNewState{ getPinState(rotationPin) };
246
247 if (pinRotationState && !pinNewState)
248 {
249 DBUGLN(F("Trigger rotation!"));
250
252 }
253 pinRotationState = pinNewState;
254 }
255 else if constexpr (PRIORITY_ROTATION == RotationModes::AUTO)
256 {
258 {
260
262 }
263 }
264
265 if constexpr (OVERRIDE_PIN_PRESENT)
266 {
267 const auto pinState{ getPinState(forcePin) };
268
269 for (auto &bOverrideLoad : b_overrideLoadOn)
270 {
271 bOverrideLoad = !pinState;
272 }
273 }
274
275 return false;
276}
277
295void setup()
296{
297 delay(initialDelay); // allows time to open the Serial Monitor
298
299 DEBUG_PORT.begin(9600);
300 Serial.begin(9600); // initialize Serial interface, Do NOT set greater than 9600
301
302 // On start, always display config info in the serial monitor
304
305 // initializes all loads to OFF at startup
307
309
310 if constexpr (TEMP_SENSOR_PRESENT)
311 {
312 temperatureSensing.initTemperatureSensors();
313 }
314
315 DBUG(F(">>free RAM = "));
316 DBUGLN(freeRam()); // a useful value to keep an eye on
317 DBUGLN(F("----"));
318}
319
334{
335 tx_data.power = 0;
336 for (uint8_t phase = 0; phase < NO_OF_PHASES; ++phase)
337 {
338 tx_data.power_L[phase] = copyOf_sumP_atSupplyPoint[phase] / copyOf_sampleSetsDuringThisDatalogPeriod * f_powerCal[phase];
339 tx_data.power_L[phase] *= -1;
340
341 tx_data.power += tx_data.power_L[phase];
342
343 if constexpr (DATALOG_PERIOD_IN_SECONDS > 10)
344 {
345 tx_data.Vrms_L_x100[phase] = static_cast< uint32_t >((100U << 2) * f_voltageCal[phase] * sqrt(copyOf_sum_Vsquared[phase] / copyOf_sampleSetsDuringThisDatalogPeriod));
346 }
347 else
348 {
349 tx_data.Vrms_L_x100[phase] = static_cast< uint32_t >(100U * f_voltageCal[phase] * sqrt(copyOf_sum_Vsquared[phase] / copyOf_sampleSetsDuringThisDatalogPeriod));
350 }
351 }
352}
353
371{
372 uint8_t idx{ temperatureSensing.get_size() };
373 do
374 {
375 auto tmp = temperatureSensing.readTemperature(--idx);
376
377 // if read temperature is 85 and the delta with previous is greater than 5, skip the value
378 if (8500 == tmp && (abs(tmp - tx_data.temperature_x100[idx]) > 500))
379 {
381 }
382
383 tx_data.temperature_x100[idx] = tmp;
384 } while (idx);
385
386 temperatureSensing.requestTemperatures(); // for use next time around
387}
388
407void handlePerSecondTasks(bool &bOffPeak, int16_t &iTemperature_x100)
408{
409 if (EDD_isIdle)
410 {
412 }
413
414 if constexpr (WATCHDOG_PIN_PRESENT)
415 {
417 }
418
420
421 if (!forceFullPower())
422 {
423 bOffPeak = proceedLoadPrioritiesAndOverriding(iTemperature_x100); // called every second
424 }
425
426 if constexpr (RELAY_DIVERSION)
427 {
428 relays.inc_duration();
429 relays.proceed_relays();
430 }
431}
432
448void loop()
449{
450 static uint8_t perSecondTimer{ 0 };
451 static bool bOffPeak{ false };
452 static int16_t iTemperature_x100{ 0 };
453
454 if (b_newMainsCycle) // flag is set after every pair of ADC conversions
455 {
456 b_newMainsCycle = false; // reset the flag
457 ++perSecondTimer;
458
459 if (perSecondTimer >= SUPPLY_FREQUENCY)
460 {
461 perSecondTimer = 0;
462 handlePerSecondTasks(bOffPeak, iTemperature_x100);
463 }
464 }
465
467 {
468 b_datalogEventPending = false;
469
471
472 if constexpr (RELAY_DIVERSION)
473 {
474 relays.update_average(tx_data.power);
475 }
476
477 if constexpr (TEMP_SENSOR_PRESENT)
478 {
480 }
481
482 sendResults(bOffPeak);
483 }
484} // end of loop()
Calibration values definition.
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:91
constexpr uint8_t dualTariffPin
Definition config.h:71
constexpr TemperatureSensing temperatureSensing
Definition config.h:84
constexpr uint8_t forcePin
Definition config.h:74
constexpr RelayEngine relays
Definition config.h:77
constexpr bool DUAL_TARIFF
Definition config.h:41
constexpr uint8_t diversionPin
Definition config.h:72
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:82
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:73
constexpr uint8_t watchDogPin
Definition config.h:75
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:333
void handlePerSecondTasks(bool &bOffPeak, int16_t &iTemperature_x100)
Handles tasks that need to be executed every second.
Definition main.cpp:407
bool proceedLoadPrioritiesAndOverridingDualTariff(const int16_t &currentTemperature_x100)
Handles load priorities and overriding during dual tariff periods.
Definition main.cpp:170
void checkDiversionOnOff()
Checks and updates the diversion state based on the diversion pin.
Definition main.cpp:106
bool forceFullPower()
Forces all loads to full power if the override pin is active.
Definition main.cpp:63
void proceedRotation()
Proceeds with load priority rotation.
Definition main.cpp:139
bool proceedLoadPrioritiesAndOverriding(const int16_t &currentTemperature_x100)
Handles load priorities and overriding logic.
Definition main.cpp:235
void sendResults(bool bOffPeak)
Prints or sends telemetry data logs based on the selected output format.
Definition utils.h:412
void logLoadPriorities()
Prints the load priorities to the Serial output.
Definition utils.h:453
void loop()
Main processor loop.
Definition main.cpp:448
void setup()
Called once during startup.
Definition main.cpp:295
void printConfiguration()
Print the configuration during startup.
Definition utils.h:46
void initializeProcessing()
Initializes the processing engine, including ports, load states, and ADC setup.
void processTemperatureData()
Processes temperature data from DS18B20 sensors.
Definition main.cpp:370
Header file for the main application.
Public functions/variables of processing engine.
volatile bool b_reOrderLoads
Definition processing.h:34
volatile int32_t copyOf_sumP_atSupplyPoint[NO_OF_PHASES]
Definition processing.h:41
volatile int32_t copyOf_sum_Vsquared[NO_OF_PHASES]
Definition processing.h:42
volatile uint16_t copyOf_sampleSetsDuringThisDatalogPeriod
Definition processing.h:45
volatile bool b_overrideLoadOn[NO_OF_DUMPLOADS]
Definition processing.h:33
volatile bool b_newMainsCycle
Definition processing.h:32
volatile bool EDD_isIdle
Definition processing.h:36
volatile bool b_datalogEventPending
Definition processing.h:31
volatile bool b_diversionOff
Definition processing.h:35
constexpr uint16_t initialDelay
Definition processing.h:26
PayloadTx_struct< NO_OF_PHASES > tx_data
Definition processing.h:51
volatile uint16_t absenceOfDivertedEnergyCount
Definition processing.h:30
Some basics classes/types.
Some utility functions.
int freeRam()
Get the available RAM during setup.
Definition utils.h:478
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.