Arduino/Pololu motor shield 2 dc motors and a servo (Servo moving by itslef)

Good day,

I am experimenting with the following setup.

1 Pololu motor dual_vnh5019_motor_driver_shield
1 Arduino Uno
2 DC geared motors 12V
1 servo SG92R 5V
1 ThumbJoystick

As seen in the picture I have a joystick using 5V from Arduino and Y/X using A0 and A1. Arduino and Pololu shield is powered by a 12 V power supply using the jumper and 2 dc motors connected to the shield.

I added a servo to the project and experimented different ways to build the circuit but in the end all resulted to the same situation where when using the joystick to turn the DC motors the servo turns as well. I did not even build a code yet to have the servo working.

I power up the servo independently from Arduino and I have no idea why the servo is acting up like this.

Anyone would have an idea on the reason why the servo is moving when I move the joystick? only the dc motors should be moving which they do by the way.

I noticed the servo doesn't move when I put joystick in the direction to have dc motors go backward.

#include "DualVNH5019MotorShield.h"

DualVNH5019MotorShield md;

void stopIfFault()
{
  if (md.getM1Fault())
  {
    Serial.println("M1 fault");
    while(1);
  }
  if (md.getM2Fault())
  {
    Serial.println("M2 fault");
    while(1);
  }
}


const int potpinY = A0;
const int potpinX = A1;

void setup()
{
Serial.begin (9600); //initialize serial communications
md.init(); //initiates default pololu shield pins
}

void loop()
{
  int valY = analogRead(potpinY);
  int valX = analogRead(potpinX);
  valY = map(valY, 0, 1023, -255, 255);
  valX = map(valX, 0, 1023, -255, 255);

Serial.println(valX);
if (valX >= 150)
{
md.setM1Speed(valX);
md.setM2Speed(valX);
  stopIfFault();
}


 else if  (valX <= -150)
  {
    md.setM1Speed(valX);
    md.setM2Speed(valX);
   stopIfFault();
  }

   else if  (valY <= -150)
  {
    md.setM1Speed(valY);
    md.setM2Speed(-valY);
    stopIfFault();
  }


   else if  (valY >= 150)
  {
    md.setM1Speed(-valY);
    md.setM2Speed(valY);
    stopIfFault();
  }
  
else {
md.setM1Speed(0);
md.setM2Speed(0);
}
}

Servo power negative/ground needs to be connected to Arduino GND.

Steve

Steve,

Thank You for the advice, I did change the ground of servo to Arduino ground pin.

I completed more of the code and is basically final, the idea is simply having both dc motors go forward/backward/left/right using the joystick and 2 buttons for a plow to go up/down.

I still observe the issue where when using the joystick both dc motors and servo turn.

I saw a topic mentioning about timer1 and libraries conflict but I don't believe this is the issue? Any guidance would be appreciated.

thank you

here is the final sketch I built

#include <DualVNH5019MotorShield.h>
#include <Servo.h>

DualVNH5019MotorShield md;

void stopIfFault()
{
  if (md.getM1Fault())
  {
    Serial.println("M1 fault");
    while (1);
  }
  if (md.getM2Fault())
  {
    Serial.println("M2 fault");
    while (1);
  }
}

Servo myservo;  // create servo object to control a servo

int angle = 90;   // initial angle  for servo
int angleStep = 10;


#define LEFT A2   // pin A2 is connected to left button
#define RIGHT  A3  // pin A3 is connected to right button

const int potpinY = A0;
const int potpinX = A1;

void setup()
{
  Serial.begin (9600); //initialize serial communications
  myservo.attach(3);  // attaches the servo on pin 3 to the servo object
  pinMode(LEFT, INPUT_PULLUP); // assign pin A2 ass input for Left button
  pinMode(RIGHT, INPUT_PULLUP); // assing pin A3 as input for right button
  myservo.write(angle);// send servo to the middle at 90 degrees
  md.init(); //initiates default pololu shield pins
}

void loop()
{
  int valY = analogRead(potpinY);
  int valX = analogRead(potpinX);
  valY = map(valY, 0, 1023, -255, 255);
  valX = map(valX, 0, 1023, -255, 255);


  if (valX >= 150)
  {
    md.setM1Speed(valX);
    md.setM2Speed(valX);
    stopIfFault();
  }


  else if  (valX <= -150)
  {
    md.setM1Speed(valX);
    md.setM2Speed(valX);
    stopIfFault();
  }

  else if  (valY <= -150)
  {
    md.setM1Speed(valY);
    md.setM2Speed(-valY);
    stopIfFault();
  }


  else if  (valY >= 150)
  {
    md.setM1Speed(-valY);
    md.setM2Speed(valY);
    stopIfFault();
  }

  else {
    md.setM1Speed(0);
    md.setM2Speed(0);
  }


  while (digitalRead(RIGHT) == LOW) {

    if (angle > 0 && angle <= 165) {
      angle = angle - angleStep;
      if (angle < 0) {
        angle = 0;
      } else {
        myservo.write(angle); // move the servo to desired angle
        Serial.print("Moved to: ");
        Serial.print(angle);   // print the angle
        Serial.println(" degree");
      }
    }

    delay(100); // waits for the servo to get there
  }// while


  while (digitalRead(LEFT) == LOW) {


    if (angle >= 0 && angle <= 165) {
      angle = angle + angleStep;
      if (angle > 165) {
        angle = 165;
      } else {
        myservo.write(angle); // move the servo to desired angle
        Serial.print("Moved to: ");
        Serial.print(angle);   // print the angle
        Serial.println(" degree");
      }
    }

    delay(100); // waits for the servo to get there
  }//
}

I just tried a test using only the below code and everything works fine when running the portion for the servo excluding the motors.

Seem like a wiring problem or my code.

#include <Servo.h>

Servo myservo;  // create servo object to control a servo

int angle =90;    // initial angle  for servo
int angleStep =10;


#define LEFT A2   // pin 12 is connected to left button
#define RIGHT  A3  // pin 2 is connected to right button

void setup() {

  Serial.begin(9600);          //  setup serial
  myservo.attach(3);  // attaches the servo on pin 9 to the servo object
  pinMode(LEFT,INPUT_PULLUP); // assign pin A2 ass input for Left button
  pinMode(RIGHT,INPUT_PULLUP);// assing pin A3 as input for right button
  myservo.write(angle);// send servo to the middle at 90 degrees
 Serial.println("Robojax Servo Button ");
}

void loop() {
 
  while(digitalRead(RIGHT) == LOW){

    if (angle > 0 && angle <= 165) {
      angle = angle - angleStep;
       if(angle < 0){
        angle = 0;
       }else{
      myservo.write(angle); // move the servo to desired angle
      Serial.print("Moved to: ");
      Serial.print(angle);   // print the angle
      Serial.println(" degree");
       }
    }
    
  delay(100); // waits for the servo to get there
  }// while
 

  while(digitalRead(LEFT) == LOW){

    
    if (angle >= 0 && angle <= 165) {
      angle = angle + angleStep;
      if(angle >165){
        angle =165;
       }else{
      myservo.write(angle); // move the servo to desired angle
      Serial.print("Moved to: ");
      Serial.print(angle);   // print the angle
      Serial.println(" degree");
       }
    }
    
  delay(100); // waits for the servo to get there
  }// 

  
}

Looking at the code that motorshield driver does seem to grab Timer1 and so probably messes with the servo library use of it.

As an experiment you could try replacing Servo.h with ServoTimer2.h. You'll need to change the writes because ServoTimer2 uses milliseconds not degrees so 0 to 180 becomes roughly 600 to 2400.

Steve

Steve,

thank you, I made the change to library ServoTimer2.

I do see improvement but I observe strange behavior still that I am trying to fix. There seem to be interference when using the joystick.

question#1 can I make the servo go faster?
question#2 can the noise problem when using the joystick and servo moving be caused by my circuit being incorrect?

I will change my code and use digital pins instead of the analog pins for the buttons

#include <ServoTimer2.h>

#include <DualVNH5019MotorShield.h>
//#include <Servo.h>

DualVNH5019MotorShield md;

void stopIfFault()
{
  if (md.getM1Fault())
  {
    Serial.println("M1 fault");
    while (1);
  }
  if (md.getM2Fault())
  {
    Serial.println("M2 fault");
    while (1);
  }
}

ServoTimer2 myservo;  // create servo object to control a servo

int angle = 1000;   // initial angle  for servo



#define LEFT A2   // pin 12 is connected to left button
#define RIGHT  A3  // pin 2 is connected to right button

const int potpinY = A0;
const int potpinX = A1;

void setup()
{
  Serial.begin (9600); //initialize serial communications
  myservo.attach(3);  // attaches the servo on pin 3 to the servo object
  pinMode(LEFT, INPUT_PULLUP); // assign pin 5 ass input for Left button
  pinMode(RIGHT, INPUT_PULLUP); // assing pin 11 as input for right button
  myservo.write(angle);// send servo to the middle at 90 degrees
  md.init(); //initiates default pololu shield pins
}

void loop()
{
  int valY = analogRead(potpinY);
  int valX = analogRead(potpinX);
  valY = map(valY, 0, 1023, -255, 255);
  valX = map(valX, 0, 1023, -255, 255);


  if (valX >= 150)
  {
    md.setM1Speed(valX);
    md.setM2Speed(valX);
    stopIfFault();
  }


  else if  (valX <= -150)
  {
    md.setM1Speed(valX);
    md.setM2Speed(valX);
    stopIfFault();
  }

  else if  (valY <= -150)
  {
    md.setM1Speed(valY);
    md.setM2Speed(-valY);
    stopIfFault();
  }


  else if  (valY >= 150)
  {
    md.setM1Speed(-valY);
    md.setM2Speed(valY);
    stopIfFault();
  }

  else {
    md.setM1Speed(0);
    md.setM2Speed(0);
  }

  while (digitalRead(LEFT) == LOW && angle < 2400) {
    angle++;
    myservo.write(angle);
    delay(10);
  }

  while (digitalRead(RIGHT) == LOW && angle > 600) {
    angle--;
    myservo.write(angle);
    delay(10);
  }
}

I think I found the reason.

the below link points to an example using servo with pololu shield.

I will attempt to understand it and apply to my existing sketch......... :o

ServoTimer2 already uses T2 instead of T1...but there's no harm trying. And the analog pins are digital pins anyway when you use digitalRead on them.

But looking at your video there's something very wrong with your servo. An SG92R should not be able to rotate more than 180 degrees and yours is doing full circles. Is it a genuine TowerPro? Can you try a different one?

You can get the servo to go faster by reducing the delay(10). If you want full speed don't move the servo 1 step at a time, just write the end position directly. Or instead of angle++ add 5 or 10 to angle every time.

Steve