HELP! Sending data through Modbus RS485

Hello i really need some help, i am trying to send some simple data from an Arduino acting as a master to some software acting as the slave. I am currently using Modbus poll to read the data that is being transmitted from the Arduino but i am having some errors.

I am using some example code found online which incorporates the ModbusMaster.h library in order to send data to a holding register. I want to send a binary 1 to the register from the Arduino in order to use this as a trigger in my software.

I am confident that my hardware is configured in the right way as i am seeing expected results when pressing the push button (writes to LCD correctly & Modbuspoll receives some kind of data). I have digital inputs connected to the DE & RE Pins on the Rs 485 and the Arduino RX & TX connected to DI & RO. I then have the A+ and B- connected to the respective terminals on the Rs485 IC to the SH-U10 USB converter.

My problem feels like it is within the software side of the project, when i compile my code which isn’t much different from the example code i found online, i am receiving an error;

warning: large integer implicitly truncated to unsigned type [-Woverflow]

     node.writeSingleRegister(0x40001, 1);

But the code still compiles and let’s me upload to Arduino device.

I open modbus poll to see if the data has been transmitted correctly i get an error when i push the button, the LCD prints S1: High but modbus poll shows

“insufficient bytes received”

The Arduino IDE serial monitor also show’s 3-4 square boxes and a weird character, not the information expected to be transmitted. I am quite frankly not sure what is going wrong here as the code is identical to the example and people have been able to get that working fine, it just seems like my byte data being trasmitted isn’t correct. Any help would be gratefully appreciated and Thankyou in advance!

The hardware i’m using;

Arduino Uno
5V TTL to Rs485 Module
SH-U10 USB to RS485 Converter
Push Button
LCD

The code i’m using:

#include <ModbusMaster.h>               
#include <LiquidCrystal.h>

#define MAX485_DE      9
#define MAX485_RE_NEG  3

ModbusMaster node;

LiquidCrystal lcd(8, 2, 4, 5, 6, 7);

void preTransmission()            
{
  digitalWrite(MAX485_RE_NEG, 1);
  digitalWrite(MAX485_DE, 1);
}

void postTransmission()
{
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);
}
const int button1 = 10;
const int button2 = 11;
const int button3 = 12;
const int button4 = 13;




void setup() {
  lcd.begin(14, 2);
 

  pinMode(button3, INPUT);
  
  pinMode(MAX485_RE_NEG, OUTPUT); //declaring pinmode output for max485
  pinMode(MAX485_DE, OUTPUT); //declaring pinmode output for max485



  lcd.print("Welcome!");
  delay(1000);
  lcd.clear();
  lcd.print("Project Simulation");
  delay(1000);

  digitalWrite(MAX485_RE_NEG, 0); //initialise
  digitalWrite(MAX485_DE, 0); //initialise

  Serial.begin(9600);


  node.begin(1, Serial);     //Slave ID as 1
  node.preTransmission(preTransmission);         //Callback for configuring RS-485 Transreceiver correctly
  node.postTransmission(postTransmission);


}


void loop() {


  int a = digitalRead(button3);
 

  if (a == 1)
  {
    node.writeSingleRegister(0x40001, 1);
    lcd.setCursor(0, 1);
    lcd.print("S1: HIGH");
  }

}

2.jpg

3.jpg

4.jpg

Can anyone help? Can provide pictures of my wiring setup. Keep getting checksum error or insufficient bytes received

hi, are you know if your device is possible use this function ?
usually the functions are 03 - Read Holding Registers
06 - write Single Register

are you can show more the project ?

Hi Yago, thanks for the reply. I am attempting to use function 06 write single register and write a single bit 1 to that register. I have just uploaded some pictures of the setup and the errors that i am receiving. I am not sure if i am sending the data correctly through the code

b

I may not be much help here as i'm not familiar with Modbus.

But, you may not get the expected output on the Arduino Serial Monitor if your Modbus data is being sent at an oddball speed (i.e. something other than 2400, 4800, 9600 etc). That might explain your strange characters.

There's an interesting article here that talks about Modbus and Arduino.They have a PC app called Modbustester that you might be able to use to determine what is happening on your bus.

Hi mark, i downloaded modbus tester and at the top next to read to says "error in RS port". I have included a picture above labelled modbus tester, any ideas?

Hmm, I don’t have any modbus capable equipment here so i’m not sure. I downloaded the tester and it doesn’t look like the one shown in your “modbus tester.png” file. Maybe when you have a real bus connected up, and hit read, then you end up with the screen you see.

Mine looks like the one in the attached screenshot.

The link I followed took me to here which is a page on the Schneider Electric website.

Generic Modbus Tester.png

Hello Mark, i couldn't find the download link for that tester. After doing some research i came across the modscan64 software. I have reconnected my project and i am still receiving the same errors. When i try to write

"node.writeSingleRegister(0x10001,1 );" i receive on the tester software the following -

Whilst system is idle i get " Modbus Message "TIME-OUT" " and when i press my discrete input to send the above data i receive "checksum error in response message" I have posted a picture to these errors above under modscan64 "timeout" & modscan64 "checksum error"

I have connected the software to COM3 through the rs485 to usb converter.

Strange.

I just checked and it's there. If you follow the link I gave you, you should end up on the Schneider Electric web site in the Browse FAQs section with a subject of "Video: What is Modbus Tester and how do I use it?".

There's some text, then a screenshot of the tool with some annotation and then a YouTube video.

Just below that, it says "Attached is a copy of the program: " and next to that is an icon for "Tester.exe". Clicking on the icon should download the file.

Okay thanks for the explanation, i found the program and downloaded. Typed the settings in and attempted to read the modbus through COM3. I then got a CRC error which can be seen in the CRC error.png i just posted, maybe this will shed a little light on the situation? Am i just not sending the data correctly?

I have also just added a screen caption of the wiring diagram, i'm sure my wiring is correct. I've rewired the project 5 times now and still receiving same errors. I have seen on other posts to do with rs 485 chip that people sometimes ground some of the pins like DI,DE etc. Could this maybe help here?

I was about to try and lead you through a step by step fault finding process but then I re-read your original post.

You said:

I open modbus poll to see if the data has been transmitted correctly i get an error when i push the button, the LCD prints S1: High but modbus poll shows

"insufficient bytes received"

My first thought, and it's quite a common gotcha with this type of setup, is that you may well be setting DE low too quickly. Once you've written the final byte to your serial hardware, you need to allow a bit of time for the byte to actually get out the UART Tx buffer before you set DE low. If you set DE low too quickly, you end up cutting off part of the last byte when you turn off the MAX485 transmit driver. That may be why you are getting the "insufficient bytes received".

I would try introducing a small delay between writing to the serial and setting DE low.

I had a quick look at the code of Modbusmaster on github and it looks like it's down to the user to implement the delay.

I would change:

void postTransmission()
{
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);
}

to something like:

void postTransmission()
{
  delay(2);
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);
}

That should insert a 2ms delay into your code before turning off the transmit driver. You're running at 9600 baud so one byte + start bit + parity bit + stop bit (i.e. 11 bits) takes about 11x 104us = 1.1ms to get all the bits clocked out.

If you are still getting "insufficient bytes received", then try increasing the delay a bit. You don't want to make the delay too big or you may get a bus conflict with 2 devices transmitting at the same time.

Okay so i added a delay into the post transmission of 2ms which in my IDE is (2000) and i still received insufficient bytes received, i kept moving it up 1ms a time and still received the same error. I've tried this up to 8ms, i also still get this compile error in the arduino IDE -

"warning: large integer implicitly truncated to unsigned type [-Woverflow]

node.writeSingleRegister(0x40001, 1);"

I have also added a 1ms delay into when the input is pressed and have the same results. When the code uploads to the arduino, the mbuspoll software when connected to the device instantly says " Timeout Error" whilst the code is idling and when the input is pressed i occasionally get "Checksum Error" but often "Insufficient Bytes received".

It still feels like something is conflicting with the data being sent, maybe it could be the way i am sending the actual data by printing to 06 single write register but i'm sure i have seen online that this works with other people. This is rather stressful as i have a project that's in soon and i have everything in front of me ready to work but the flipping data communication is not playing ball.

I have just posted a screenshot of the communication traffic between RX & TX. Does this data look correct to you?

I'm trying to get my head around Modbus as i've not used it.

What I can tell you is that the error message you are getting:

arduino303:
"warning: large integer implicitly truncated to unsigned type [-Woverflow]

node.writeSingleRegister(0x40001, 1);"

is because the writeSingleRegister() function is expecting a 16 bit address and the 0x40001 is bigger than 16 bits. Perhaps you meant to write 0x4001?

Looking at the screenshot of the traffic, i'm trying to decode it just to see if everything is there.

In the message "01 06 00 01 00 01 19 CA", it looks like:

"01"    = Slave Address - looks good as that's the address you've set
"06"    = WriteSingleRegister - looks good as that's the command you want
"00 01" = Address you are writing to - the lower 16 bits of the 0x40001
"00 01" = Data to write
"19 CA" = Checksum

From my limited knowledge, you are communicating in binary, rather than ASCII, so your message should be 8 bytes, which it is. This may also explain why the Arduino IDE serial monitor "show's 3-4 square boxes and a weird character".

For a number of years i've used a free program called Hercules from HW-Group that can view binary serial data. You can find it here. That might show you the data that you are sending.

Just another thought whilst it's in my mind: that address you are using 0x40001 - I'm going to hazard a guess that it is an address shown in the Modbus Tester screenshot you provided. It looks like those addresses are in decimal so if you want to use address 40001, then that's 0x9C41 in your writeSingleRegister() function.

If you want to write to address 40001, then just do:

node.writeSingleRegister(40001, 1);

That will also fix your compiler warning as 40001 will fit in 16-bits.

Okay so i changed the address to “node.writeSingleRegister(40001, 1);” and the compile error disappeared great! One step closer, i downloaded Hercules and pressed the input 3 times on COM3 to see the serial data which is strange characters i think this is to be expected as have read in places it’s hard to intercept the actual serial data. I have posted a screenshot of this in the original post, i tested Modbuspoll again and i’m unfortunately still receiving the errors “timeout error” and when the input is pressed, “insufficient bytes received”.

The communication traffic has changed, it now looks like it is writing to the address 9C 41 which as you stated above translates to 40001 as opposed to 00 01 address in the previous communication snapshot.

I’m still a little puzzled as to why as soon as i open modbuspoll and connect COM3 i instantly get “timeout error”

If I recall correctly, in Hercules, you can right click on the received data window and change the display format so that it shows bytes rather than ascii characters.

I had a quick look at modbuspoll and I don't think it's what you want to be using. The docs imply that it is a modbus master simulator designed to help develop slave devices. If that's the case, then it sort of makes sense that it would want to do the talking and expect a response from a slave device - maybe the reason for your timeout message.

Your scenario seems to be the opposite in that your arduino is the master and you want the pc to be the slave. If that's the case, then there's a free modbus slave simulator that might be of use. You can find it here.

One of the command line options is a master activity timeout which implies that maybe the modbus master is supposed to be constantly active to avoid these timeouts.

Of course all this could be completely wrong as I'm no modbus expert by any means.