1-phase PV router
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1
11
12static_assert(__cplusplus >= 201703L, "**** Please define 'gnu++17' in 'platform.txt' ! ****");
13static_assert(__cplusplus >= 201703L, "See also : https://github.com/FredM67/PVRouter-3-phase/blob/main/Mk2_fasterControl_Full/README.md");
14
15#include <Arduino.h> // may not be needed, but it's probably a good idea to include this
16
17#include "config.h"
18#include "calibration.h"
19#include "processing.h"
20#include "types.h"
21#include "utils.h"
22#include "utils_relay.h"
23#include "utils_display.h"
24#include "utils_oled.h"
25#include "utils_temp.h"
26#include "validation.h"
27
28// -------------- general global variables -----------------
29//
30// Some of these variables are used in multiple blocks so cannot be static.
31// For integer maths, some variables need to be 'int32_t'
32//
33
56{
57 if constexpr (OVERRIDE_PIN_PRESENT)
58 {
59 const auto pinState{ getPinState(forcePin) };
60
61#ifdef ENABLE_DEBUG
62 static uint8_t previousState{ HIGH };
63 if (previousState != pinState)
64 {
65 DBUGLN(!pinState ? F("Trigger override!") : F("End override!"));
66 }
67
68 previousState = pinState;
69#endif
70
71 for (auto &bOverrideLoad : Shared::b_overrideLoadOn)
72 {
73 bOverrideLoad = !pinState;
74 }
75
76 return !pinState;
77 }
78 else
79 {
80 return false;
81 }
82}
83
103{
105
106 // waits till the priorities have been rotated from inside the ISR
107 do
108 {
109 delay(10);
110 } while (Shared::b_reOrderLoads);
111
112 // prints the (new) load priorities
114}
115
142bool proceedLoadPrioritiesAndOverridingDualTariff(const int16_t currentTemperature_x100)
143{
144 constexpr int16_t iTemperatureThreshold_x100{ iTemperatureThreshold * 100 };
145 static bool pinOffPeakState{ HIGH };
146 const auto pinNewState{ getPinState(dualTariffPin) };
147
148 if (pinOffPeakState && !pinNewState)
149 {
150 // we start off-peak period
151 DBUGLN(F("Change to off-peak period!"));
152
153 ul_TimeOffPeak = millis();
154
155 if constexpr (PRIORITY_ROTATION == RotationModes::AUTO)
156 {
158 }
159 }
160 else
161 {
162 const auto ulElapsedTime{ static_cast< uint32_t >(millis() - ul_TimeOffPeak) };
163 const auto pinState{ getPinState(forcePin) };
164
165 for (uint8_t i = 0; i < NO_OF_DUMPLOADS; ++i)
166 {
167 // for each load, if we're inside off-peak period and within the 'force period', trigger the ISR to turn the load ON
168 if (!pinOffPeakState && !pinNewState && (ulElapsedTime >= rg_OffsetForce[i][0]) && (ulElapsedTime < rg_OffsetForce[i][1]))
169 {
170 Shared::b_overrideLoadOn[i] = !pinState || (currentTemperature_x100 <= iTemperatureThreshold_x100);
171 }
172 else
173 {
174 Shared::b_overrideLoadOn[i] = !pinState;
175 }
176 }
177 }
178 // end of off-peak period
179 if (!pinOffPeakState && pinNewState)
180 {
181 DBUGLN(F("Change to peak period!"));
182 }
183
184 pinOffPeakState = pinNewState;
185
186 return (LOW == pinOffPeakState);
187}
188
216bool proceedLoadPrioritiesAndOverriding(const int16_t currentTemperature_x100)
217{
218 if constexpr (DUAL_TARIFF)
219 {
220 return proceedLoadPrioritiesAndOverridingDualTariff(currentTemperature_x100);
221 }
222
223 if constexpr (EMONESP_CONTROL)
224 {
225 static uint8_t pinRotationState{ HIGH };
226 const auto pinNewState{ getPinState(rotationPin) };
227
228 if (pinRotationState && !pinNewState)
229 {
230 DBUGLN(F("Trigger rotation!"));
231
233 }
234 pinRotationState = pinNewState;
235 }
237 {
238 if constexpr (PRIORITY_ROTATION == RotationModes::AUTO)
239 {
241 }
243 }
244 if constexpr (OVERRIDE_PIN_PRESENT)
245 {
246 const auto pinState{ getPinState(forcePin) };
247
248 for (auto &bOverrideLoad : Shared::b_overrideLoadOn)
249 {
250 bOverrideLoad = !pinState;
251 }
252 }
253
254 return false;
255}
256
271{
272 if constexpr (DIVERSION_PIN_PRESENT)
273 {
274 const auto pinState{ getPinState(diversionPin) };
275
276#ifdef ENABLE_DEBUG
277 static auto previousState{ HIGH };
278 if (previousState != pinState)
279 {
280 DBUG(F("Trigger - diversion turned "));
281 DBUGLN(!pinState ? F("'OFF'!") : F("'ON'!"));
282 }
283
284 previousState = pinState;
285#endif
286
288 }
289}
290
313{
314 if constexpr (TEMP_SENSOR_PRESENT)
315 {
316 uint8_t idx{ temperatureSensing.get_size() };
317 do
318 {
319 auto tmp = temperatureSensing.readTemperature(--idx);
320
321 // if read temperature is 85 and the delta with previous is greater than 5, skip the value
322 if (8500 == tmp && (abs(tmp - tx_data.temperature_x100[idx]) > 500))
323 {
325 }
326
327 tx_data.temperature_x100[idx] = tmp;
328 } while (idx);
329
330 temperatureSensing.requestTemperatures(); // for use next time around
331 }
332}
333
366
391void setup()
392{
393 delay(delayBeforeSerialStarts); // allow time to open Serial monitor
394
395 DEBUG_PORT.begin(9600);
396 Serial.begin(9600, SERIAL_OUTPUT_TYPE == SerialOutputType::IoT ? SERIAL_7E1 : SERIAL_8N1); // initialize Serial interface, Do NOT set greater than 9600
397
398 // On start, always display config info in the serial monitor
400
401 setupOLED();
402
404
405 // initializes all loads to OFF at startup
407
409
410 if constexpr (TEMP_SENSOR_PRESENT)
411 {
412 temperatureSensing.initTemperatureSensors();
413 }
414
415 DBUG(F(">>free RAM = "));
416 DBUGLN(freeRam()); // a useful value to keep an eye on
417 DBUGLN(F("----"));
418}
419
441void handlePerSecondTasks(bool &bOffPeak, int16_t iTemperature_x100)
442{
443 if constexpr (WATCHDOG_PIN_PRESENT)
444 {
446 }
447
450
451 if (!forceFullPower())
452 {
453 bOffPeak = proceedLoadPrioritiesAndOverriding(iTemperature_x100);
454 }
455
456 if constexpr (RELAY_DIVERSION)
457 {
458 relays.inc_duration();
459 relays.proceed_relays();
460 }
461}
462
487void loop()
488{
489 static bool initLoop{ true };
490 static uint8_t perSecondTimer{ 0 };
491 static bool bOffPeak{ false };
492 static uint8_t timerForDisplayUpdate{ 0 };
493 static int16_t iTemperature_x100{ 0 };
494
495 if (Shared::b_newCycle) // flag is set after each main cycle
496 {
497 Shared::b_newCycle = false; // reset the flag
498
499 if (++timerForDisplayUpdate >= UPDATE_PERIOD_FOR_DISPLAYED_DATA)
500 { // the 4-digit display needs to be refreshed every few mS. For convenience,
501 // this action is performed every N times around this processing loop.
502 timerForDisplayUpdate = 0;
503
505 }
506
507 if (++perSecondTimer >= SUPPLY_FREQUENCY)
508 {
509 perSecondTimer = 0;
510 handlePerSecondTasks(bOffPeak, iTemperature_x100);
511 }
512 }
513
515 {
516 if (initLoop)
517 {
518 initLoop = false;
519 clearDisplay();
520 }
521
522 Shared::b_datalogEventPending = false; // Reset the flag
523
525
526 if constexpr (RELAY_DIVERSION)
527 {
528 relays.update_average(tx_data.powerGrid);
529 }
530
532
533 sendResults(bOffPeak);
534
536 }
537} // end of loop()
Calibration values definition.
constexpr float f_voltageCal
Definition calibration.h:37
constexpr float powerCal_grid
Definition calibration.h:34
constexpr float powerCal_diverted
Definition calibration.h:35
Configuration values to be set by the end-user.
constexpr bool RELAY_DIVERSION
Definition config.h:43
constexpr bool OVERRIDE_PIN_PRESENT
Definition config.h:40
constexpr uint8_t dualTariffPin
Definition config.h:73
constexpr TemperatureSensing temperatureSensing
Definition config.h:89
constexpr uint8_t forcePin
Definition config.h:76
constexpr RelayEngine relays
Definition config.h:79
constexpr bool DUAL_TARIFF
Definition config.h:44
constexpr uint8_t diversionPin
Definition config.h:74
constexpr SerialOutputType SERIAL_OUTPUT_TYPE
Definition config.h:33
constexpr bool EMONESP_CONTROL
Definition config.h:37
constexpr uint16_t ROTATION_AFTER_SECONDS
Definition config.h:92
constexpr uint8_t NO_OF_DUMPLOADS
Definition config.h:35
constexpr bool TEMP_SENSOR_PRESENT
Definition config.h:45
constexpr int16_t iTemperatureThreshold
Definition config.h:88
constexpr bool WATCHDOG_PIN_PRESENT
Definition config.h:42
constexpr bool DIVERSION_PIN_PRESENT
Definition config.h:38
constexpr uint8_t rotationPin
Definition config.h:75
constexpr uint8_t watchDogPin
Definition config.h:77
constexpr uint8_t DATALOG_PERIOD_IN_SECONDS
constexpr uint16_t delayBeforeSerialStarts
constexpr uint8_t SUPPLY_FREQUENCY
constexpr int16_t DEVICE_DISCONNECTED_RAW
Definition constants.h:25
#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
void sendResults(bool bOffPeak)
Prints or sends telemetry data logs based on the selected output format.
Definition utils.h:327
void logLoadPriorities()
Prints the load priorities to the Serial output.
void printConfiguration()
Print the configuration during startup.
Definition utils.h:55
void initializeProcessing()
Initializes the processing engine, including ports, load states, and ADC setup.
void updateWatchdog()
Update the watchdog on the display.
Definition utils_oled.h:221
void setupOLED()
Setup the OLED display.
Definition utils_oled.h:188
void updateOLED(uint16_t value)
Update the OLED display with the given value.
Definition utils_oled.h:249
void clearDisplay()
Clear the display.
Definition utils_oled.h:211
void initializeDisplay()
Initializes the display for hardware-driven 7-segment displays.
void configureValueForDisplay(const bool _EDD_isActive, const uint16_t _ValueToDisplay, const bool _diversionEnabled=false, const bool _loadForced=false)
Configures the value for display on a 7-segment display.
void handlePerSecondTasks(bool &bOffPeak, int16_t iTemperature_x100)
Handles tasks that need to be executed every second.
Definition main.cpp:441
void processCalculationsForLogging()
Performs calculations on data for logging purposes.
Definition main.cpp:350
void checkDiversionOnOff()
Checks and updates the diversion state.
Definition main.cpp:270
void setup()
Called once during startup.
Definition main.cpp:391
bool forceFullPower()
Forces all loads to full power.
Definition main.cpp:55
bool proceedLoadPrioritiesAndOverridingDualTariff(const int16_t currentTemperature_x100)
Handles load priority in combination with dual tariff.
Definition main.cpp:142
void proceedRotation()
Rotates the load priorities.
Definition main.cpp:102
bool proceedLoadPrioritiesAndOverriding(const int16_t currentTemperature_x100)
Handles load priority rotation and overriding logic.
Definition main.cpp:216
void updateTemperature()
Updates the temperature readings and sends a new request for the next cycle.
Definition main.cpp:312
void loop()
Main processor loop.
Definition main.cpp:487
volatile uint16_t copyOf_divertedEnergyTotal_Wh_forDL
Definition shared_var.h:25
volatile bool b_newCycle
Definition shared_var.h:11
volatile int32_t copyOf_sum_Vsquared
Definition shared_var.h:26
volatile int32_t copyOf_sumP_grid_overDL_Period
Definition shared_var.h:22
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:29
volatile int32_t copyOf_sumP_diverted_overDL_Period
Definition shared_var.h:23
volatile uint16_t copyOf_divertedEnergyTotal_Wh
Definition shared_var.h:24
volatile bool EDD_isActive
Definition shared_var.h:16
volatile uint16_t absenceOfDivertedEnergyCountInSeconds
Definition shared_var.h:17
volatile bool b_diversionEnabled
Definition shared_var.h:14
Public functions/variables of processing engine.
uint8_t i
Some basics classes/types.
Some utility functions.
PayloadTx_struct tx_data
Definition utils.h:37
int freeRam()
Get the available RAM during setup.
Definition utils.h:366
7-segments display functions
constexpr uint8_t UPDATE_PERIOD_FOR_DISPLAYED_DATA
Some utility functions for OLED display.
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.
Provides utilities for managing temperature sensors.