0

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 Juraj

  • Changed the define location of #define SERIAL_BUFFER_SIZE 256 in both sketches to the top.

1

In ModbusRtu.h:

#define MAX_BUFFER 64 //!< maximum size for the communication buffer in bytes

27*2=54 bytes for registers and 10 for header and crc.

Change the MAX_BUFFER define. On Mega you have enough RAM.

btw: RS485 doesn't imply mandatory use of Modbus. You could use your own protocol.

  • Thank you for the answer @Juraj. Oh sorry forget to mention that in the original post. After I increased the Arduino buffer size to 256 byte I did the same inside the ModbusRTU.h library #define MAX_BUFFER 256 . So thats not the problem. Using my own protocol what do you mean by that? I dont have a clue how to do that so Im guessing its either not in my skillrange or I simply dont know where to begin. Can you explain or point me to an example? That I could use for my ultimate goal a master with many slaves? Cheers ueberBrot – ueberBrot Nov 15 '18 at 8:18
  • if it allows only 27 registers, then it didn't apply. what "Arduino buffer"? – Juraj Nov 15 '18 at 8:21
  • In the file ***\Arduino\hardware\arduino\avr\cores\arduino\USBAPI.h the SERIAL BUFFER SIZE (Arduino buffer) is defined from line 77 to 86. If the buffer is not defined like I did in my sketches #define SERIAL_BUFFER_SIZE 256 it has two default values 16 or 64 byte dependening of the Arduino RAM. Or is this wrong? – ueberBrot Nov 15 '18 at 8:29
  • not wrong, but not needed. The Serial buffer is really a 'buffer'. If full, write() waits a little until there is space (bytes are send out continuously). The buffer in ModbusRtu.h is not a real buffer, it is an array to build the complete message. – Juraj Nov 15 '18 at 8:36
  • Ah ok thought it may be connected to my problem thats why I increased it. If the change I did inside the library did not apply how is that? Do you have a clue? – ueberBrot Nov 15 '18 at 8:56
0

I did change the MAX_BUFFER inside ModbusRTU.h from 64 to 256. As you stated before in there its only the size for the used array. What I also did was move the #define SERIAL_BUFFER_SIZE 256 inside both my sketches to the top. That did nothing, After that I found a way to increase the RX and TX buffer size with the help of this post. I changed it from 64 to 256. maybe I could have changed those with a #define in my sketches aswell?.

Now I can send a max of 59 registers at once. Im not sure why I cant send more because the max should be 123 registers at once and the buffer is 256 bytes so 123 registers x 2 bytes = 246 is enough space in the buffer.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.