Skip to content

Commit 32830bd

Browse files
authored
Merge pull request #10 from bcmi-labs/feature/expose-modbus-sensor
Demonstration: expose RS485 connected Modbus sensor via OPC/UA
2 parents 1c007bf + afd9b88 commit 32830bd

File tree

3 files changed

+109
-0
lines changed

3 files changed

+109
-0
lines changed

examples/opcua_server/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
:floppy_disk: `opcua_server.ino`
2+
================================
3+
4+
### How-to-build Modbus MD02 demo
5+
```bash
6+
arduino-cli compile --fqbn arduino:mbed_opta:opta examples/opcua_server -v --build-property compiler.cpp.extra_flags="-DUSE_MODBUS_SENSOR_MD02=1"
7+
```

examples/opcua_server/opcua_server.ino

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,26 @@
1313
#include "mbed_mem_trace.h"
1414
#endif
1515

16+
#if USE_MODBUS_SENSOR_MD02
17+
# include <ArduinoRS485.h>
18+
# include <ArduinoModbus.h>
19+
#endif
20+
21+
/**************************************************************************************
22+
* CONSTANTS
23+
**************************************************************************************/
24+
25+
#if USE_MODBUS_SENSOR_MD02
26+
static unsigned int const MODBUS_BAUDRATE = 9600;
27+
static float const MODBUS_BIT_DURATION = 1.f / MODBUS_BAUDRATE;
28+
static float const MODBUS_PRE_DELAY_BR = MODBUS_BIT_DURATION * 9.6f * 3.5f * 1e6;
29+
static float const MODBUS_POST_DELAY_BR = MODBUS_BIT_DURATION * 9.6f * 3.5f * 1e6;
30+
31+
static int const MODBUS_DEVICE_ID = 1;
32+
static int const MODBUS_DEVICE_TEMPERATURE_REGISTER = 0x0001;
33+
static int const MODBUS_DEVICE_HUMIDITY_REGISTER = 0x0002;
34+
#endif
35+
1636
/**************************************************************************************
1737
* GLUE CODE
1838
**************************************************************************************/
@@ -77,6 +97,9 @@ O1HeapInstance * o1heap_ins = nullptr;
7797
rtos::Thread opc_ua_server_thread(osPriorityNormal, OPC_UA_SERVER_THREAD_STACK.size(), OPC_UA_SERVER_THREAD_STACK.data());
7898

7999
opcua::ArduinoOpta::SharedPtr arduino_opta_opcua;
100+
#if USE_MODBUS_SENSOR_MD02
101+
UA_NodeId modbus_md02_temperature_node_id;
102+
#endif
80103

81104
/**************************************************************************************
82105
* DEFINES
@@ -186,6 +209,16 @@ void setup()
186209
//for (; !Serial && (millis() - start) < 1000; ) { }
187210
while (!Serial) { }
188211

212+
#if USE_MODBUS_SENSOR_MD02
213+
RS485.setDelays(MODBUS_PRE_DELAY_BR, MODBUS_POST_DELAY_BR);
214+
if (!ModbusRTUClient.begin(MODBUS_BAUDRATE, SERIAL_8N1))
215+
{
216+
Serial.println("Failed to start Modbus RTU Client!");
217+
for (;;) { }
218+
}
219+
ModbusRTUClient.setTimeout(2 * 1000UL); /* 2 seconds. */
220+
#endif
221+
189222
/* Initialize Ethernet interface and print obtained IP to Serial. */
190223
if (!Ethernet.begin()) {
191224
Serial.println("\"Ethernet.begin()\" failed.");
@@ -266,6 +299,54 @@ void setup()
266299
arduino_opta_opcua->led_mgr()->add_led_output(opc_ua_server, "User LED", [](bool const value) { pinMode(LEDB, OUTPUT); digitalWrite(LEDB, value); });
267300
}
268301

302+
#if USE_MODBUS_SENSOR_MD02
303+
{
304+
UA_StatusCode rc = UA_STATUSCODE_GOOD;
305+
UA_ObjectAttributes oAttr = UA_ObjectAttributes_default;
306+
oAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Modbus RS485 MD02 Sensor");
307+
UA_NodeId modbus_md02_node_id;
308+
rc = UA_Server_addObjectNode(opc_ua_server,
309+
UA_NODEID_NULL,
310+
arduino_opta_opcua->node_id(),
311+
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
312+
UA_QUALIFIEDNAME(1, "ModbusRs485Md02"),
313+
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),
314+
oAttr,
315+
NULL,
316+
&modbus_md02_node_id);
317+
if (UA_StatusCode_isBad(rc)) {
318+
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Modbus MD02 Sensor: UA_Server_addObjectNode(...) failed with %s", UA_StatusCode_name(rc));
319+
return;
320+
}
321+
322+
UA_VariableAttributes temperature_value_attr = UA_VariableAttributes_default;
323+
324+
/* Obtain the current value of the input pin. */
325+
UA_Float temperature_value = 0.f;
326+
UA_Variant_setScalar(&temperature_value_attr.value, &temperature_value, &UA_TYPES[UA_TYPES_FLOAT]);
327+
328+
temperature_value_attr.displayName = UA_LOCALIZEDTEXT("en-US", "Temperature / °C");
329+
temperature_value_attr.dataType = UA_TYPES[UA_TYPES_FLOAT].typeId;
330+
temperature_value_attr.accessLevel = UA_ACCESSLEVELMASK_READ;
331+
332+
/* Add the variable node. */
333+
rc = UA_Server_addVariableNode(opc_ua_server,
334+
UA_NODEID_NULL,
335+
modbus_md02_node_id,
336+
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
337+
UA_QUALIFIEDNAME(1, "md02_temperature_deg"),
338+
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
339+
temperature_value_attr,
340+
NULL,
341+
&modbus_md02_temperature_node_id);
342+
if (UA_StatusCode_isBad(rc))
343+
{
344+
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Modbus MD02 Sensor: UA_Server_addVariableNode(...) failed with %s", UA_StatusCode_name(rc));
345+
return;
346+
}
347+
}
348+
#endif
349+
269350
/* Print some threading related message. */
270351
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
271352
"stack: size = %d | free = %d | used = %d | max = %d",
@@ -314,4 +395,24 @@ void loop()
314395
{
315396
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
316397
delay(500);
398+
399+
#if USE_MODBUS_SENSOR_MD02
400+
if (!ModbusRTUClient.requestFrom(MODBUS_DEVICE_ID, INPUT_REGISTERS, MODBUS_DEVICE_TEMPERATURE_REGISTER, 1)) {
401+
Serial.print("failed to read temperature register! ");
402+
Serial.println(ModbusRTUClient.lastError());
403+
return;
404+
}
405+
if (ModbusRTUClient.available())
406+
{
407+
int16_t const temperature_raw = ModbusRTUClient.read();
408+
float const temperature_deg = temperature_raw / 100.f;
409+
Serial.println(temperature_deg);
410+
411+
UA_Float temperature_deg_opcua_value = temperature_deg;
412+
UA_Variant temperature_deg_opcua_variant;
413+
UA_Variant_init(&temperature_deg_opcua_variant);
414+
UA_Variant_setScalar(&temperature_deg_opcua_variant, &temperature_deg_opcua_value, &UA_TYPES[UA_TYPES_FLOAT]);
415+
UA_Server_writeValue(opc_ua_server, modbus_md02_temperature_node_id, temperature_deg_opcua_variant);
416+
}
417+
#endif
317418
}

src/ArduinoOpta.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class ArduinoOpta
4949
RelayManager::SharedPtr relay_mgr();
5050
LedManager::SharedPtr led_mgr();
5151

52+
[[nodiscard]] UA_NodeId node_id() const { return _node_id; }
5253

5354
private:
5455
UA_Server * _server;

0 commit comments

Comments
 (0)