Changing the default comm port in the RS485 library

Hi,

I am trying to modify the Arduino RS485 library to work with Serial port 4. (number 1 is already in use). have anyone successfully manage to do it? I have tried a few of the recommendations I could find on the internet but no one seems to work.

The idea id to utilize the Arduino Modbus library at the end for some remote IO application.

Thanks in advance

I think you might need to put this at the top of your code (even before the #includes)

#define RS485_SERIAL_PORT Serial3

Hi, thanks for the response, I have tried the defines both on top and just before the setup phase still no communication. I am including the code if it will help.

#include <wiring_private.h>     // Required for pinPeripheral() function
#include <ArduinoRS485.h>

//SERCOM4 on analog pins A2 (Tx) and A3 (Rx) as Serial4
Uart Serial4 (&sercom4, A3, A2, SERCOM_RX_PAD_1, UART_TX_PAD_0);

void SERCOM4_0_Handler()
{
  Serial4.IrqHandler();
}
void SERCOM4_1_Handler()
{
  Serial4.IrqHandler();
}
void SERCOM4_2_Handler()
{
  Serial4.IrqHandler();
}
void SERCOM4_3_Handler()
{
  Serial4.IrqHandler();
}

#define RS485_SERIAL_PORT Serial4
#define RS485_CONTROL_PIN 5

void setup() {
  Serial.begin(9600);
  RS485.begin(9600);

    // Assign pins A2 & A3 SERCOM functionality
  pinPeripheral(A2, PIO_SERCOM_ALT);
  pinPeripheral(A3, PIO_SERCOM_ALT);

  // enable transmission, can be disabled with: RS485.endTransmission();
  RS485.beginTransmission();

  // enable reception, can be disabled with: RS485.noReceive();
  RS485.receive();
}

void loop() {
  if (Serial.available()) {
    RS485.write(Serial.read());
  }

  if (RS485.available()) {
    Serial.write(RS485.read());
  }
}

Hmm... Ok. There does seem to be an open issue about this on the library's GitHub repo.

Try this, replacing <TX_PIN>, <DE_PIN> and <RE_PIN> with the pins you want to use.

#include <wiring_private.h>     // Required for pinPeripheral() function
#include <ArduinoRS485.h>

//SERCOM4 on analog pins A2 (Tx) and A3 (Rx) as Serial4
Uart Serial4 (&sercom4, A3, A2, SERCOM_RX_PAD_1, UART_TX_PAD_0);

void SERCOM4_0_Handler()
{
  Serial4.IrqHandler();
}
void SERCOM4_1_Handler()
{
  Serial4.IrqHandler();
}
void SERCOM4_2_Handler()
{
  Serial4.IrqHandler();
}
void SERCOM4_3_Handler()
{
  Serial4.IrqHandler();
}

RS485Class myRS485(&Serial4, <TX_PIN>, <DE_PIN>, <RE_PIN>);

void setup() {
  Serial.begin(9600);
  myRS485.begin(9600);

    // Assign pins A2 & A3 SERCOM functionality
  pinPeripheral(A2, PIO_SERCOM_ALT);
  pinPeripheral(A3, PIO_SERCOM_ALT);

  // enable transmission, can be disabled with:     RS485.endTransmission();
  myRS485.beginTransmission();

  // enable reception, can be disabled with: RS485.noReceive();
  myRS485.receive();
}

void loop() {
  if (Serial.available()) {
    myRS485.write(Serial.read());
  }

  if (myRS485.available()) {
    Serial.write(myRS485.read());
  }
}

Which Arduino board is this being compiled for?

Try Serial4 instead of &Serial4.

Might be necessary to modify the library RS485.h and RS485.cpp files to remove the default RS485 object.

Hi David, your suggestion to work with just serial4 solved the error of compiling but still no communication. To answer the question of the processor I am using a feather M4 from Adafruit.

RS485Class myRS485(Serial4, A2, 5, 5);

My other solution may be to connect the GSM modem currently on Serial1 to this serial and move the RS485 back to Serial1. may be the least effort.

Are you sure your test code is suitable for use with RS485? I'm no expert but I think it's not as simple as a naked UART. There are additional protocols, and if your code doesn't follow them, perhaps you won't receive any comms.

Running the following code on my hardware does give me communication, my own make shift RS485. the reason i am now trying the official lib is that the modbus library is based on this one.

#include <wiring_private.h>     // Required for pinPeripheral() function

//SERCOM4 on analog pins A2 (Tx) and A3 (Rx) as Serial4
Uart Serial4 (&sercom4, A3, A2, SERCOM_RX_PAD_1, UART_TX_PAD_0);

void SERCOM4_0_Handler()
{
  Serial4.IrqHandler();
}
void SERCOM4_1_Handler()
{
  Serial4.IrqHandler();
}
void SERCOM4_2_Handler()
{
  Serial4.IrqHandler();
}
void SERCOM4_3_Handler()
{
  Serial4.IrqHandler();
}

// what's the name of the hardware serial port?
#define RS485 Serial4

//RS485.setSerial(&Serial4); 
#define RS485_CONTROL_PIN 5
//#define RS485_serial(Serial4);

void setup() {
  Serial.begin(9600);
   RS485.begin(9600);

  // Assign pins A2 & A3 SERCOM functionality
  pinPeripheral(A2, PIO_SERCOM_ALT);
  pinPeripheral(A3, PIO_SERCOM_ALT);

  pinMode(RS485_CONTROL_PIN, OUTPUT);
  digitalWrite(RS485_CONTROL_PIN, LOW); // Receive mode

}

void loop() 
{

  
  if (Serial.available()) 
  {
    digitalWrite(RS485_CONTROL_PIN, HIGH); // Transmit Mode
    delay(2);
    RS485.write(Serial.read());
    Serial.flush();                // Wait for data to finish sending
    digitalWrite(RS485_CONTROL_PIN, LOW); // Receive Mode
  }

  if (RS485.available()) 
  {
    Serial.write(RS485.read());
    //Serial.print(RS485.read(),HEX);
    //Serial.println();
  }
  
}

Yes, that code will work, I'm sure. You are calling the Serial object "RS485" but actually it's just plain 'ol UART. You are not even #including the RS485 library.

But in the code you were testing before, you were using the RS485 library, but using it as though it was just a UART. Maybe that's why that code wasn't apparently working as you expected.

I think you need to find some other test code that is written to work with the RS485 library. Check the examples menu for the library.

Also try this, but I'm not sure if this is right either.

#include <wiring_private.h>     // Required for pinPeripheral() function
#include <ArduinoRS485.h>

//SERCOM4 on analog pins A2 (Tx) and A3 (Rx) as Serial4
Uart Serial4 (&sercom4, A3, A2, SERCOM_RX_PAD_1, UART_TX_PAD_0);

void SERCOM4_0_Handler()
{
  Serial4.IrqHandler();
}
void SERCOM4_1_Handler()
{
  Serial4.IrqHandler();
}
void SERCOM4_2_Handler()
{
  Serial4.IrqHandler();
}
void SERCOM4_3_Handler()
{
  Serial4.IrqHandler();
}

RS485Class myRS485(Serial4, <TX_PIN>, <DE_PIN>, <RE_PIN>);

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

    // Assign pins A2 & A3 SERCOM functionality
  pinPeripheral(A2, PIO_SERCOM_ALT);
  pinPeripheral(A3, PIO_SERCOM_ALT);

  myRS485.begin(9600);
}

void loop() {
  if (Serial.available()) {
    myRS485.beginTransmission();
    while (Serial.available()) {
      myRS485.write(Serial.read());
    }
    myRS485.endTransmission();
  }

  myRS485.receive();
  if (myRS485.available()) {
    Serial.write(myRS485.read());
  }
}

I don't think you can use the same pin for DE_PIN and RE_PIN. If one is not needed, set it to a value of -1.

< edit > Looking at the library, using the same pin for both would likely work, main difference is there is an option to have a delay when changing the state of the DE pin.

Did you remove the default RS485 object in the library? There is one line declaring it as extern in the RS485.h file, and a couple of lines at the end of the RS485.cpp file with the constructor.

Is there an important reason to do that, do you think?

When I was reading the library code, my thought was that so long as RS485.begin() is not called, that object should not cause a problem and can be ignored. That's why I suggested creating the myRS485 object using the standard constructor, which allows you to specify the UART and pins you want to use.

Probably not important, it does increase the size of the code, by creating an instance of the class, but doesn't actually do anything with the serial port.

Agreed, but @anpretorius is using Adaftuit Feather M4, so memory resources should not be a problem.