I am trying to implement an modbus device with a lot of registers, right now I need around 350 registers. However, once I try to send over 255 registers, Modbus poll gets an Illegal Data Address error
EDIT: To be clear, my device is the slave, I am using Modbus Poll to read the information.
Processor atmega2560, programming in Microchip Studio. I am using the library Modbus-Master-Slave-for-Arduino (github.com/smarmengol/Modbus-Master-Slave-for-Arduino)
Another user had the same issue and solved it (supposedly) with this library. Modbus Registers beyond 255 cannot be accessed SimpleModbus
However, once I increase my poll size to 256 I get an Illegal Data Address in Modbus Poll.
usb.poll(au16dataTotal, 255); works fine, I expanded the buffer to 256 so I can poll up to 123 registers at a time on modbus poll usb.poll(au16dataTotal, 256); Does not work.
The array of data that it is pulling from is large enough uint16_t au16dataTotal[500];
Taking a look at the library I don't think this is possible, as the size appears to be 8 bits or am I doing something wrong? Or is it worth trying to edit the library?
from the library:
/**
* @brief
* *** Only for Modbus Slave ***
* This method checks if there is any incoming query
* Afterwards, it would shoot a validation routine plus a register query
* Avoid any delay() function !!!!
* After a successful frame between the Master and the Slave, the time-out timer is reset.
*
* @param *regs register table for communication exchange
* @param u8size size of the register table
* @return 0 if no query, 1..4 if communication error, >4 if correct query processed
* @ingroup loop
*/
int8_t Modbus::poll( uint16_t *regs, uint8_t u8size )
{
au16regs = regs;
u8regsize = u8size;
uint8_t u8current;
// check if there is any incoming frame
u8current = port->available();
if (u8current == 0) return 0;
// check T35 after frame end or still no frame end
if (u8current != u8lastRec)
{
u8lastRec = u8current;
u32time = millis();
return 0;
}
if ((unsigned long)(millis() -u32time) < (unsigned long)T35) return 0;
u8lastRec = 0;
int8_t i8state = getRxBuffer();
u8lastError = i8state;
if (i8state < 7) return i8state;
// check slave id
if (au8Buffer[ ID ] != u8id) return 0;
// validate message: CRC, FCT, address and size
uint8_t u8exception = validateRequest();
if (u8exception > 0)
{
if (u8exception != NO_REPLY)
{
buildException( u8exception );
sendTxBuffer();
}
u8lastError = u8exception;
return u8exception;
}
u32timeOut = millis();
u8lastError = 0;
// process message
switch( au8Buffer[ FUNC ] )
{
case MB_FC_READ_COILS:
case MB_FC_READ_DISCRETE_INPUT:
return process_FC1( regs, u8size );
break;
case MB_FC_READ_INPUT_REGISTER:
case MB_FC_READ_REGISTERS :
return process_FC3( regs, u8size );
break;
case MB_FC_WRITE_COIL:
return process_FC5( regs, u8size );
break;
case MB_FC_WRITE_REGISTER :
return process_FC6( regs, u8size );
break;
case MB_FC_WRITE_MULTIPLE_COILS:
return process_FC15( regs, u8size );
break;
case MB_FC_WRITE_MULTIPLE_REGISTERS :
return process_FC16( regs, u8size );
break;
default:
break;
}
return i8state;
}
EDIT: My code below, I simplified it for this example. I currently have this running on my device.
#include <Arduino.h>
#include <ModbusRtu.h>
uint16_t au16dataTotal[500];
Modbus usb(1, 3, 0);
modbus_t telegram;
void setup() {
Serial3.begin(115200);
}
void loop() {
for(int i = 0; i <= 499; i++){
au16dataTotal[i] = i;
}
usb.poll(au16dataTotal, 255);
}