How to use servo controller with SoftSerial

Hi,

I’m struggling with the Pololu 8 port servo controller on the arduino board. I got it working perfectly on pin 1 (the hardware serial) but I have to free this port up for a shield. I saw some projects where the port has been changed with use of the NewSoftSerial library, but when using it, the servo controller lights up the onboerd red LED and the green LED keeps on flashing.

Does anybody has a foolproof example which uses another port (for example port 10) as the port for serial communication with the Pololu servo controller ?

thanks in advance,

Arjan

Hello.

If you have code that works using hardware serial, it should be very easy to change it to use software serial. Can you post a simple Arduino sketch that does something with the servo controller (i.e. that you actually successfully run with the controller connected to pin 1) and your attempt to convert it to use the NewSoftSerial library?

- Ben

Hi Ben,

Thanks for your reply.

The complete working code is a bit big to post here, so I took some time to find some demos. One hardware version running on pin 1 (hardware serial) en one that uses
pin 4.

Hardware version:

/*******************************************\
 Servo Controller code
\********************************************/
 
void setup()
{
  Serial.begin(9600);
}
 
void loop()
{
  // Use the SetPosition command to do stuff.
  // Takes values between 0 and 5000
  SetServo(1, 2500);
}
 
// Set a servo position.  Returns 0 on success, -1 on error
// Uses the Pololu protocol, so the jumper has to be off of the controller
// Makes use of "Absolute Position" command
// VALID POSITION VALUES: 0-5000
int SetServo(int servo, int position)
{
  byte data1 = 0;
  byte data2 = 0;
 
  // Check to make sure the servo is right
  if (servo <0 || servo >8)
   return -1;
 
  // Check to make sure position is within bounds
  if (position < 0 || position > 5000)
    return -1;
 
  // Controller actually takes values between 500 and 5500,
  // so just add 500
  position+=500;
  // Calculate data bytes from position
  data2 = position & B01111111;
  data1 = position >> 7;
 
  // Start Byte
  Serial.print(0x80, BYTE);
  // Device ID
  Serial.print(0x01, BYTE);
  // Command: 0x04 is set absolute position
  Serial.print(0x04, BYTE);
  // Servo number
  Serial.print((byte)servo, BYTE);
  // First data byte
  Serial.print(data1, BYTE);
  // Second data byte
  Serial.print(data2, BYTE);
 
  // Everything seems ok, return 0
  return (0);
}

SoftSerial version:

/*******************************************\
Pololu Serial Servo Controller code
\********************************************/
 
#include <SoftwareSerial.h>
 
// Define pins you're using for serial communication
// Don't need to use pins 0 and 1
#define RXPIN 3
#define TXPIN 4
 
// Set up the new serial port to transmit data
// You only need to connect the TXPIN and Ground
// to the Pololu controller...RXPIN is unused
// (Pololu incapable of sending data back to arduino)
SoftwareSerial pololu(RXPIN, TXPIN);
 
void setup()
{
  // define pin modes for tx, rx:
  pinMode(RXPIN, INPUT);
  pinMode(TXPIN, OUTPUT);
 
  Serial.begin(9600);
  pololu.begin(9600);
}
 
void loop()
{
  // Use the SetPosition command to do stuff.
  // Takes values between 0 and 5000
  SetServo(1, 2500);
}
 
// Set a servo position.  Returns 0 on success, -1 on error
// Uses the Pololu protocol, so the jumper has to be off of the controller
// Makes use of "Absolute Position" command
// VALID POSITION VALUES: 0-5000
int SetServo(int servo, int position)
{
  byte data1 = 0;
  byte data2 = 0;
 
  // Check to make sure the servo is right
  if (servo <0 || servo >8)
   return -1;
 
  // Check to make sure position is within bounds
  if (position < 0 || position > 5000)
    return -1;
 
  // Controller actually takes values between 500 and 5500,
  // so just add 500
  position+=500;
  // Calculate data bytes from position
  data2 = position & B01111111;
  data1 = position >> 7;
 
  // Start Byte
  pololu.print(0x80, BYTE);
  // Device ID
  pololu.print(0x01, BYTE);
  // Command: 0x04 is set absolute position
  pololu.print(0x04, BYTE);
  // Servo number
  pololu.print((byte)servo, BYTE);
  // First data byte
  pololu.print(data1, BYTE);
  // Second data byte
  pololu.print(data2, BYTE);
 
  // Everything seems ok, return 0
  return (0);
}

I’ve tested both version using an oscilloscope monitoring the Tx pin, and the output pattern looks the same. The odd thing is
that with the hardware version the pololu servo controller board lights up a green LED but with the
SoftSerial version the orange LED lights up and the RED LED blinks, no servo is moving.

Arjan

I’m pretty sure your problem is due to some noise on the transmit line that occurs when initializing the software serial module. The servo controller you’re using uses the first byte it receives to learn the baud rate, and an invalid first byte or even random noise on the line can confuse it. Can you try resetting the servo controller after you initialize and enable the software serial module?

For example:

void setup()
{
  // define pin modes for tx, rx:
  pinMode(RXPIN, INPUT);
  pinMode(TXPIN, OUTPUT);

  Serial.begin(9600);
  pololu.begin(9600);

  pinMode(RSTPIN, OUTPUT);  // drive reset pin low to reset the servo controller
  delay(10);
  pinMode(RSTPIN, INPUT);  // let controller run again (RST internally pulled high)
  delay(10);
}

Please let me know if this fixes the problem.

- Ben

Hi Ben,

You were right, adding those 4 lines solves the problem. You saved my day !!!. Only drawback is the fact that I need another digital line for the Reset Pin. Till now I used the RST pin from the arduino to reset the servo controller …

regards,

Arjan

I’m glad to hear it’s working for you now! For future projects, I suggest you consider our newer Maestro servo controllers. They have a lot more features than our original servo controllers (e.g. you can use the channels as general-purpose digital outputs or additional analog/digital inputs), and their baud-rate detection is much more robust, so it doesn’t get confused by initial noise like this.

- Ben