Modicon Modbus RTU Slave protocol comes to the Arduino/Freed

Post your projects. Pictures, code, and bragging welcome.
Post Reply
mdAndy
Posts: 15
Joined: Thu Jul 17, 2008 7:59 pm

Modicon Modbus RTU Slave protocol comes to the Arduino/Freed

Post by mdAndy » Thu Jul 31, 2008 4:56 pm

The functions codes have been reduced to only two (Function codes 3 and 6). This industrial PLC networking protocol will allow multiple Slaves (Arduinos/Freeduinos) to be connected to one Master via RS485. You can also use it "point to point" using RS232. Error checking is provided by a CRC16 data checking algorithm. The I/O points are 10 words (Read only) and 6 words (Read write). The overhead on the Arduino/Freeduino is less than 5k and 303 bytes of Ram used.

I have it working with three Modbus RTU simulators/testors and a data acquisition software (DaqFactory):

Works with "Modbus Tester" Simulator ver 0.3 from (modbus.pl ) (no demo timeout with this version)
Works with "ModbusView" Simulator ver 1.35 from (oceancontrols.com.au) (For 15 minutes using demo)
Works with (Azeotech.com) "DaqFactory"
They have a 30 day demo and a Free Modbus simulator which does not expire. <---- very cool

Modbus Ref:
Modbus Reference: Modicon Modbus Protocol Reference Guide PI–MBUS–300 Rev. J June 1996 obtained from
(eecs.umich.edu/~modbus/documents/PI_MBUS_300.pdf)

MODBUS APPLICATION PROTOCOL SPECIFICATION V1.1b obtained from
(modbus.org/docs/Modbus_Application_Protocol_V1_1b.pdf)

Having this "open source" Modicon Modbus Slave protocol opens up many applications that use to run only on programmable logic controllers (PLCs) but can be run on the Arduino/Freeduino. Take, for example, the 3" C-Touch Micro-Graphic color touch panel from automationdirect.com. The only "open source" network protocol is "guess what?" The Modicon Modbus RTU Slave protocol. Imagine have a color LCD touch screen tied to your Arduino/Freeduino controlling your home automation system.

I will be testing this protocol on this new "touch screen" in a few weeks and if there are many requests I will release it to the public.
Below is additional information on the Modbus RTU Slave software and some other information on communications, PLCs and networking.


//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
// Modicon "Modbus RTU Slave R1" Sketch for the Arduino/Freeduino
//---------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------
//
// Section 1 Modbus RTU Simulator Tester Instructions
// Section 2 Modicon Modbus RTU Reference
// Section 3 Modbus RTU Slave Protocol for the Arduino/Freeduino - Program Description and Design
// Section 4 "Think like a PLC"
//
//---------------------------------------------------------------------------------------------------------
// Section 1. Modbus RTU Simulator Tester Instructions
//---------------------------------------------------------------------------------------------------------
/*

Download the Modbus Tester from modbus.pl - version 0.3 Jan 2004
Note: This Modbus Tester/Master Simulator only works in the RTU mode (Hex) not the ASCII mode.
Note: This program is only made for a Modicon Modbus Slave RTU NOT ASCII protocol!

<Notes or helpful hints>
Make sure you can upload to the Audrino/Freeduino using comport 2 or the same comport used by the Modbus simulator.
Then exit the Audrion C compiler program to keep the comport 2 conflicting the the Modbus simulator on comport 2.
Then start the Modbus simulator and set up the following parameters before "connecting" to comport 2
Note: Default communication settings of Arduino/Freeduino = 9600 Baud, 8 Data, N - No parity, 1 - one stop bit
Note: You need to make sure that both the Arduino software upload comport and the Modbus simulator comport can be both selected for the same comport.
If not, go to your PC "Control panel", select "System", select "Hardware", select "Device manager", go to "Ports (Com & LPT)" Then find the "USB Serial Port" of the Arduino and under "Port Setting" and "Advanced" try to change the port to an unused port (comport) that can be BOTH selected by the Arduino and the Modbus simulator tester.

---------------------------------------------------------------------------------------------------------------
ModbusView Simulator Parameters Setup
---------------------------------------------------------------------------------------------------------------
<To read the Slave registers fill in the parameters below and then select "Connect">

[View Data Page]
Device address = 1 (Set in software constant SLAVE_ID for unique address per slave. Master has ID of 0 - Do not use)
Data type = 4: Holding register (the slave contains 16 holding register 6 of which can be written to)
Start address = 1 (Modbus 40,001 dec starting address)
Length = 16 - (This includes 16 holding registers 40,001-40,016 dec 6 of which are writable 40,011-40,016
Scan rate = 1000 ms - 1 sec - (The Master RTU polls the Slave Audrino/Freeduino at this interval)
Data format = Hex - (User adjustable to others formats)

[Modbus Settings Page]
(Modbus)
Modbus = RTU - Remote Terminal Unit - Hex transmission (Byte)

(RS settings)
Comport = COM2 <---- user adjustable/selectable
Baud rate = 9600
Data bits = 8
Parity = None (No parity checking due to Arduino/Freeduino comport/communications serial port default 9600,N,1 but CRC checking in protocol
Stop bits = 1
Time out = 5000 - 5 sec - on receipt of no data within 5000 ms (5 secs) from the slave (Arduino/Freeduino) the Master will indicate a time-out error
Note: On the first Master RTU Query/poll to the RTU Arduino/Freeduino Slave there will be one timeout error only the first query/poll.

<To write to points/register 40,011-40,016 just click on the (proper) cell and input the number and select the write button>
Note: Be sure to check the box for function code 6 and expand the box for the write button! <---------------

-------------------------------------------------------------------------------------------------------------------------------------------
Section 2. Modicon Modbus RTU Reference
-------------------------------------------------------------------------------------------------------------------------------------------
Modbus Reference: Modicon Modbus Protocol Reference Guide PI–MBUS–300 Rev. J June 1996 obtained from
http://www.eecs.umich.edu/~modbus/docum ... US_300.pdf

MODBUS APPLICATION PROTOCOL SPECIFICATION V1.1b obtained from
http://www.modbus.org/docs/Modbus_Appli ... _V1_1b.pdf

------------------------------------------
Modbus RTU Function Code Action Table Name
------------------------------------------
01 (01 hex) Read Discrete Output Coils
05 (05 hex) Write single Discrete Output Coil
15 (0F hex) Write multiple Discrete Output Coils
02 (02 hex) Read Discrete Input Contacts
04 (04 hex) Read Analog Input Registers
03 (03 hex) Read Analog Output Holding Registers <---- This function code implemented in slave sketch code
06 (06 hex) Write single Analog Output Holding Register <---- This function code implemented in slave sketch code
16 (10 hex) Write multiple Analog Output Holding Registers

-----------------------------
Modicon Modbus RTU Addressing
-----------------------------

Memory Type Address Range Bit Specification Description Read/Write Type Data Type
0 1 to 65536 Coil R/W Discrete
1 1 to 65536 Input Read Only Discrete
3 1 to 65536 0 to 15 Read Only Discrete
3 1 to 65536 Input Register Read Only Word
4 1 to 65536 0 to 15 R/W Discrete
4 1 to 65536 Holding Register R/W Word

-------------------------------------
The Master/Slave Transaction Sequence
-------------------------------------
1. The Modbus master composes the message.
2. The master device modem RTS and CTS status are checked. - not used
3. The query message is transmitted to the slave. (with CRC)
4. The slave processes the query message.
5. The slave calculates an error check field.
6. The slave device modem RTS and CTS status are checked. - not used
7. The response message is transmitted to the master. (with CRC)
8. The master application acts upon the response and its data.

A typical Modbus query/poll/telegram shown in hex characters is:
Request from master 02 03 00 08 00 01 05 FB // 05 FB is a test CRC check
with the answer from slave 02 03 02 02 01 3C E4 // 3C E4 is a test CRC check

To slave 02 request 03, to send back from his address 0008, one word (00 01), with checksum 05 FB,
and from slave 02 answer 03, with 02 bytes, the values 02 01, and checksum 3C E4.

Note: The allowable characters transmitted for all fields are hexadecimal 0–9, A–F for Modbus RTU

-----------------------------------
Function 03 Read Holding Registers
-----------------------------------
Description
Reads the binary contents of holding registers (4X references) in the slave.
Broadcast is not supported.
Appendix B lists the maximum parameters supported by various controller models.
Query
The query message specifies the starting register and quantity of registers to be
read. Registers are addressed starting at zero: registers 1–16 are addressed as
0–15.

Here is an example of a request to read registers 40108–40110 from slave device 17:
------------------------
Example Field Name (Hex)
------------------------
Slave Address 11
Function 03
Starting Address Hi 00
Starting Address Lo 6B
No. of Points Hi 00
No. of Points Lo 03
Error Check (CRC)

----------------------------------
Slave Response to Function Code 03
----------------------------------
The register data in the response message are packed as two bytes per register,
with the binary contents right justified within each byte. For each register, the first
byte contains the high order bits and the second contains the low order bits.
Data is scanned in the slave at the rate of 125 registers per scan for 984–X8X
controllers (984–685, etc), and at the rate of 32 registers per scan for all other
controllers. The response is returned when the data is completely assembled.

Here is an example of a response to the query:
-------------------------
Example Field Name (Hex)
-------------------------
Slave Address 11
Function 03
Byte Count 06
Data Hi (Register 40108) 02
Data Lo (Register 40108) 2B
Data Hi (Register 40109) 00
Data Lo (Register 40109) 00
Data Hi (Register 40110) 00
Data Lo (Register 40110) 64
Error Check (CRC)

RESPONSE
Figure 15 Read Holding Registers – Response
The contents of register 40108 are shown as the two byte values of 02 2B hex, or
555 decimal. The contents of registers 40109–40110 are 00 00 and 00 64 hex, or
0 and 100 decimal.

----------------
Function Code 6
----------------

Here is an example of a request to preset register 40002 to 00 03 hex in slave device 17:

------------------------
Example Field Name (Hex)
------------------------
Slave Address 11
Function 06
Register Address Hi 00
Register Address Lo 01
Preset Data Hi 00
Preset Data Lo 03
Error Check (CRC)
-------------------------

<Here is an example of a response to the query>

-----------------------
Example Field Name (Hex)
-----------------------
Slave Address 11
Function 06
Register Address Hi 00
Register Address Lo 01
Preset Data Hi 00
Preset Data Lo 03
Error Check (CRC)
----------------------

-------------------
Modbus Exceptions
-------------------
If a slave receives the query without a communication error but cannot respond to it then it will
issue an exception code to inform the master the reason for its failure to respond correctly.
One common reason for an exception code is where the slave device doesn’t have all the coils, status inputs
and registers that Modbus can address
The exception code response from the slave is indicated by the Function code being equal to
80Hex + Function Code from the Master


The exception code response from the slave would look like
Slave Address 12
Function 81
Exception Code 02
Error Check (CRC) LRC or CRCHi, CRCLo

----------------
Exception Codes
----------------

Exception Code 01 – ILLEGAL FUNCTION
The function code received in the query from the master cannot be carried out by the slave
Exception Code 02 – ILLEGAL DATA ADDRESS
The data address received in the query from the master is not a valid address in the slave.
For example the slave may only have 8 coil outputs but the master is trying to read or write to coil 56.
Exception Code 03 – ILLEGAL DATA VALUE
The data value received in the query from the master is not an allowable value in the slave.
For example the slave may only have a holding register that can only have a value between 0 and 100 but
the master is trying write a value of 456.
Exception Code 04 – SLAVE DEVICE FAILURE
An unrecoverable error occurred while the slave was attempting to perform the requested action.
Exception Code 05 – ACKNOWLEDGE
The slave has received the request from the master and is processing it.
Exception Code 06 – SLAVE DEVICE BUSY
The slave is busy and will not respond to the request from the master. The master should retry the query at a later date.
Exception Code 07 – NEGATIVE ACKNOWLEDGE
The slave cannot perform the program function received in the query from the master.
Exception Code 08 – MEMORY PARITY ERROR
The slave attempted to read extended memory, but detected a parity error in the memory.


----------------------------------
Freeduino/Arduino Resource Summary
----------------------------------
Microcontroller ATmega168
Operating Voltage 5V
Input Voltage (recommended) 7-12 V
Input Voltage (limits) 6-20 V
Digital I/O Pins 14 (of which 6 provide PWM output)
Analog Input Pins 6
DC Current per I/O Pin 40 mA
DC Current for 3.3V Pin 50 mA
Flash Memory 16 KB (of which 2 KB used by bootloader)
SRAM 1 KB
EEPROM 512 bytes
Clock Speed 16 MHz

<Input and Output>
Each of the 14 digital pins on the Diecimila can be used as an input or output,
using pinMode(), digitalWrite(), and digitalRead() functions.
They operate at 5 volts. Each pin can provide or receive a maximum of 40 mA and has an internal pull-up resistor
(disconnected by default) of 20-50 kOhms. In addition, some pins have specialized functions:

Serial: 0 (RX) and 1 (TX). Used to receive (RX) and transmit (TX) TTL serial data.
These pins are connected to the corresponding pins of the FTDI USB-to-TTL Serial chip.

External Interrupts: 2 and 3. These pins can be configured to trigger an interrupt on a low value,
a rising or falling edge, or a change in value. See the attachInterrupt() function for details.

PWM: 3, 5, 6, 9, 10, and 11. Provide 8-bit PWM output with the analogWrite() function.

SPI: 10 (SS), 11 (MOSI), 12 (MISO), 13 (SCK).
These pins support SPI communication, which, although provided by the underlying hardware, is not currently included in the Arduino language.

LED: 13. There is a built-in LED connected to digital pin 13.
When the pin is HIGH value, the LED is on, when the pin is LOW, it's off.

The Diecimila has 6 analog inputs, each of which provide 10 bits of resolution (i.e. 1024 different values).
By default they measure from ground to 5 volts, though is it possible to change the upper end of their range using
the AREF pin and some low-level code. Additionally, some pins have specialized functionality:

I2C: 4 (SDA) and 5 (SCL). Support I2C (TWI) communication using the Wire library (documentation on the Wiring website).

------------------------------
Ardunio/Freeduino I/O Summary
For Modbus Holding Registers
------------------------------

Digital I/O --> 0-13 Pins [0 Rec & 1 Trans used] [Interrupts (inputs) Pin 2 & Pin 3] [Pin 13 = LED/RS485 DIR] -> use 8 pins for digital I/O
Analog --> 1-6 Pins [I2C Pins 4 (SDA) Pins 5 (SCL) for I2C bus] -> use 4 analogs


------------------------------------------------------------------------------------------------------------------------
Section 3. Modbus RTU Protocol for the Arduino/Freeduino - Program Description and Design
------------------------------------------------------------------------------------------------------------------------

On the 4th of July weekend a group of my buddies were drinking and a wager was made. The bet was made that I could not produce C programming code using an industrial network protocol. The chosen microcontroller was the Arduino/Freeduino. I had no prior C training and no knowledge of the Arduino but had many years experience with programmable logic controllers (PLCs). Guess who won the bet? Here it is...

A PLC (Programmable Logic Controller [Industrial Controller]) has digital inputs/outputs & and analog inputs/outputs, a CPU, memory & comports.
The Arduino/Freeduino has the same general inputs and outputs (except analog outputs [PWM exception]) built into the AVR microcontroller.
Note: The Arduino/Freeduino is NOT the same as an industrial real time PLC with all the safety precautions and protections built in.

There are many communication protocols used to communicate to a PLC. Modicon, one of the earlier PLC manufacturers, created the "open standard" Modicon Modbus communications protocol. There are two types "Modicon RTU" (Remote Terminal Unit using Hex) and Modicon ASCII.
Transmission of ASCII characters (1 char per byte) is slower and less efficient than using one Modbus RTU hex byte to transmit data. Most companies choose the Modicon "Modbus RTU" for their communication protocol.
Note: There are many other protocols but the "Modicon Modbus" is one the very few that is "open source"

The Modbus protocol has only one "Master" and many "Slaves" or PLCs connected into a network. Each slave has a unique node address beginning with 0x01 hex. (The "Master" is always addressed as 0 hex). The "Master" polls/query each slave for read/write data. All slaves listen on the network for their unique node address and respond to the commands from the "Master". Only one Master or Slave can "talk" at one time using "half duplex". The master talks/polls/query the network of slaves then ONLY ONE of the slaves respond on the network if addressed properly.

RS232 is only good for 50 feet but to drive longer distances RS485 is a good inexpensive choice in a communciations network. RS232 can only have one Master/Slave in a single "point to point" network. Using the Modbus tester/simulator from the PC to the Arduino/Freeduino is an example of a "point to point" network. (See above)

RS485 wiring can be used to transport communication data hundreds of feet (4000 feet max) between a network Master multiple Slaves.
You can use your Arduino/Freeduino serial TTL data with a RS485 transceiver/driver in RS485 network up to 32 nodes or points.
Imagine multiple Arduinos/Freeduinos each doing their own program code and communicating over a network - awesome!

The Arduino/Freeduino is very resource limited (program flash - see above) so I chose "Memory type 4" (See above Modicon Modbus RTU Addressing)
Note: The pin compatible AtMega368p is coming out soon with double the resources - can't wait.
Note: The code flash size for this sketch is less than 5 k

-----------------------------------------------------------------------------------------------
Memory Type Address Range Bit Specification Description Read/Write Type Data Type
-----------------------------------------------------------------------------------------------
4 1 to 65536 Holding Register R/W Word
(Starts at 40,001 register)
----------------------------------------------------------------------------------------------

There are many (see manual) Modicon Modbus RTU "Function Codes" and it would be ludicous to implement them all in the Arduino/Freeduino.
I created a "Modicon Modbus RTU reduced subset" function commands to run on the Arduino/Freeduino.

This reduces the "Modicon Modbus RTU "Function Codes" commands down to two functions to save program code space and comm speed.
03 (03 hex) Read Analog Output Holding Registers <---- This function code implemented in slave sketch code
06 (06 hex) Write single Analog Output Holding Register <---- This function code implemented in slave sketch code

There are 10 "read only" and 6 "read/write" only registers (PLC words or PLC points) were created.
Note: This can be expanded @ a high resource cost eg flash and ram.
The Modicon Modbus RTU block decimal range is 40,001-40,016. 40,011-40,016 are the writable registers.
Note: Registers are numbered in a standard block format between function codes. (see Modbus manual)
Note: Writing or reading the wrong block will cause an exception error (see above)

Having only 16 registers/16 words/32 Bytes/16 I/O points to read seems quite small but it isn't. Having only 14 (8 usable) input/output
pins on the Arduino/Freeduino all the "bit I/O flags" can be coded in to one register or less ! Be very resourceful in coding your bytes
for the input/output points for the network!

The Modicon Modbus RTU calls for parity checking but since the Arduino/Freeduino default is 9600, 8, N, 1 there is no parity checking.
Not to worry, because the sketch has CRC16 Modbus error checking on all data transmissions.

--------------------------------------------------------------------------------------------------------------
Using this Code or Sketch
--------------------------------------------------------------------------------------------------------------

To used this code or sketch:
1. Set unique SLAVE_ID 1-32 in #define. (Default of 0x01 is good) (Each slave should/must have a "unique" slave address in software!)
2. Enable the function "Modbus_RTU_Slave_Enable();" in software. (uncomment the line of code)
3. Upload the test code. (This sketch program)
4. Shutdown the Sketch compiler IDE program.
5. Run the Modbus Tester/Simulator on the Arduino/Freeduino (see the instructions above)

--------------------
Additional Notes
--------------------
1. You can network multiple Arduinos/Freeduinos via RS485 for data acquisition and for home automation.
2. Inexpensive "dirt cheap" mini-boards for power, communications (RS485) and time keeping (DS1307 RTC) can be obtained from http://www.Futurlec.com
3. I made this sketch so it could be easily understood and patched if need be. Code reduction can be done by the "professional programmers"
on this forum.
4. I did NOT make the sketch for a Master RTU because you need plenty of CPU horsepower to talk/poll/query to multiple RTU Slaves. (32 of them)
You would probably run out of micocontroller resources using another Arduino/Freeduino. The pin compatible AtMega368p is coming out soon??
Note: You could use one Arduino/Freeduino for polling "several other slaves" on a small scale but using a PC gives you many more options and flexibility. I will leave this up to the other forum members.
Note: One of the two Modbus RTU Test Simulator(s) works both ways eg as a Master or as a Slave. (See above) (For Master code development)
5. There are many Modicon Modbus RTU programs that can run on the PC and poll a Modbus RTU Slave. You can use just one Master and one Slave
talking "point to "point" from a PC using the standard RS232/USB VCP comport connection. You would need a PC/RS485 driver interface for networking multiple Modbus Slaves.
6. Most TTL to RS485 boards have a direction transceiver input pin. On this pin, normally a HIGH will allow transmitting on the RS485 bus
and a LOW will allow receiving on the RS485 bus (Default). I created a global pin "define" on the Arduino/Freeduino to allow this output from the Arduio/Freeduino to be selectable and to interface with TTL logic of the RS485 interface board. (Default on pin 13)
7. I did not make a library as of yet for the Modbus RTU Slave sketch until all bugs are worked out and the code reduced.
8. All testing were done with ONLY the two FREE Modbus Testers/Simulators. Hardware testing of networking multiple RS485 Slaves has not been done.
9. The polling is done in "blocks of I/O". All 16 I/O points have to be addressed at the same time to read them. Out of the 16 points,
there are 6 read/write points (12 bytes). If need be, the points can be expanded, but I recommend polling in "standard blocks" of 16 so the next step up would be 32 points which is overkill for the limited I/O of the Arduino/Freeduino.
10. There are many "off the shelf" PC data acquisition programs that can talk Modbus RTU. There is, for example, the "32 I/O point limited" "DAQFactory" from http://www.azeotech.com. Its has a very good FREE Modbus Modicon RTU simulator/tester and after 25 days of the demo this simulator is still FREE.

---------------------------------------------------------------------------------------------------------
Section 4. Very Important! - Think like a PLC
------------------------------------------------------------------------------------------------------------
The program logic inside this "minature Arduino/Freeduino Slave PLC" is the program code uploaded to the flash memory in the Arduino/Freeduino. It works as a antomous independent controller eg it does not depend on the "networked"
Master Modbus RTU (Remote Terminal Unit) to work. The Master RTU querys/polls the Slave(s) for data response (digital data inputs/outputs, analog inputs/outputs and general data registers or variables). Only on ocassion, does the Master does write to the "minature Arduino/Freeduino Slave PLC" but keep in mind the minature slave controller is programmed so it can run by itself without the Master.

There are 10 "read only" "holding registers" (20 bytes) in the Arduino/Freeduino Modbus channels and there are also 6 read/write registers (12 bytes).
Considering the very limited I/O pins for the analogs and digitals this is more than enough channels for networked data communications.
The write channels are written to 12 upper bytes in the EEPROM memory. If power is shutdown and restarted the data in the write channels will still be there. Warning! Be extremely careful not to continuously write to these special write channels because there is an limit of 100,000 write/erase cycles allowed for the EEPROM in the Arduino/Freeduino!

# of Modbus Network "Read Only" Channels: 10 (I/O points or holding registers or words or Modbus channels 40,001 - 40,010 or bytes 20)
Global variable names in the Arduino/Freeduino are: [POINT_1_HI_RO THRU POINT_10_HI_RO] (High 8 bits or Low 8 bits and the "Read only" desination.)

# of Modbus Network "Read Write" Channels: 6 (I/O points or holding registers or words or Modbus channels 40,011 - 40,016 or bytes 12)
Global variable names in the Arduino/Freeduino are: [POINT_11_HI_RO THRU POINT_16_HI_RO] (High 8 bits or Low 8 bits and the "Read Write" desination.)

You need to write to the "Read Only" channels in the Arduino/Freeduino so the polling Master can read them.
Example: POINT_1_HI_RO = 0x08; In this example the user is writing "user data of 8 dec" to the high byte of Point 1 of the "read only" Modbus channel.

To read the data the Master RTU sent the Arduino/Freeduino you need to read the 12 bytes in the upper EEPROM memory. To the Master the "read write" channel range is from 40,011- 40,016.

Example: x = EEPROM.read(499,POINT_11_HI_RW ); This takes the high byte sent to the RTU Slave from the RTU Master and reads it into a user variable.

*/

Program Global Variables:

/* Modbus RTU Slave Global Variable Channels - The user code writes to these channels so the Master can read them. For Reference Only
POINT_1_HI_RO = 0x00; <--- Modbus Holding Register 40,001 - Read Only
POINT_1_LOW_RO = 0x00; <--- Modbus Holding Register 40,001 - Read Only
POINT_2_HI_RO = 0x00; <--- Modbus Holding Register 40,002 - Read Only
POINT_2_LOW_RO = 0x00; <--- Modbus Holding Register 40,002 - Read Only
POINT_3_HI_RO = 0x00; <--- Modbus Holding Register 40,003 - Read Only
POINT_3_LOW_RO = 0x00; <--- Modbus Holding Register 40,003 - Read Only
POINT_4_HI_RO = 0x00; <--- Modbus Holding Register 40,004 - Read Only
POINT_4_LOW_RO = 0x00; <--- Modbus Holding Register 40,004 - Read Only
POINT_5_HI_RO = 0x00; <--- Modbus Holding Register 40,005 - Read Only
POINT_5_LOW_RO = 0x00; <--- Modbus Holding Register 40,005 - Read Only
POINT_6_HI_RO = 0x00; <--- Modbus Holding Register 40,006 - Read Only
POINT_6_LOW_RO = 0x00; <--- Modbus Holding Register 40,006 - Read Only
POINT_7_HI_RO = 0x00; <--- Modbus Holding Register 40,007 - Read Only
POINT_7_LOW_RO = 0x00; <--- Modbus Holding Register 40,007 - Read Only
POINT_8_HI_RO = 0x00; <--- Modbus Holding Register 40,008 - Read Only
POINT_8_LOW_RO = 0x00; <--- Modbus Holding Register 40,008 - Read Only
POINT_9_HI_RO = 0x00; <--- Modbus Holding Register 40,009 - Read Only
POINT_9_LOW_RO = 0x00; <--- Modbus Holding Register 40,009 - Read Only
POINT_10_HI_RO = 0x00; <--- Modbus Holding Register 40,010 - Read Only
POINT_10_LOW_RO = 0x00; <--- Modbus Holding Register 40,010 - Read Only
------------------------------------------------------------------------
Modbus RTU Slave Global Variable Channels - The user code reads from these channels and the Master writes to them. For Reference Only
user variable = EEPROM.read(499); <--- POINT_11_HI_RW Modbus Holding Register 40,011 - Read Write
user variable = EEPROM.read(500); <--- POINT_11_LOW_RW Modbus Holding Register 40,011 - Read Write
user variable = EEPROM.read(501); <--- POINT_12_HI_RW Modbus Holding Register 40,012 - Read Write
user variable = EEPROM.read(502); <--- POINT_12_LOW_RW Modbus Holding Register 40,012 - Read Write
user variable = EEPROM.read(503); <--- POINT_13_HI_RW Modbus Holding Register 40,013 - Read Write
user variable = EEPROM.read(504); <--- POINT_13_LOW_RW Modbus Holding Register 40,013 - Read Write
user variable = EEPROM.read(505); <--- POINT_14_HI_RW Modbus Holding Register 40,014 - Read Write
user variable = EEPROM.read(506); <--- POINT_14_LOW_RW Modbus Holding Register 40,014 - Read Write
user variable = EEPROM.read(507); <--- POINT_15_HI_RW Modbus Holding Register 40,015 - Read Write
user variable = EEPROM.read(508); <--- POINT_15_LOW_RW Modbus Holding Register 40,015 - Read Write
user variable = EEPROM.read(509); <--- POINT_16_HI_RW Modbus Holding Register 40,016 - Read Write
user variable = EEPROM.read(510); <--- POINT_16_LOW_RW Modbus Holding Register 40,016 - Read Write
------------------------------------------------------------------------------------------------------
Note 1: Do not use global variables Point_11_Hi/Low_RW - Point_11_Hi/Low in any of the user code. You have to use the EEPROM.read(addr) to obtain the Modbus RTU channel(s) written from the Master RTU to the Slave RTU.
Note 2: To speed up communications only blocks of 16 channels are allowed to be read all at once. In this block of 16, it also reads the 6 read/write Modbus RTU channels so the Master can also have a "feedback" on the write channels.
Note 3: For the Master to read the Modbus RTU Slave Channels (above) all 16 channels will have to be designated. 40,001-40,016 or 1-16 or starting at 1 with 16 channels which defaults to 40,001-40,016.
Note 4: The Master RTU writes only one channel (Function code 6) at a time to the Slave RTU channel(s) (not multiple channels)
Note 5: Do not allow the Master RTU to write to the Slave RTU EEPROM over 100,000 write/erase cycles and by no means write continuously.
Note 6: The user code will have to finish within or less than 1.00 second of the Master Poll Time. This value is adjustable.
Note 7: Be very resourceful in coding the digital channels for communication. In one holding register all digital I/O points could be included.
Note 8: There are two bytes per Modbus RTU "holding registers". The Hi byte and the Low byte - Know which one you are writing to at all times. The global variable name indicates which byte is high or low. Both bytes are recombined in the Master as one unsigned integer or word.
Note 9: The #Define for "SLAVE_ID" (default 1), The #Define "RS485_Dir_Pin" (default 13) The above global variables and one function code below "Modbus_RTU_Slave_Enable(SLAVE_ID);" are the only items that are user selectable and changable. All other code modifications are done at the user's risk.
Note 10: The test code below changes the "read only" holding registers so you can see it on the Modbus Master RTU simulator/tester.

paul
Site Admin
Posts: 733
Joined: Mon May 12, 2008 4:19 pm

Re: Modicon Modbus RTU Slave protocol comes to the Arduino/Freed

Post by paul » Fri Aug 01, 2008 8:58 pm

Thanks for this mdAndy,

I'm unfamiliar with the modbus, but it seems like a Programmable Logic Controller protocol from what you say. Parallax seems like they were pretty successful with their BS based programmable logic controller - because lots of people thought PLC programming was arcane and unfriendly, from what I've read.

Do PLC's have any kind of hardware standards (form factors)?

Paul

mdAndy
Posts: 15
Joined: Thu Jul 17, 2008 7:59 pm

Re: Modicon Modbus RTU Slave protocol comes to the Arduino/Freed

Post by mdAndy » Sat Aug 02, 2008 6:46 am

It's really any device that has digital inputs, digital outputs, analog inputs, analog outputs, a comport for communications, memory for program storage and a CPU for processing control instructions. The ATMega168/Arduino/Freeduino fits this description. With the Modbus RTU networking protocol you can link 32 nodes togeither using RS485. :ugeek: :ugeek: :ugeek:

stComms
Posts: 1
Joined: Wed Nov 19, 2008 11:05 am

Re: Modicon Modbus RTU Slave protocol comes to the Arduino/Freed

Post by stComms » Wed Nov 19, 2008 11:14 am

A very detailed investigation. Did you get round to releasing the Modbus sketch? I'm looking for some type of serial comms to play around with in a home automation project.

Steve

stigmatic
Posts: 1
Joined: Tue Nov 08, 2011 4:49 am
Contact:

Re: Modicon Modbus RTU Slave protocol comes to the Arduino/F

Post by stigmatic » Tue Nov 08, 2011 4:53 am

I agree with other users. This is a really good detailed research. That helped me to understand much stuff that I haven't done before.

keval
Posts: 1
Joined: Tue Aug 28, 2012 11:14 pm

Re: Modicon Modbus RTU Slave protocol comes to the Arduino/F

Post by keval » Tue Aug 28, 2012 11:41 pm

hello friends

i am working on a project in which i have made my PLC as a modbus rtu slave and arduino as a modbus rtu master i want a code or library through which i can can read or write the modbus function through arduino because i have made it master

can anybody help me ??

flpro
Posts: 1
Joined: Sun Feb 10, 2013 8:41 pm

Re: Modicon Modbus RTU Slave protocol comes to the Arduino/F

Post by flpro » Sun Feb 10, 2013 8:51 pm

Hi mdAndy, i see that you have done this in 2008, but i could not find the link for the slave sketch code, can you post it again? :D :roll:

AJITnayak
Posts: 2
Joined: Tue Apr 01, 2014 5:45 am

Re: Modicon Modbus RTU Slave protocol comes to the Arduino/F

Post by AJITnayak » Tue Apr 01, 2014 5:49 am

Dear Mandy . You have Done great job
I Wanted to implement above Thing with Arduino. Can also share some of example code.

Michaelsmit
Posts: 3
Joined: Tue Jun 11, 2019 5:54 am

Re: Modicon Modbus RTU Slave protocol comes to the Arduino/Freed

Post by Michaelsmit » Thu Jun 13, 2019 5:04 am

It's extremely any gadget that has computerized inputs, advanced yields, simple data sources, simple yields, a comport for interchanges, memory for program stockpiling and a CPU for handling control guidelines. The ATMega168/Arduino/Freeduino fits this portrayal. With the Modbus RTU organizing convention you can interface 32 hubs togeither utilizing RS485.

Electrical Design Training

Post Reply