Skip to content

Commit aa7e069

Browse files
committed
Modbus: Wait for response before sending new request. Enforce 50ms quiet time between messages, this improves reading slow modbus meters.
1 parent 4c83f8c commit aa7e069

File tree

1 file changed

+29
-21
lines changed

1 file changed

+29
-21
lines changed

SmartEVSE-3/src/main.cpp

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2644,15 +2644,12 @@ void requestPowerMeasurement(uint8_t Meter, uint8_t Address, uint16_t PRegister)
26442644
}
26452645

26462646

2647-
// Task that handles the Cable Lock and modbus
2647+
// Task that handles the Cable Lock
26482648
//
26492649
// called every 100ms
26502650
//
26512651
void Timer100ms(void * parameter) {
2652-
2653-
unsigned int locktimer = 0, unlocktimer = 0, energytimer = 0;
2654-
uint8_t PollEVNode = NR_EVSES, updated = 0;
2655-
2652+
unsigned int locktimer = 0, unlocktimer = 0;
26562653

26572654
while(1) // infinite loop
26582655
{
@@ -2697,10 +2694,25 @@ uint8_t PollEVNode = NR_EVSES, updated = 0;
26972694
}
26982695
}
26992696

2700-
2697+
// Pause the task for 100ms
2698+
vTaskDelay(100 / portTICK_PERIOD_MS);
2699+
2700+
} //while(1) loop
27012701

2702+
}
2703+
2704+
// Sequentially call the Mains/EVmeters, and polls Nodes
2705+
// Called by MBHandleError, and MBHandleData response functions.
2706+
// Once every two seconds started by Timer1s()
2707+
//
2708+
void ModbusRequestLoop() {
2709+
2710+
static uint8_t PollEVNode = NR_EVSES;
2711+
static uint16_t energytimer = 0;
2712+
uint8_t updated = 0;
2713+
27022714
// Every 2 seconds, request measurements from modbus meters
2703-
if (ModbusRequest) { // Slaves all have ModbusRequest at 0 so they never enter here
2715+
// Slaves all have ModbusRequest at 0 so they never enter here
27042716
switch (ModbusRequest) { // State
27052717
case 1: // PV kwh meter
27062718
ModbusRequest++;
@@ -2746,19 +2758,21 @@ uint8_t PollEVNode = NR_EVSES, updated = 0;
27462758
case 5: // EV kWh meter, Power measurement (momentary power in Watt)
27472759
// Request Power if EV meter is configured
27482760
if (Node[PollEVNode].EVMeter && Node[PollEVNode].EVMeter != EM_API) {
2761+
updated = 1;
27492762
switch(EVMeter.Type) {
27502763
//these meters all have their power measured via receiveCurrentMeasurement already
27512764
case EM_EASTRON1P:
27522765
case EM_EASTRON3P:
27532766
case EM_EASTRON3P_INV:
27542767
case EM_ABB:
27552768
case EM_FINDER_7M:
2769+
updated = 0;
27562770
break;
27572771
default:
27582772
requestPowerMeasurement(Node[PollEVNode].EVMeter, Node[PollEVNode].EVAddress,EMConfig[Node[PollEVNode].EVMeter].PRegister);
27592773
break;
27602774
}
2761-
break;
2775+
if (updated) break; // do not break when EVmeter is one of the above types
27622776
}
27632777
ModbusRequest++;
27642778
// fall through
@@ -2824,8 +2838,6 @@ uint8_t PollEVNode = NR_EVSES, updated = 0;
28242838
}
28252839
ModbusRequest++;
28262840
// fall through
2827-
break; // TODO: remove break; read modbus registers more evenly.
2828-
// For now this gives the next modbus broadcast some room.
28292841
default:
28302842
// slave never gets here
28312843
// what about normal mode with no meters attached?
@@ -2848,16 +2860,9 @@ uint8_t PollEVNode = NR_EVSES, updated = 0;
28482860
break;
28492861
} //switch
28502862
if (ModbusRequest) ModbusRequest++;
2851-
}
2852-
2853-
2854-
// Pause the task for 100ms
2855-
vTaskDelay(100 / portTICK_PERIOD_MS);
2856-
2857-
} //while(1) loop
2858-
28592863
}
28602864

2865+
28612866
#if MQTT
28622867
void mqtt_receive_callback(const String topic, const String payload) {
28632868
if (topic == MQTTprefix + "/Set/Mode") {
@@ -3484,7 +3489,8 @@ void Timer1S(void * parameter) {
34843489
// Every two seconds request measurement data from sensorbox/kwh meters.
34853490
// and send broadcast to Node controllers.
34863491
if (LoadBl < 2 && !Broadcast--) { // Load Balancing mode: Master or Disabled
3487-
if (!ModbusRequest) ModbusRequest = 1; // Start with state 1, also in Normal mode we want MainsMeter and EVmeter updated
3492+
ModbusRequest = 1; // Start with state 1, also in Normal mode we want MainsMeter and EVmeter updated
3493+
ModbusRequestLoop();
34883494
//timeout = COMM_TIMEOUT; not sure if necessary, statement was missing in original code // reset timeout counter (not checked for Master)
34893495
Broadcast = 1; // repeat every two seconds
34903496
}
@@ -3727,10 +3733,11 @@ void MBhandleData(ModbusMessage msg, uint32_t token)
37273733
// Node EV meter settings
37283734
// _LOG_A("Node EV Meter settings received\n");
37293735
receiveNodeConfig(MB.Data, MB.Address - 1u);
3736+
return; // Do not call ModbusRequestLoop(), we still expect an Ack from the Node
37303737
}
37313738
}
37323739
}
3733-
3740+
ModbusRequestLoop(); // continue with the next request.
37343741
}
37353742

37363743

@@ -3752,6 +3759,7 @@ void MBhandleError(Error error, uint32_t token)
37523759
else {
37533760
_LOG_A("Error response: %02X - %s, address: %02x, function: %02x, reg: %04x.\n", error, (const char *)me, address, function, reg);
37543761
}
3762+
if (ModbusRequest) ModbusRequestLoop(); // continue with the next request.
37553763
}
37563764

37573765

@@ -3794,7 +3802,7 @@ void ConfigureModbusMode(uint8_t newmode) {
37943802
MBclient.onDataHandler(&MBhandleData);
37953803
MBclient.onErrorHandler(&MBhandleError);
37963804
// Start ModbusRTU Master background task
3797-
MBclient.begin(Serial1, 1); //pinning it to core1 reduces modbus problems
3805+
MBclient.begin(Serial1, 1, (uint32_t)50000U); // pinning it to core1 reduces modbus problems. Make sure there is 50ms quiet time between messages
37983806
}
37993807
} else if (newmode > 1) {
38003808
// Register worker. at serverID 'LoadBl', all function codes

0 commit comments

Comments
 (0)