Issue with Serial Communication while running servo motors

Hello everyone,

I tried reading up other posts in the forum on similar issues, but I was not able to resolve my problem, so I would appreciate any help on this project. This is my first post on the forum so I appreciate feedback on posts/using the forum as well.
I’ll start with a brief introduction of my project, followed by the detailed implementation and I’ll end with the problems I’m facing and what troubleshooting I have tried so far.

Introduction:

  • I am trying to build a Kiwi drive using Omni wheels, basically trying to run 4 servo motors.
  • I want to drive this with a wireless controller.
  • I am using HC12 module (Datasheet attached) for the wireless communication.
  • The details on the transmitter and receiver, including description on the circuit, components and the code is given below.

Details:
Transmitter:

  • I am using an Arduino Nano, which is connected to HC12 module and a joystick.
  • I usually power it using USB.
  • The code is as follows:
#define Vrx1 A1
int Xvalint;
#define Vry1 A2
int Yvalint;
#define SW1 2
int SWvalint;
#define setPin 7

#include <SoftwareSerial.h>
SoftwareSerial HC12(10, 11); // HC-12 TX Pin, HC-12 RX Pin

void setup() {
  pinMode(Vrx1, INPUT);
  pinMode(Vry1, INPUT);
  pinMode(SW1, INPUT_PULLUP);
  // Begin serial communication at a baud rate of 9600:
  Serial.begin(9600);
  HC12.begin(9600);               // Serial port to HC12

}

void loop() {

  Xvalint = map(analogRead(Vrx1 ), 0, 1023, 0, 180);

  Yvalint = map(analogRead(Vry1 ), 0, 1023, 0, 180);

  SWvalint = digitalRead(SW1);

  //Binary
  HC12.print("<");
  HC12.print(Xvalint / 4);
  HC12.print(",");
  HC12.print(Yvalint / 4);
  HC12.print(",");
  HC12.print(SWvalint);
  HC12.print(">");
  delay(20);
}

Receiver:

  • I am using an Arduino Uno for the receiver.
  • The arduino is connected to a HC12 module and PCA9685 16 channel PWM servo driver (data sheet attached).
  • 4 servo motors are connected to the PCA9685. The servo motors used are FS5103R (datasheet attached)
  • I usually power the arduino with laptop USB while looking at data through serial monitor.
  • I use 4AAs to power the servo motors (V+ of PCA9685).
  • All grounds are connected to avoid ground loops.
//Initialization//

#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
#include <AltSoftSerial.h>
AltSoftSerial HC12;
#define SERVO_FREQ 50 // Analog servos run at ~50 Hz updates

const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing
int X = 0;
int Y = 0;
int x = 0;
int y = 0;
int SW = 0;
boolean newData = false;

//Setup//

void setup() {

  Serial.begin(9600);             // Serial port to computer
  HC12.begin(9600);               // Serial port to HC12

  pwm.begin();
  pwm.setOscillatorFrequency(27000000);
  pwm.setPWMFreq(SERVO_FREQ);  // Analog servos run at ~50 Hz updates

  delay(2000);
}

//HC12 Communication Functions//

void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<';
  char endMarker = '>';
  char rc;

  while (HC12.available() > 0 && newData == false) {
    rc = HC12.read();

    if (recvInProgress == true) {
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      }
      else {
        receivedChars[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }

    else if (rc == startMarker) {
      recvInProgress = true;
    }
  }
}

void parseData() {      // split the data into its parts

  char * strtokIndx; // this is used by strtok() as an index

  strtokIndx = strtok(tempChars, ",");     // get the first part - the string
  x = atoi(strtokIndx);

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  y = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ",");
  SW = atoi(strtokIndx);     // convert this part to a float
}

//Loop//

void loop() {

  recvWithStartEndMarkers();
  if (newData == true) {
    Serial.println("newdata");
    strcpy(tempChars, receivedChars);
    // this temporary copy is necessary to protect the original data
    //   because strtok() used in parseData() replaces the commas with \0
    parseData();
    newData = false;
  }
  X = x * 4;
  Y = y * 4;

  Serial.print(X);
  Serial.print("  ");
  Serial.print(Y);
  Serial.print("  ");
  Serial.println(SW);

  if (X > 95 && Y < 95 && Y > 80) {
    pwm.setPWM(0, 0, 600);
    pwm.setPWM(1, 0, 50);
    pwm.setPWM(2, 0, 600);
    pwm.setPWM(3, 0, 50);
  }
  else if (X < 80 && Y < 95 && Y > 80) {
    pwm.setPWM(0, 0, 50);
    pwm.setPWM(1, 0, 600);
    pwm.setPWM(2, 0, 50);
    pwm.setPWM(3, 0, 600);
  }
  else if (Y > 95 && X < 95 && X > 80) {
    pwm.setPWM(0, 0, 600);
    pwm.setPWM(1, 0, 50);
    pwm.setPWM(2, 0, 50);
    pwm.setPWM(3, 0, 600);
  }
  else if (Y < 80 && X < 95 && X > 80) {
    pwm.setPWM(0, 0, 50);
    pwm.setPWM(1, 0, 600);
    pwm.setPWM(2, 0, 600);
    pwm.setPWM(3, 0, 50);
  }
  else {
    pwm.setPWM(0, 0, 0);
    pwm.setPWM(1, 0, 0);
    pwm.setPWM(2, 0, 0);
    pwm.setPWM(3, 0, 0);
  }
}

Problem:

  • When i run the code attached, as long as the motors are at standstill, the values from joystick are updated regularly (So nominal joystick position is continuously printed on the serial monitor) .
  • However, if i move the joystick and the servos start running, the data from the hc12 is no longer updated regularly. This leads to the servos being stuck in one of the conditions until eventually the value is updated (This update can take >1 minute at times)

Troubleshooting:

  • If the servos are not powered (or if the motors are disconnected) the code runs fine, all joystick values are updated regularly without any interruptions and the code enters and exits the conditional loops as expected.
  • I modified the code to remove all the condition statements and commanded all motors to be at standstill (i.e. pwm.setPWM(i, 0, 0)) and printed the input data- the serial communication worked fine, the values from joystick are updated regularly without issues.
  • If I repeat the same while commanding the servos to run (without conditions- so loop only consists of pwm.setPWM(i, 0, 50)) then the same issue is observed- the HC12 data is not updated. Apparently the code does not regularly detect ‘newData’.
  • I tried connecting only 1 servo instead of 4 to understand if the issue is related to current drawn by 4 motors, however the same issue persisted with single motor. I also tried a smaller FS90R servo motor but didn’t make a difference.
  • Before using PCA9685, i tried to run the servo motors directly via the arduino using servo.h and ServoTimer2 libraries but faced the same problem. I also tried HW serial pins and other Software Serial libraries but it didn’t make a difference.

HC-12-Documentations.pdf (282 KB)

FS5103R.pdf (175 KB)

16 Channel PWM Servo driver PCA9685 data sheet attached

16-channel-pwm-servo-driver.pdf (1.76 MB)

It sounds like either som powerproblem or electrical noise.
Did You pwr the vehicle UNO by USB and servos by AAAs?
How is the HC12 powered?
Suppose You make all the software calls to the servo functions but the servo connectors being pulled out? What happends?

With every iteration of loop() you increase X and Y and update the servo driver. Better update all that only if new data (new x,y) are available.

Also understand that software Serial is not very reliable, maybe blocking or blocked by other activities.

Railroader:
It sounds like either som powerproblem or electrical noise.
Did You pwr the vehicle UNO by USB and servos by AAAs?
How is the HC12 powered?
Suppose You make all the software calls to the servo functions but the servo connectors being pulled out? What happends?

The vehicle UNO is powered by USB and the servos are powere by 4AAs.
The HC12 and Vin of PCA9685 are powered by Arduino UNO’s 5V output.
If I make all software calls to the Servo functions but the Servo connectors are pulle out the code works fine. The values are updated regularly.

DrDiettrich:
With every iteration of loop() you increase X and Y and update the servo driver. Better update all that only if new data (new x,y) are available.

Also understand that software Serial is not very reliable, maybe blocking or blocked by other activities.

Thanks I’ll try updating only for new data.
I also tried using hardware serial ports but ran into the same problem

Attach a wiring diagram. Use pen and paper if necessary.
Something is strange.

Railroader:
Attach a wiring diagram. Use pen and paper if necessary.
Something is strange.

Please find attached receiver wiring schematic.

The power supply is highly questionable.
The 4 AA is fed into something and from there 5 volt is distributed to both controller and transmitter. Have You checked that 5 volt? I don't give that a chance to work.
Arrange a proper 5 volt to those 2 devices.

Railroader:
The power supply is highly questionable.
The 4 AA is fed into something and from there 5 volt is distributed to both controller and transmitter. Have You checked that 5 volt? I don’t give that a chance to work.
Arrange a proper 5 volt to those 2 devices.

Sorry for the confusion I should’ve been more clear in the wiring diagram- the controller is powered by laptop usb (revised wiring schematic attached). I have also tried powering the Arduino with a 9V battery but had the same problem.
I checked the 5V power supply with a DMM and it looks fine, I even tried a fresh set of AA batteries but same issue.

Okey. That wiring looks a little bit better but….

It's worrying me a bit that You try different power solutions in a way that I think You are not 100%* sure what You are doing.
Why the yellow cable across the controller? It connects GND to GND as it looks like on my UNO board. Might be different on Your controller.

My next theory is that the AA-pack is not good enough for that load. I don't know what voltage You need so check that and try using a stronger powersupply for those 4 servos.

One desperat test Cold be testing using onle one servo. That could confirm my theory.

Railroader:
Okey. That wiring looks a little bit better but….

It's worrying me a bit that You try different power solutions in a way that I think You are not 100%* sure what You are doing.

Since the problem was occurs when the servos are connected and works fine when they are not, my first thought was that the problem is due to the power supplies which is why I tried few different configurations of power supplies i.e using usb as well as 9V battery to power the controller. New AAs etc.

Railroader:
Why the yellow cable across the controller? It connects GND to GND as it looks like on my UNO board. Might be different on Your controller.

In one of my previous projects I notices some problems (I assumed it was ground loops) which were solved when I connected the GND to GND, not sure if that’s some problem related to my Arduino.

Railroader:
My next theory is that the AA-pack is not good enough for that load. I don't know what voltage You need so check that and try using a stronger powersupply for those 4 servos.

One desperat test Cold be testing using onle one servo. That could confirm my theory.

I updated my code to only send new data as suggested by DrDiettrich. In the receiver code, I removed all conditions and commanded a single motor to run continuously. Here is a list of my observations

  1. single FS5103R connected to the PCA9685 - data not updated after every change in joystick. Probably ~50% of the data updated
  2. used a smaller servo FS90R- performance was much better, data updated correctly ~95% of the time.
  3. I connected another 4x AAs supply in parallel and tried single FS5103R - still same problem.

The FS5103R datasheet specifies 5V operating voltage. I don’t understand what’s wrong with the power supply that I’m using. Not sure if I need additional electronics like capacitors in circuit.

I prefer not to use an AC Adapter as the drive chassis is supposed to be portable. I can buy one to troubleshoot the issue if needed.

Any recommendations?

Appreciate all the help!

Could You help me to get a specification regarding current for those servos? I did try but no Amps told.

My theory is that there is not current enough for them. AA cells are not delivering Amps, rather mA.

Railroader:
Could You help me to get a specification regarding current for those servos? I did try but no Amps told.

My theory is that there is not current enough for them. AA cells are not delivering Amps, rather mA.

I wasn’t able to find any information from data sheets online but I measured the current drawn while running 1 servo with a DMM and it’s looks like .16A.
I read online that AAs can provide 50mA so I guess your theory is correct.
I’m confused about battery capabilities, i.e. how do I know what’s the maximum current a battery can provide if I only know mAh/Wh specs?

All battories works as voltage sorces. When they need to deliver current the variation is huge.
There are quite pwoerful LiPo battories, used for charging phones, laptops and so on. The bigger ones have size of a bricl and can store some 20 000 mAh. They are also capable of giving out Amperes. 3 Amps I’ve seen but there might be more.
There are 6 volt old fashioned lead battories….

Know that radio, wireless transmitters, uses quite some current when transmitting.

Use separate power supplies for the Arduino and wireless receiver, and the servos. I think that will make the Communication run uninterrupted. Use AA for servos, for testing, if You like. You’ll see how long they last and likely try better stuff.

Railroader:
All battories works as voltage sorces. When they need to deliver current the variation is huge.
There are quite pwoerful LiPo battories, used for charging phones, laptops and so on. The bigger ones have size of a bricl and can store some 20 000 mAh. They are also capable of giving out Amperes. 3 Amps I've seen but there might be more.
There are 6 volt old fashioned lead battories….

Know that radio, wireless transmitters, uses quite some current when transmitting.

Use separate power supplies for the Arduino and wireless receiver, and the servos. I think that will make the Communication run uninterrupted. Use AA for servos, for testing, if You like. You'll see how long they last and likely try better stuff.

I bought a 5V 3000mA AC power adapter and used it to power servo+hc12. Seems to be working alright. Thanks for all your help, appreciate it!

Thanks for telling us!