Ardunio can't provide stable pwm signal.

I am trying to control 2 sg09 micro servos with my Arduino Mega 2560.

I have some servos connected to it as well.

When only the signal input of the servos are connected to my Ardunio(The vcc and gnd of the servos are connected to an external 5v 2A Regulator which has common ground with the ardunio), servos kind of wiggle. Still controllable but still wiggles. Both ardunio and the 5v 2A regulator are connected to 12v battery.

Important thing. When I plug off some sensors, servos go back to normal.

Another Important thing, When I use a Rf reveiver to create the same servo signal, Everything works
well(Ardunio is still operating sensor, just not servos).

I measured the pwm signals created by ardunio it is like:

 1500
 1560
 1800
 1300
 1000
 1400
 1250

When I plug off some sensors from Arduino:

1500
1500
1500
1500
1500

I am not an electronics pro but I think that ardunio just can’t provide enough current to generate pwm signals. So do I buy some type of external servo driver, or what?

I am certain that my software is good, because it is very very basic. I just use the Servo library.

The Servo library uses interrupts to drive the outputs, so will exhibit jitter if other interrupts are
flying around and affecting the timing, or if you disable interrupts for more than a few microseconds.

Its nothing to do with current, logic signals involve very little current.

As you've not posted your code its hard to say what's causing the jitter. The interrupt that drives millis()
and delay() will produce a small amount of jitter, but nothing like the 500µs that those figures imply.

What you said makes a lot more sense. I actually didn’t post my code initially to make my question look basic :D.

This is the code. I simplified it to the smallest piece of code that repreduces the problem. I tried to anotate is so you can understand more easily.

Important note: When I comment the line that starts the Serial communication with my GPS, Everything works good again.

This is my GPS: https://www.waveshare.com/wiki/UART_GPS_NEO-7M-C

Code:

#include <Thread.h>
#include <TinyGPS++.h> //GPS library
#include <SoftwareSerial.h>
#define shouldPin 4
#include "PWM.hpp"
#include "Queue.h"
#include <Servo.h>

//Servos
Servo Elevator;
Servo Aileron;


//Unrelated
uint8_t filterWidth = 20;
volatile float filterAverage = 0;

//Gps constants
static const int RXPin = 11, TXPin = 10;
static const uint32_t GPSBaud = 9600;

//The object I use to read pwm for my shouldThread, unrelated to the problem
PWM my_pwm(2); // Setup pin 2 for PWM

// The TinyGPS++ object
TinyGPSPlus gps;

// Thread Object
Thread GpsThread = Thread();
Thread shouldThread = Thread();
Thread exeThread = Thread();

//Unrelated
Queue<int> queue(filterWidth);



// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);

void setup() {
  Serial.begin(9600);

  /*
    !!! Very Important Note
    When I remove the following line, Everything works marvelously. I think this line is causing the jittes
  */
  ss.begin(GPSBaud); /// Starting Serial Connecting with the GPS using UART Protocole



  pinMode(shouldPin, OUTPUT);
  //Setting Interupt pin 0 to Input in order to use it to Read pwm values for my ShoulThread, unrelated to the problem
  pinMode(2, INPUT);

  digitalWrite(shouldPin, HIGH); // Unrelated

  my_pwm.begin(true); // PWM on pin 2 reading PWM HIGH duration, this uses interrupt pin 0(pin 2 on ardunio)


  /// Unrelated queue setup
  for (int i = 0; i < filterWidth; i++) {
    queue.push(0);
  }

  //Servo Setup

  Elevator.attach(5);
  Aileron.attach(6);



  //Prothreads setup

  GpsThread.enabled = true;
  GpsThread.setInterval(100);
  GpsThread.onRun(readgp);

  shouldThread.enabled = true; // Default enabled value is true
  shouldThread.setInterval(25); // Setts the wanted interval to be 10ms
  shouldThread.onRun(shouldfunc); // callback_function is the name of the function

  exeThread.enabled = true; // Default enabled value is true
  exeThread.setInterval(10); // Setts the wanted interval to be 10ms
  exeThread.onRun(exe); // callback_function is the name of the function
}



/*
   This is my manuever execution function, I conrol the servos from here
*/
void exe() {
  Elevator.writeMicroseconds(1500 );
  Aileron.writeMicroseconds(1500);
}


/*
   This two functions are part of an algorith unrelated to the problem
*/
void getQueueAverage(int nv, int poppedValue) {
  filterAverage = ((filterAverage * filterWidth) - poppedValue + nv) / filterWidth;

}
int average(int value) {
  int s;

  if (value >= 1500) {
    s = 1;
  } else {
    s = 0;
  }
  if (queue.count() != filterWidth) {
    queue.push(s);
    return s;
  } else {
    getQueueAverage(s, queue.pop());
    queue.push(s);

    return round(filterAverage);
  }
}


/*
  This should function is basically takes an input pwm signal and then passes it through an algorithm
  Depending on the the output of the algorithm, digital writes to a pin for reasons unrelated to the problem.
  I know they are unrelated because I tried to bypass this whole thing and problem persisted
  This is triggered when the ShouldThread is triggered
*/
void shouldfunc() {
  int a = average(my_pwm.getValue());
  Serial.println(a);
  if (a) {
    digitalWrite(shouldPin, HIGH);
  } else {
    digitalWrite(shouldPin, LOW);
  }
}


/*
   This is the function that I read the GPS with SoftwareSerial, UART protocol. I don't do anything with them yet for the sake of simplicity
   This is triggered when the GPS thread is triggered
*/
void readgp() {
  while (ss.available() > 0) {
    gps.encode(ss.read());
    if (gps.location.isUpdated()) {
      Serial.print("Latitude= ");
      Serial.print(gps.location.lat(), 6);
      Serial.print(" Longitude= ");
      Serial.println(gps.location.lng(), 6);
    }
  }
}

void loop() {
  // These are basically thread run functions

  if (GpsThread.shouldRun()) {
    // Yes, the Thread should run, let's run it
    GpsThread.run();
  }
  if (exeThread.shouldRun()) {
    // Yes, the Thread should run, let's run it
    exeThread.run();
  }

  if (shouldThread.shouldRun()) {
    // Yes, the Thread should run, let's run it
    shouldThread.run();
  }
}

If GPS is the problem, How can I solve it? Do I buy a different one. I want this problem to be over as soons as possible.

Hi.

Which Arduino are you using, and why are you using software serial ?

SoftwareSerial use interrupts for receiving characters, I think it will be particularly bad for slow baudrates like
9600.

I am using software serial to communicate with my GPS. I use Arduino Mega 2560

The baud rate of GPS Neo-7M-C is 9600, as stated in the wiki. I don't think I can change that without changing the hardware

Is there any way to solve this intertwining between interrupts. I just want to control 4 servos in total. 2 also works actually.

The Mega has four hardware serial ports.

Use one for the GPS, instead of the poorest performing one of the software serial libraries.

Oh my god. It is working now. I literally stared at those pins everyday and did not know their use exactly. Now I am all clear. Thank you everybody.

For future references:

I found some Software Serial alternatives if you are having this issue on an uno or any other single serial Ardunios.

HardwareSerial is always the best. Simply connect the device to pins 0 & 1 and use the pre-defined Serial variable. On some Arduinos, there are extra HardwareSerial ports, called Serial1, Serial2, etc. The UNO only has Serial. Serial would not interfere with the Servo.

AltSoftSerial is the best of the software serial libraries. Only one instance is allowed, and it is must be used on the Input Capture pins (pins 8 & 9 for a Nano). It would not interfere with the Servo.

My NeoSWSerial is next best. It works on any two pins, but only at baud rates 9600, 19200 and 38400. Receiving characters does not disable interrupts, but transmitting does (i.e., TX would interfere with the Servo).

SoftwareSerial is the worst choice. It works on any two pins, but it is very inefficient. It disables interrupts for the entire time that a character is being sent OR received, and it cannot transmit and receive at the same time (unlike all other choices). This can interfere with other parts of your sketch, other device communications, or with libraries (e.g., Servo)

This is where I found it :