Skip to content

Commit f53379a

Browse files
added methods to configure modbus server's tables to existing data structs and example
1 parent 62098a6 commit f53379a

File tree

3 files changed

+232
-2
lines changed

3 files changed

+232
-2
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
Ethernet Modbus TCP Server LED using existing varibles as modbus memory
3+
4+
This sketch creates a Modbus TCP Server with a simulated coil.
5+
The value of the simulated coil is set on the LED
6+
7+
Circuit:
8+
- Any Arduino MKR Board
9+
- MKR ETH Shield
10+
11+
created 16 July 2018
12+
by Sandeep Mistry
13+
*/
14+
15+
#include <SPI.h>
16+
#include <Ethernet.h>
17+
18+
#include <ArduinoRS485.h> // ArduinoModbus depends on the ArduinoRS485 library
19+
#include <ArduinoModbus.h>
20+
21+
// Enter a MAC address for your controller below.
22+
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
23+
// The IP address will be dependent on your local network:
24+
byte mac[] = {
25+
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
26+
};
27+
IPAddress ip(192, 168, 1, 177);
28+
29+
EthernetServer ethServer(502);
30+
31+
ModbusTCPServer modbusTCPServer;
32+
33+
const int ledPin = LED_BUILTIN;
34+
35+
//create an example struct of a modbus memory map
36+
struct mb_context{
37+
uint8_t coils[10];
38+
uint8_t inputStats[10];
39+
uint16_t inputRegs[10];
40+
uint16_t holdingRegs[10];
41+
};
42+
43+
mb_context myModbusMap;
44+
45+
void updateLED() {
46+
// read the current value of the coil
47+
48+
49+
if (myModbusMap.coils[0]) {
50+
// coil value set, turn LED on
51+
digitalWrite(ledPin, HIGH);
52+
} else {
53+
// coild value clear, turn LED off
54+
digitalWrite(ledPin, LOW);
55+
}
56+
}
57+
58+
void setup() {
59+
// You can use Ethernet.init(pin) to configure the CS pin
60+
//Ethernet.init(10); // Most Arduino shields
61+
//Ethernet.init(5); // MKR ETH shield
62+
//Ethernet.init(0); // Teensy 2.0
63+
//Ethernet.init(20); // Teensy++ 2.0
64+
//Ethernet.init(15); // ESP8266 with Adafruit Featherwing Ethernet
65+
//Ethernet.init(33); // ESP32 with Adafruit Featherwing Ethernet
66+
67+
// Open serial communications and wait for port to open:
68+
Serial.begin(9600);
69+
while (!Serial) {
70+
; // wait for serial port to connect. Needed for native USB port only
71+
}
72+
Serial.println("Ethernet Modbus TCP Example");
73+
74+
// start the Ethernet connection and the server:
75+
Ethernet.begin(mac, ip);
76+
77+
// Check for Ethernet hardware present
78+
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
79+
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
80+
while (true) {
81+
delay(1); // do nothing, no point running without Ethernet hardware
82+
}
83+
}
84+
if (Ethernet.linkStatus() == LinkOFF) {
85+
Serial.println("Ethernet cable is not connected.");
86+
}
87+
88+
// start the server
89+
ethServer.begin();
90+
91+
// start the Modbus TCP server
92+
if (!modbusTCPServer.begin()) {
93+
Serial.println("Failed to start Modbus TCP Server!");
94+
while (1);
95+
}
96+
97+
// configure the LED
98+
pinMode(ledPin, OUTPUT);
99+
digitalWrite(ledPin, LOW);
100+
101+
// configure a each modbus table's pointer and length
102+
modbusTCPServer.configureCoilPointer(myModbusMap.coils, 0x00, 10);
103+
modbusTCPServer.configureDiscreteInputPointer(myModbusMap.inputStats, 0x00, 10);
104+
modbusTCPServer.configureInputRegisterPointer(myModbusMap.inputRegs, 0x00, 10);
105+
modbusTCPServer.configureHoldingRegisterPointer(myModbusMap.holdingRegs, 0x00, 10);
106+
}
107+
108+
void loop() {
109+
// listen for incoming clients
110+
EthernetClient client = ethServer.available();
111+
112+
if (client) {
113+
// a new client connected
114+
Serial.println("new client");
115+
116+
// let the Modbus TCP accept the connection
117+
modbusTCPServer.accept(client);
118+
119+
while (client.connected()) {
120+
// poll for Modbus TCP requests, while client connected
121+
modbusTCPServer.poll();
122+
123+
// update the LED
124+
updateLED();
125+
}
126+
127+
Serial.println("client disconnected");
128+
}
129+
}

src/ModbusServer.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,21 @@ ModbusServer::~ModbusServer()
5050
}
5151
}
5252

53+
int ModbusServer::configureCoilPointer(uint8_t *ptr, int startAddress, int nb)
54+
{
55+
if (startAddress < 0 || nb < 1) {
56+
errno = EINVAL;
57+
58+
return -1;
59+
}
60+
61+
_mbMapping.tab_bits = ptr;
62+
_mbMapping.start_bits = startAddress;
63+
_mbMapping.nb_bits = nb;
64+
65+
return 1;
66+
}
67+
5368
int ModbusServer::configureCoils(int startAddress, int nb)
5469
{
5570
if (startAddress < 0 || nb < 1) {
@@ -76,6 +91,20 @@ int ModbusServer::configureCoils(int startAddress, int nb)
7691
return 1;
7792
}
7893

94+
int ModbusServer::configureDiscreteInputPointer(uint8_t *ptr, int startAddress, int nb)
95+
{
96+
if (startAddress < 0 || nb < 1) {
97+
errno = EINVAL;
98+
99+
return -1;
100+
}
101+
_mbMapping.tab_input_bits = ptr;
102+
_mbMapping.start_input_bits = startAddress;
103+
_mbMapping.nb_input_bits = nb;
104+
105+
return 1;
106+
}
107+
79108
int ModbusServer::configureDiscreteInputs(int startAddress, int nb)
80109
{
81110
if (startAddress < 0 || nb < 1) {
@@ -102,6 +131,20 @@ int ModbusServer::configureDiscreteInputs(int startAddress, int nb)
102131
return 1;
103132
}
104133

134+
135+
int ModbusServer::configureHoldingRegisterPointer(uint16_t *ptr, int startAddress, int nb)
136+
{
137+
if (startAddress < 0 || nb < 1) {
138+
errno = EINVAL;
139+
140+
return -1;
141+
}
142+
_mbMapping.tab_registers = ptr;
143+
_mbMapping.start_registers = startAddress;
144+
_mbMapping.nb_registers = nb;
145+
return 1;
146+
}
147+
105148
int ModbusServer::configureHoldingRegisters(int startAddress, int nb)
106149
{
107150
if (startAddress < 0 || nb < 1) {
@@ -128,6 +171,20 @@ int ModbusServer::configureHoldingRegisters(int startAddress, int nb)
128171
return 1;
129172
}
130173

174+
int ModbusServer::configureInputRegisterPointer(uint16_t *ptr, int startAddress, int nb)
175+
{
176+
if (startAddress < 0 || nb < 1) {
177+
errno = EINVAL;
178+
179+
return -1;
180+
}
181+
_mbMapping.tab_input_registers = ptr;
182+
_mbMapping.start_input_registers = startAddress;
183+
_mbMapping.nb_input_registers = nb;
184+
185+
return 1;
186+
}
187+
131188
int ModbusServer::configureInputRegisters(int startAddress, int nb)
132189
{
133190
if (startAddress < 0 || nb < 1) {

src/ModbusServer.h

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ extern "C" {
2929
class ModbusServer {
3030

3131
public:
32+
/**
33+
* Configure the servers coil starting address.
34+
*
35+
* @param ptr pointer address of existing data struct
36+
* @param startAddress start address of holding registers
37+
* @param nb number of holding registers to configure
38+
*
39+
* @return 0 on success, 1 on failure
40+
*/
41+
int configureCoilPointer(uint8_t *ptr, int startAddress, int nb);
3242
/**
3343
* Configure the servers coils.
3444
*
@@ -38,7 +48,16 @@ class ModbusServer {
3848
* @return 0 on success, 1 on failure
3949
*/
4050
int configureCoils(int startAddress, int nb);
41-
51+
/**
52+
* Configure the servers discrete inputs starting address.
53+
*
54+
* @param ptr pointer address of existing data struct
55+
* @param startAddress start address of holding registers
56+
* @param nb number of holding registers to configure
57+
*
58+
* @return 0 on success, 1 on failure
59+
*/
60+
int configureDiscreteInputPointer(uint8_t *ptr, int startAddress, int nb);
4261
/**
4362
* Configure the servers discrete inputs.
4463
*
@@ -49,15 +68,39 @@ class ModbusServer {
4968
*/
5069
int configureDiscreteInputs(int startAddress, int nb);
5170

71+
5272
/**
53-
* Configure the servers holding registers.
73+
* Configure the servers holding registers starting address.
5474
*
75+
* @param ptr pointer address of existing data struct
5576
* @param startAddress start address of holding registers
5677
* @param nb number of holding registers to configure
5778
*
5879
* @return 0 on success, 1 on failure
5980
*/
81+
int configureHoldingRegisterPointer(uint16_t *ptr, int startAddress, int nb);
82+
83+
84+
/**
85+
* Configure the servers holding registers.
86+
*
87+
* @param startAddress start address of holding registers
88+
* @param nb number of holding registers to configure
89+
*
90+
* @return 0 on success, 1 on failure
91+
*/
6092
int configureHoldingRegisters(int startAddress, int nb);
93+
94+
/**
95+
* Configure the servers input registers starting address.
96+
*
97+
* @param ptr pointer address of existing data struct
98+
* @param startAddress start address of holding registers
99+
* @param nb number of holding registers to configure
100+
*
101+
* @return 0 on success, 1 on failure
102+
*/
103+
int configureInputRegisterPointer(uint16_t *ptr, int startAddress, int nb);
61104

62105
/**
63106
* Configure the servers input registers.
@@ -67,6 +110,7 @@ class ModbusServer {
67110
*
68111
* @return 0 on success, 1 on failure
69112
*/
113+
70114
int configureInputRegisters(int startAddress, int nb);
71115

72116
// same as ModbusClient.h

0 commit comments

Comments
 (0)