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 "calibration.h"
15#include "dualtariff.h"
16#include "processing.h"
17#include "utils_pins.h"
18#include "shared_var.h"
19
20// Define operating limits for the LP filters which identify DC offset in the voltage
21// sample streams. By limiting the output range, these filters always should start up
22// correctly.
23constexpr int32_t l_DCoffset_V_min{ (512L - 100L) * 256L };
24constexpr int32_t l_DCoffset_V_max{ (512L + 100L) * 256L };
25constexpr int16_t i_DCoffset_I_nom{ 512L };
26
28
34constexpr float f_offsetOfEnergyThresholdsInAFmode{ 0.1F };
35
37
38bool b_diversionStarted{ false };
39
52
53constexpr float f_lowerThreshold_default{ initThreshold(true) };
54constexpr float f_upperThreshold_default{ initThreshold(false) };
55
56float f_energyInBucket_main{ 0.0F };
59
60// for improved control of multiple loads
61bool b_recentTransition{ false };
62uint8_t postTransitionCount{ 0 };
63constexpr uint8_t POST_TRANSITION_MAX_COUNT{ 3 };
64// constexpr uint8_t POST_TRANSITION_MAX_COUNT{50}; /**< for testing only */
66
67int32_t l_sumP[NO_OF_PHASES]{};
72
75
77
79
80// For an enhanced polarity detection mechanism, which includes a persistence check
84
87
89
90uint8_t perSecondCounter{ 0 };
91
92bool beyondStartUpPeriod{ false };
93
110template< size_t N >
111constexpr void initializeArray(int32_t (&array)[N], int32_t value)
112{
113 for (size_t i = 0; i < N; ++i)
114 {
115 array[i] = value;
116 }
117}
118
133constexpr uint16_t getOutputPins()
134{
135 uint16_t output_pins{ 0 };
136
137 for (const auto &loadPin : physicalLoadPin)
138 {
139 if (bit_read(output_pins, loadPin))
140 return 0;
141
142 bit_set(output_pins, loadPin);
143 }
144
145 if constexpr (WATCHDOG_PIN_PRESENT)
146 {
147 if (bit_read(output_pins, watchDogPin))
148 return 0;
149
150 bit_set(output_pins, watchDogPin);
151 }
152
153 if constexpr (RELAY_DIVERSION)
154 {
155 for (uint8_t idx = 0; idx < relays.get_size(); ++idx)
156 {
157 const auto relayPin = relays.get_relay(idx).get_pin();
158
159 if (bit_read(output_pins, relayPin))
160 return 0;
161
162 bit_set(output_pins, relayPin);
163 }
164 }
165
166 return output_pins;
167}
168
184constexpr uint16_t getInputPins()
185{
186 uint16_t input_pins{ 0 };
187
188 if constexpr (DUAL_TARIFF)
189 {
190 if (bit_read(input_pins, dualTariffPin))
191 return 0;
192
193 bit_set(input_pins, dualTariffPin);
194 }
195
196 if constexpr (DIVERSION_PIN_PRESENT)
197 {
198 if (bit_read(input_pins, diversionPin))
199 return 0;
200
201 bit_set(input_pins, diversionPin);
202 }
203
204 if constexpr (PRIORITY_ROTATION == RotationModes::PIN)
205 {
206 if (bit_read(input_pins, rotationPin))
207 return 0;
208
209 bit_set(input_pins, rotationPin);
210 }
211
212 if constexpr (OVERRIDE_PIN_PRESENT)
213 {
214 if (bit_read(input_pins, forcePin))
215 return 0;
216
217 bit_set(input_pins, forcePin);
218 }
219
220 return input_pins;
221}
222
237{
238 initializeArray(l_DCoffset_V, 512L * 256L); // nominal mid-point value of ADC @ x256 scale
239
240 setPinsAsOutput(getOutputPins()); // set the output pins as OUTPUT
241 setPinsAsInputPullup(getInputPins()); // set the input pins as INPUT_PULLUP
242
243 for (uint8_t i = 0; i < NO_OF_DUMPLOADS; ++i)
244 {
247 }
248
249 // First stop the ADC
250 bit_clear(ADCSRA, ADEN);
251
252 // Activate free-running mode
253 ADCSRB = 0x00;
254
255 // Set up the ADC to be free-running
256 bit_set(ADCSRA, ADPS0); // Set the ADC's clock to system clock / 128
257 bit_set(ADCSRA, ADPS1);
258 bit_set(ADCSRA, ADPS2);
259
260 bit_set(ADCSRA, ADATE); // set the Auto Trigger Enable bit in the ADCSRA register. Because
261 // bits ADTS0-2 have not been set (i.e. they are all zero), the
262 // ADC's trigger source is set to "free running mode".
263
264 bit_set(ADCSRA, ADIE); // set the ADC interrupt enable bit. When this bit is written
265 // to one and the I-bit in SREG is set, the
266 // ADC Conversion Complete Interrupt is activated.
267
268 bit_set(ADCSRA, ADEN); // Enable the ADC
269
270 bit_set(ADCSRA, ADSC); // start ADC manually first time
271
272 sei(); // Enable Global Interrupts
273}
274
290{
291 uint16_t pinsON{ 0 };
292 uint16_t pinsOFF{ 0 };
293
294 uint8_t i{ NO_OF_DUMPLOADS };
295
296 do
297 {
298 --i;
299 // update the local load's state.
301 {
302 // setPinOFF(physicalLoadPin[i]);
303 pinsOFF |= bit(physicalLoadPin[i]);
304 }
305 else
306 {
307 ++countLoadON[i];
308 // setPinON(physicalLoadPin[i]);
309 pinsON |= bit(physicalLoadPin[i]);
310 }
311 } while (i);
312
313 setPinsOFF(pinsOFF);
314 setPinsON(pinsON);
315}
316
342{
343 if constexpr (PRIORITY_ROTATION != RotationModes::OFF)
344 {
346 {
347 uint8_t i{ NO_OF_DUMPLOADS - 1 };
348 const auto temp{ loadPrioritiesAndState[i] };
349 do
350 {
352 --i;
353 } while (i);
354 loadPrioritiesAndState[0] = temp;
355
357 }
358 }
359
360 const bool bDiversionEnabled{ Shared::b_diversionEnabled };
361 uint8_t idx{ NO_OF_DUMPLOADS };
362 do
363 {
364 --idx;
365 const auto iLoad{ loadPrioritiesAndState[idx] & loadStateMask };
367 } while (idx);
368}
369
387void processPolarity(const uint8_t phase, const int16_t rawSample)
388{
389 // remove DC offset from each raw voltage sample by subtracting the accurate value
390 // as determined by its associated LP filter.
391 l_sampleVminusDC[phase] = (static_cast< int32_t >(rawSample) << 8) - l_DCoffset_V[phase];
393}
394
412void processCurrentRawSample(const uint8_t phase, const int16_t rawSample)
413{
414 // extra items for an LPF to improve the processing of data samples from CT1
415 static int32_t lpf_long[NO_OF_PHASES]{}; // new LPF, for offsetting the behaviour of CTx as a HPF
416
417 // remove most of the DC offset from the current sample (the precise value does not matter)
418 int32_t sampleIminusDC = (static_cast< int32_t >(rawSample - i_DCoffset_I_nom)) << 8;
419
420 // extra filtering to offset the HPF effect of CTx
421 const int32_t last_lpf_long{ lpf_long[phase] };
422 lpf_long[phase] += alpha * (sampleIminusDC - last_lpf_long);
423 sampleIminusDC += (lpf_gain * lpf_long[phase]);
424
425 // calculate the "real power" in this sample pair and add to the accumulated sum
426 const int32_t filtV_div4 = l_sampleVminusDC[phase] >> 2; // reduce to 16-bits (now x64, or 2^6)
427 const int32_t filtI_div4 = sampleIminusDC >> 2; // reduce to 16-bits (now x64, or 2^6)
428 int32_t instP = filtV_div4 * filtI_div4; // 32-bits (now x4096, or 2^12)
429 instP >>= 12; // scaling is now x1, as for Mk2 (V_ADC x I_ADC)
430
431 l_sumP[phase] += instP; // cumulative power, scaling as for Mk2 (V_ADC x I_ADC)
432 l_sumP_atSupplyPoint[phase] += instP; // cumulative power, scaling as for Mk2 (V_ADC x I_ADC)
433}
434
451void confirmPolarity(const uint8_t phase)
452{
453 static uint8_t count[NO_OF_PHASES]{};
454
456 {
457 count[phase] = 0;
458 return;
459 }
460
461 if (++count[phase] > PERSISTENCE_FOR_POLARITY_CHANGE)
462 {
463 count[phase] = 0;
465 }
466}
467
485void processVoltage(const uint8_t phase)
486{
487 // for the Vrms calculation (for datalogging only)
488 const int32_t filtV_div4{ l_sampleVminusDC[phase] >> 2 }; // reduce to 16-bits (now x64, or 2^6)
489 int32_t inst_Vsquared{ filtV_div4 * filtV_div4 }; // 32-bits (now x4096, or 2^12)
490
491 if constexpr (DATALOG_PERIOD_IN_SECONDS > 10)
492 {
493 inst_Vsquared >>= 16; // scaling is now x1/16 (V_ADC x I_ADC)
494 }
495 else
496 {
497 inst_Vsquared >>= 12; // scaling is now x1 (V_ADC x I_ADC)
498 }
499
500 l_sum_Vsquared[phase] += inst_Vsquared; // cumulative V^2 (V_ADC x I_ADC)
501 //
502 // store items for use during next loop
503 l_cumVdeltasThisCycle[phase] += l_sampleVminusDC[phase]; // for use with LP filter
504 polarityConfirmedOfLastSampleV[phase] = polarityConfirmed[phase]; // for identification of half cycle boundaries
505 ++n_samplesDuringThisMainsCycle[phase]; // for real power calculations
506}
507
524void processStartUp(const uint8_t phase)
525{
526 // wait until the DC-blocking filters have had time to settle
527 if (millis() <= (initialDelay + startUpPeriod))
528 {
529 return; // still settling, do nothing
530 }
531
532 // the DC-blocking filters have had time to settle
533 beyondStartUpPeriod = true;
534 l_sumP[phase] = 0;
535 l_sumP_atSupplyPoint[phase] = 0;
538
540 // can't say "Go!" here 'cos we're in an ISR!
541}
542
557{
558 bool bOK_toAddLoad{ true };
559 const auto tempLoad{ nextLogicalLoadToBeAdded() };
560
561 if (tempLoad == NO_OF_DUMPLOADS)
562 {
563 return;
564 }
565
566 // a load which is now OFF has been identified for potentially being switched ON
568 {
569 // During the post-transition period, any increase in the energy level is noted.
571
572 // the energy thresholds must remain within range
574 {
576 }
577
578 // Only the active load may be switched during this period. All other loads must
579 // wait until the recent transition has had sufficient opportunity to take effect.
580 bOK_toAddLoad = (tempLoad == activeLoad);
581 }
582
583 if (bOK_toAddLoad)
584 {
586 activeLoad = tempLoad;
588 b_recentTransition = true;
589 }
590}
591
606{
607 bool bOK_toRemoveLoad{ true };
608 const auto tempLoad{ nextLogicalLoadToBeRemoved() };
609
610 if (tempLoad == NO_OF_DUMPLOADS)
611 {
612 return;
613 }
614
615 // a load which is now ON has been identified for potentially being switched OFF
617 {
618 // During the post-transition period, any decrease in the energy level is noted.
620
621 // the energy thresholds must remain within range
623 {
625 }
626
627 // Only the active load may be switched during this period. All other loads must
628 // wait until the recent transition has had sufficient opportunity to take effect.
629 bOK_toRemoveLoad = (tempLoad == activeLoad);
630 }
631
632 if (bOK_toRemoveLoad)
633 {
635 activeLoad = tempLoad;
637 b_recentTransition = true;
638 }
639}
640
657{
658 // Restrictions apply for the period immediately after a load has been switched.
659 // Here the b_recentTransition flag is checked and updated as necessary.
660 // if (b_recentTransition)
661 // b_recentTransition = (++postTransitionCount < POST_TRANSITION_MAX_COUNT);
662 // for optimization, the next line is equivalent to the two lines above
664
666 {
667 // the energy state is in the upper half of the working range
668 f_lowerEnergyThreshold = f_lowerThreshold_default; // reset the "opposite" threshold
670 {
671 // Because the energy level is high, some action may be required
673 }
674 }
675 else
676 {
677 // the energy state is in the lower half of the working range
678 f_upperEnergyThreshold = f_upperThreshold_default; // reset the "opposite" threshold
680 {
681 // Because the energy level is low, some action may be required
683 }
684 }
685
686 updatePhysicalLoadStates(); // allows the logical-to-physical mapping to be changed
687
688 updatePortsStates(); // update the control ports for each of the physical loads
689
691 {
693 }
694 else
695 {
697 }
698
699 // Now that the energy-related decisions have been taken, min and max limits can now
700 // be applied to the level of the energy bucket. This is to ensure correct operation
701 // when conditions change, i.e. when import changes to export, and vice versa.
702 //
704 {
706 }
707 else if (f_energyInBucket_main < 0)
708 {
710 }
711}
712
728void processMinusHalfCycle(const uint8_t phase)
729{
730 // This is a convenient point to update the Low Pass Filter for removing the DC
731 // component from the phase that is being processed.
732 // The portion which is fed back into the integrator is approximately one percent
733 // of the average offset of all the SampleVs in the previous mains cycle.
734 //
735 l_DCoffset_V[phase] += (l_cumVdeltasThisCycle[phase] >> 12);
736 l_cumVdeltasThisCycle[phase] = 0;
737
738 // To ensure that this LP filter will always start up correctly when 240V AC is
739 // available, its output value needs to be prevented from drifting beyond the likely range
740 // of the voltage signal.
741 //
742 if (l_DCoffset_V[phase] < l_DCoffset_V_min)
743 {
745 }
746 else if (l_DCoffset_V[phase] > l_DCoffset_V_max)
747 {
749 }
750}
751
765{
766 for (uint8_t index = 0; index < NO_OF_DUMPLOADS; ++index)
767 {
768 if (0x00 == (loadPrioritiesAndState[index] & loadStateOnBit))
769 {
770 return (index);
771 }
772 }
773
774 return (NO_OF_DUMPLOADS);
775}
776
790{
791 uint8_t index{ NO_OF_DUMPLOADS };
792 do
793 {
795 {
796 return (index);
797 }
798 } while (index);
799
800 return (NO_OF_DUMPLOADS);
801}
802
819void processLatestContribution(const uint8_t phase)
820{
821 // for efficiency, the energy scale is Joules * SUPPLY_FREQUENCY
822 // add the latest energy contribution to the main energy accumulator
824
825 // apply any adjustment that is required.
826 if (0 == phase)
827 {
828 // If diversion hasn't started yet, use start threshold, otherwise use regular offset
830 {
832
833 // Check if we've exceeded the threshold to start diversion
835 {
836 b_diversionStarted = true;
837 // Once started, we divert all surplus according to the configured fixed offset
838 }
839 }
840 else
841 {
842 // When diversion is already started, apply normal export offset if configured
843 // Comment or remove this if you want to divert ALL surplus once started
845 }
846
848 {
850
852 {
854 // Reset diversion state if we've had no diversion for a full second
855 b_diversionStarted = false;
856 }
857 else
859 }
860
861 Shared::b_newMainsCycle = true; // a 50 Hz 'tick' for use by the main code
862 }
863 // Applying max and min limits to the main accumulator's level
864 // is deferred until after the energy related decisions have been taken
865 //
866}
867
883{
885 {
886 return; // data logging period not yet reached
887 }
888
890
891 uint8_t phase{ NO_OF_PHASES };
892 do
893 {
894 --phase;
896 l_sumP_atSupplyPoint[phase] = 0;
897
899 l_sum_Vsquared[phase] = 0;
900 } while (phase);
901
902 uint8_t i{ NO_OF_DUMPLOADS };
903 do
904 {
905 --i;
907 countLoadON[i] = 0;
908 } while (i);
909
913
916
917 // signal the main processor that logging data are available
918 // we skip the period from start to running stable
920}
921
939void processPlusHalfCycle(const uint8_t phase)
940{
941 processLatestContribution(phase); // runs at 6.6 ms intervals
942
943 // A performance check to monitor and display the minimum number of sets of
944 // ADC samples per mains cycle, the expected number being 20ms / (104us * 6) = 32.05
945 //
946 if (0 == phase)
947 {
949 {
951 }
952
954 }
955
956 l_sumP[phase] = 0;
958}
959
977void processRawSamples(const uint8_t phase)
978{
979 // The raw V and I samples are processed in "phase pairs"
980 const auto &lastPolarity{ polarityConfirmedOfLastSampleV[phase] };
981
983 {
984 // the polarity of this sample is positive
985 if (Polarities::POSITIVE != lastPolarity)
986 {
987 // This is the start of a new +ve half cycle, for this phase, just after the zero-crossing point.
989 {
991 }
992 else
993 {
994 processStartUp(phase);
995 }
996 }
997
998 // still processing samples where the voltage is POSITIVE ...
999 // check to see whether the trigger device can now be reliably armed
1000 if ((0 == phase) && beyondStartUpPeriod && (2 == n_samplesDuringThisMainsCycle[0])) // lower value for larger sample set
1001 {
1002 // This code is executed once per 20mS, shortly after the start of each new mains cycle on phase 0.
1004 }
1005 }
1006 else
1007 {
1008 // the polarity of this sample is negative
1009 if (Polarities::NEGATIVE != lastPolarity)
1010 {
1011 // This is the start of a new -ve half cycle (just after the zero-crossing point)
1012 processMinusHalfCycle(phase);
1013 }
1014 }
1015}
1016
1034void processVoltageRawSample(const uint8_t phase, const int16_t rawSample)
1035{
1036 processPolarity(phase, rawSample);
1037 confirmPolarity(phase);
1038
1039 processRawSamples(phase); // deals with aspects that only occur at particular stages of each mains cycle
1040
1041 processVoltage(phase);
1042
1043 if (phase == 0)
1044 {
1046 }
1047}
1048
1063{
1064 // display relevant settings for selected output mode
1065 DBUG(F("Output mode: "));
1067 {
1068 DBUGLN(F("normal"));
1069 }
1070 else
1071 {
1072 DBUGLN(F("anti-flicker"));
1073 DBUG(F("\toffsetOfEnergyThresholds = "));
1075 }
1076 DBUG(F("\tf_capacityOfEnergyBucket_main = "));
1078 DBUG(F("\tf_lowerEnergyThreshold = "));
1080 DBUG(F("\tf_upperEnergyThreshold = "));
1082}
1083
1114ISR(ADC_vect)
1115{
1116 static uint8_t sample_index{ 0 };
1117 int16_t rawSample;
1118
1119 switch (sample_index)
1120 {
1121 case 0:
1122 rawSample = ADC; // store the ADC value (this one is for Voltage L1)
1123 ADMUX = bit(REFS0) + sensorV[1]; // the conversion for I1 is already under way
1124 ++sample_index; // increment the control flag
1125 //
1126 processVoltageRawSample(0, rawSample);
1127 break;
1128 case 1:
1129 rawSample = ADC; // store the ADC value (this one is for Current L1)
1130 ADMUX = bit(REFS0) + sensorI[1]; // the conversion for V2 is already under way
1131 ++sample_index; // increment the control flag
1132 //
1133 processCurrentRawSample(0, rawSample);
1134 break;
1135 case 2:
1136 rawSample = ADC; // store the ADC value (this one is for Voltage L2)
1137 ADMUX = bit(REFS0) + sensorV[2]; // the conversion for I2 is already under way
1138 ++sample_index; // increment the control flag
1139 //
1140 processVoltageRawSample(1, rawSample);
1141 break;
1142 case 3:
1143 rawSample = ADC; // store the ADC value (this one is for Current L2)
1144 ADMUX = bit(REFS0) + sensorI[2]; // the conversion for V3 is already under way
1145 ++sample_index; // increment the control flag
1146 //
1147 processCurrentRawSample(1, rawSample);
1148 break;
1149 case 4:
1150 rawSample = ADC; // store the ADC value (this one is for Voltage L3)
1151 ADMUX = bit(REFS0) + sensorV[0]; // the conversion for I3 is already under way
1152 ++sample_index; // increment the control flag
1153 //
1154 processVoltageRawSample(2, rawSample);
1155 break;
1156 case 5:
1157 rawSample = ADC; // store the ADC value (this one is for Current L3)
1158 ADMUX = bit(REFS0) + sensorI[0]; // the conversion for V1 is already under way
1159 sample_index = 0; // reset the control flag
1160 //
1161 processCurrentRawSample(2, rawSample);
1162 break;
1163 default:
1164 sample_index = 0; // to prevent lockup (should never get here)
1165 }
1166} // 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
constexpr uint8_t loadPrioritiesAtStartup[NO_OF_DUMPLOADS]
Definition config.h:82
constexpr bool RELAY_DIVERSION
Definition config.h:40
constexpr bool OVERRIDE_PIN_PRESENT
Definition config.h:37
constexpr uint8_t dualTariffPin
Definition config.h:85
constexpr uint8_t forcePin
Definition config.h:88
constexpr RelayEngine relays
Definition config.h:91
constexpr uint8_t physicalLoadPin[NO_OF_DUMPLOADS]
Definition config.h:81
constexpr bool DUAL_TARIFF
Definition config.h:41
constexpr uint8_t diversionPin
Definition config.h:86
constexpr uint8_t NO_OF_DUMPLOADS
Definition config.h:32
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 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 float copyOf_energyInBucket_main
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: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:14
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