Modbus RTU library on Serial3 using module

Hi
I need to implement ModbusRTU on RS485. I'm using this module and it's connected to Serial3 pins on the Mega2560 board which are 14 and 15. Also, the DE and RE pins from the module are connected to pin 46 on the board. I wanted to use this library because it lets me choose the pins I'm using but I don't really understand how to use the _D variable (e.g. to turn on the built in LED). I thought maybe I could edit the source code on the ArduinoModbus and ArduinoRS485 libraries to set it up to use serial3 but I think I broke my library now LOL. If anyone could give me a hand on how to use that _D or how to edit the Arduino library I would be really grateful.
The code below is the example in the library I wanted to use first. I will also attach the .zip file of this library and the original arduinoRS485 and arduinoModbus libraries.
ModbusRTU_Slave_RS485.zip (22.0 KB)
ArduinoRS485 and ArduinoModbus.zip (101.7 KB)

#include <ModbusRTUSlave.h>

// size of data which will be read and written
#define DATA_SIZE 100
// data array which will be read and written
u16 _D[DATA_SIZE];

// address (kind of name) of above data, maybe anything
#define VIRTUAL_ADDRESS 0x7000

#define OUR_ID_AS_A_SLAVE 1
#define PIN_CONNECTED_TO_BOTH_DE_AND_RE 46

ModbusRTUSlave rtu(OUR_ID_AS_A_SLAVE, &Serial3, PIN_CONNECTED_TO_BOTH_DE_AND_RE);

void setup()
{ 
  rtu.addWordArea(VIRTUAL_ADDRESS, _D, DATA_SIZE);
  rtu.begin(9600);

  //Serial.begin(9600); // not needed, for logging purpose only

  // set some value in data array to test if master can read and modify it
  _D[0] = 160;
}

void loop()
{
  // waiting for requests from master
  // reading and writing _D according to requests from master happens here
  rtu.process();
}

The following is my attempt to set up the ArduinoRS485 library


#ifndef _RS485_H_INCLUDED
#define _RS485_H_INCLUDED

#include <Arduino.h>

#ifdef PIN_SERIAL3_TX
#define RS485_DEFAULT_TX_PIN PIN_SERIAL3_TX
#else
#define RS485_DEFAULT_TX_PIN 14 
#endif

#ifdef __AVR__
#define RS845_DEFAULT_DE_PIN 46
#define RS845_DEFAULT_RE_PIN 46
#else
#define RS845_DEFAULT_DE_PIN 46
#define RS845_DEFAULT_RE_PIN 46
#endif

class RS485Class : public Stream {
  public:
    RS485Class(HardwareSerial& hwSerial, int txPin, int dePin, int rePin);

    virtual void begin(unsigned long baudrate);
    virtual void begin(unsigned long baudrate, uint16_t config);
    virtual void end();
    virtual int available();
    virtual int peek();
    virtual int read(void);
    virtual void flush();
    virtual size_t write(uint8_t b);
    using Print::write; // pull in write(str) and write(buf, size) from Print
    virtual operator bool();

    void beginTransmission();
    void endTransmission();
    void receive();
    void noReceive();

    void sendBreak(unsigned int duration);
    void sendBreakMicroseconds(unsigned int duration);

    void setPins(int txPin, int dePin, int rePin);

  private:
    HardwareSerial* _serial;
    int _txPin;
    int _dePin;
    int _rePin;

    bool _transmisionBegun;
    unsigned long _baudrate;
    uint16_t _config;
};

extern RS485Class RS485;

#endif

This is the original arduino rs485.h looked like


#ifndef _RS485_H_INCLUDED
#define _RS485_H_INCLUDED

#include <Arduino.h>

#ifdef PIN_SERIAL1_TX
#define RS485_DEFAULT_TX_PIN PIN_SERIAL1_TX
#else
#define RS485_DEFAULT_TX_PIN 1 
#endif

#ifdef __AVR__
#define RS845_DEFAULT_DE_PIN 2
#define RS845_DEFAULT_RE_PIN -1
#else
#define RS845_DEFAULT_DE_PIN A6
#define RS845_DEFAULT_RE_PIN A5
#endif

class RS485Class : public Stream {
  public:
    RS485Class(HardwareSerial& hwSerial, int txPin, int dePin, int rePin);

    virtual void begin(unsigned long baudrate);
    virtual void begin(unsigned long baudrate, uint16_t config);
    virtual void end();
    virtual int available();
    virtual int peek();
    virtual int read(void);
    virtual void flush();
    virtual size_t write(uint8_t b);
    using Print::write; // pull in write(str) and write(buf, size) from Print
    virtual operator bool();

    void beginTransmission();
    void endTransmission();
    void receive();
    void noReceive();

    void sendBreak(unsigned int duration);
    void sendBreakMicroseconds(unsigned int duration);

    void setPins(int txPin, int dePin, int rePin);

  private:
    HardwareSerial* _serial;
    int _txPin;
    int _dePin;
    int _rePin;

    bool _transmisionBegun;
    unsigned long _baudrate;
    uint16_t _config;
};

extern RS485Class RS485;

#endif

I have no clue why you modified the ArduinoRS485 library as you don't use it in the code you posted. BTW you should not use it as it is designed for the MKR series of Arduino, the AVR platform doesn't have enough RAM for that library.

What problem do you have? Doesn't the posted code work? What kind of device do you connect to (link to manual)?

The options were to either use ModbusRTUSlave.h or use ArduinoModbus.h that needs ArduinoRS485.h. So I thought someone could help me understand how to use the _D variable on the first option or help me modify the code in option two which is the library ArduinoRS485.h. I did my research and now it works. These are the changes I made to the RS485.h file.


#ifndef _RS485_H_INCLUDED
#define _RS485_H_INCLUDED

#include <Arduino.h>

#ifdef PIN_SERIAL3_TX
#define RS485_DEFAULT_TX_PIN PIN_SERIAL3_TX
#else
#define RS485_DEFAULT_TX_PIN 1 
#endif

#ifdef __AVR__
#define RS845_DEFAULT_DE_PIN 46
#define RS845_DEFAULT_RE_PIN 46
#else
#define RS845_DEFAULT_DE_PIN A6
#define RS845_DEFAULT_RE_PIN A5
#endif

class RS485Class : public Stream {
  public:
    RS485Class(HardwareSerial& hwSerial, int txPin, int dePin, int rePin);

    virtual void begin(unsigned long baudrate);
    virtual void begin(unsigned long baudrate, uint16_t config);
    virtual void end();
    virtual int available();
    virtual int peek();
    virtual int read(void);
    virtual void flush();
    virtual size_t write(uint8_t b);
    using Print::write; // pull in write(str) and write(buf, size) from Print
    virtual operator bool();

    void beginTransmission();
    void endTransmission();
    void receive();
    void noReceive();

    void sendBreak(unsigned int duration);
    void sendBreakMicroseconds(unsigned int duration);

    void setPins(int txPin, int dePin, int rePin);

  private:
    HardwareSerial* _serial;
    int _txPin;
    int _dePin;
    int _rePin;

    bool _transmisionBegun;
    unsigned long _baudrate;
    uint16_t _config;
};

extern RS485Class RS485;

#endif

And also I had to change this in the RS485.cpp file on the last line

RS485Class RS485(SERIAL_PORT_HARDWARE3, RS485_DEFAULT_TX_PIN, RS845_DEFAULT_DE_PIN, RS845_DEFAULT_RE_PIN);

I strongly recommend to use the other library if you want to run that on a Mega2560 reliably. The ArduinoModbus library is wasting quite some memory as it's core library (libmodbus) is developed for full-fledged PCs where RAM is no problem.

If that _D variable is a problem, tell us what problems you have with it.