I have the following problem:
I want send 200 registers from a modbus master to a slave. Both are arduinos.
I can't send more than 27 registers. When I send more i get the Errorcode 255
which means timeout
. I know that the modbus message is limited to 253 bytes (256 bytes - server address (1 byte) - CRC (2 bytes)). Listed here: MODBUS APPLICATION PROTOCOL SPECIFICATION page.5
My setup:
I use two Arduino Mega 2560. One as a master and the other as the slave. If that works I want to use more than one slave. They are connected via Serial1 master TX1 (pin18) to slave RX1 (pin19) and master RX1 (pin19) to slave TX1 (pin18).
The modbus library I'm using is ModbusRtu.h from smarmengol.
Because i want to ultimately communicate with more than one slave device I use RS-485. To send the message as a broadcasat but thats not relevant now because first I want to send to one slave to test it out.
I know that the array is much bigger as the registers I want to send. Thats because I wanted to know when the the timeout happens. Sending 27 registers works fine and the slave recieves all of the 27. But when sending more than 27 registers I get the timeout and nothing will be send.
Master code
#define SERIAL_BUFFER_SIZE 256
#include "ModbusRtu.h"
#define Timeout 150
#define QUERYINTERVALL 50
/* Defined the buffersize as stated in
* C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\USBAPI.h
*/
modbus_t telegram;
// Test sending large array
uint16_t sendLargeArray[200] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153,
154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165,
166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
190, 191, 192, 193, 194, 195, 196, 197, 198, 199};
Modbus master;
void dataSend();
void setup()
{
/**
* Modbus object declaration
* u8id : node id = 0 for master, = 1..247 for slave
* u8serno : serial port (use 0 for Serial)
* u8txenpin : 0 for RS-232 and USB-FTDI
* or any pin number > 1 for RS-485
*/
master = Modbus(0, 1, 8); // this is master with RS-485 config
master.begin(9600, SERIAL_8N2);
master.setTimeOut(Timeout);
Serial.begin(9600); // setup Serial for USB debugging
}
void loop()
{
uint8_t error = master.getLastError(); //get errorcode
uint8_t state = master.getState(); // get state from master 0 = idle 1 = waiting
dataSend(); // function for sending array
// Error Code
Serial.print("Error code: ");
Serial.print(error);
Serial.println();
// Print master state
Serial.print("Master State: ");
Serial.print(state);
Serial.println();
}
void dataSend()
{
uint8_t slaveId;
uint8_t u8state;
unsigned long u32wait;
slaveId = 1;
u32wait = millis() + QUERYINTERVALL;
bool staywhile = true;
// telegram for sending sendLargeArray
telegram.u8id = 1;
telegram.u8fct = 16;
telegram.u16RegAdd = 0;
telegram.u16CoilsNo = 28; // 27 or less works fine
telegram.au16reg = sendLargeArray;
u8state = 0;
// Master broadcasts data
while (staywhile)
{
switch (u8state)
{
case 0:
if (millis() > u32wait)
u8state++; // wait state
break;
case 1:
master.query(telegram); // send query (only once)
u8state++;
case 2:
master.poll(); // check incoming messages
if (master.getState() == COM_IDLE)
{
u8state = 0;
u32wait = millis() + QUERYINTERVALL;
staywhile = false;
}
break;
}
}
}
Slave code
#define SERIAL_BUFFER_SIZE 256
#include "ModbusRtu.h"
/* Defined the buffersize as stated in
* C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\USBAPI.h
*/
// data array for modbus network sharing
uint16_t recieveLargeArray[200] = {};
/**
* Modbus object declaration
* u8id : node id = 0 for master, = 1..247 for slave
* u8serno : serial port (use 0 for Serial)
* u8txenpin : 0 for RS-232 and USB-FTDI
* or any pin number > 1 for RS-485
*/
Modbus slave(1, 1, 8); // this is slave @1 and RS-485
void setup()
{
Serial.begin(9600);
slave.begin(9600, SERIAL_8N2); // baud-rate at 9600
}
void loop()
{
uint8_t error = slave.getLastError();
slave.poll(recieveLargeArray, 28); // receiving 27 or less registers works fine
// print every 5th element of the recieved array
// no spamming console that way
Serial.print("Recieve: ");
for (int i = 0; i < 200; i += 5)
{
Serial.print(recieveLargeArray[i]);
Serial.print(",");
}
// Error Code
Serial.println();
Serial.print("Error code: ");
Serial.print(error);
Serial.println();
memset(recieveLargeArray, 0, 200 * sizeof(uint16_t)); // recieveLargeArray = {}
}
Questions
- Does anyone know why I cant send more than 27 registers?
- Did anyone made a simillar project and can share the code?
- Has anyone a fix for that?
Help is very appreciated.
Cheers ueberBrot
Link issuepage on ModbusRTU.h GitHub
Edit
Forgot to mention that I increased the buffer size inside the
ModbusRTU.h
library aswell. I did it like that#define MAX_BUFFER 256
as mentioned in this comment from JurajChanged the define location of
#define SERIAL_BUFFER_SIZE 256
in both sketches to the top.