Problem Esc SoftwareSerial

Hello, I have on an Arduino Pro Micro, an ESC, an HC-12 and a GPS for a remote control car. But when I want to retrieve the GPS data with SoftwareSerial (because the TX and RX pins are already used for communication with the HC-12 and cannot be changed), SoftwareSerial sends PWM data to my ESC, changing the motor value, which is disastrous. Do you have an alternative that would not cause this problem?

I was unaware that SoftwareSerial had PWM support. I was under the impression that it acted as a software UART and send/received serial data.

I would be most interested in seeing your evidence proving PWM support in the SoftwareSerial library.

1 Like

Please provide your sketch; don't forget to use code tags as described in https://forum.arduino.cc/t/how-to-get-the-best-out-of-this-forum/679966#posting-code-and-common-code-problems.

1 Like

here is the code.
(I temporarily disabled the GPS part to avoid the problem)

#include <Servo.h>
#include <SoftwareSerial.h>
#include <TinyGPS++.h>

// --- Constants ---
const String PLAYER = "A";
const byte WHEEL_PIN = 9;
const byte SERVO_PIN = 5;

// --- Motors ---
Servo esc;
Servo servo;

// --- GPS ---
TinyGPSPlus gps;

// --- Variables ---
int wheel;
int servoDir;
int pwmVal;
float batteryVoltage = 0;
String vitesse = "...";
String vitesseSave = "...";
unsigned long long lastSng = 0;
unsigned long long lastSend = 0;
int pwmValSave = 1500;

// --- Serial Communication ---
SoftwareSerial manetteSerial(6, 7);
SoftwareSerial gpsSerial(8, 3);

void setup() {
    esc.attach(WHEEL_PIN);
    Serial.begin(9600);
    esc.writeMicroseconds(1500);
    delay(7000);

    Serial1.begin(9600);
    manetteSerial.begin(9600);
    //gpsSerial.begin(9600);
    
    servo.attach(SERVO_PIN);
    servo.write(90);
}

void loop() {
    getData();
    disconnected();
    checkBatteryVoltage();
    //getGPS();
    sendData();
    delay(1);
}

void getData() {
    if (Serial1.available()) {
        String input = Serial1.readStringUntil('!');
        input.trim();

        int lastAIndex = input.lastIndexOf("A/");
        if (lastAIndex != -1) {
            input = input.substring(lastAIndex);
        }

        int firstSlashIndex = input.indexOf('/');
        int secondSlashIndex = input.indexOf('/', firstSlashIndex + 1);

        if (input.startsWith("A/") && firstSlashIndex != -1 && secondSlashIndex != -1 && secondSlashIndex < input.length() - 1) {
            wheel = input.substring(firstSlashIndex + 1, secondSlashIndex).toInt();
            pwmVal = map(wheel, 0, 1023, 2000, 1000);
            pwmVal = (pwmVal / 10) * 10;
            servoDir = input.substring(secondSlashIndex + 1).toInt();

            esc.writeMicroseconds(pwmVal);
            servo.write(servoDir);

            Serial.println(servoDir);
            pwmValSave = pwmVal;
            lastSng = millis();  
        }
    }
}

void disconnected() {
    if (lastSng + 100 < millis()) {
        Serial.println("reset");
        esc.writeMicroseconds(1500);
        servo.write(90);
    }
}

void checkBatteryVoltage() {
    int adcValue = analogRead(A0);
    float voltageMesure = (adcValue * 5.0) / 1023;
    batteryVoltage = voltageMesure * ((1770.0 + 1000.0) / 1000.0);
    batteryVoltage = (0.993 * batteryVoltage) + 0.16;
}

void getGPS() {
    if (gpsSerial.available() > 0) {
        gps.encode(gpsSerial.read());
        if (gps.speed.isUpdated()) {
            vitesse = gps.speed.kmph();
        }
    }
}

void sendData() {
    if (vitesse != vitesseSave || lastSend + 1000 < millis()) {
        String buildString = PLAYER + "/" + String(batteryVoltage) + "/" + vitesse + "&";
        vitesseSave = vitesse;
        lastSend = millis();
        manetteSerial.print(buildString);
    }
}

And where exactly is SoftwareSerial sending PWM data to your ESC? That's what I inquired about.

The ESC is a "servo" on an unrelated pin.

But I do not know SoftwareSerial well enough to state that it does not interfere with the necessary continuous production of the ESC signal.

Some small amount of research suggests that maybe. I saw one reference to an alternate servo library known to not conflict.

a7

1 Like

I recall having to change servo.h with a project on the Pro Mini.

And my question to ChatGPT
“Can the servo.H library be used onArduino Pro Micro”
confirmed that. In particular note the comment on PWM.

ChatGPT said:

No, the servo.H library (Arduino Servo library) can be used on most Arduino boards, but it is not directly compatible with the Arduino Pro Micro because this board is based on the ATmega32U4 microcontroller, which handles timers differently than the ATmega328P (used in Arduino Uno).

Issues with Servo.h on Pro Micro:

  1. Timer Conflicts – The Servo library relies on Timer1, which is used differently in the ATmega32U4.
  2. USB Communication Conflicts – The Pro Micro's USB functionality may interfere with the library.

Alternatives:

  • PWMServo Library – Works better with Pro Micro as it uses software PWM.
  • Manually Controlling PWM – Using analogWrite() for servo control (though limited in precision).
  • Use a Servo Driver – Like the PCA9685 for multiple servos.
2 Likes

I asked for a step further, a list of all libraries for using servos with Arduino.

Here are some commonly used libraries for controlling servos with Arduino:
1 Servo.h
2 VarSpeedServo.h
3 Adafruit_MotorShield
4 ServoEasing.h
5 ESP32Servo.h
6 ServoTimer2.h
7 FlexibleServo.h
8 AccelStepper.h

File under "who knew?".

I think I noticed ServoTimer2 in my earlier researches.

a7

2 Likes

A major problem using SoftwareSerial and Servo is that both make extensive use of interrupts.

Are you actually using the Rx pin for the HC-12? The sketch only shows the Tx being used. If the Rx is not needed, then its possible to use the Tx pin for the HC-12 and the Rx pin for the GPS and avoid SoftwareSerial entirely.

1 Like

Handy list.
VarSpeedServo was what I've used when Servo.h didn't work properly.

And maybe worth adding
Servo_ATTinyCore
for the atTiny85, and probably other Tiny devices.


EDIT:
Possible ambiguity about 'Arduino Pro Micro', the OP's device. Although that name is used frequently, I understand its correct name is just 'Pro Micro'. It's Arduino-compatible, using the ATmega32U4 chip, with built-in USB communication. Unlike the Arduino Pro Mini.

1 Like

No, I use 2 hc-12 but the one on Tx Rx only use the Rx.

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