ESP32 RS485 Bad characters

Hello, forum members!

I’m kind of new to the ESP32 field, so I might be making a simple mistake, but I haven’t found any solutions yet. Here’s the situation: I have 3 ESP32 devices, where:

  • 1 is a master and 2 are slaves.
  • When a button is pressed on the master (it has 2 buttons), it makes either Slave 1 or Slave 2 activate an LED, generate a random number between 0-100, and send it to an MQTT server.

Everything works fine, but the problem is with the serial print on the master:

When I try to print the random number to the serial monitor, it returns a special character like shown here:

makefile

09:35:46.444 -> Slave 1 sent: �
09:35:48.714 -> Slave 2 sent: �

I’m not sure why it’s returning this value in the Serial.println. I’ve already tried:

  • Changing the baud rate from 115200 to 9600, but it didn’t work.
  • Converting the value to a string manually on the slave side, but that didn’t help either.

Does anyone know what might be causing this?

Original code

Master code:

#include <Arduino.h>
#include <stdio.h>
#include <string.h>
#include <HardwareSerial.h>
HardwareSerial SerialPort(2);

int slave_1_id = 1;
int slave_2_id = 2;

const int BUTTON_PIN_01 = 12;
const int BUTTON_PIN_02 = 13;
const int Enable =  15;

void setup() {
  Serial.begin(115200);
  SerialPort.begin(115200, SERIAL_8N1, 16, 17);
  pinMode(Enable, OUTPUT);
  digitalWrite(Enable, LOW);
  pinMode(BUTTON_PIN_01, INPUT_PULLUP);
  pinMode(BUTTON_PIN_02, INPUT_PULLUP);
}

void loop() {
  /* Master Program  */
  if(digitalRead(BUTTON_PIN_01) == 0){
    digitalWrite(Enable, HIGH);
    SerialPort.print(slave_1_id);
    SerialPort.print("ON");
    SerialPort.flush();
    digitalWrite(Enable, LOW);

    delay(500);  // Delay to wait for response

    // Wait for response from slave 1
    if(SerialPort.available()){
      String response = SerialPort.readStringUntil('\n');  // Read until newline
      Serial.println("Slave 1 sent: " + response); // Print the random number sent by the slave
    }
  }
  
  if(digitalRead(BUTTON_PIN_02) == 0){
    digitalWrite(Enable, HIGH);
    SerialPort.print(slave_2_id);
    SerialPort.print("ON");
    SerialPort.flush();
    digitalWrite(Enable, LOW);

    delay(500);  // Delay to wait for response

    // Wait for response from slave 2
    if(SerialPort.available()){
      String response = SerialPort.readStringUntil('\n');  // Read until newline
      Serial.println("Slave 2 sent: " + response); // Print the random number sent by the slave
    }
  }

  delay(200);
}

Slave code (both of them are equal, just changing the slave id

#include <WiFi.h>
#include <PubSubClient.h>
#include <HardwareSerial.h>

// Slave definitions
HardwareSerial SerialPort(2);
const int Enable = 15;
const int SlaveNumber = 1; // Slave ID for master's read
int Slave;
const int LED = 4;

// WiFi definitions
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";

// MQTT definitions
const char* server = "YOUR_MQTT_SERVER_ADDRESS";
const int porta = 1883;
const char* topic_base = "YOUR_TOPIC_BASE";
WiFiClient ethClient;
PubSubClient mqttClient(ethClient);

void connectToWiFi() {
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");
}

void connectToMQTT() {
  mqttClient.setServer(server, porta);
  while (!mqttClient.connected()) {
    Serial.println("Connecting to MQTT...");
    if (mqttClient.connect("slave_device")) {
      Serial.println("Connected to MQTT");
    } else {
      delay(1000);
    }
  }
}

void setup() { 
  Serial.begin(115200);
  SerialPort.begin(115200, SERIAL_8N1, 16, 17); 
  SerialPort.setTimeout(250);
  pinMode(Enable, OUTPUT);
  pinMode(LED, OUTPUT);
  digitalWrite(Enable, LOW);
  digitalWrite(LED, LOW);
  randomSeed(analogRead(0));  // Initialize random number generator

  // Connect to WiFi and MQTT
  connectToWiFi();
  connectToMQTT();
}

void loop() {
  digitalWrite(Enable, LOW); 
  if (SerialPort.available()) {
    Slave = SerialPort.parseInt();
    Serial.println(Slave);

    if (Slave == SlaveNumber) {   
      String command = SerialPort.readString();  
      Serial.println(command);

      if (command == "ON") {
        digitalWrite(LED, HIGH);

        // Generate and print a random number between 0 and 100
        int randomNumber = random(0, 101);
        Serial.print("Random number: ");
        Serial.println(randomNumber);

        // Send the random number via MQTT
        char message[100];
        sprintf(message, "Slave %d sent number: %d", SlaveNumber, randomNumber);

        // Publish to MQTT topic corresponding to the slave
        char topic[50];
        sprintf(topic, "%s%d/number", topic_base, SlaveNumber); // E.g., YOUR_TOPIC_BASE1/number
        bool enviado = mqttClient.publish(topic, message);

        if (enviado) {
          Serial.print("Number sent via MQTT: ");
          Serial.println(message);
        } else {
          Serial.println("Failed to send number via MQTT.");
        }

        digitalWrite(Enable, HIGH);
        SerialPort.println(randomNumber);  // Send the number back to the master as a string
        digitalWrite(Enable, LOW);

        delay(500);
        digitalWrite(LED, LOW);
      }
    }
    Serial.println("loop");
  }

  // Maintain MQTT connection
  if (!mqttClient.connected()) {
    while (!mqttClient.connected()) {
      Serial.println("Reconnecting to MQTT...");
      if (mqttClient.connect("device")) {
        Serial.println("Reconnected");
      } else {
        delay(5000);
      }
    }
  }
}

That doe not seem to follow the correct syntax for Serial.println(). Try making that two separate prints with the println() (response) the second line.

Thank you for your response, Paul.
I tried what you suggested, but it still didn't work.
I also tried testing with String response = SerialPort.readString(); instead String response = SerialPort.readStringUntil('\n'); , but without success.

The print the response in HEX to really see what is being returned!

Also you would not receive a number sent with serial.print.
And you could add a small delay before writing the bus low

I added this:

void printInHex(const String &data) {
  for (int i = 0; i < data.length(); i++) {
    Serial.print("0x");
    if (data[i] < 0x10) Serial.print("0"); 
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }

  Serial.println();
}

Than, returned me this:

11:14:03.809 -> Sent to Slave 2 em HEX: 0x32 0x4F 0x4E

11:14:05.304 -> Slave 2 sent: �

11:14:06.511 ->Sent to Slave Slave 1 em HEX: 0x31 0x4F 0x4E

11:14:07.993 -> Slave 1 sent: �

Thank you!
It worked.

You're welcome.

Now you have learned how to begin debugging programs!

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