UNO SPE Shield libraries

Hi community!

I'm currently working in a project with RS485 involved. I'm trying to replace a device in a RS485 modbus line. First advances were made with a MOXA Nport 5130 to read the commands in a computer and get to know the addressing and data. Now I need to read those same commands in a Arduino to work as a translator for the new device.

My first attempt was with a RS485 CAN Shield from WaveShare. I just used the Receive example in the library and I was able to read the commands in the serial port but the reading was unstable and after some time the connection just fails until I reboot my arduino (Arduino UNO R3)

Recently after looking for some other options to read RS485 and with more industrial protection to avoid noise (more reliable readings) I stumbled upon UNO SPE shield with a lot of good characteristics (SPE shield) wich is directly compatible with Arduino R4 and according to the forum would have a specific library for it but I've been unable to find it (maybe is still in development) and the only references in the official page related to the shield (SPE Shield Getting Started) just uses ArduinoRS405.h and ArduinoModbus library wich are made for ArduinoMKR and the RS485 shield for MKR.

My confusion is related to pinout and connection. According to tech specs (MKR 485 shield) the comunication is made through D6(RXP) and D7(TXP) and the libraries should use by default those pins but in the library page (ArduinoRS485 library) it states in the setPins() instruction that by default used pins are:

Modify the pins used to communicate with the MAX3157 chipset. By default the library uses pin 14 for TX, pin A6 for drive output enable, and pin A5 for receiver output enable.

Wich is logical since pin 14 is labeled as TX but I dont understadn why that instruction just let set 3 pins and the RX (pin 13) can't be modified.

Now, going through SPE shield schematics (Schematic PDF SPE shield) the communication with Arduino is made with UART pins (D0-RX and D1-TX) and RE and DE is connected to D7 and D8 to control the chip.

So my question is about the command setPins() for the ArduinoRS485 library (I want to try that one first instead of Modbus library due some observation I did during first tests) and if the configuration for the Arduino R4 and SPE shield should be like this:

RS485.setPins(1, 7, 8);

I don't really understand why I can't set the pin for RX and most information related to SPE shield is about the ethernet side and the few examples for RS485 communication is used with OPTA devices wich I don't have experience at all.

Thanks in advance

Hi @joaquinmart256. The "TX" pin is used in two distinct ways:

  • serial communication
  • set LOW when sending "break" signals

The serial communication is done using a HardwareSerial object. For example:

Setting the pin low while sending the "break" signals can not be done using the serial interface functions of the Arduino core API. This must be done by manipulating the TX pin as a normal GPIO pin via digitalWrite:

So the Arduino pin number of the TX pin must be known by the library in addition to the HardwareSerial object of the serial interface. The Arduino core API doesn't provide a way for the TX pin to be determined from the HardwareSerial object.

For this reason, in order for the user to configure the serial interface used by the library, the user must provide the library with two separate, but intrinsically linked pieces of information:

  • The HardwareSerial object of the serial interface
  • The Arduino pin number of the TX pin of the serial interface

The interface used for serial communication is configured via the hwSerial parameter of the library's constructor:

(configured as Serial1 by default: ArduinoRS485/src/RS485.cpp at 1.1.0 · arduino-libraries/ArduinoRS485 · GitHub ArduinoRS485/src/RS485.h at 1.1.0 · arduino-libraries/ArduinoRS485 · GitHub)

The TX pin of that same serial interface is configured via the txPin parameter of the constructor.

Unless I miss some odd use case, it really doesn't make sense to allow configuration of the TX pin via the library's setPins function because any time you would want to configure the TX pin you would also want to configure the serial interface object and so would need to use the constructor. The inclusion of that parameter in the setPins function only misleads the user into thinking the serial interface can be configured via that function. It does make sense to provide a function for configuring the "DE" and "RE" pins because the user will typically be using the default serial interface (with some boards, there is only the one anyway), but may well want to choose whichever arbitrary pins are most convenient for "DE" and "RE".

First of all, thanks @ptillisch for your help in this problem. I was started to think that maybe I did this post too confusing.

Just to summarize!

Basically the construction of the object helps the library (since core API don’t do it by itself) to determine the use of the correct pin to do/send break signals.

So declaring a HardwareSerial object sets the way of communication between the hardware and software and the library’s constructor hwSerial lets the library know wich pins to use.

And that’s totally true, completely misleads to understand the functioning of the library. For example I just checked again the example for the Waveshare module I used first:

#include <SoftwareSerial.h>

SoftwareSerial RS485(2, 8); // RX, TX
int RS485_E = 7;
int i=0;
String comdata = "";
void setup()
{
Serial.begin(9600);
Serial.println("*** RS485 CAN Shield Receive Test Program ***\r\n");

RS485.begin(9600);
pinMode(RS485_E,OUTPUT);
digitalWrite(RS485_E,LOW);
}

void loop() // run over and over
{
while(RS485.available() > 0)
{
comdata += char(RS485.read());
delay(2);
}
if(comdata.length() > 0)
{
Serial.println("RS485 Receive: "+comdata);
comdata = "";
}
}

And reading what you just explained is really makes sense, In this code basically creates a serial object, because uses the dedicated one to print the data through the usb port, and also declares a GPIO as a enable since isn’t using any other library and the chip in the module does the conversion and I read again all the examples for the UNO SPE Shield (Getting Started) and this caught my attention:

And the code for the arduinos R4 as transducer node wich:

Serial.begin(115200);
  Serial1.begin(9600);
  delay(1000);
  
  Serial.print("\nGateway Node ");
  Serial.println(MY_ID);
  
  pinMode(7, OUTPUT);  // RS485_DE
  pinMode(8, OUTPUT);  // RS485_RE
  digitalWrite(7, HIGH);
  digitalWrite(8, HIGH);

Declares the Serial1 as the pins for communication and pins 7 and 8 as enablers

Then after reading the information from the central with the SPE protocol just uses serial port for normal communication sending the data

if (cmd == "LED " + String(MY_ID)) {
      Serial1.println("T");
      Serial1.flush();
      Serial.println("Toggle sent");
    }

And this makes me understand that I just need to declare Serial1, wich is physically connected to those pins (TX, RX) and also the enablers to control the RS485 chip and send and read the data using the serial port as usual.

Thanks again, your answer brought light to my doubts

You are welcome. I'm glad if I was able to be of assistance.

Note that the "ArduinoRS485" library uses Serial1 on the UNO R4 Minima by default:

So you don't need to explicitly configure the HardwareSerial object of the serial interface and the TX pin number in your sketch.

It is only necessary to use the library's constructor in your sketch in the case where you want to use a different serial interface than the one configured in the library by default. Doing so wouldn't really make sense with the UNO R4 Minima, for which the core only provides a single HardwareSerial object. However, it could be useful for other boards that have multiple HardwareSerial objects (e.g., if you had a project using the Arduino Mega 2560, which has multiple hardware serial objects, and Serial1 was already in use for another purpose so you found it convenient to use the board's Serial2 for the RS-485 interface).

1 Like