Modbus RTU Arduino Nano & PLC

Hello, I am trying to use modbus from a plc through a gate way connected to a line of PCB. The nano is on the pcb. I have tried multiple modbus libraries and none of them seemed to be working for me. I am wondering if I am missing something in my code or if it's a hardware issue. I am continuing a project that someone else has started so it's been a journey to figure out what is going on.

Plc is master, nanos are slaves.
RS485, using a RS487 max on the pcb.
Also using a usb converter.

I have primarily been working with the Simple Modbus slave library. Then I converted it to ModbusRTU library and also ModbusRTUSlave.

I tried different types of modbus simulators, none of them can communicate to the arduino.
I have downloaded drivers, updated everything I can, research every part I am using to make sure I have correct software and connections. Ive research modbus on arduino for two weeks now and nothing has help solved my problem.
I have tried switching the connections of the rx and tx pins.

The board has LED lights and buttons. Those are the values for the registers. There is a dipswitch that determines the address. I've changed somethings since making the comments. Also somethings like the intensity is commented out because it is not being used.

SimpleModbus

#include <SimpleModbusSlave.h>

//Working with Amber- setup for the PCB circuit
/* parameters(HardwareSerial* SerialPort,
                long baudrate, 
    unsigned char byteFormat,
                unsigned char ID, 
                unsigned char transmit enable pin, 
                unsigned int holding registers size,
                unsigned int* holding register array)
  */
  
  /* Valid modbus byte formats are:
     SERIAL_8N2: 1 start bit, 8 data bits, 2 stop bits
     SERIAL_8E1: 1 start bit, 8 data bits, 1 Even parity bit, 1 stop bit
     SERIAL_8O1: 1 start bit, 8 data bits, 1 Odd parity bit, 1 stop bit
     
     You can obviously use SERIAL_8N1 but this does not adhere to the
    
  */
 

#define TXEnable 2
//LED colors set by different pins
#define GRN 9
#define RED 6
#define BLU 5
#define Intensity 255

//Functions
byte address();
void Regs();
//void Testing();

//////////////// registers of your slave ///////////////////
enum 
{     
  // just add or remove registers and your good to go...
  
  COLOR,
  Button, 
  
  HOLDING_REGS_SIZE // leave this one
  // total number of registers for function 3 and 16 share the same register array
  // i.e. the same address space
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array

////////////////////////////////////////////////////////////


void setup()
{ 
Serial.begin(9600,SERIAL_8N2); 

  int SlaveID;
        SlaveID = address();
        
  modbus_configure(&Serial, 9600, SERIAL_8N2, SlaveID, TXEnable, HOLDING_REGS_SIZE, holdingRegs);

  // modbus_update_comms(baud, byteFormat, id) 
  modbus_update_comms(9600, SERIAL_8N2, SlaveID);
  
 // pinMode(LED, OUTPUT);
  pinMode(RED, OUTPUT);
  pinMode(GRN, OUTPUT);
  pinMode(BLU, OUTPUT);
  pinMode(10, INPUT);
  
   //Intialize all LEDs off
   analogWrite(GRN, 0);
   analogWrite(RED, 0);
   analogWrite(BLU, 0);

   
}

void loop()
{
  // modbus_update() is the only method used in loop().

  modbus_update();

   Regs();
/
  
}

/* The function address sets up the dipswitch with the pins on the Arduino. 
 The values of each pin are then made into one binary address. 
 The address is used by the Master (PLC) to communicated with individual lights. 
 The Slave (lights) compare its address to the address the master sends out.*/
byte address(){
 //Serial.begin(9600);//Begin Serial Communication at baud rate of 9600
  
 char dipPins[] = {A4, A3, A2, A1, A0}; //DIP Switch Pins
 int i,j=0; //Counter variables
 
 //Initialize Dipswitch
  for(i = 0; i<=4; i++){
        pinMode(dipPins[i], INPUT);      // sets the digital pin 2-5 as input
        digitalWrite(dipPins[i], HIGH);} //Set pullup resistor on
          delay(100);
          
//Read Dipswitch's Values for pins 1-5
  for(i=0; i<=4; i++){
      j = (j << 1) | digitalRead(dipPins[i]);}   // read the input pin then shift to the next bit
       return j;} //return address




/*The Regs function reads or writes to the slaves registers.
  The Master sends a binary string, the first section is color, second is address, third is intensity. 
  
  There are 3 registers: Button, PWM_VAL, and COLOR.
     Button tells the Master if the button is pressed or unpressed. The Slave writes to this register and the master reads it.
     PWM_VAL is the intensity or the flashing speed of the light. The Slave reads from this register and the Master writes to it.
     COLOR is the color of the LED. Each color is a pin on the board that connect to LED pins. The Slave reads this register and the Master writes to it.
     
  The shift instruction is to read from each bit of the binary string. A 1 indicates the settings that are wanted and a 0 is for the settings that aren't wanted.*/

void Regs(){

  int btnState;//State of Button
  
  //Button Register
    btnState = digitalRead(10); //Read if button is HIGH or Low from pin 10
    
   //Button Pressed
    if(btnState == HIGH) 
      holdingRegs[Button] = 1; 

   //Button NOT Pressed 
    else if(btnState == LOW)
      holdingRegs[Button] = 2;
      
//    Error
 else
    holdingRegs[Button] = 3;
    
    
//Pulse Width Modulation Register

  //High
  /*if(holdingRegs[PWM_VAL] & (1<<0))
      Intensity = 255; 
      
  //MEDIUM
  else if(holdingRegs[PWM_VAL] & (1<<1))
     Intensity = 125;
     
  //LOW 
  else if(holdingRegs[PWM_VAL] & (1<<2))
     Intensity = 50; */



//Color Register 

//GREEN
  if(holdingRegs[COLOR] = 1){
      analogWrite(GRN, Intensity); 
      analogWrite(RED, 0);
      analogWrite(BLU, 0);}
      
//RED
else if(holdingRegs[COLOR] = 2) {
      analogWrite(GRN, 0); 
      analogWrite(RED, Intensity);
      analogWrite(BLU, 0);}
      
//BLUE
else if(holdingRegs[COLOR]= 4) {
      analogWrite(GRN, 0); 
      analogWrite(RED, 0);
      analogWrite(BLU, Intensity);}
      
//YELLOW
else if(holdingRegs[COLOR] = 8) {
      analogWrite(GRN, Intensity*.39); 
      analogWrite(RED, Intensity);
      analogWrite(BLU, 0);}
      
// Wrong number, defaults to White
else{
      analogWrite(GRN, 255); 
      analogWrite(RED, 255);
      analogWrite(BLU, 255);} 
}

//Turns on all the lights to test if they are working
/*void Testing(){
 int j =0;
     modbus_update_comms(9600, SERIAL_8N2, j);
     
      analogWrite(GRN, 255); 
      analogWrite(RED, 255);
      analogWrite(BLU, 255);
}*/

My Problem:
The Modbus simulations / Gateway cant read or write to the arduino.
I got the arduino to return 0s instead of just not being able to transmit or receive anything.

Do not be hateful, I am asking for assistance and CONSTRUCTIVE criticism please.

I'm not that familiar with modbus but I have a suggestion that may help you. If you go right back to basics and write a simple bit of code that just monitors the serial port and prints out what it receives, that might be a starting point.

You would need to get the baud rate, parity & stop bits right but you already know what they should be.

You can then print out every byte received as a 2 digit hexadecimal number.

You might end up with a lot of data being printed out, depending on the amount of activity in your bus.

That should bypass everything to do with modbus protocol and simply monitor what's going on.

You can then look to see if any of the raw modbus messages are displayed.

Would you suggest monitoring it through something like putty?

You could use something like Putty.

I assume that you have used the hardware serial port for your modbus connection. If you are only receiving, then the TX pin could connect to a USB-TTL UART such as an FTDI board of a CH340g board. You could then simply send out what you receive on your RX pin. Obviously it would have to be the same baud rate etc.

That way you would know that your nano is receiving raw data correctly.

You could even go one stage simpler and take the nano out of the equation and connect the USB-TTL UART direct to the TTL side of your bus.

You would need a serial monitor program that can display raw hexadecimal data rather than just ASCII characters. I've used a free program on the pc called Hercules for this in the past.

At least you would know what's happening on your bus.

I should have said that you can get Hercules here. There's not a lot of documentation about for it but once you have your serial port setup, you can right click on the main area of the screen where the received data is displayed and a menu should pop up allowing you to display the received data as hexadecimal bytes rather than ASCII characters.

Also, there's a useful modbus tool on the Schneider Electric website that may help you. You can find it here. Scroll down past the video to where it says "here is a copy of the program".

I have tried using that modbus tool, I have few to make sure that it works on all of them.

I tried a serial monitor that let's use choose how to read the data (hex, binary, ..etc).
I only saw what the master was sending out.
So I tried just writing something onto serial from the board just to see if I could send anything at all. It is not working, I cant do basic serial communication. Im not sure if it's because the max487 chip or some other hardware issue. Im starting to think it's most likely not a software issue.

Now after thinking, reading, and researching some more. I am thinking the problem is the timing in the library because it states that it is not 100% following modbus standards.

Where did you connect your serial monitor to?

Did you connect to the Rx pin on the nano? If so, then you should see what the master is sending out. That shows that your RS485 receiver is working.

rmcdonaldembry:
Plc is master, nanos are slaves.
RS485, using a RS487 max on the pcb.
Also using a usb converter.

I think you are saying that you are using a MAX487 as the RS-485 transceiver chip?

If you connect your serial monitor to the Tx pin on the nano, can you see the Modbus response messages from the nano?

If you can, then it sounds like the nano is not switching the the MAX487 into transmit mode.

Or maybe the nano is switching the MAX487 into transmit mode, but then it is switching back to receive mode too quickly and not allowing the final byte of the message to clear the UART Tx buffer, so as far as the PLC is concerned, it receives only part of the final byte of the message.

The usb converter is connected to the computer, where I am using a serial monitor.

Ok, you should be able to connect the receive pin on your usb converter to the receive pin on the nano and see the raw modbus messages that are being received.

From what I understand of your posts, you've done this already and confirmed that the modbus messages are getting as far as the receive pin on the nano.

If that works ok, you can connect the receive pin on your usb converter to the transmit pin on your nano and see the raw modbus replies being generated by your nano.

If you see nothing at all, then maybe your nano doesn't think the message is for it.

So it turns out the intern before me got a refund on these nanos and didn't say anything to me or the supervisor but she was still using them?.?. So the nanos are broken, I just ordered some unos instead. They both use the AtMEGA328p, but this still doesn't explain why the pcbs dont work. So, I also order the AtMEGA328p on its own.

I have been emailing with support for over a week (they take 2 days to respond and didn't read my emails very well). Then over the past few days they started getting warm / hot. That's when arduino support told me to get a refund, then I came to find out they got a refund a year ago.

This project has really been an adventure to say the least.