Skip to content

Commit 61d4c50

Browse files
committed
[SenseAir] Some more improvements Modbus implementation
1 parent 6290cb4 commit 61d4c50

File tree

1 file changed

+86
-31
lines changed

1 file changed

+86
-31
lines changed

src/_P052_SenseAir.ino

Lines changed: 86 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ boolean Plugin_052_init = false;
111111
String detected_device_description;
112112

113113
unsigned int _plugin_052_last_measurement = 0;
114-
uint32_t _plugin_052_reads_processed = 0;
114+
uint32_t _plugin_052_reads_pass = 0;
115115
uint32_t _plugin_052_reads_crc_failed = 0;
116116

117117
ESPeasySerial *P052_easySerial;
@@ -213,7 +213,7 @@ boolean Plugin_052(byte function, struct EventStruct *event, String &string) {
213213
}
214214
addRowLabel(F("Checksum (pass/fail)"));
215215
String chksumStats;
216-
chksumStats = _plugin_052_reads_processed;
216+
chksumStats = _plugin_052_reads_pass;
217217
chksumStats += '/';
218218
chksumStats += _plugin_052_reads_crc_failed;
219219
addHtml(chksumStats);
@@ -329,6 +329,7 @@ boolean Plugin_052(byte function, struct EventStruct *event, String &string) {
329329
String Plugin_052_getDevice_description(byte slaveAddress) {
330330
bool more_follows = true;
331331
byte next_object_id = 0;
332+
byte conformity_level = 0;
332333
unsigned int object_value_int;
333334
String description;
334335
String obj_text;
@@ -338,33 +339,51 @@ String Plugin_052_getDevice_description(byte slaveAddress) {
338339
if (object_id == 6) {
339340
object_id = 0x82; // Skip to the serialnr/sensor type
340341
}
341-
if (0 == Plugin_052_modbus_get_MEI(slaveAddress, object_id, obj_text,
342+
int result = Plugin_052_modbus_get_MEI(slaveAddress, object_id, obj_text,
342343
object_value_int, next_object_id,
343-
more_follows)) {
344-
String label;
345-
switch (object_id) {
346-
case 0x01:
347-
label = F("Pcode");
348-
break;
349-
case 0x02:
350-
label = F("Rev");
351-
break;
352-
case 0x82:
353-
label = F("S/N");
354-
break;
355-
case 0x83:
356-
label = F("Type");
357-
break;
358-
default:
359-
break;
344+
more_follows, conformity_level);
345+
String label;
346+
switch (object_id) {
347+
case 0x01:
348+
if (result == 0) label = F("Pcode");
349+
break;
350+
case 0x02:
351+
if (result == 0) label = F("Rev");
352+
break;
353+
case 0x82:
354+
{
355+
if (result != 0) {
356+
uint32_t sensorId = Plugin_052_readSensorId();
357+
obj_text = String(sensorId, HEX);
358+
result = 0;
359+
360360
}
361+
if (result == 0) label = F("S/N");
362+
break;
363+
}
364+
case 0x83:
365+
{
366+
if (result != 0) {
367+
uint32_t sensorId = Plugin_052_readTypeId();
368+
obj_text = String(sensorId, HEX);
369+
result = 0;
370+
}
371+
if (result == 0) label = F("Type");
372+
break;
373+
}
374+
default:
375+
break;
376+
}
377+
if (result == 0) {
361378
if (label.length() > 0) {
362379
// description += Plugin_052_MEI_objectid_to_name(object_id);
363380
description += label;
364381
description += F(": ");
365382
}
366-
description += obj_text;
367-
description += F(" - ");
383+
if (obj_text.length() > 0) {
384+
description += obj_text;
385+
description += F(" - ");
386+
}
368387
}
369388
}
370389
return description;
@@ -408,6 +427,12 @@ void Plugin_052_build_modbus_MEI_frame(byte slaveAddress, byte device_id,
408427
_plugin_052_sendframe[0] = slaveAddress;
409428
_plugin_052_sendframe[1] = 0x2B;
410429
_plugin_052_sendframe[2] = 0x0E;
430+
431+
// The parameter "Read Device ID code" allows to define four access types :
432+
// 01: request to get the basic device identification (stream access)
433+
// 02: request to get the regular device identification (stream access)
434+
// 03: request to get the extended device identification (stream access)
435+
// 04: request to get one specific identification object (individual access)
411436
_plugin_052_sendframe[3] = device_id;
412437
_plugin_052_sendframe[4] = object_id;
413438
_plugin_052_sendframe_used = 5;
@@ -444,7 +469,8 @@ String Plugin_052_MEI_objectid_to_name(byte object_id) {
444469

445470
String Plugin_052_parse_modbus_MEI_response(unsigned int &object_value_int,
446471
byte &next_object_id,
447-
bool &more_follows) {
472+
bool &more_follows,
473+
byte &conformity_level) {
448474
String result;
449475
if (_plugin_052_recv_buf_used < 8) {
450476
// Too small.
@@ -454,9 +480,10 @@ String Plugin_052_parse_modbus_MEI_response(unsigned int &object_value_int,
454480
more_follows = false;
455481
return result;
456482
}
457-
int pos = 3; // Data skipped: slave_address, FunctionCode, MEI type
458-
const byte device_id = _plugin_052_recv_buf[pos++];
459-
const byte conformity_level = _plugin_052_recv_buf[pos++];
483+
int pos = 4; // Data skipped: slave_address, FunctionCode, MEI type, ReadDevId
484+
// See http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b.pdf
485+
// Page 45
486+
conformity_level = _plugin_052_recv_buf[pos++];
460487
more_follows = _plugin_052_recv_buf[pos++] != 0;
461488
next_object_id = _plugin_052_recv_buf[pos++];
462489
const byte number_objects = _plugin_052_recv_buf[pos++];
@@ -656,6 +683,7 @@ byte Plugin_052_processCommand() {
656683
int nrRetriesLeft = 2;
657684
byte return_value = 0;
658685
while (nrRetriesLeft > 0) {
686+
return_value = 0;
659687
// Send the byte array
660688
P052_easySerial->write(_plugin_052_sendframe, _plugin_052_sendframe_used);
661689
delay(50);
@@ -675,10 +703,11 @@ byte Plugin_052_processCommand() {
675703
}
676704
// Check checksum
677705
crc = Plugin_052_ModRTU_CRC(_plugin_052_recv_buf, _plugin_052_recv_buf_used);
678-
++_plugin_052_reads_processed;
679706
if (crc != 0u) {
680707
++_plugin_052_reads_crc_failed;
681708
return_value = Plugin_052_MODBUS_BADCRC;
709+
} else {
710+
++_plugin_052_reads_pass;
682711
}
683712
switch (return_value) {
684713
case MODBUS_EXCEPTION_ACKNOWLEDGE:
@@ -695,6 +724,18 @@ byte Plugin_052_processCommand() {
695724
return return_value;
696725
}
697726

727+
uint32_t Plugin_052_read_32b_InputRegister(short address) {
728+
uint32_t result = 0;
729+
int idHigh = Plugin_052_readInputRegister(address);
730+
int idLow = Plugin_052_readInputRegister(address + 1);
731+
if (idHigh >= 0 && idLow >= 0) {
732+
result = idHigh;
733+
result = result << 16;
734+
result += idLow;
735+
}
736+
return result;
737+
}
738+
698739
int Plugin_052_readInputRegister(short address) {
699740
// Only read 1 register
700741
return Plugin_052_process_16b_register(P052_MODBUS_SLAVE_ADDRESS,
@@ -716,12 +757,15 @@ int Plugin_052_writeSingleRegister(short address, short value) {
716757

717758
byte Plugin_052_modbus_get_MEI(byte slaveAddress, byte object_id,
718759
String &result, unsigned int &object_value_int,
719-
byte &next_object_id, bool &more_follows) {
760+
byte &next_object_id, bool &more_follows,
761+
byte &conformity_level) {
762+
// Force device_id to 4 = individual access (reading one ID object per call)
720763
Plugin_052_build_modbus_MEI_frame(slaveAddress, 4, object_id);
721764
const byte process_result = Plugin_052_processCommand();
722765
if (process_result == 0) {
723766
result = Plugin_052_parse_modbus_MEI_response(object_value_int,
724-
next_object_id, more_follows);
767+
next_object_id, more_follows,
768+
conformity_level);
725769
} else {
726770
more_follows = false;
727771
}
@@ -733,14 +777,15 @@ void Plugin_052_modbus_log_MEI(byte slaveAddress) {
733777
// Modbus command (0x2B / 0x0E) Read Device Identification
734778
// And add to log.
735779
bool more_follows = true;
780+
byte conformity_level = 0;
736781
byte object_id = 0;
737782
byte next_object_id = 0;
738783
while (more_follows) {
739784
String result;
740785
unsigned int object_value_int;
741786
const byte process_result = Plugin_052_modbus_get_MEI(
742787
slaveAddress, object_id, result, object_value_int, next_object_id,
743-
more_follows);
788+
more_follows, conformity_level);
744789
if (process_result == 0) {
745790
if (result.length() > 0) {
746791
String log = Plugin_052_MEI_objectid_to_name(object_id);
@@ -758,6 +803,8 @@ void Plugin_052_modbus_log_MEI(byte slaveAddress) {
758803
break;
759804
}
760805
}
806+
// If more parts are needed, collect them or iterate over the known list.
807+
// For example with "individual access" a new request has to be sent for each single item
761808
if (more_follows) {
762809
object_id = next_object_id;
763810
} else if (object_id < 0x84) {
@@ -814,6 +861,14 @@ int Plugin_052_readErrorStatus(void) {
814861
return Plugin_052_readInputRegister(0x00);
815862
}
816863

864+
uint32_t Plugin_052_readTypeId() {
865+
return Plugin_052_read_32b_InputRegister(25);
866+
}
867+
868+
uint32_t Plugin_052_readSensorId() {
869+
return Plugin_052_read_32b_InputRegister(29);
870+
}
871+
817872
int Plugin_052_readCo2(void) { return Plugin_052_readInputRegister(0x03); }
818873

819874
int Plugin_052_readCo2_from_RAM(void) {
@@ -888,7 +943,7 @@ bool Plugin_052_prepare_single_measurement_from_RAM() {
888943

889944
float Plugin_052_readTemperature(void) {
890945
int temperatureX100 = Plugin_052_readInputRegister(0x04);
891-
float temperature = (float)temperatureX100 / 100;
946+
float temperature = (float)temperatureX100 / 100.0;
892947
return temperature;
893948
}
894949

0 commit comments

Comments
 (0)