SoftwareSerial and SoftwareServo twitching problems.

Hi all,

I am making a drone project that uses softwareSerial for gps and SoftwareServo for the servo(normal servo is in conflict with VirtualWire).

However, the servo is twitching whenever the servo and softwareSerial are attached. I read that it is caused due to both libraries having the same Timer.

I heard that HardwareSerial can be used for this to replace softwareSerial, but I don’t know where to find the hardwareSerial and if I searched it on the web I get the arduino Serial…

#include <SoftwareSerial.h>
#include <SoftwareServo.h>
#include <TinyGPS.h>
SoftwareSerial gps(4,3);
SoftwareServo servo;
TinyGPS gpsW;
.
.
.
void setup(){
servo.attach(14);
Serial.begin(115200);
}
void loop(){
//the rest of the code here...
}

I’m not home right now so I can only post the code that I remember. I will post the full code if needed later once I get home.

How do I get the HardwareSerial library or where?

any other solutions for this will greatly be appreciated.

-Christian

If you are using an Uno then HardwareSerial is what you use to talk to the PC via USB and which appears on pins 0 and 1. It cannot be used on any other Pins. A Mega has 4 HardwareSerial USARTs.

You seem to be using at least 4 libraries - SoftwareSerial, Servo, TinyGPS and VirtualWire. It may be difficult to avoid a conflict. Can you identify the resources that each of them needs?

You could try the ServoTimer2 library or the very simple yet another software serial

...R

I don't know about SoftwareServo but Servo uses a timer interrupt to generate the servo pulses. Unfortunately SoftwareSerial turns off interrupts for the duration of each character received or sent. At slow bit rates this can easily be long enough to randomly stretch servo pulses. Try the highest baud rate your GPS can manage to minimize jitter.

AVR USARTs can do master mode SPI.
I have to wonder if AVR SPI can do USART type serial?

When you're resource-short, sometimes you do less with what you do have if you can.

In this thread I controlled a servo using a hardware timer. Since this doesn't use interrupts, it would not be affected by software serial.

Example code from that thread:

/*
Servo motor controlled by Timer 1

Author: Nick Gammon
Date: 1 February 2015
*/

const byte potpin = A0;  // analog pin used to connect the potentiometer
 
const unsigned long PRESCALER = 8;         // Timer 1 prescaler
const float PULSE_PERIOD = 0.020;          // 20 mS
const float ZERO_POSITION_WIDTH = 0.0005;  // 0.5 mS
const float FULL_POSITION_WIDTH = 0.0024;  // 2.4 mS

// how far apart the pulses are
const unsigned long PULSE_WIDTH_COUNT = F_CPU / PRESCALER * PULSE_PERIOD;
// minimum pulse width (-45 degrees)
const unsigned long ZERO_POSITION_COUNT = F_CPU / PRESCALER * ZERO_POSITION_WIDTH;
// minimum pulse width (+45 degrees)
const unsigned long FULL_POSITION_COUNT = F_CPU / PRESCALER * FULL_POSITION_WIDTH;

void setup() 
  { 
  TCCR1A = 0;          // disable all PWM on Timer1 whilst we set it up
  ICR1 = PULSE_WIDTH_COUNT - 1;   // frequency is every 20ms (zero-relative)
  
  // Configure timer 1 for Fast PWM mode using ICR1, with 8x  prescaling
  TCCR1A = bit (WGM11);
  TCCR1B = bit (WGM13) | bit (WGM12) |  bit (CS11);  // fast PWM top at ICR1
  TCCR1A |= bit (COM1A1);  // Clear OC1A/OC1B on Compare Match,
  pinMode (9, OUTPUT);
  }   // end of setup
 
void loop() 
{ 
  int val = analogRead(potpin);  // reads the value of the potentiometer (value between 0 and 1023) 
  OCR1A = ZERO_POSITION_COUNT + (val * (FULL_POSITION_COUNT - ZERO_POSITION_COUNT) / 1024) - 1;
  delay(15);                     // wait for the servo to get there 
} // end of loop

You may need to change the constants ZERO_POSITION_WIDTH and FULL_POSITION_WIDTH to match the specs for your servo.

The code above changes the servo pulse width in loop() based on reading a potentiometer. You could of course change it some other way. Once changed the hardware sends out the pulses whether or not the processor is servicing an interrupt.