Using Modbus to Communicate Between DUE and UNO using RS485

Hello all, I hope you are doing well as you read this message.

I currently have an Arduino DUE that is stacked with a few shields that carries out the actions of measuring different parameters of a system I am analyzing. I ordered a thermocouple shield that is originally created to work on the UNO. After many hours of forums and personal work, I decided to give up and use Modbus as a work around.

Since the shield was incompatible with the DUE, I am going to use Modbus with RS485. I am going to use the working code/shield with the UNO to get the data I need, and then feed that into the DUE with modbus protocol.

I currently have the code for Modbus through Doc Walker's "ModbusMaster" files on Github, and I believe to have this side working on the DUE. But now I would need some assistance on getting the code set up for the ModbusSlave on the Arduino UNO. I have never experienced using Modbus or any other communication protocols like this, so even pointing me to an online example would help a lot!
As a beginner, I am already so confused on how this would work out without someone to guide me because I already do not understand at all how different libraries that were written by different people could work well together.

Have you searched for Modbus on the forums or Google? I know for certain it's been discussed a bit and should give you at least a few ideas. Possibly too many, but at least something to start with that's a little less open ended.

I would recommend you check out the "how to get the most out of this forum" and post what you've done so far. Schematics, code, etc.

I used Modbus professionally prior to my retirement 7 years ago. Different libraries written by different people will work together because the communication protocol is a standard, https://modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf. It's really intended for industrial use and is probably "overkill" for what you are trying to do. If the two Arduino boards are next to each other consider using I2C and the Arduino Wire library for drivers. Beyond that distance use the Serial interface, possibly with RS232 level converters. This will be much easier!

1 Like

Did some Modbus units few months back..
Modbus example
basically, you'd be reading registers, words..
some overhead and limitations but would work..
could also use 485 and send structures..
how many params??
and what type??

good luck.. ~q

you can try my modbus server simple:
https://werner.rothschopf.net/microcontroller/202112_arduino_modbus_server.htm

the API uses similar naming conventions like DocWalkers Modbus Master.

If you don't really need to use the Modbus approach, then have a read of Nick Gammon's RS485 posts here:
https://www.gammon.com.au/forum/?id=11428

So then are you saying that it might be better to use another method? If so, what is this method of communication called so that I can find more resources to help?

Does this work with RS485?

I am using RS485 shields, and also, I am unsure of what you mean when you say parameters?

these.. what data types and how many??

example
int Temp
int Humidity

the actual data to be transmitted and received needs to be defined..

that's step 1..

~q

yes.
This Modbus Slave (Server) Library
https://werner.rothschopf.net/microcontroller/202112_arduino_modbus_server.htm

will work with SoftSerial and HW Serial.

I see.
We have:
uint8_t th_types[4]
float cj_Voktage[4]
float th_Voltage_read[4]
float th_Voltage[4]
int32_t _ADCValaue0[4]
int32_t _ADCValue1[4]

Okay, I am trying one more library before trying to use yours.

It appears that there will be a stream of data from the Uno to the Due. And the two boards are next to each other and not, say, in different rooms. RS-485 is intended for fairly long distances and (electrically) noisy environments such as factory floors.

There are basically three interfaces provided on these boards that might be appropriate, Serial, I2C ("TWI"), and SPI. I would rule out SPI because while there is Arduino Library support for the controller role, there isn't for the peripheral role.

For Serial, you use one of the serial ports on the Due and the single serial port of the Uno, or you might be able to use the Software Serial on the UNO. The problem with the UNO is the serial port is also used to communicate to a computer for programming, so Software Serial might be more convenient. You will need level converters between the 5v signaling on the Uno and the 3.3v signaling on the Due. Serial - Arduino Reference
If you do a Google search for "serial communication+between two arduino using tx and rx" you will find many examples.

I2C is a bit more involved but you won't need the level converters but instead have pull-up resistors to 3.3v. The Due requests data from the Uno and the Uno sends the data back. Wire - Arduino Reference
There are examples in the IDE under "Wire": master_reader, master_writer, slave_sender, and slave_receiver. A tutorial is here: https://docs.arduino.cc/learn/communication/wire.

1 Like

maybe something like this..

#include <SoftwareSerial.h>

//serial comm pins
const byte rxPin = 2;
const byte txPin = 3;
const unsigned long baud = 9600;
//create software serial port
SoftwareSerial SoftSerial(rxPin, txPin);


struct __attribute__((__packed__)) DataPacket {
  uint8_t th_types[4];
  float cj_Voktage[4];
  float th_Voltage_read[4];
  float th_Voltage[4];
  int32_t _ADCValaue0[4];
  int32_t _ADCValue1[4];
};

//buffer for receiving structure
byte buff[sizeof(DataPacket)];
//keep track of bytes received
int  recvCount = 0;
//the data
DataPacket Data;


void setup() {
  Serial.begin(9600);
  Serial.println(sizeof(DataPacket));

  Data.th_types[0] = 1;


}

void loop() {
  // put your main code here, to run repeatedly:

}


void SendData() {
  //send data
  SoftSerial.write((uint8_t *)&Data, sizeof(DataPacket));
}

bool RecvData()
{
  bool recvd = false;
  while (SoftSerial.available()) {
    byte abyte = SoftSerial.read();
    if (recvCount < sizeof(DataPacket)) {
      buff[recvCount] = abyte;
      recvCount++;
      if (recvCount == sizeof(DataPacket))
      { //got all data
        recvd = true;
        memcpy(&Data, &buff, sizeof(DataPacket));
        //zero incoming buffer
        memset(buff, 0, sizeof(buff));
        //zero counter
        recvCount = 0;
      }
    }

  }
  return recvd;
}

untested sorry..
let me know how it goes..

~q

1 Like

@stephenaga judging by the OPs first post I think we can safely assume that they already know this...

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.