@@ -96,23 +96,72 @@ extern uint8_t WIFImode;
9696String SmartEVSEHost = " " ;
9797
9898unsigned long ModbusTimer=0 ;
99- unsigned char dataready=0 , CTcount, DSMRver, IrmsMode = 0 ;
99+ unsigned char dataready=0 , datareadyAPI= 0 , CTcount, DSMRver, IrmsMode = 0 ;
100100unsigned char LedCnt, LedState, LedSeq[4 ] = {0 ,0 ,0 ,0 };
101101float Irms[3 ], Volts[3 ], IrmsCT[3 ]; // float is 32 bits; current in A
102102int16_t MainsMeterIrms[3 ]; // current in dA (10 * A) !!!
103- uint8_t datamemory = 0 ;
103+ bool lockedToP1 = false ;
104104unsigned char led = 0 , Wire = WIRES4 + CW;
105105uint16_t blinkram = 0 , P1taskram = 0 ;
106106extern bool LocalTimeSet;
107107int phasesLastUpdate = 0 ;
108108
109109
110+ void SetLedSequence (uint8_t source) {
111+ uint8_t n = 1 ;
112+
113+ // Set Led sequence for the next 2 seconds
114+ // reset to first part of sequence
115+ LedCnt = 0 ;
116+ LedState = 8 ;
117+
118+ // When we have received a valid measurement from the SmartMeter, the led will blink only once.
119+ if (source & 0xC0 ) {
120+ // DSMR version not 5.x! Blink RED
121+ if (DSMRver < 50 ) LedSeq[0 ] = LED_RED;
122+ // DSMR version OK, Blink GREEN
123+ else LedSeq[0 ] = LED_GREEN;
124+
125+ // No SmartMeter connected, we use the CT's
126+ // CT measurement available?
127+ } else if (source & 0x03 ) {
128+ // CT measurements with current direction?
129+ if (IrmsMode == 0 ) {
130+ if (IrmsCT[0 ] < -0.1 ) LedSeq[0 ]=LED_GREEN; else LedSeq[0 ]=LED_ORANGE;
131+ if (IrmsCT[1 ] < -0.1 ) LedSeq[1 ]=LED_GREEN; else LedSeq[1 ]=LED_ORANGE;
132+ if (IrmsCT[2 ] < -0.1 ) LedSeq[2 ]=LED_GREEN; else LedSeq[2 ]=LED_ORANGE;
133+ // 6 States, ON/OFF (3 CT's)
134+ n = 3 ;
135+ } else {
136+ // Blink 1x Orange when not using MAINS input
137+ LedSeq[0 ] = LED_ORANGE;
138+ }
139+ // LED_RED_ON (PIC chip not programmed?)
140+ } else {
141+ LedSeq[0 ] = LED_RED;
142+ }
143+
144+ // Show WiFi mode as last blink in sequence
145+ if (WIFImode == 2 ) LedSeq[n] = LED_RED;
146+ else if (WIFImode == 1 ) LedSeq[n] = LED_GREEN;
147+ }
148+
110149
111150// Every ~2 seconds send measurement data to APIs
112151void Timer2S (void * parameter) {
113152 while (true ) {
114153 if (WiFi.status () == WL_CONNECTED) {
115- if ((datamemory & 0x80 ) || (datamemory & 0x03 )) { // we have data
154+
155+ // We have valid data. Does not allow switching from P1 back to CT data !
156+ // A broken P1 connection now creates a comm error instead of (invalid) CT measurements being used.
157+ if ( (lockedToP1 == true && datareadyAPI & 0x80 ) || (lockedToP1 == false && datareadyAPI & 0x03 ) ) {
158+
159+ for (uint8_t x = 0 ; x < 3 ; x++) {
160+ // P1 data has precedence over CT data, although CT data might be newer.
161+ if (datareadyAPI & 0x80 ) MainsMeterIrms[x] = round (Irms[x] * 10 );
162+ else MainsMeterIrms[x] = round (IrmsCT[x] * 10 );
163+ }
164+
116165 #if MQTT
117166 // publishing to the broker
118167 MQTTclient.publish (MQTTprefix + " /MainsCurrentL1" , MainsMeterIrms[0 ], false , 0 );
@@ -145,10 +194,11 @@ void Timer2S(void * parameter) {
145194 FREE (currents);
146195 #endif
147196 }
197+ SetLedSequence (datareadyAPI);
148198 }
149199 }
150200
151- datamemory = 0 ;
201+ datareadyAPI = 0 ;
152202 }
153203 vTaskDelay (2000 / portTICK_PERIOD_MS);
154204 }
@@ -193,27 +243,6 @@ void read_settings(bool write) {
193243}
194244
195245
196- // Poly used is x^16+x^15+x^2+x
197- unsigned int CRC16 (unsigned int crc, unsigned char *buf, int len)
198- {
199- for (int pos = 0 ; pos < len; pos++)
200- {
201- crc ^= (unsigned int )buf[pos]; // XOR byte into least sig. byte of crc
202-
203- for (int i = 8 ; i != 0 ; i--) { // Loop over each bit
204- if ((crc & 0x0001 ) != 0 ) { // If the LSB is set
205- crc >>= 1 ; // Shift right and XOR 0xA001
206- crc ^= 0xA001 ;
207- }
208- else // Else LSB is not set
209- crc >>= 1 ; // Just shift right
210- }
211- }
212- return crc;
213- }
214-
215-
216-
217246// ----------------------------------------------------------------------------------------------------------------
218247// CT data is measured by the PIC, is send on a serial line to Serial0 of the ESP32
219248// The final calculations and phase angle corrections are done by the ESP32.
@@ -309,9 +338,6 @@ void CTReceive() {
309338 IrmsMode = 0 ;
310339 }
311340
312- for (int x = 0 ; x < 3 ; x++) {
313- MainsMeterIrms[x] = round (IrmsCT[x] * 10 );
314- }
315341 phasesLastUpdate = time (NULL );
316342
317343 // very small values will be displayed as 0.0A
@@ -332,6 +358,7 @@ void CTReceive() {
332358
333359 // update dataready, so the Master knows the CT's have been read with new data
334360 dataready |= 0x03 ;
361+ datareadyAPI |= 0x03 ;
335362 _LOG_V (" \r CT1: %2.1f A CT2: %2.1f A CT3: %2.1f A " ,IrmsCT[0 ],IrmsCT[1 ],IrmsCT[2 ] );
336363
337364 } else {
@@ -414,13 +441,13 @@ void P1Extract() {
414441 Irms[1 ] = (L2Power-L2PowerReturn)/Volts[1 ];
415442 Irms[2 ] = (L3Power-L3PowerReturn)/Volts[2 ];
416443
417- for (int x = 0 ; x < 3 ; x++) {
418- MainsMeterIrms[x] = round (Irms[x] * 10 );
419- }
420444 phasesLastUpdate = time (NULL );
421445
422- if (DSMRver >= 50 ) dataready |= 0x80 ; // P1 dataready
423- else dataready |= 0x40 ; // DSMR version not 5.0 !!
446+ if (DSMRver >= 50 ) {
447+ dataready |= 0x80 ; // P1 dataready
448+ datareadyAPI |= 0x80 ;
449+ lockedToP1 = true ;
450+ } else dataready |= 0x40 ; // DSMR version not 5.0 !!
424451
425452 _LOG_V (" L1: %3d V L2: %3d V L3: %3d V " ,(int )(Volts[0 ]),(int )(Volts[1 ]),(int )(Volts[2 ]) );
426453 _LOG_V (" L1: %2.1f A L2: %2.1f A L3: %2.1f A \r\n " ,Irms[0 ],Irms[1 ],Irms[2 ] );
@@ -511,17 +538,14 @@ void P1Task(void * parameter) {
511538 _LOG_A (" \n heap error after CT receive\n " );
512539 }
513540
514- // remember state of dataready, as it will be cleared after sending the data to the modbus Master.
515- if (dataready > datamemory) datamemory = dataready;
516-
517541 if (WiFi.status () != WL_CONNECTED && esp_timer_get_time () / 1000000 > 5 && WIFImode != 2 && esp_timer_get_time () / 1000000 < 180 ) {
518542 // if we have no wifi
519543 // and we are not in the first 5 seconds of startup (to give the existing wifi time to connect and P1 data to be entered)
520544 // and we are not already in wifimode 2
521545 // and we are not later then the first 180s after startup; perhaps we are not interested in having a wifi connection?
522546 // we go to wifimode 2 smartconfig
523547 WIFImode = 2 ;
524- if (datamemory & 0x80 ) {
548+ if (lockedToP1 ) {
525549 handleWIFImode (&Serial); // P1 data comes in so Serial0 is available
526550 blockCT = true ;
527551 } else {
@@ -613,42 +637,8 @@ ModbusMessage MBReadFC04(ModbusMessage request) {
613637 // Prepare start of response
614638 response.add (request.getServerID (), request.getFunctionCode (), (uint8_t )(words * 2 ));
615639
616- // Set Led sequence for the next 2 seconds
617- // reset to first part of sequence
618- LedCnt = 0 ;
619- n = 1 ;
620- LedState = 8 ;
621-
622- // When we have received a valid measurement from the SmartMeter, the led will blink only once.
623- if (dataready & 0xC0 ) {
624- // DSMR version not 5.x! Blink RED
625- if (DSMRver < 50 ) LedSeq[0 ] = LED_RED;
626- // DSMR version OK, Blink GREEN
627- else LedSeq[0 ] = LED_GREEN;
628-
629- // No SmartMeter connected, we use the CT's
630- // CT measurement available?
631- } else if (dataready & 0x03 ) {
632- // CT measurements with current direction?
633- if (IrmsMode == 0 ) {
634- if (IrmsCT[0 ] < -0.1 ) LedSeq[0 ]=LED_GREEN; else LedSeq[0 ]=LED_ORANGE;
635- if (IrmsCT[1 ] < -0.1 ) LedSeq[1 ]=LED_GREEN; else LedSeq[1 ]=LED_ORANGE;
636- if (IrmsCT[2 ] < -0.1 ) LedSeq[2 ]=LED_GREEN; else LedSeq[2 ]=LED_ORANGE;
637- // 6 States, ON/OFF (3 CT's)
638- n = 3 ;
639- } else {
640- // Blink 1x Orange when not using MAINS input
641- LedSeq[0 ] = LED_ORANGE;
642- }
643- // LED_RED_ON (PIC chip not programmed?)
644- } else {
645- LedSeq[0 ] = LED_RED;
646- }
647-
648- // Show WiFi mode as last blink in sequence
649- if (WIFImode == 2 ) LedSeq[n] = LED_RED;
650- else if (WIFImode == 1 ) LedSeq[n] = LED_GREEN;
651-
640+ SetLedSequence (dataready);
641+
652642 // Set Modbus Sensorbox version 2.0 (20) + Wire settings.
653643 // Set Software version in MSB
654644 ModbusData[0 ] = (SENSORBOX_SWVER << 8 ) + SENSORBOX_VERSION + Wire;
@@ -699,8 +689,9 @@ ModbusMessage MBReadFC04(ModbusMessage request) {
699689
700690 if ((millis () - ModbusTimer) > 2500 ) {
701691 LOG_W (" Missed modbus response\n " );
702- ModbusTimer = millis ();
703- }
692+ }
693+ ModbusTimer = millis ();
694+
704695
705696 // Loop over all words to be sent
706697 for (uint16_t i = 0 ; i < words; i++) {
0 commit comments