Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

Pololu Forum

Pololu Dual TB9051FTG Motor Driver - Attaching Servo through Alternate Pins

Hi!

I have the Pololu Dual TB9051FTG Motor Driver and am running a Pololu GB37-131 0J12183 Gear Motor on it. I also need to attach two servos to the Arduino Uno controlling the motor driver. How can I pass the servo control wires to the Arduino? Do I need to cut traces on the motor driver board?

Thanks!

Please note that we have multiple Dual TB9051FTG Motor Driver products; however, since you are talking about an Arduino, I’m going to assume you are referring to the Dual TB9051FTG Motor Driver Shield for Arduino.

You should not need to cut any traces on the board. The shield uses Arduino pins 2, 4, 6, 7, 8, 9, 10, 12, A0, and A1. So you can use any of the other pins for your servo signals (e.g. pins 0, 1, 3, 5, 11, A2, A3, A4, and A5). You can find more information about which pins are used in the “Shield connections: signals, power, and motors” section of the Dual TB9051FTG Motor Driver Shield User’s Guide.

By the way, Arduino’s Servo.h library and our Arduino library for the Dual TB9051FTG Motor Driver Shield both use Timer 1, so they will conflict if you try to use them together. One solution would be to use Timer 2 for the servo signals instead; you can find an example this in the “Controlling a servo with an Arduino Uno” section of our Zumo Shield for Arduino user’s guide. Alternatively, you might consider a Software Servo Library

Brandon

Thanks for this Brandon! This was very helpful! I am going to attempt to make use of the Software Servo library as the other option seems over my head. I downloaded and installed the library and can get the servo to work on its own however I believe there is a conflict as I am using interrupts to set the encoder to keep track of the dc motor position and I believe this is messing up the refresh rate for the Software Servo (I could be wrong though). Is there a way to operate this motor and shield without using interrupts? Am I barking up the wrong tree? Is there a more straight forward solution? Pasting my code below in case it is helpful:

#include "DualTB9051FTGMotorShield.h"
#include <SoftwareServo.h>
DualTB9051FTGMotorShield md;
SoftwareServo elbow;  // create servo object to control a servo 
const byte encoder1 = 2;
const byte encoder2 = 3;
volatile unsigned int encoder = 0;
volatile unsigned int copyOfEncoder = 0;
#define CCW 0
#define CW 1
boolean dialDirection = CW;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);  //Initialize the serial connection
  elbow.attach(1);  // attaches the servo on pin 1 to the servo object
  digitalWrite(encoder1, HIGH); // internal pull up resistor
  digitalWrite(encoder2, HIGH); // internal pull up resistor
  attachInterrupt(0, encoderISR, CHANGE);
  md.init(); // Initialize the motor driver
  md.flipM1(dialDirection); // Set original motor driection based on user input
  md.enableDrivers();
  elbow.write(0);              // tell servo to go to a known positionto avoid jitter
  delay(5000);
  armExtend();
  delay(5000);
  armRetract();
}

void loop() {
SoftwareServo::refresh();
}

void armExtend() {
    while (copyOfEncoder < 1500) {
    setMotorSpeed(CW, 100);
    noInterrupts();
    copyOfEncoder = encoder;
    interrupts();
  }
    setMotorSpeed(CW, 0);
    elbow.write(160);              // tell servo to go to position in variable 'pos'
}

void armRetract() {
    dialDirection = CCW;
    while (copyOfEncoder  >= 100 ) {
    setMotorSpeed(CCW, 100);
    noInterrupts();
    copyOfEncoder = encoder;
    interrupts();
  }
    setMotorSpeed(CCW, 0);
    elbow.write(0);              // tell servo to go to position in variable 'pos'
}
void setMotorSpeed(bool dialDir, int motorSpeed) {
  //THIS FUNCTION EXPECTS AN ALWAYS POSITIVE INPUT and will convert to a negative if necessary based on current dial driection passed to the function.
  //motorSpeed should be between -400 and 400. Negative is counterclockwise and Positive is clockwise.
  if (dialDir == CW) {
    //Serial.println((String)"CCW Speed: " + (motorSpeed * -1));
    md.setM1Speed((motorSpeed * -1));
  }else{
    md.setM1Speed((motorSpeed));
  }
}
void encoderISR() {
  if (bitRead(encoder1, 2) == bitRead(encoder2, 3)&&(dialDirection==CW) ) {
    encoder += 1;
  }
  else encoder -= 1;
}

Thanks!

It looks like you are trying to use pin 2 to read one of your encoders, but the shield uses pin 2 to control the M1EN pin, so that is likely creating a conflict. You might try using pin change interrupts instead, since the Arduino Uno can use those on any of its digital input pins.

In general, doing a lot of timing sensitive applications like PWM signals, servo signals, and encoders can take some careful programming. One option for making it more straight forward might be to use some pre-written libraries. For example, some of the rotary encoder examples and libraries on Arduino Playground’s Reading Rotary Encoders page, like AdaEncoder, support pin change interrupts and are designed to be easy to use.

Brandon