Use Servo and SoftwareSerial together on UNO

Is there a way to both control a servo and to maintain a softwareserial connection on an Arduino UNO board? I know the two default libraries conflict, because they both need to use timer1 or something like that.

I have looked around a bit and tried every possible combination. The servo libraries I tried:

The sofwareserial libraries:

The pin connections: 8 and 12 to rx/tx on the serial connection, and the servo connected to either 5 or 9 (I tried all combinations)
None the 332 = 18 combinations works, the problem was always one of:

  • servo doesn't work at all
  • servo jitters when serial is receiving data
  • softwareserial doesn't work at all
  • softwareserial desyncs (drops bytes) as soon as the arduino sends something to it

Is there anything I've missed? Are there any libraries that really fix this clash? Thanks.

I always thought that SoftwareSerial would work alongside ServoTimer2 - which is NOT to rule out other combinations.

The problem with the SoftwareSerial and the standard servo library is that they both use the same hardware Timer.

You need to post the program you tried and describe what it actually does and what you want it to do that is different.

...R

...or you could try a different approach. Use Serial for the serial device. You have to disconnect pin 0 to upload new sketches over USB. Or get an ISP and leave it connected.

You didn't identify the serial device, so I can't tell whether you could still do debug prints. Some devices ignore data that isn't in its required format (e.g., GPS devices).

Even if you can't do debug prints to Serial, you might be able to use AltSoftSerial for debug prints. Connect pins 8 & 9 to a TTL Serial-to-USB adapter (aka FTDI). AltSoftSerial is the best software serial library, but it disables PWM on pin 10 (on an UNO).

Need more information, including the code. Loop structure is very important.

The problem with the SoftwareSerial and the standard servo library is that they both use the same hardware Timer.

No, SoftwareSerial does not use a timer. But it's programmed so badly that it blocks the complete CPU during send out and reception of complete bytes. As the timer interrupts are not handled during this time, the signaling for the servos get out of sync.

You might get it to work if you let the hardware PWM do all the servos stuff and use one of the interrupt serial emulations but the best solution is definitely as -dev suggested: use the hardware serial interface. If you need more than one serial interface, change the hardware platform (Leonardo has one additional hardware serial, Mega2560 has 3 additional hardware serial interfaces).

The couple of times I've tried SoftwareSerial and ServoTimer2 have worked together fine.

The only thing you need to be aware of is that ServoTimer2.write() takes a pulse length in microseconds not a 0-180 angle, so it is equivalent to Servo.writeMicroseconds() not Servo.write(). If you try doing write(90) nothing will happen because 90 microseconds is below the minimum.

Steve

slipstick:
The couple of times I've tried SoftwareSerial and ServoTimer2 have worked together fine.

Citation needed. :wink: According to the documentation,

This library uses Timer2 to drive up to 8 servos using interrupts so no refresh activity is required from within the sketch.

And this routine in ServoTimer2.cpp:

ISR (TIMER2_OVF_vect)
{

... will not get called for 1 complete character time, because SoftwareSerial disables interrupts. I suppose if your pulse width is much longer than 1 character time (1ms @ 9600), you may not notice the difference. The performance gets worse with slower baud rates and/or shorter pulse width.

Since the MAX_PULSE_WIDTH is 2250us, SoftwareSerial @ 9600 could cause an actual pulse width of 3250us.

With a MIN_PULSE_WIDTH of 750us, SoftwareSerial @ 9600 could cause an actual pulse width of 1750us. :o

If it worked for you, it may be because you weren't receiving much data, or the servo smoothed out some of the spikes... simple inertia. You may not know it without an oscilloscope. Or maybe the servo didn't quite act like you expected, and you added a fudge factor?

Cheers,
/dev

First of all sorry for the delay, and thanks a lot for all of the reactions! Replaying to everyone:

Robin2:
I always thought that SoftwareSerial would work alongside ServoTimer2 - which is NOT to rule out other combinations.

The problem with the SoftwareSerial and the standard servo library is that they both use the same hardware Timer.

You need to post the program you tried and describe what it actually does and what you want it to do that is different.

...R

It really doesn't. For example this code causes the servo to twitch whenever SoftwareSerial communication is happening, while the servo works fine if I either just use hardware serial.

-dev:
...or you could try a different approach. Use Serial for the serial device. You have to disconnect pin 0 to upload new sketches over USB. Or get an ISP and leave it connected.

You didn't identify the serial device, so I can't tell whether you could still do debug prints. Some devices ignore data that isn't in its required format (e.g., GPS devices).

Even if you can't do debug prints to Serial, you might be able to use AltSoftSerial for debug prints. Connect pins 8 & 9 to a TTL Serial-to-USB adapter (aka FTDI). AltSoftSerial is the best software serial library, but it disables PWM on pin 10 (on an UNO).

Need more information, including the code. Loop structure is very important.

I can't use hardware serial because I need both usb serial output and serial communication over bluetooth with a HC-05 module, so yes it's a general serial device. I tried AltSoftSerial as well, but I think that library occasionally dropped serial communication bytes when used together with a servo.

For code see above, and no loop structure to speak of.

pylon:
No, SoftwareSerial does not use a timer. But it's programmed so badly that it blocks the complete CPU during send out and reception of complete bytes. As the timer interrupts are not handled during this time, the signaling for the servos get out of sync.

You might get it to work if you let the hardware PWM do all the servos stuff and use one of the interrupt serial emulations but the best solution is definitely as -dev suggested: use the hardware serial interface. If you need more than one serial interface, change the hardware platform (Leonardo has one additional hardware serial, Mega2560 has 3 additional hardware serial interfaces).

Thanks, didn't know the issue wans't a timer! I'll consider changing platform if it turns out this approach really doesn't work.

slipstick:
The couple of times I've tried SoftwareSerial and ServoTimer2 have worked together fine.

The only thing you need to be aware of is that ServoTimer2.write() takes a pulse length in microseconds not a 0-180 angle, so it is equivalent to Servo.writeMicroseconds() not Servo.write(). If you try doing write(90) nothing will happen because 90 microseconds is below the minimum.

Steve

Didn't know that, thanks! I tried a couple of small and big values for the write function, but the servo always twitches while serial communication is happening.