I need some help for my first project. I know this Problem, using a servo and a GPS sensor, is I guess well known. I found a few discussion already. Unfortunately never a solution which worked with my setup.
Problem:
The Servo jitters as soon I pickup GPS data.
Components:
Arduino Uno Rev. 3
Servo Vilros SG90
Adafruit Ultimate GPS Breakout v3
SW Components:
Adafruit GPS Library example: "parsing" OR TinyGPSplus-0.94b Library example: "DeviceExample"
and
servo Library example: "sweep" OR servoTimer2 Library example: "servoTimer2"
What I know so far:
Both GPS Libs are using an interrupt to read GPS signals. That interrupt stop's also my PWM signals for the servo, therefore the servo starts to jitter, because it receives random signals. The arduino UNO has three timers I could use. Now it gets loose: It looks like the Adafruit GPS Lib is useing timer1 for UNO boards, therefor I tried to use timer2 Lib for my servo. But I have the same Problem as before.
I tried a lot of different ideas, the timer2 was my biggest hope and often mentioned in other forum topics.
It is more than just a simple timer conflict. It is a case of what is called "interrupt contention" When one interrupt comes in, the processor disables other interrupts until the first interrupt is handled. Then the other interrupt is allowed to proceed. So if the servo timer interrupt occurs while handling a software serial interrupt, the servo timer may be delayed by a microsecond or two. The problem is that the servo pulse timing needs to be very precise and even a couple of microseconds delay can cause servo 'jitter'. The options are to use hardware serial or to offload the servo timing to a dedicated servo controller like the PWM/Servo Shield or Breakout.
I ordered a motor shield today. Guess this is the only solution.
I am having the same problem. I am using an Adafruit HUZZAH ESP8266. I have a Parallax 16x2 LCD and an Ultimate GPS connected to the ESP8266. I also have two servos, on a separate power supply, connected to the ESP8266. The two servos and the LCD work fine together. When I introduce the Ultimate GPS, I get a 1hz servo jitter.
Unless anyone has any better ideas, I am going to order the servo breakout to stop the jitter.
A possible solution is to use the Atmega 328P's phase and frequency correct PWM instead of the servo library. As this hardware PWM isn't interrupt driven it should be unaffected by jitter caused by the GPS.
Phase and frequency correct PWM uses the 16-bit Timer1. This means that you can't simultaneousely use libraries that require this timer. On the Uno timer1 outputs are on digital pins 9 and 10, enough to drive two servos. As its name suggests, phase and frequency correct PWM allows control over the PWM frequency and it's possible to drive the servos at 50Hz with a 14-bit resolution.
The following code controls two servos with a 50Hz PWM signal on D9 and D10:
void setup() {
// Initialise timer 1 for phase and frequency correct PWM
pinMode(9, OUTPUT); // Set digital pin 9 (D9) to an output
pinMode(10, OUTPUT); // Set digital pin 10 (D10) to an output
TCCR1A = _BV(COM1A1) | _BV(COM1B1); // Enable the PWM outputs OC1A, and OC1B on digital pins 9, 10
TCCR1B = _BV(WGM13) | _BV(CS11); // Set phase and frequency correct PWM and prescaler of 8 on timer 1
ICR1 = 20000; // Set the PWM frequency to 50Hz
OCR1A = 1500; // Centre the servo on D9
OCR1B = 1500; // Centre the servo on D10
}
void loop() {
OCR1A = 1000; // Move the servo to min position on D9
OCR1B = 1000; // Move the servo to min position on D10
delay(1000); // Wait for 1 second
OCR1A = 2000; // Move the servo to max position on D9
OCR1B = 2000; // Move the servo to max position on D10
delay(1000); // Wait for 1 second
}
Just load the OCR1A or the OCR1B registers with the value in microseconds you'd like to send to each servo, for example to center the servo just load 1500, minimum 1000 and maximum 2000.
I started out with the Adafruit (Mediatek) GPS, but eventually switched to uBlox. uBlox allows communication over the serial port with their proprietary UBX protocol. This protocol sends fixed length data packets that can be loaded directly into a structure in your sketch and is far less computationally expensive than parsing a variable length NMEA string. I found this video on Youtube really helpful: 10Hz U-blox binary GPS data in 66 lines of code (arduino) - YouTube
Could your oscillator code be used to solve this problem?
The advantage of using hardware PWM is that it works independently of the CPU. Once you've loaded the OCR1x registers with your required duty cycle, it will continue outputting that duty cycle at the specified frequency irrespective of processor load.
The servo library on the other hand is software driven. It can cause jitter on the outputs if the processor is unable to service servo outputs quickly enough.
That's not to say it's not possible to experience jitter with hardware PWM, but the cause will be further upstream in the code that's controlling the PWM output to the servo, not the hardware PWM itself.
Thanks Martin, do you think this problem be solved if GPS is connected to the UNO HW serial pins 0/1? I haven't seen any example code that is able to move servo according to gps data for example according to gps speed on UNO board. Read GPS serial -> parse speed -> convert it to servo position...seem simple but in reality, for UNO, this seems very difficult. I'd be very delighted if someone could give functioning example code how to get this work.
So is it so that if I use the UNOs HW serial for GPS I will not have these servo issues? Actually I don't need to use computer serial monitor or LCD at the same time. Any advice/example code?