Software Serial Pin Question - Garbage characters in Serial Monitor

I haven't yet found a good set of documentation for this so enlisting insights here on the forum.

I have an ESP8266 for which I'm trying to connect to RS485. The code I started with from an existing Github project defined pin mappings as the follow (which corresponds to the markings on the ESP8266 from which I connect wires to the RS485 board:

// RS485 Software Serial
#define SSerialRX D5 // RS485 Serial Receive pin
#define SSerialTX D6 // RS485 Serial Transmit pin

My issue: Everything compiles fine with no issues but when I attempt to monitor in the serial monitor window I get garbage characters: `@⸮=3⸮

If I change the configuration to the following I appear to get the correct outputs to the serial monitor window:
#define SSerialRX 5 // RS485 Serial Receive pin
#define SSerialTX 6 // RS485 Serial Transmit pin

My concern/question: Since the labels on the ESP8266 says D5 and D6, if I use the config that seems to work I'm not sure if it's really sending/receiving data on the D5/D6 pins. (I haven't put a voltmeter there to verify so it might just be that simple).

My code example is below and is a subset of code from the larger project from which I isolated my issue the SoftwareSerial setup. (

#include <SoftwareSerial.h>

// this is from the Github code that doesn't seem to work
#define SSerialRX D5 // RS485 Serial Receive pin
#define SSerialTX D6 // RS485 Serial Transmit pin

// this at least allows the code to appear to work
//#define SSerialRX 5 // RS485 Serial Receive pin
//#define SSerialTX 6 // RS485 Serial Transmit pin

// set up a new serial object
SoftwareSerial mySerial (SSerialRX, SSerialTX);

void setup() {
Serial.begin(9600);
delay(1000);
Serial.println("starting...");
}

//
// Main application loop
//
void loop() {
Serial.println ("Looping");
delay (500);
}

Nowhere in your code are you actually using the SoftwareSerial object. What is your question?

Why do you need it? SoftwareSerial is a hack that wastes a ton of resources. See if you can use Serial1 if you need to transmit only, or use Serial.swap() to use Serial on different pins.

Pieter

The original codes is from this project but when I install it, it give the results I mention:

Yes, this example code does nothing but it does replicate the problem I see for which I'm seeking better understanding and advice.

Rather than posting extraneous lines of unnecessary code, I only posted a test portion where I replicate the issue. The cause of my symptoms comes from the SerialSet up call and the parameters.

I'm using SoftwareSerial only because I don't have the technical knowledge and expertise to do something different than the original software developer. It doesn't make sense to scrap a good starting point if it's something someone has already proven to work.

I'm not a hard-core coder and I'm looking for someone to share knowledge or point me to a resource where I can learn.

thanks.

Okay, good, so if you only start SoftwareSerial on D5 and D6, it messes up the Serial output? Very strange ...

What board are you using? The D5 and D6 differ between ESP8266 boards.

Either way, you should never try to use GPIO 6 (or 7, 8, 9, 10 or 11) because those pins are used for communication with the on-board flash memory chip that contains your program. Using these pins will crash the program if you're not careful.

Yes, the interesting issue is the code I started with didn't have this issue a month ago when I was doing all my initial testing. I put it aside for a while and then when I came back to hook it up to actual RS485 devices it showed these symptoms. That's when I started stripping away all the code to isolate the symptom.

I'm using a NODEMCU manufactured by Amica.

Rather than trying to maybe understand what is wrong, I'd like to focus on what is really the recommended approach for linking the NODEMCU to my RS485 board.

Many of the examples on Software serial define the pin with just a number like 5, 6 etc rather than D5, D6 that's marked on the circuit board. I'm guessing those examples apply to some other type board than what I have but I'm not sure. (that's what happens when you start with something someone else did and I'm trying to learn)

Thank you for the help.

Those numbers refer to the actual GPIO numbers defined in the ESP8266 datasheet. The D-numbers are just randomly assigned by dev board manufacturers. They only create confusion, IMHO, because every manufacturer seems to do it differently.

The recommended approach is to use a hardware UART.

The ESP8266 has two: Serial (UART0) that can be configured on GPIO1 and GPIO3 (default) or on GPIO15 and GPIO13. GPIO1 and GPIO3 are connected to the USB-to-Serial interface and are used for programming and debugging.
Serial1 (UART1) is connected to GPIO2 and GPIO8. As mentioned before, GPIO8 cannot be used, because it's used for the flash memory.

Usually, you would use UART0 on GPIO1 & 3 for programming, then when your program starts, you swap UART0 in software, so it uses GPIO15 & 13. Then you connect the RS485 to GPIO15 & 13.

If you need debugging over USB, you can use UART1 by connecting GPIO2 to GPIO1 using a 1kΩ resistor.

Read more in the reference:
http://esp8266.github.io/Arduino/versions/2.1.0-rc2/doc/reference.html

Try using I2C. That's pretty easy.

If not, try this:

#include <SoftwareSerial.h>


// this is from the Github code that doesn't seem to work
#define SSerialRX         D5                    // RS485 Serial Receive pin
#define SSerialTX         D6                    // RS485 Serial Transmit pin

// this at least allows the code to appear to work
//#define SSerialRX         5                    // RS485 Serial Receive pin
//#define SSerialTX         6                    // RS485 Serial Transmit pin

// set up a new serial object
SoftwareSerial mySerial (SSerialRX, SSerialTX);

void setup() {
  mySerial.begin(9600);
  delay(1000);
  mySerial.println("starting...");
}

//
//  Main application loop
//
void loop() {
  mySerial.println ("Looping");
  delay (500);
}

Also, did you set the correct baud rate?

Thanks that helps. By the way the board I have is a development board. It has a AI-THINKER chip on it but what you are saying, the actual board pin markings may not be consistent depending on how the vendor assembled and marked it.

So the ultimate question is: if all the manufacturers mark the boards differently how does one know which pin is really GPIO1 or GPIO3 especially if there's no included documentation?

If my board has pins labeled TX and RX are they the same as GPIO1/3?

I think it is based on the schematic here

If my board which has labels at TX really maps to GPIO1 and RX maps to CPIO3 would my define statement then look like the following?

#define SSerialRX 3
#define SSerialTX 1

Or would it be the following since NODEMCU is different.

#define SSerialRX D3
#define SSerialTX D1

and the setup call:

SoftwareSerial mySerial (SSerialRX, SSerialTX);

I think I'm understanding more now...

No, just forget about SoftwareSerial for now, and whatever you do, don't use pins 1 and 3 for it, that't the HardwareSerial port.
Also, don't use #define, use constants.

You have to check the pinout of your specific board to check the actual GPIO numbers, for example:

D3 and D1 have nothing to do with GPIO3 and GPIO1.

I'm not sure I can forget about SoftwareSerial because that's where my questions started.

If I may, let's me go back to my goal I'm trying to connect the attached hardware to my NodeMCU hardware.

In order to connect them, I'm not sure where the three wires (Rx, Tx and FlowControl) of the RS485 board connect on my NodeMCU.

Once wired correctly, I'd like to know how my program needs to define these three attributes so the program will function as intended.

I started with code I didn't write. The original author does not respond to give insights into how his hardware was connected so I'm left trying to decompose this from his code while also learning how this hardware works.

Not sure how to insert an image so attaching here.

My approach would be:

  • Connect RX to GPIO15, and TX to GPIO13. Flow Control can be any pin you'd like.
  • In the setup, call Serial.begin(115200); Serial.swap(); (or any baud rate you want to use on the RS485 connection). This connects "Serial" to the RS485 interface.
  • Everywhere where the original code used "mySerial", use "Serial" instead.
  • If you want to debug using USB (TX only), connect a 1kΩ resistor between GPIO2 and GPIO1. Then use Serial1.begin(115200); and use Serial1.println(...) to print debug information.

So for validation:

I will connect the RXD labeled wire from the rs485 transceiver to the NodeMCU pin labeled D7 as I understand this should be GPIO13 as you reference.

Then connect the TXD pin from the rs485 to the pin labeled D8 as this should be GPIO15.

Directional control pins labeled DE and RE will connect to any pin so I'll pick D6.

In my code this should all correspond to the following:// RS485 Software Serial
#define SSerialRX D7 // RS485 Serial Receive pin
#define SSerialTX D8 // RS485 Serial Transmit pin
#define SSerialTxControl D6 // RS485 Direction control

SoftwareSerial rs485(SSerialRX, SSerialTX, false, 256);

Let me know if I correctly understood your advice.

Then the next question. Is there a way to test this works without actually hooking up the to other rs485 device (it's in another location 750 miles away from me)? Is there anyway to sense voltage or something similar to validate at least the RS485 setup is correct although I won't be able to read/write actual values that I can validate?

No, don't use SoftwareSerial. GPIO13 & GPIO15 support hardware Serial.
Please read the reference page I linked to on a previous reply.

I'm slowly understanding. That's what happens when you start with someone elses code as there's no understanding how the author really used it or connected the devices together.

Is there some example code you can point me to which would enable hardware RS485 serial and also have the ability for me to see debug results in a separate monitor window? It sounds like my original problem was causing my debug output to become garbage because software serial seems to cause issues with the serial monitor window. Correct?

Get another Arduino on the other end of the Serial line for testing and hook the Arduinos to different serial ports.

The connection to the Serial monitor is on GPIO1 and GPIO3. By default, these pins are connected to UART0 (Serial). You need UART0 for the RS485 interface, so you disconnect UART0 from GPIO1 & 3 and connect it to GPIO15 & 13 instead, by using Serial.swap(). Then you no longer have a UART connected to the Serial monitor. Solution: Connecto UART1 to the Serial monitor. This cannot be done internally (AFAIK), so just connect a 1kΩ resistor from GPIO2 (UART1 TX) to GPIO1. Then you can send data to the Serial monitor using UART1 (Serial1).