Frustration with PLC to Arduino communication using Modbus RTU

Hi guys, first time poster here but long time reader. I am working on a project in which I am using a Leonardo (keyestudio version) to control a stepper motor driver. The Leonardo needs to communicate with a PLC which contains the main control system for the machine. I am able to connect the PLC (Automation Direct Click PLC) to the Leonardo via Modbus RTU. I am also using a MAX485 RS-485 module to get from Modbus to TTL.

The crux I have now arrived at is how to ensure I have the proper settings on both the PLC and the Leonardo sides such that the two are communicating.

When configuring the PLC, I am being prompted to specify certain things that I am unsure how to set on the Leonardo side:

  • Slave ID of Serial Device - how do I check/change this on the Leonardo?
  • Addressing type: it is requiring me to choose between Modbus 984 addressing and Modbus Hex addressing, which should I choose?
  • Modbus Function Code: I want to read/write a value therefore I am assuming "06 - Write Single Register" is correct?
  • Starting Slave Address: How do I set this on the Leonardo?

Furthermore, on the Comm Port settings of the PLC, I am being prompted to select:

  • Parity: it is requiring me to choose from None, Even or Odd. Which is required for the Leonardo?
  • Stop Bit: I can choose between 1 or 2?
  • Node Address: can be 1 to 247. I'm assuming that this is the Slave ID - is this right?

I've attached some screenshots from the PLC software for your information.
Thanks!

Slave ID of Serial Device - how do I check/change this on the Leonardo?

That's set in the software. You can choose any valid Modbus ID, just set in accordingly in your slave sketch.

Addressing type: it is requiring me to choose between Modbus 984 addressing and Modbus Hex addressing, which should I choose?

That's nothing defined in the Modbus standard. Consult your manual for an explanation of what these terms mean.

Modbus Function Code: I want to read/write a value therefore I am assuming "06 - Write Single Register" is correct?

Function 6 writes a single holding register, reading the same is function 3.

Starting Slave Address: How do I set this on the Leonardo?

You have to define it in the sketch. Probably 40000 is translated into address 0 in the Leonardo sketch but the depends on the PLC manufacturers implementation, many of them are wrong this way.

Parity: it is requiring me to choose from None, Even or Odd. Which is required for the Leonardo?

You can set that in your sketch. Modbus usually uses even parity.

Stop Bit: I can choose between 1 or 2?

Should be 1 in most situations but also depends on the used sketch.

Node Address: can be 1 to 247. I'm assuming that this is the Slave ID - is this right?

Might be, but unclear without consulting the PLCs manual.

I am able to connect the PLC (Automation Direct Click PLC) to the Leonardo via Modbus RTU.

I'm missing the wiring diagram of this setup.

Thanks pylon. I have made some headway with this project and have succeeded in getting partial communication going between the PLC and the Arduino. But I have arrived at another crux…

With the following code, I can successfully write values from the PLC to the Arduino, but cannot read values from the Arduino to the PLC. Any ideas what I need to do? I have verified that the settings on the PLC side are all correct as I can receive data from another Modbus slave device.

//RS-485 Modbus Slave (Arduino Leonardo)

#include<ModbusRtu.h>       //Library for using Modbus in Arduino

#define input1 13              //Define digital pin 13 as input pin

Modbus bus;                          //Define Object bus for class modbus 
uint16_t modbus_array[] = {0,0,0,3,4,5};    //Array initilized with values shown
                      
void setup()
{
        
  pinMode(input1,INPUT);           
  
  bus = Modbus(1,1,11);            //Modbus slave ID as 1 and 1 connected via RS-485 and DIGITAL PIN 11 connected to DE & RE pin of RS-485 Module 
  bus.begin(9600);                //Modbus slave baudrate at 9600
}

void loop()

{
   bus.poll(modbus_array,sizeof(modbus_array)/sizeof(modbus_array[0]));       //Used to receive or write value from Master 
    
     modbus_array[2] = digitalRead(input1);

}

I would have expected that the PLC should be able to read register 0-5 using that sketch. Do you get an error code on the PLC? The poll() method returns an error code maybe you should write it to the USB serial interface for debugging if it isn't 0.