smarmengol / Modbus-Master-Slave-for-Arduino

Modbus Master-Slave library for Arduino
GNU Lesser General Public License v2.1
473 stars 328 forks source link

Problem with modbus communication between two arduinos when writing more than 27 registers #40

Closed ueberBrot closed 4 years ago

ueberBrot commented 5 years ago

Hey,

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 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

    #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
    */
    #define SERIAL_BUFFER_SIZE 256
    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

    #include "ModbusRtu.h"

    /* Defined the buffersize as stated in 
         * C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\USBAPI.h
        */
    #define SERIAL_BUFFER_SIZE 256

    // 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

Help is very appreciated.

Cheers ueberBrot

Link to Arduino Stackexchange

smarmengol commented 5 years ago

Dear ueberBrot,

I've left this project some time ago, as you may have appreciated. I've never used more than 16 registers in the same telegram. Indeed there is a limitation in the telegram constructor:

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

This is at line 137 in "ModbusRtu.h" file. You should extend this value.

Try this!

Cheers,