HC12 + Brushless motor + 2 Servos

Hello,

I'm new to this and I'm trying to do an RC airplane transmitter and receiver. The problem that I encounter is that both servos and the brushless motor jitter/chatter/vibrate.

In the transmitter, I use an Arduino UNO + HC12 + 1 joystick that controls the 2 servos + 1 potentiometer that controls the brushless motor + 1 switch to stop/start transmitting.

In the receiver, I use an Arduino Nano + HC12 + 2 Servos + 1 Brushless motor.

I was reading a lot about it and it could be caused by:

  • Servo.h and SoftwareSerial.h library timers: I have changed the library Sevo.h for ServoTimer2.h
  • Instability of the joystick, the values change too quick: I have included a code that the servo will only be moved if the new value change more than 20
  • The voltage drops when the servos start: I have added a capacitor in the receiver

However, it is still vibrating and I have run out of ideas. Does anyone know how I can solve this problem?

This is the transmitter code and I also attach the sketch so you can see how I have connected everything:

#include <SoftwareSerial.h>

#define joyX1 A0
#define joyX2 A1
#define joyY1 A2

SoftwareSerial hc12(0,1); //TX,RX

const int switchpin=5;
const int greenled=8;

int buttonpushcounter=1;
int buttonstate=0;
int lastbuttonstate=0;

void setup() {
  // put your setup code here, to run once:
  
  pinMode(A0,INPUT);
  pinMode(A1,INPUT);
  pinMode(A2,INPUT);
  pinMode(switchpin,INPUT);
  pinMode(greenled,OUTPUT);
  
  digitalWrite(greenled,LOW);
    
  Serial.begin(9600);
  hc12.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:

  buttonstate=digitalRead(switchpin);
  if (buttonstate != lastbuttonstate){
    if (buttonstate==HIGH){
      buttonpushcounter++;
    }
    else{Serial.println("OFF");}

    delay(100);
  }
  lastbuttonstate=buttonstate;
  
  if (buttonpushcounter%2==0){
    digitalWrite(greenled,HIGH);

    int elevator=map(analogRead(A1),0,1023,800,2200);
    int rudder=map(analogRead(A2),0,1023,800,2200);
    int thrust=map(analogRead(A0),0,1023,800,2200);

    hc12.print(elevator);
    hc12.print(",");
    hc12.print(rudder);
    hc12.print(",");
    hc12.print(thrust);
    hc12.print(",");
    hc12.println("");

    Serial.print(elevator);
    Serial.print(",");
    Serial.print(rudder);
    Serial.print(",");
    Serial.print(thrust);
    Serial.print(",");
    Serial.println("");

    delay(200);
  }
  else{digitalWrite(greenled,LOW);}

}

Even though in this code I am connecting the HC12 to the ports 0 and 1, I have also tried with 2,3 and 4,5.

This is the receiver code:

#include <SoftwareSerial.h>
#include <ServoTimer2.h>

ServoTimer2 servo1;
ServoTimer2 servo2;
ServoTimer2 motor;

//#include <Servo.h>
//
//Servo servo1;
//Servo servo2;
//Servo motor;

String input;
SoftwareSerial hc12(0,1); //TX,RX

int elevatorold=1504;
int rudderold=1493;
int thrustold=800;
int x;
int y;
int z;
const char coma=',';

void setup() {
  // put your setup code here, to run once:
servo1.attach(9);
servo2.attach(10);
motor.attach(11);

pinMode(9,OUTPUT);
pinMode(10,OUTPUT);
pinMode(11,OUTPUT);
Serial.begin(9600);
hc12.begin(9600);

//motor.write(170);
//delay(2000);
//motor.write(90);
//delay(2000);
//motor.write(140);
//delay(2000);
//motor.write(90);
//delay(2000);
}

void loop() {
  // put your main code here, to run repeatedly:

while (hc12.available()){
  input=hc12.readStringUntil('\n');
  
  if (input.length()>0){
    
    Serial.println(input);

    x=input.indexOf(coma);
    int elevatornew=input.substring(0,x).toInt();
    y=input.indexOf(coma,x+1);
    int ruddernew=input.substring(x+1,y).toInt();
    z=input.indexOf(coma,y+1);
    int thrustnew=input.substring(y+1,z).toInt();

    if (abs(elevatornew-elevatorold)>=20){
    elevatorold=elevatornew;
    servo1.write(elevatorold);
    }

    if (abs(ruddernew-rudderold)>=20){
      rudderold=ruddernew;
      servo2.write(rudderold);
    }

    if (abs(thrustnew-thrustold)>=20){
      thrustold=thrustnew;
      motor.write(thrustold);
    }

    delay(10);
    
  }
}
}

If it is necessary, I can also attach a video.

Thanks in advance!

An important consideration when servos and ESCs/motors are jittering is often how they are powered. You seem to be powering the Arduino via the ESC's BEC to Vin then servos from the 5V pin, so through the internal linear regulator, usually a bad idea. What ESC are you using and what is its BEC output voltage? They are normally 5V which is too low for Vin.

Also using SoftwareSerial on the hardware serial pins 0 and 1 is really not a good idea particularly when you're trying to use the same pins for serial monitor via Serial.begin(), which suggests that you have the USB connection so you are maybe dual-powering the Nano.

Steve

Hi,
The controller in the receiver is in no way going to keep 5V output for two servos, the internal 5V regulator is not able to supply the current needed by them, up to 2A.


Test your setup by powering the servos from their own separate 5V supply, but make sure the gnd of the separate supply and the controller are connected.

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?
Not Fritzy picture please.
Do you have a DMM?

Thanks.. Tom.. :slight_smile:

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with '\0' (NULL).

I would most certainly not use the String class where a software crash would also lead to an airplane crash.

Also, I would not use readStringUntil() because it blocks until it gets all the data.

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data.

Plus everything that has been said about powering your systems.

...R

Hi Anna,

There are a whole lot of things that could be happening here that would cause jitter, including but not limited to the 5v line on the arduino not having enough power. As evidenced by others, using a separate power supply for your servos and especially the DC motor is advisable as all three are likely to draw more power than you might expect.

You could also be getting electrical noise or possibly more likely you are getting spurious emissions from your transmitter and receiver modules. These radio modules don't have great RF filtration, because they are small and intended for hobbyist use, they only have as much filtration circuitry as there is room for.

The RF modules you say you are using are low power and they operate in a portion of the 70 centimeter amateur radio band and 433mHz specifically is widely used for home weather stations, remote vehicle starters, garage door openers, security systems and a plethora of consumer electronics that offer some sort of remote control. So you're going to be getting a lot of interference if you are in a populated area. Looping back to my last point about electrical noise, if any of your wires are roughly the same length as your antenna when straightened out flat, they are going to be resonant at the same frequency and essentially work like antennas. Try shortening leads as much as possible where you can. If this doesn't help, you might be able to attach some ferrite beads to either end of the longer leads and hopefully reduce some of that but not likely all.

Thank you all for helping!!

The ESC I use is BEC 2A@5V connected to a LiPo 3S battery.

@Tom If I connect the ESC to the servos and the Arduino Nano, shouldn't the ESC be able to keep the 5V? I would like to use only 1 battery in order to make the airplane lighter.

About the serial pins 0 and 1. I connected like this just to check if the jittering was due to some bad connection of the HC12. Taking inot account the advice from @slipstick, I will put it back to pins 2 and 3.

I wanted to clarify that even if I connect only 1 servo, it jitters. I checked that if I program the Arduino Nano to change the position of the servo periodically, it doesn't jitter but as soon as I transmitt the data through the HC12, it starts jittering.

I will try the ferrite beads as soon as I get some like @steverobey says.

@Robin2 Regarding using cstring....I really don't understand how it works....or how I should use it...I will keep investigating.

P.D: @Tom I have a DMM. I will try to upload the circuit in CAD as soon as possible. By the way, what is a fritzy picture?

Before all the more complicated fixes the first thing to try is powering it correctly. The 5V from the ESC/BEC must connect to the servos and the Arduino 5V pin NOT to Vin. You might find that makes all the difference.

BTW unless they are very small servos a 2A BEC may not be enough.

Steve

Hi Steve,

I have just connected to Arduino 5V and it's still jittering, even with just 1 servo.

How many Amperes would you suggest for an ESC? The two servos are EMAX ES08AII

Thanks!

anna_folch:
The two servos are EMAX ES08AII

Post a link to their datasheet.

...R

You can find the product decription and features in the following link:

That is a small servo so I would be surprised if it draws more than 1 amp. I had been concerned that you were using a huge servo.

You could measure the current with a suitable multimeter. Get your Arduino to move the servo arm to some position and then gently push against the arm with your finger and see how the current varies.

...R

I wanted to revisit this thread and share a couple of thoughts with everybody who is participating. The first question I have is while we can drive a servo with almost any pin we choose, is it best to use pins that are marked as being PWM? The servo moves based on PWM right?

I'm also reading that the flow of your code can affect the timing specific to the pulses going to the servo. Sometimes those pulses could be a little bit mis-timed depending on what else the processor is handling at the moment. With that, I wonder if you have tried the code without the delays in it. While they are short delays, they might be affecting PWM timing as well, is there a possibility you can do without them? The blink without delay example comes to mind but there might be another solution there as well.

I have also found the recommendation of adding a capacitor between the power leads of the servo. Something like a 470uF electrolytic might help to smooth out the current, but that is still a bit of a band aid solution and we are talking about a radio controlled aircraft so extra weight is a bad thing.

Coming back to the transmitter and receiver modules though, I really think the current solution is a bad idea. What is the power output of the transmitter module? Have you tested it's range? Even slow moving RC planes can get away from you quickly if they're not turning tight enough and especially if they get out of transmitter range. That's going to happen fairly quickly at 70 cm, especially at such low power. A lot of these type of transmitter and receiver modules say they can go up to one watt at maximum input power, but rarely actually test out above 300 milliwatts and the filtering is usually pretty bad because they are cheap. Modern RC receivers operate at 2.4ghz and there are a few different options there for an Arduino controlled equivalent.

I'm assuming the reason you have elected to start this project is not because of the cost of an RC receiver considering the OrangeRX four channel goes for around $5 USD, but rather the cost of the transmitter, which are usually $100 and up for a "Good one" like a Spektrum or a Tanaris. Though you can get some other brands for around $40.

This is not the best transmitter/receiver but I would definitely rely on it before something I've put together on my workbench. I'm not trying to discourage you from continuing this project, but if the end goal is simply an inexpensive solution, you might want to consider something like this.

If none of the solutions we have suggested help, you may just be fighting interference being caused by your radio modules.

Steverobey:
I wanted to revisit this thread and share a couple of thoughts with everybody who is participating. The first question I have is while we can drive a servo with almost any pin we choose, is it best to use pins that are marked as being PWM? The servo moves based on PWM right?

No.

The signal to control a servo is different from the PWM produced by analogWrite(). It is unfortunate that both are referred to as PWM.

...R

Hello everybody,

I'm very sorry for not answering until now. For several reasons I had to leave this project. Now I'm returning back to it and I would like to let you know all the tests I've been doing:

  1. Powering the servos separetly.
  2. Use capacitors to smooth the signal.
  3. Delete the delays form the code and create a function with millis() in order to send the data every 150 milliseconds.
  4. Use ferrite leads to reduce the noise.
  5. Use char instead of string in the code.

After all this changes, there is still some twitching but I realized that:

  1. The twitching only happens when I transmit data so I decided to only send data when there is a considerable change in the input value of the joysticks. This reduces the twitching considerably but it still exists when I want to change the position of the servos or engine.

  2. Then I observed that the twitching happens when the servos don't change the position but they receive a signal. So I modified the code to only sent the data of one servo while having the other still attached and I measured the voltage, I could see that it decreases around 0.2V and it recovers. This does not happen if I transmit the data directly without HC12.

Any idea why does this happen? I'm totally lost....

Hi again,

I have just discovered that if I use the library PWMServo.h, this twitching doesn't happen!!!
The problem is that with this library I can only use pin 9 and 10 and I need more. Any suggestions?

Thanks!

Finally!!!! Jittering/Twitching solved after using NeoSWSerial.h instead of SoftwareSerial.h!! Yahoooooo!!

Thank you very much to everybody!

1 Like

anna_folch:
Finally!!!! Jittering/Twitching solved after using NeoSWSerial.h instead of SoftwareSerial.h!! Yahoooooo!!

Then it was definitely some kind of interrupt issue: SoftwareSerial is known to disable interrupts while receiving or even transmitting, and the servo signal is produced using interrupts...

hello anna, I found your project very interesting. could you post the latest program version with the changes you've made? thank you

hello anna

i am also working on the same king of projet.

did you change your receiver code after changing to neoSWserial.h ?

i did have the same jittering cancelling with neoSWserial.

i'am now trying to parsing my values on differents Integers

did you used Cstrings ? did you used interupt ?

thanks