Skip to content

Commit 2c86f1e

Browse files
committed
Initial Commit
0 parents  commit 2c86f1e

File tree

137 files changed

+12944
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

137 files changed

+12944
-0
lines changed

Doxyfile

+2,492
Large diffs are not rendered by default.

ModbusTCP.cpp

+731
Large diffs are not rendered by default.

ModbusTCP.h

+273
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
/**
2+
@file
3+
Arduino library for communicating with Modbus server over Ethernet in TCP.
4+
5+
@defgroup setup ModbusTCP Object Instantiation/Initialization
6+
@defgroup buffer ModbusTCP Buffer Management
7+
@defgroup discrete Modbus Function Codes for Discrete Coils/Inputs
8+
@defgroup register Modbus Function Codes for Holding/Input Registers
9+
@defgroup constant Modbus Function Codes, Exception Codes
10+
*/
11+
/**
12+
\mainpage Modbus over TCP/IP
13+
ModbusTCP.h - Arduino library for communicating with Modbus server
14+
over Ethernet (via TCP protocol).
15+
16+
This file is part of ModbusTCP.
17+
18+
@see **README** for details.
19+
20+
ModbusTCP is free software: you can redistribute it and/or modify
21+
it under the terms of the GNU General Public License as published by
22+
the Free Software Foundation, either version 3 of the License, or
23+
(at your option) any later version.
24+
25+
ModbusTCP is distributed in the hope that it will be useful,
26+
but WITHOUT ANY WARRANTY; without even the implied warranty of
27+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28+
GNU General Public License for more details.
29+
30+
You should have received a copy of the GNU General Public License
31+
along with ModbusTCP library. If not, see <http://www.gnu.org/licenses/>.
32+
33+
Adopted from ModbusMaster for RTU over RS-485 by Doc Walker
34+
35+
Modified by Narendra Dehury for TCP.
36+
37+
Copyright @ phoenixrobotix.com
38+
39+
*/
40+
41+
42+
#ifndef Modbus_TCPIP_h
43+
#define Modbus_TCPIP_h
44+
45+
#define WIZNET_W5100 0 /**< define 1 if WIZNET W5100 IC is used, otherwise 0 */
46+
#define ENC28J60 1 /**< define 1 if ENC28J60 IC is used, otherwisw 0 */
47+
48+
49+
50+
/* _____STANDARD INCLUDES____________________________________________________ */
51+
// include types & constants of Wiring core API
52+
#if defined(ARDUINO) && ARDUINO >= 100
53+
#include "Arduino.h"
54+
#else
55+
#include "WProgram.h"
56+
#endif
57+
58+
#include <SPI.h>
59+
60+
#if WIZNET_W5100
61+
#include <Ethernet.h>
62+
#endif
63+
64+
#if ENC28J60
65+
#include <UIPEthernet.h>
66+
#endif
67+
68+
69+
/* _____PROJECT INCLUDES_____________________________________________________ */
70+
71+
// functions to manipulate words
72+
#include "util/word.h"
73+
74+
75+
/* _____CLASS DEFINITIONS____________________________________________________ */
76+
/**
77+
Arduino class library for communicating with Modbus server over TCP/IP.
78+
*/
79+
class ModbusTCP
80+
{
81+
public:
82+
83+
IPAddress serverIP;
84+
85+
#if WIZNET_W5100
86+
EthernetClient ModbusClient;
87+
#elif ENC28J60
88+
UIPClient ModbusClient;
89+
#endif
90+
91+
char MBconnectionFlag = 0;
92+
93+
ModbusTCP();
94+
ModbusTCP(uint8_t);
95+
void setUnitId(uint8_t);
96+
void setTransactionID(uint16_t);
97+
void setServerIPAddress(IPAddress);
98+
void idle(void (*)());
99+
100+
// Modbus exception codes
101+
/**
102+
Modbus protocol illegal function exception.
103+
104+
The function code received in the query is not an allowable action for
105+
the server. This may be because the function code is only
106+
applicable to newer devices, and was not implemented in the unit
107+
selected. It could also indicate that the server is in the
108+
wrong state to process a request of this type, for example because it is
109+
unconfigured and is being asked to return register values.
110+
111+
@ingroup constant
112+
*/
113+
static const uint8_t MBIllegalFunction = 0x01;
114+
115+
/**
116+
Modbus protocol illegal data address exception.
117+
118+
The data address received in the query is not an allowable address for
119+
the server. More specifically, the combination of reference
120+
number and transfer length is invalid. For a controller with 100
121+
registers, the ADU addresses the first register as 0, and the last one
122+
as 99. If a request is submitted with a starting register address of 96
123+
and a quantity of registers of 4, then this request will successfully
124+
operate (address-wise at least) on registers 96, 97, 98, 99. If a
125+
request is submitted with a starting register address of 96 and a
126+
quantity of registers of 5, then this request will fail with Exception
127+
Code 0x02 "Illegal Data Address" since it attempts to operate on
128+
registers 96, 97, 98, 99 and 100, and there is no register with address
129+
100.
130+
131+
@ingroup constant
132+
*/
133+
static const uint8_t MBIllegalDataAddress = 0x02;
134+
135+
/**
136+
Modbus protocol illegal data value exception.
137+
138+
A value contained in the query data field is not an allowable value for
139+
server. This indicates a fault in the structure of the
140+
remainder of a complex request, such as that the implied length is
141+
incorrect. It specifically does NOT mean that a data item submitted for
142+
storage in a register has a value outside the expectation of the
143+
application program, since the MODBUS protocol is unaware of the
144+
significance of any particular value of any particular register.
145+
146+
@ingroup constant
147+
*/
148+
static const uint8_t MBIllegalDataValue = 0x03;
149+
//static const uint8_t MBIllegalResponseLength = 0x04;
150+
151+
/**
152+
Modbus TCP server connection failure exception.
153+
154+
An unrecoverable error occurred while the client is attempting to connect to
155+
the server but fails, Usually a case with ENC82J60.
156+
157+
@ingroup constant
158+
*/
159+
160+
static const uint8_t MBServerConnectionTimeOut = 0x05;
161+
162+
// Class-defined success/exception codes
163+
/**
164+
ModbusTCP success.
165+
166+
Modbus transaction was successful; the following checks were valid:
167+
- slave ID
168+
- function code
169+
- response code
170+
- data
171+
172+
@ingroup constant
173+
*/
174+
static const uint8_t MBSuccess = 0x00;
175+
176+
/**
177+
ModbusTCP invalid response slave ID exception.
178+
179+
The slave ID in the response does not match that of the request.
180+
181+
@ingroup constant
182+
*/
183+
static const uint8_t MBInvalidTransactionID = 0xE0;
184+
185+
/**
186+
ModbusTCP invalid response function exception.
187+
188+
The function code in the response does not match that of the request.
189+
190+
@ingroup constant
191+
*/
192+
static const uint8_t MBInvalidFunction = 0xE1;
193+
194+
/**
195+
ModbusTCP response timed out exception.
196+
197+
The entire response was not received within the timeout period,
198+
ModbusTCP::MBResponseTimeout.
199+
200+
@ingroup constant
201+
*/
202+
static const uint8_t MBResponseTimedOut = 0xE2;
203+
204+
/**
205+
ModbusTCP invalid response CRC exception.
206+
207+
The CRC in the response does not match the one calculated.
208+
209+
@ingroup constant
210+
*/
211+
static const uint8_t MBInvalidUnitID = 0xE3;
212+
static const uint8_t MBInvalidProtocol = 0xE4;
213+
214+
uint8_t getResponseBufferLength();
215+
uint16_t getResponseBuffer(uint8_t);
216+
void clearResponseBuffer();
217+
uint8_t setTransmitBuffer(uint8_t, uint16_t);
218+
void clearTransmitBuffer();
219+
220+
221+
uint8_t readCoils(uint16_t, uint16_t);
222+
uint8_t readDiscreteInputs(uint16_t, uint16_t);
223+
uint8_t readHoldingRegisters(uint16_t, uint16_t);
224+
uint8_t readInputRegisters(uint16_t, uint8_t);
225+
uint8_t writeSingleCoil(uint16_t, uint8_t);
226+
uint8_t writeSingleRegister(uint16_t, uint16_t);
227+
uint8_t writeMultipleCoils(uint16_t, uint16_t);
228+
uint8_t writeMultipleRegisters(uint16_t, uint16_t);
229+
uint8_t maskWriteRegister(uint16_t, uint16_t, uint16_t);
230+
uint8_t readWriteMultipleRegisters(uint16_t, uint16_t, uint16_t, uint16_t);
231+
232+
private:
233+
234+
uint8_t _u8MBUnitID; ///< Unit Identifier for individual unit-identification
235+
uint16_t _u16MBTransactionID = 1; ///< Transaction id for each transaction
236+
uint16_t _u16MBProtocolID = 0; ///< Constant
237+
static const uint8_t MaxBufferSize = 64; ///< size of response/transmit buffers
238+
uint16_t _u16ReadAddress; ///< slave register from which to read
239+
uint16_t _u16ReadQty; ///< quantity of words to read
240+
uint16_t _u16TxRxBuffer[MaxBufferSize]; ///Both transmit and receive buffer murged to one buffer.
241+
uint16_t _u16WriteAddress; ///< slave register to which to write
242+
uint16_t _u16WriteQty; ///< quantity of words to write
243+
uint8_t _u8ResponseBufferLength;
244+
245+
// Modbus function codes for bit access
246+
static const uint8_t MBReadCoils = 0x01; ///< Modbus function 0x01 Read Coils
247+
static const uint8_t MBReadDiscreteInputs = 0x02; ///< Modbus function 0x02 Read Discrete Inputs
248+
static const uint8_t MBWriteSingleCoil = 0x05; ///< Modbus function 0x05 Write Single Coil
249+
static const uint8_t MBWriteMultipleCoils = 0x0F; ///< Modbus function 0x0F Write Multiple Coils
250+
251+
// Modbus function codes for 16 bit access
252+
static const uint8_t MBReadHoldingRegisters = 0x03; ///< Modbus function 0x03 Read Holding Registers
253+
static const uint8_t MBReadInputRegisters = 0x04; ///< Modbus function 0x04 Read Input Registers
254+
static const uint8_t MBWriteSingleRegister = 0x06; ///< Modbus function 0x06 Write Single Register
255+
static const uint8_t MBWriteMultipleRegisters = 0x10; ///< Modbus function 0x10 Write Multiple Registers
256+
static const uint8_t MBMaskWriteRegister = 0x16; ///< Modbus function 0x16 Mask Write Register
257+
static const uint8_t MBReadWriteMultipleRegisters = 0x17; ///< Modbus function 0x17 Read Write Multiple Registers
258+
259+
260+
static const uint16_t ku16MBResponseTimeout = 2000; ///< Modbus timeout [milliseconds]
261+
262+
// master function that conducts Modbus transactions
263+
uint8_t ModbusMasterTransaction(uint8_t u8MBFunction);
264+
265+
// idle callback function; gets called during idle time between TX and RX
266+
void (*_idle)();
267+
};
268+
#endif
269+
270+
/**
271+
@example examples/modbusTCPlib_w5100/modbusTCPlib_w5100.ino
272+
@example examples/modbusTCPlib_watchdog/modbusTCPlib_watchdog.ino
273+
*/

README.md

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
README
2+
============
3+
4+
Overview
5+
--------
6+
This is an Arduino library for communicating with Modbus server over Ethernet (via TCP protocol).
7+
8+
9+
Features
10+
--------
11+
The following Modbus functions have been implemented:
12+
13+
Discrete Coils/Flags
14+
15+
* 0x01 - Read Coils
16+
* 0x02 - Read Discrete Inputs
17+
* 0x05 - Write Single Coil
18+
* 0x0F - Write Multiple Coils
19+
20+
Registers
21+
22+
* 0x03 - Read Holding Registers
23+
* 0x04 - Read Input Registers
24+
* 0x06 - Write Single Register
25+
* 0x10 - Write Multiple Registers
26+
* 0x16 - Mask Write Register
27+
* 0x17 - Read Write Multiple Registers
28+
29+
30+
31+
32+
Hardware
33+
--------
34+
This library has been tested with an Arduino [Mega](https://www.arduino.cc/en/Main/ArduinoBoardMega) with following Compatible Ethernet ICs.
35+
36+
1. Wizent W5100 - [Ethernet library](https://www.arduino.cc/en/Reference/Ethernet).
37+
2. ENC28J60 - [UIPEthernet library](https://github.com/UIPEthernet/UIPEthernet).
38+

0 commit comments

Comments
 (0)