Components and supplies
Arduino UNO
Resistor 10k ohm
Breadboard (generic)
LED (generic)
Professional RS422 / RS485 Shield for Arduino
USB-to-RS485 converter
Resistor 221 ohm
Pushbutton switch 12mm
Jumper wires (generic)
Apps and platforms
Modbustester
Arduino IDE
Project description
Code
Sample code for Arduino UNO
arduino
1/* 2 * Test program for Arduino RS422/RS485 Shield 3 * Version 1.0 4 * Copyright (C) 2018 Hartmut Wendt www.zihatec.de 5 * 6 * (based on sources of https://github.com/angeloc/simplemodbusng) 7 * 8 * 9 * This program is free software: you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation, either version 3 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program. If not, see <http://www.gnu.org/licenses/>. 21*/ 22 23#include <SimpleModbusSlave.h> 24 25#define ledPin 12 // onboard led 26#define buttonPin 7 // push button 27 28 29 30/* This example code has 9 holding registers. 6 analogue inputs, 1 button, 1 digital output 31 and 1 register to indicate errors encountered since started. 32 Function 5 (write single coil) is not implemented so I'm using a whole register 33 and function 16 to set the onboard Led on the Atmega328P. 34 35 The modbus_update() method updates the holdingRegs register array and checks communication. 36 37 Note: 38 The Arduino serial ring buffer is 128 bytes or 64 registers. 39 Most of the time you will connect the arduino to a master via serial 40 using a MAX485 or similar. 41 42 In a function 3 request the master will attempt to read from your 43 slave and since 5 bytes is already used for ID, FUNCTION, NO OF BYTES 44 and two BYTES CRC the master can only request 122 bytes or 61 registers. 45 46 In a function 16 request the master will attempt to write to your 47 slave and since a 9 bytes is already used for ID, FUNCTION, ADDRESS, 48 NO OF REGISTERS, NO OF BYTES and two BYTES CRC the master can only write 49 118 bytes or 59 registers. 50 51 Using the FTDI USB to Serial converter the maximum bytes you can send is limited 52 to its internal buffer which is 60 bytes or 30 unsigned int registers. 53 54 Thus: 55 56 In a function 3 request the master will attempt to read from your 57 slave and since 5 bytes is already used for ID, FUNCTION, NO OF BYTES 58 and two BYTES CRC the master can only request 54 bytes or 27 registers. 59 60 In a function 16 request the master will attempt to write to your 61 slave and since a 9 bytes is already used for ID, FUNCTION, ADDRESS, 62 NO OF REGISTERS, NO OF BYTES and two BYTES CRC the master can only write 63 50 bytes or 25 registers. 64 65 Since it is assumed that you will mostly use the Arduino to connect to a 66 master without using a USB to Serial converter the internal buffer is set 67 the same as the Arduino Serial ring buffer which is 128 bytes. 68*/ 69 70 71// Using the enum instruction allows for an easy method for adding and 72// removing registers. Doing it this way saves you #defining the size 73// of your slaves register array each time you want to add more registers 74// and at a glimpse informs you of your slaves register layout. 75 76//////////////// registers of your slave /////////////////// 77enum 78{ 79 // just add or remove registers and your good to go... 80 // The first register starts at address 0 81 ADC0, 82 ADC1, 83 ADC2, 84 ADC3, 85 ADC4, 86 ADC5, 87 LED_STATE, 88 BUTTON_STATE, 89 TOTAL_ERRORS, 90 // leave this one 91 TOTAL_REGS_SIZE 92 // total number of registers for function 3 and 16 share the same register array 93}; 94 95unsigned int holdingRegs[TOTAL_REGS_SIZE]; // function 3 and 16 register array 96//////////////////////////////////////////////////////////// 97 98void setup() 99{ 100 /* parameters(long baudrate, 101 unsigned char ID, 102 unsigned char transmit enable pin, 103 unsigned int holding registers size, 104 unsigned char low latency) 105 106 The transmit enable pin is used in half duplex communication to activate a MAX485 or similar 107 to deactivate this mode use any value < 2 because 0 & 1 is reserved for Rx & Tx. 108 Low latency delays makes the implementation non-standard 109 but practically it works with all major modbus master implementations. 110 */ 111 112 modbus_configure(9600, 1, 6, TOTAL_REGS_SIZE, 0); 113 pinMode(ledPin, OUTPUT); 114 pinMode(buttonPin, INPUT); 115 116} 117 118void loop() 119{ 120 // modbus_update() is the only method used in loop(). It returns the total error 121 // count since the slave started. You don't have to use it but it's useful 122 // for fault finding by the modbus master. 123 holdingRegs[TOTAL_ERRORS] = modbus_update(holdingRegs); 124 for (byte i = 0; i < 6; i++) 125 { 126 holdingRegs[i] = analogRead(i); 127 delayMicroseconds(50); 128 } 129 130 byte buttonState = digitalRead(buttonPin); // read button states 131 132 // assign the buttonState value to the holding register 133 holdingRegs[BUTTON_STATE] = buttonState; 134 135 // read the LED_STATE register value and set the onboard LED high or low with function 16 136 byte ledState = holdingRegs[LED_STATE]; 137 138 if (ledState) // set led 139 { 140 digitalWrite(ledPin, HIGH); 141 } 142 else if (ledState == 0) // reset led 143 { 144 //digitalWrite(ledPin, LOW); 145 holdingRegs[LED_STATE] = 0; 146 } 147 148}
Sample code for Arduino UNO
arduino
1/* 2 * Test program for Arduino RS422/RS485 Shield 3 * Version 4 1.0 5 * Copyright (C) 2018 Hartmut Wendt www.zihatec.de 6 * 7 * (based 8 on sources of https://github.com/angeloc/simplemodbusng) 9 * 10 * 11 * This 12 program is free software: you can redistribute it and/or modify 13 * it under 14 the terms of the GNU General Public License as published by 15 * the Free Software 16 Foundation, either version 3 of the License, or 17 * (at your option) any later 18 version. 19 * 20 * This program is distributed in the hope that it will be useful, 21 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 * MERCHANTABILITY 24 or FITNESS FOR A PARTICULAR PURPOSE. See the 25 * GNU General Public License 26 for more details. 27 * 28 * You should have received a copy of the GNU General 29 Public License 30 * along with this program. If not, see <http://www.gnu.org/licenses/>. 31*/ 32 33 34#include <SimpleModbusSlave.h> 35 36#define ledPin 12 // onboard led 37 38#define buttonPin 7 // push button 39 40 41 42/* This example code has 43 9 holding registers. 6 analogue inputs, 1 button, 1 digital output 44 and 1 register 45 to indicate errors encountered since started. 46 Function 5 (write single coil) 47 is not implemented so I'm using a whole register 48 and function 16 to set the 49 onboard Led on the Atmega328P. 50 51 The modbus_update() method updates the 52 holdingRegs register array and checks communication. 53 54 Note: 55 The 56 Arduino serial ring buffer is 128 bytes or 64 registers. 57 Most of the time 58 you will connect the arduino to a master via serial 59 using a MAX485 or similar. 60 61 62 In a function 3 request the master will attempt to read from your 63 slave 64 and since 5 bytes is already used for ID, FUNCTION, NO OF BYTES 65 and two BYTES 66 CRC the master can only request 122 bytes or 61 registers. 67 68 In a function 69 16 request the master will attempt to write to your 70 slave and since a 9 bytes 71 is already used for ID, FUNCTION, ADDRESS, 72 NO OF REGISTERS, NO OF BYTES and 73 two BYTES CRC the master can only write 74 118 bytes or 59 registers. 75 76 77 Using the FTDI USB to Serial converter the maximum bytes you can send is limited 78 79 to its internal buffer which is 60 bytes or 30 unsigned int registers. 80 81 82 Thus: 83 84 In a function 3 request the master will attempt to read 85 from your 86 slave and since 5 bytes is already used for ID, FUNCTION, NO OF 87 BYTES 88 and two BYTES CRC the master can only request 54 bytes or 27 registers. 89 90 91 In a function 16 request the master will attempt to write to your 92 slave 93 and since a 9 bytes is already used for ID, FUNCTION, ADDRESS, 94 NO OF REGISTERS, 95 NO OF BYTES and two BYTES CRC the master can only write 96 50 bytes or 25 registers. 97 98 99 Since it is assumed that you will mostly use the Arduino to connect to a 100 101 master without using a USB to Serial converter the internal buffer is set 102 103 the same as the Arduino Serial ring buffer which is 128 bytes. 104*/ 105 106 107// 108 Using the enum instruction allows for an easy method for adding and 109// removing 110 registers. Doing it this way saves you #defining the size 111// of your slaves 112 register array each time you want to add more registers 113// and at a glimpse informs 114 you of your slaves register layout. 115 116//////////////// registers of your slave 117 /////////////////// 118enum 119{ 120 // just add or remove registers and 121 your good to go... 122 // The first register starts at address 0 123 ADC0, 124 125 ADC1, 126 ADC2, 127 ADC3, 128 ADC4, 129 ADC5, 130 LED_STATE, 131 132 BUTTON_STATE, 133 TOTAL_ERRORS, 134 // leave this one 135 TOTAL_REGS_SIZE 136 137 // total number of registers for function 3 and 16 share the same register array 138}; 139 140unsigned 141 int holdingRegs[TOTAL_REGS_SIZE]; // function 3 and 16 register array 142//////////////////////////////////////////////////////////// 143 144void 145 setup() 146{ 147 /* parameters(long baudrate, 148 unsigned char 149 ID, 150 unsigned char transmit enable pin, 151 unsigned 152 int holding registers size, 153 unsigned char low latency) 154 155 156 The transmit enable pin is used in half duplex communication to activate a 157 MAX485 or similar 158 to deactivate this mode use any value < 2 because 0 & 159 1 is reserved for Rx & Tx. 160 Low latency delays makes the implementation non-standard 161 162 but practically it works with all major modbus master implementations. 163 164 */ 165 166 modbus_configure(9600, 1, 6, TOTAL_REGS_SIZE, 0); 167 pinMode(ledPin, 168 OUTPUT); 169 pinMode(buttonPin, INPUT); 170 171} 172 173void loop() 174{ 175 176 // modbus_update() is the only method used in loop(). It returns the total error 177 178 // count since the slave started. You don't have to use it but it's useful 179 180 // for fault finding by the modbus master. 181 holdingRegs[TOTAL_ERRORS] = modbus_update(holdingRegs); 182 183 for (byte i = 0; i < 6; i++) 184 { 185 holdingRegs[i] = analogRead(i); 186 187 delayMicroseconds(50); 188 } 189 190 byte buttonState = digitalRead(buttonPin); 191 // read button states 192 193 // assign the buttonState value to the holding 194 register 195 holdingRegs[BUTTON_STATE] = buttonState; 196 197 // read the LED_STATE 198 register value and set the onboard LED high or low with function 16 199 byte ledState 200 = holdingRegs[LED_STATE]; 201 202 if (ledState) // set led 203 { 204 205 digitalWrite(ledPin, HIGH); 206 } 207 else if (ledState == 0) // reset led 208 209 { 210 //digitalWrite(ledPin, LOW); 211 holdingRegs[LED_STATE] = 0; 212 } 213 214 215}
Downloadable files
Wiring Arduino
Wiring of some test components to the Arduino
Wiring Arduino
Comments
Only logged in users can leave comments