3-phase PV router
Loading...
Searching...
No Matches
processing.cpp
Go to the documentation of this file.
1
11
12#include <Arduino.h>
13
14#include "config.h"
15#include "calibration.h"
16#include "dualtariff.h"
17#include "processing.h"
18#include "utils_pins.h"
19#include "shared_var.h"
20
21// Define operating limits for the LP filters which identify DC offset in the voltage
22// sample streams. By limiting the output range, these filters always should start up
23// correctly.
24constexpr int32_t l_DCoffset_V_min{ (512L - 100L) * 256L };
25constexpr int32_t l_DCoffset_V_max{ (512L + 100L) * 256L };
26constexpr int16_t i_DCoffset_I_nom{ 512L };
27
29
35constexpr float f_offsetOfEnergyThresholdsInAFmode{ 0.1F };
36
38
39bool b_diversionStarted{ false };
40
53
54constexpr float f_lowerThreshold_default{ initThreshold(true) };
55constexpr float f_upperThreshold_default{ initThreshold(false) };
56
57float f_energyInBucket_main{ 0.0F };
60
61// for improved control of multiple loads
62bool b_recentTransition{ false };
63uint8_t postTransitionCount{ 0 };
64constexpr uint8_t POST_TRANSITION_MAX_COUNT{ 3 };
65// constexpr uint8_t POST_TRANSITION_MAX_COUNT{50}; /**< for testing only */
67
68int32_t l_sumP[NO_OF_PHASES]{};
73
76
78
80
81// For an enhanced polarity detection mechanism, which includes a persistence check
85
88
90
91uint8_t perSecondCounter{ 0 };
92
93bool beyondStartUpPeriod{ false };
94
111template< size_t N >
112constexpr void initializeArray(int32_t (&array)[N], int32_t value)
113{
114 for (size_t i = 0; i < N; ++i)
115 {
116 array[i] = value;
117 }
118}
119
134constexpr uint16_t getOutputPins()
135{
136 uint16_t output_pins{ 0 };
137
138 for (const auto &loadPin : physicalLoadPin)
139 {
140 if (bit_read(output_pins, loadPin))
141 return 0;
142
143 bit_set(output_pins, loadPin);
144 }
145
146 if constexpr (WATCHDOG_PIN_PRESENT)
147 {
148 if (bit_read(output_pins, watchDogPin))
149 return 0;
150
151 bit_set(output_pins, watchDogPin);
152 }
153
154 if constexpr (RELAY_DIVERSION)
155 {
156 for (uint8_t idx = 0; idx < relays.size(); ++idx)
157 {
158 const auto relayPin = relays.get_relay(idx).get_pin();
159
160 if (bit_read(output_pins, relayPin))
161 return 0;
162
163 bit_set(output_pins, relayPin);
164 }
165 }
166
167 return output_pins;
168}
169
185constexpr uint16_t getInputPins()
186{
187 uint16_t input_pins{ 0 };
188
189 if constexpr (DUAL_TARIFF)
190 {
191 if (bit_read(input_pins, dualTariffPin))
192 return 0;
193
194 bit_set(input_pins, dualTariffPin);
195 }
196
197 if constexpr (DIVERSION_PIN_PRESENT)
198 {
199 if (bit_read(input_pins, diversionPin))
200 return 0;
201
202 bit_set(input_pins, diversionPin);
203 }
204
205 if constexpr (PRIORITY_ROTATION == RotationModes::PIN)
206 {
207 if (bit_read(input_pins, rotationPin))
208 return 0;
209
210 bit_set(input_pins, rotationPin);
211 }
212
213 if constexpr (OVERRIDE_PIN_PRESENT)
214 {
215 // Add all configured override pins
216 for (uint8_t i = 0; i < overridePins.size(); ++i)
217 {
218 const uint8_t pin = overridePins.getPin(i);
219 if (bit_read(input_pins, pin))
220 return 0;
221
222 bit_set(input_pins, pin);
223 }
224 }
225
226 return input_pins;
227}
228
243{
244 initializeArray(l_DCoffset_V, 512L * 256L); // nominal mid-point value of ADC @ x256 scale
245
246 setPinsAsOutput(getOutputPins()); // set the output pins as OUTPUT
247 setPinsAsInputPullup(getInputPins()); // set the input pins as INPUT_PULLUP
248
249 uint8_t i{ NO_OF_DUMPLOADS };
250 do
251 {
252 --i;
255 } while (i);
256
257 // First stop the ADC
258 bit_clear(ADCSRA, ADEN);
259
260 // Activate free-running mode
261 ADCSRB = 0x00;
262
263 // Set up the ADC to be free-running
264 bit_set(ADCSRA, ADPS0); // Set the ADC's clock to system clock / 128
265 bit_set(ADCSRA, ADPS1);
266 bit_set(ADCSRA, ADPS2);
267
268 bit_set(ADCSRA, ADATE); // set the Auto Trigger Enable bit in the ADCSRA register. Because
269 // bits ADTS0-2 have not been set (i.e. they are all zero), the
270 // ADC's trigger source is set to "free running mode".
271
272 bit_set(ADCSRA, ADIE); // set the ADC interrupt enable bit. When this bit is written
273 // to one and the I-bit in SREG is set, the
274 // ADC Conversion Complete Interrupt is activated.
275
276 bit_set(ADCSRA, ADEN); // Enable the ADC
277
278 bit_set(ADCSRA, ADSC); // start ADC manually first time
279
280 sei(); // Enable Global Interrupts
281}
282
299{
300 uint16_t pinsON{ 0 };
301 uint16_t pinsOFF{ 0 };
302
303 uint8_t i{ NO_OF_DUMPLOADS };
304
305 do
306 {
307 --i;
308 // update the local load's state.
310 {
311 // setPinOFF(physicalLoadPin[i]);
312 pinsOFF |= bit(physicalLoadPin[i]);
313 }
314 else
315 {
316 ++countLoadON[i];
317 // setPinON(physicalLoadPin[i]);
318 pinsON |= bit(physicalLoadPin[i]);
319 }
320 } while (i);
321
322 // Apply override bitmask directly to pinsON
323 pinsON |= Shared::overrideBitmask;
324
325 setPinsOFF(pinsOFF);
326 setPinsON(pinsON);
327}
328
354{
355 if constexpr (NO_OF_DUMPLOADS == 0)
356 {
357 return;
358 }
359
360 if constexpr (PRIORITY_ROTATION != RotationModes::OFF)
361 {
363 {
364 uint8_t i{ static_cast< uint8_t >(NO_OF_DUMPLOADS - 1) };
365 const auto temp{ loadPrioritiesAndState[i] };
366 do
367 {
369 --i;
370 } while (i);
371 loadPrioritiesAndState[0] = temp;
372
374 }
375 }
376
377 const bool bDiversionEnabled{ Shared::b_diversionEnabled };
378 uint8_t idx{ NO_OF_DUMPLOADS };
379 do
380 {
381 --idx;
382 const auto iLoad{ loadPrioritiesAndState[idx] & loadStateMask };
383 const bool bOverrideActive = Shared::overrideBitmask & (1U << physicalLoadPin[iLoad]);
384 physicalLoadState[iLoad] = bDiversionEnabled && (bOverrideActive || (loadPrioritiesAndState[idx] & loadStateOnBit)) ? LoadStates::LOAD_ON : LoadStates::LOAD_OFF;
385 } while (idx);
386}
387
405void processPolarity(const uint8_t phase, const int16_t rawSample)
406{
407 // remove DC offset from each raw voltage sample by subtracting the accurate value
408 // as determined by its associated LP filter.
409 l_sampleVminusDC[phase] = (static_cast< int32_t >(rawSample) << 8) - l_DCoffset_V[phase];
411}
412
430void processCurrentRawSample(const uint8_t phase, const int16_t rawSample)
431{
432 // extra items for an LPF to improve the processing of data samples from CT1
433 static int32_t lpf_long[NO_OF_PHASES]{}; // new LPF, for offsetting the behaviour of CTx as a HPF
434
435 // remove most of the DC offset from the current sample (the precise value does not matter)
436 int32_t sampleIminusDC = (static_cast< int32_t >(rawSample - i_DCoffset_I_nom)) << 8;
437
438 // extra filtering to offset the HPF effect of CTx
439 const int32_t last_lpf_long{ lpf_long[phase] };
440 lpf_long[phase] += alpha * (sampleIminusDC - last_lpf_long);
441 sampleIminusDC += (lpf_gain * lpf_long[phase]);
442
443 // calculate the "real power" in this sample pair and add to the accumulated sum
444 const int32_t filtV_div4 = l_sampleVminusDC[phase] >> 2; // reduce to 16-bits (now x64, or 2^6)
445 const int32_t filtI_div4 = sampleIminusDC >> 2; // reduce to 16-bits (now x64, or 2^6)
446 int32_t instP = filtV_div4 * filtI_div4; // 32-bits (now x4096, or 2^12)
447 instP >>= 12; // scaling is now x1, as for Mk2 (V_ADC x I_ADC)
448
449 l_sumP[phase] += instP; // cumulative power, scaling as for Mk2 (V_ADC x I_ADC)
450 l_sumP_atSupplyPoint[phase] += instP; // cumulative power, scaling as for Mk2 (V_ADC x I_ADC)
451}
452
469void confirmPolarity(const uint8_t phase)
470{
471 static uint8_t count[NO_OF_PHASES]{};
472
474 {
475 count[phase] = 0;
476 return;
477 }
478
479 if (++count[phase] > PERSISTENCE_FOR_POLARITY_CHANGE)
480 {
481 count[phase] = 0;
483 }
484}
485
503void processVoltage(const uint8_t phase)
504{
505 // for the Vrms calculation (for datalogging only)
506 const int32_t filtV_div4{ l_sampleVminusDC[phase] >> 2 }; // reduce to 16-bits (now x64, or 2^6)
507 int32_t inst_Vsquared{ filtV_div4 * filtV_div4 }; // 32-bits (now x4096, or 2^12)
508
509 if constexpr (DATALOG_PERIOD_IN_SECONDS > 10)
510 {
511 inst_Vsquared >>= 16; // scaling is now x1/16 (V_ADC x I_ADC)
512 }
513 else
514 {
515 inst_Vsquared >>= 12; // scaling is now x1 (V_ADC x I_ADC)
516 }
517
518 l_sum_Vsquared[phase] += inst_Vsquared; // cumulative V^2 (V_ADC x I_ADC)
519 //
520 // store items for use during next loop
521 l_cumVdeltasThisCycle[phase] += l_sampleVminusDC[phase]; // for use with LP filter
522 polarityConfirmedOfLastSampleV[phase] = polarityConfirmed[phase]; // for identification of half cycle boundaries
523 ++n_samplesDuringThisMainsCycle[phase]; // for real power calculations
524}
525
542void processStartUp(const uint8_t phase)
543{
544 // wait until the DC-blocking filters have had time to settle
545 if (millis() <= (initialDelay + startUpPeriod))
546 {
547 return; // still settling, do nothing
548 }
549
550 // the DC-blocking filters have had time to settle
551 beyondStartUpPeriod = true;
552 l_sumP[phase] = 0;
553 l_sumP_atSupplyPoint[phase] = 0;
556
558 // can't say "Go!" here 'cos we're in an ISR!
559}
560
575{
576 bool bOK_toAddLoad{ true };
577 const auto tempLoad{ nextLogicalLoadToBeAdded() };
578
579 if (tempLoad == NO_OF_DUMPLOADS)
580 {
581 return;
582 }
583
584 // a load which is now OFF has been identified for potentially being switched ON
586 {
587 // During the post-transition period, any increase in the energy level is noted.
589
590 // the energy thresholds must remain within range
592 {
594 }
595
596 // Only the active load may be switched during this period. All other loads must
597 // wait until the recent transition has had sufficient opportunity to take effect.
598 bOK_toAddLoad = (tempLoad == activeLoad);
599 }
600
601 if (bOK_toAddLoad)
602 {
604 activeLoad = tempLoad;
606 b_recentTransition = true;
607 }
608}
609
624{
625 bool bOK_toRemoveLoad{ true };
626 const auto tempLoad{ nextLogicalLoadToBeRemoved() };
627
628 if (tempLoad == NO_OF_DUMPLOADS)
629 {
630 return;
631 }
632
633 // a load which is now ON has been identified for potentially being switched OFF
635 {
636 // During the post-transition period, any decrease in the energy level is noted.
638
639 // the energy thresholds must remain within range
641 {
643 }
644
645 // Only the active load may be switched during this period. All other loads must
646 // wait until the recent transition has had sufficient opportunity to take effect.
647 bOK_toRemoveLoad = (tempLoad == activeLoad);
648 }
649
650 if (bOK_toRemoveLoad)
651 {
653 activeLoad = tempLoad;
655 b_recentTransition = true;
656 }
657}
658
675{
676 // Restrictions apply for the period immediately after a load has been switched.
677 // Here the b_recentTransition flag is checked and updated as necessary.
678 // if (b_recentTransition)
679 // b_recentTransition = (++postTransitionCount < POST_TRANSITION_MAX_COUNT);
680 // for optimization, the next line is equivalent to the two lines above
682
684 {
685 // the energy state is in the upper half of the working range
686 f_lowerEnergyThreshold = f_lowerThreshold_default; // reset the "opposite" threshold
688 {
689 // Because the energy level is high, some action may be required
691 }
692 }
693 else
694 {
695 // the energy state is in the lower half of the working range
696 f_upperEnergyThreshold = f_upperThreshold_default; // reset the "opposite" threshold
698 {
699 // Because the energy level is low, some action may be required
701 }
702 }
703
704 updatePhysicalLoadStates(); // allows the logical-to-physical mapping to be changed
705
706 updatePortsStates(); // update the control ports for each of the physical loads
707
709 {
711 }
712 else
713 {
715 }
716
717 // Now that the energy-related decisions have been taken, min and max limits can now
718 // be applied to the level of the energy bucket. This is to ensure correct operation
719 // when conditions change, i.e. when import changes to export, and vice versa.
720 //
722 {
724 }
725 else if (f_energyInBucket_main < 0)
726 {
728 }
729}
730
746void processMinusHalfCycle(const uint8_t phase)
747{
748 // This is a convenient point to update the Low Pass Filter for removing the DC
749 // component from the phase that is being processed.
750 // The portion which is fed back into the integrator is approximately one percent
751 // of the average offset of all the SampleVs in the previous mains cycle.
752 //
753 l_DCoffset_V[phase] += (l_cumVdeltasThisCycle[phase] >> 12);
754 l_cumVdeltasThisCycle[phase] = 0;
755
756 // To ensure that this LP filter will always start up correctly when 240V AC is
757 // available, its output value needs to be prevented from drifting beyond the likely range
758 // of the voltage signal.
759 //
760 if (l_DCoffset_V[phase] < l_DCoffset_V_min)
761 {
763 }
764 else if (l_DCoffset_V[phase] > l_DCoffset_V_max)
765 {
767 }
768}
769
783{
784 for (uint8_t index = 0; index < NO_OF_DUMPLOADS; ++index)
785 {
786 if (0x00 == (loadPrioritiesAndState[index] & loadStateOnBit))
787 {
788 return (index);
789 }
790 }
791
792 return (NO_OF_DUMPLOADS);
793}
794
808{
809 uint8_t index{ NO_OF_DUMPLOADS };
810 do
811 {
813 {
814 return (index);
815 }
816 } while (index);
817
818 return (NO_OF_DUMPLOADS);
819}
820
837void processLatestContribution(const uint8_t phase)
838{
839 // for efficiency, the energy scale is Joules * SUPPLY_FREQUENCY
840 // add the latest energy contribution to the main energy accumulator
842
843 // apply any adjustment that is required.
844 if (0 == phase)
845 {
846 // If diversion hasn't started yet, use start threshold, otherwise use regular offset
848 {
850
851 // Check if we've exceeded the threshold to start diversion
853 {
854 b_diversionStarted = true;
855 // Once started, we divert all surplus according to the configured fixed offset
856 }
857 }
858 else
859 {
860 // When diversion is already started, apply normal export offset if configured
861 // Comment or remove this if you want to divert ALL surplus once started
863 }
864
866 {
868
870 {
872 // Reset diversion state if we've had no diversion for a full second
873 b_diversionStarted = false;
874 }
875 else
877 }
878
879 Shared::b_newMainsCycle = true; // a 50 Hz 'tick' for use by the main code
880 }
881 // Applying max and min limits to the main accumulator's level
882 // is deferred until after the energy related decisions have been taken
883 //
884}
885
901{
903 {
904 return; // data logging period not yet reached
905 }
906
908
909 uint8_t phase{ NO_OF_PHASES };
910 do
911 {
912 --phase;
914 l_sumP_atSupplyPoint[phase] = 0;
915
917 l_sum_Vsquared[phase] = 0;
918 } while (phase);
919
920 uint8_t i{ NO_OF_DUMPLOADS };
921 do
922 {
923 --i;
925 countLoadON[i] = 0;
926 } while (i);
927
931
934
935 // signal the main processor that logging data are available
936 // we skip the period from start to running stable
938}
939
957void processPlusHalfCycle(const uint8_t phase)
958{
959 processLatestContribution(phase); // runs at 6.6 ms intervals
960
961 // A performance check to monitor and display the minimum number of sets of
962 // ADC samples per mains cycle, the expected number being 20ms / (104us * 6) = 32.05
963 //
964 if (0 == phase)
965 {
967 {
969 }
970
972 }
973
974 l_sumP[phase] = 0;
976}
977
995void processRawSamples(const uint8_t phase)
996{
997 // The raw V and I samples are processed in "phase pairs"
998 const auto &lastPolarity{ polarityConfirmedOfLastSampleV[phase] };
999
1001 {
1002 // the polarity of this sample is positive
1003 if (Polarities::POSITIVE != lastPolarity)
1004 {
1005 // This is the start of a new +ve half cycle, for this phase, just after the zero-crossing point.
1007 {
1008 processPlusHalfCycle(phase);
1009 }
1010 else
1011 {
1012 processStartUp(phase);
1013 }
1014 }
1015
1016 // still processing samples where the voltage is POSITIVE ...
1017 // check to see whether the trigger device can now be reliably armed
1018 if ((0 == phase) && beyondStartUpPeriod && (2 == n_samplesDuringThisMainsCycle[0])) // lower value for larger sample set
1019 {
1020 // This code is executed once per 20mS, shortly after the start of each new mains cycle on phase 0.
1022 }
1023 }
1024 else
1025 {
1026 // the polarity of this sample is negative
1027 if (Polarities::NEGATIVE != lastPolarity)
1028 {
1029 // This is the start of a new -ve half cycle (just after the zero-crossing point)
1030 processMinusHalfCycle(phase);
1031 }
1032 }
1033}
1034
1052void processVoltageRawSample(const uint8_t phase, const int16_t rawSample)
1053{
1054 processPolarity(phase, rawSample);
1055 confirmPolarity(phase);
1056
1057 processRawSamples(phase); // deals with aspects that only occur at particular stages of each mains cycle
1058
1059 processVoltage(phase);
1060
1061 if (phase == 0)
1062 {
1064 }
1065}
1066
1081{
1082 // display relevant settings for selected output mode
1083 DBUG(F("Output mode: "));
1085 {
1086 DBUGLN(F("normal"));
1087 }
1088 else
1089 {
1090 DBUGLN(F("anti-flicker"));
1091 DBUG(F("\toffsetOfEnergyThresholds = "));
1093 }
1094 DBUG(F("\tf_capacityOfEnergyBucket_main = "));
1096 DBUG(F("\tf_lowerEnergyThreshold = "));
1098 DBUG(F("\tf_upperEnergyThreshold = "));
1100}
1101
1132ISR(ADC_vect)
1133{
1134 static uint8_t sample_index{ 0 };
1135 int16_t rawSample;
1136
1137 switch (sample_index)
1138 {
1139 case 0:
1140 rawSample = ADC; // store the ADC value (this one is for Voltage L1)
1141 ADMUX = bit(REFS0) + sensorV[1]; // the conversion for I1 is already under way
1142 ++sample_index; // increment the control flag
1143 //
1144 processVoltageRawSample(0, rawSample);
1145 break;
1146 case 1:
1147 rawSample = ADC; // store the ADC value (this one is for Current L1)
1148 ADMUX = bit(REFS0) + sensorI[1]; // the conversion for V2 is already under way
1149 ++sample_index; // increment the control flag
1150 //
1151 processCurrentRawSample(0, rawSample);
1152 break;
1153 case 2:
1154 rawSample = ADC; // store the ADC value (this one is for Voltage L2)
1155 ADMUX = bit(REFS0) + sensorV[2]; // the conversion for I2 is already under way
1156 ++sample_index; // increment the control flag
1157 //
1158 processVoltageRawSample(1, rawSample);
1159 break;
1160 case 3:
1161 rawSample = ADC; // store the ADC value (this one is for Current L2)
1162 ADMUX = bit(REFS0) + sensorI[2]; // the conversion for V3 is already under way
1163 ++sample_index; // increment the control flag
1164 //
1165 processCurrentRawSample(1, rawSample);
1166 break;
1167 case 4:
1168 rawSample = ADC; // store the ADC value (this one is for Voltage L3)
1169 ADMUX = bit(REFS0) + sensorV[0]; // the conversion for I3 is already under way
1170 ++sample_index; // increment the control flag
1171 //
1172 processVoltageRawSample(2, rawSample);
1173 break;
1174 case 5:
1175 rawSample = ADC; // store the ADC value (this one is for Current L3)
1176 ADMUX = bit(REFS0) + sensorI[0]; // the conversion for V1 is already under way
1177 sample_index = 0; // reset the control flag
1178 //
1179 processCurrentRawSample(2, rawSample);
1180 break;
1181 default:
1182 sample_index = 0; // to prevent lockup (should never get here)
1183 }
1184} // end of ISR
Calibration values definition.
constexpr float alpha
Definition calibration.h:54
constexpr float lpf_gain
Definition calibration.h:53
constexpr float f_powerCal[NO_OF_PHASES]
Definition calibration.h:34
Standard three-phase PVRouter setup with 2 dump loads.
constexpr uint8_t loadPrioritiesAtStartup[NO_OF_DUMPLOADS]
Definition config.h:93
constexpr bool RELAY_DIVERSION
Definition config.h:51
constexpr bool OVERRIDE_PIN_PRESENT
Definition config.h:48
constexpr uint8_t dualTariffPin
Definition config.h:96
constexpr RelayEngine relays
Definition config.h:126
constexpr uint8_t physicalLoadPin[NO_OF_DUMPLOADS]
Definition config.h:92
constexpr bool DUAL_TARIFF
Definition config.h:52
constexpr uint8_t diversionPin
Definition config.h:97
constexpr OverridePins overridePins
Definition config.h:143
constexpr uint8_t NO_OF_DUMPLOADS
Definition config.h:42
constexpr bool WATCHDOG_PIN_PRESENT
Definition config.h:50
constexpr bool DIVERSION_PIN_PRESENT
Definition config.h:46
constexpr uint8_t rotationPin
Definition config.h:98
constexpr uint8_t watchDogPin
Definition config.h:99
constexpr int16_t REQUIRED_EXPORT_IN_WATTS
constexpr uint32_t WORKING_ZONE_IN_JOULES
constexpr conditional< DATALOG_PERIOD_IN_SECONDS *SUPPLY_FREQUENCY >=UINT8_MAX, uint16_t, uint8_t >::type DATALOG_PERIOD_IN_MAINS_CYCLES
constexpr uint8_t DATALOG_PERIOD_IN_SECONDS
constexpr uint8_t NO_OF_PHASES
constexpr uint8_t SUPPLY_FREQUENCY
constexpr int16_t DIVERSION_START_THRESHOLD_WATTS
#define DBUGLN(...)
Definition debug.h:97
#define DBUG(...)
Definition debug.h:96
Classes/types needed for dual-tariff support.
uint8_t i
constexpr uint16_t getInputPins()
Retrieves the input pins configuration.
constexpr void initializeArray(int32_t(&array)[N], int32_t value)
Initializes all elements of a given array to a specified value.
constexpr uint16_t getOutputPins()
Retrieves the output pins configuration.
void initializeProcessing()
Initializes the processing engine, including ports, load states, and ADC setup.
ISR(ADC_vect)
Interrupt Service Routine - Interrupt-Driven Analog Conversion.
void updatePhysicalLoadStates()
Updates the physical load states based on logical load priorities and states.
void processLatestContribution(const uint8_t phase)
Process the latest contribution after each phase-specific new cycle.
void updatePortsStates()
Updates the control ports for each of the physical loads.
void processStartUp(const uint8_t phase)
Processes the startup period for the router.
void processStartNewCycle()
Processes the start of a new mains cycle on phase 0.
void processMinusHalfCycle(const uint8_t phase)
Processes the start of a new negative half cycle for the specified phase.
void processVoltageRawSample(const uint8_t phase, const int16_t rawSample)
Processes the current voltage raw sample for the specified phase.
void proceedLowEnergyLevel()
Handles the case when the energy level is low, potentially removing a load.
void processPolarity(const uint8_t phase, const int16_t rawSample)
Processes the polarity of the current voltage sample for a specific phase.
void processRawSamples(const uint8_t phase)
Processes raw voltage and current samples for the specified phase.
uint8_t nextLogicalLoadToBeAdded()
Retrieve the next logical load that could be added.
void processPlusHalfCycle(const uint8_t phase)
Process the start of a new positive half cycle for the specified phase.
void processDataLogging()
Process data logging at the end of each logging period.
uint8_t nextLogicalLoadToBeRemoved()
Retrieve the next logical load that could be removed (in reverse order).
void confirmPolarity(const uint8_t phase)
Confirms the polarity of the current voltage sample for a specific phase.
void processVoltage(const uint8_t phase)
Processes the current voltage sample for the specified phase.
void proceedHighEnergyLevel()
Handles the case when the energy level is high, potentially adding a load.
void processCurrentRawSample(const uint8_t phase, const int16_t rawSample)
Processes the current raw sample for the specified phase.
volatile int32_t copyOf_sum_Vsquared[NO_OF_PHASES]
Definition shared_var.h:22
volatile uint16_t overrideBitmask
Definition shared_var.h:14
volatile float copyOf_energyInBucket_main
Definition shared_var.h:23
volatile bool b_datalogEventPending
Definition shared_var.h:10
volatile bool b_reOrderLoads
Definition shared_var.h:12
volatile uint16_t copyOf_sampleSetsDuringThisDatalogPeriod
Definition shared_var.h:25
volatile int32_t copyOf_sumP_atSupplyPoint[NO_OF_PHASES]
Definition shared_var.h:21
volatile uint8_t copyOf_lowestNoOfSampleSetsPerMainsCycle
Definition shared_var.h:24
volatile uint16_t copyOf_countLoadON[NO_OF_DUMPLOADS]
Definition shared_var.h:26
volatile uint16_t absenceOfDivertedEnergyCountInSeconds
Definition shared_var.h:16
volatile bool b_newMainsCycle
Definition shared_var.h:11
volatile bool b_diversionEnabled
Definition shared_var.h:13
Polarities polarityConfirmedOfLastSampleV[NO_OF_PHASES]
uint8_t n_lowestNoOfSampleSetsPerMainsCycle
float f_energyInBucket_main
constexpr OutputModes outputMode
constexpr int16_t i_DCoffset_I_nom
uint32_t absenceOfDivertedEnergyCountInMC
constexpr int32_t l_DCoffset_V_min
constexpr int32_t l_DCoffset_V_max
float f_upperEnergyThreshold
uint16_t countLoadON[NO_OF_DUMPLOADS]
constexpr float f_offsetOfEnergyThresholdsInAFmode
bool b_diversionStarted
remove_cv< remove_reference< decltype(DATALOG_PERIOD_IN_MAINS_CYCLES)>::type >::type n_cycleCountForDatalogging
constexpr uint8_t POST_TRANSITION_MAX_COUNT
constexpr auto initThreshold(const bool lower)
set default threshold at compile time so the variable can be read-only
constexpr float f_capacityOfEnergyBucket_main
LoadStates physicalLoadState[NO_OF_DUMPLOADS]
int32_t l_sum_Vsquared[NO_OF_PHASES]
int32_t l_sumP[NO_OF_PHASES]
Polarities polarityConfirmed[NO_OF_PHASES]
bool b_recentTransition
uint8_t n_samplesDuringThisMainsCycle[NO_OF_PHASES]
constexpr float f_lowerThreshold_default
void printParamsForSelectedOutputMode()
Print the settings used for the selected output mode.
constexpr float f_midPointOfEnergyBucket_main
bool beyondStartUpPeriod
int32_t l_cumVdeltasThisCycle[NO_OF_PHASES]
int32_t l_sampleVminusDC[NO_OF_PHASES]
Polarities polarityOfMostRecentSampleV[NO_OF_PHASES]
uint16_t i_sampleSetsDuringThisDatalogPeriod
constexpr float f_upperThreshold_default
float f_lowerEnergyThreshold
int32_t l_DCoffset_V[NO_OF_PHASES]
int32_t l_sumP_atSupplyPoint[NO_OF_PHASES]
uint8_t activeLoad
uint8_t perSecondCounter
uint8_t postTransitionCount
Public functions/variables of processing engine.
constexpr uint16_t startUpPeriod
Definition processing.h:27
constexpr uint8_t PERSISTENCE_FOR_POLARITY_CHANGE
Definition processing.h:24
uint8_t loadPrioritiesAndState[NO_OF_DUMPLOADS]
Definition processing.h:22
constexpr uint8_t sensorV[NO_OF_PHASES]
Definition processing.h:18
constexpr uint8_t sensorI[NO_OF_PHASES]
Definition processing.h:19
constexpr uint16_t initialDelay
Definition processing.h:26
Polarities
Definition types.h:35
@ NEGATIVE
Definition types.h:36
@ POSITIVE
Definition types.h:37
constexpr uint8_t loadStateMask
Definition types.h:55
constexpr uint8_t loadStateOnBit
Definition types.h:56
LoadStates
Definition types.h:49
@ LOAD_OFF
Definition types.h:50
@ LOAD_ON
Definition types.h:51
OutputModes
Definition types.h:42
@ ANTI_FLICKER
Definition types.h:43
Some utility functions for pins manipulation.
constexpr void bit_set(T &_dest, const uint8_t bit)
Set the specified bit to 1.
Definition utils_pins.h:54
void setPinsOFF(uint16_t pins)
Set the Pins state to OFF.
Definition utils_pins.h:181
constexpr uint8_t bit_read(const T &_src, const uint8_t bit)
Read the specified bit.
Definition utils_pins.h:67
void setPinsAsInputPullup(uint16_t pins)
Set the pins as INPUT_PULLUP.
Definition utils_pins.h:226
void setPinsAsOutput(uint16_t pins)
Set the pins as OUTPUT.
Definition utils_pins.h:215
void setPinsON(uint16_t pins)
Set the Pins state to ON.
Definition utils_pins.h:149
constexpr uint8_t bit_clear(T &_dest, const uint8_t bit)
Clear the specified bit.
Definition utils_pins.h:80