Help with G2 Motor Driver 24v14 Shield for Arduino combined with Adafruit Motor Shield V2

Good Evening All,
I am currently using a G2 24v14 Pololu and trying to stack it with an Adafruit V2 motor shield and a Arduino Mega. The plan is to control an underwater vehicle with the thruster motor being driven by the G2 and two servos to control direction. The issue I’ve run in to is when I attempt the code with both the motor and the servos, the dc motor doesn’t work. The G2 buzzes and the red and green lights next to the motor input flicker very rapidly. From what I’ve read online, I believe it has something to do with the Servos and the motor both using the same timer. However, when I tried to use a different library for the servo’s that uses timer 2, the buzzing does go away, but the servos now don’t move. I don’t know if maybe I need to assign the AF shield or G2 to use separate timers somehow, or if that is even the correct solution. Any help would be tremendously appreciated. Thanks in advance for all your help! I will also post the code below so maybe it will give a more clear idea of what I’m talking about.

#include "DualG2HighPowerMotorShield.h"
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
#include <SPI.h>
//include <Servo.h>
#include <ServoTimer2.h>
#include <Adafruit_MotorShield.h>
#include <Wire.h>
#include "IRremote.h"
#include "IRremoteint.h"
#define BNO055_SAMPLERATE_DELAY_MS (100)

Adafruit_MotorShield AFMS = Adafruit_MotorShield(); //Create object motor shield
ServoTimer2 myFinTop;
ServoTimer2 myFinBot;

byte N = 30;
byte runXTimes = 0;
byte servoOneControlPin = 9;
byte servoTwoControlPin = 10;
byte blueLed = 48; 
byte redLed2 = 7;
byte redLed = 50;
byte greenLed = 46;
byte remoteSensor = 11;

int servoDelay = 25;
int flag;

float heading;
float pressure;
float finPosition = 75;
float finRight = finPosition*1.50;
float finLeft = finPosition*0.50;
float headError;
float variableHeading;
float rightLimit;
float leftLimit;

DualG2HighPowerMotorShield24v14 md;
Adafruit_BNO055 bno = Adafruit_BNO055();

IRrecv irrecv(remoteSensor);
decode_results results;

void setup() {
/*-------------------------Initiate Common/Servo---------------------*/
//TCCR2B = (TCCR2B& 0xF8)|0x04;

Serial.begin(9600);
pinMode(blueLed,OUTPUT);
pinMode(greenLed,OUTPUT);
pinMode(redLed,OUTPUT);
myFinTop.attach(servoOneControlPin);
myFinBot.attach(servoTwoControlPin);

/*-------------------------Initiate Thruster Motor-------------------*/
  //md.init();
  //md.calibrateCurrentOffsets();
  //delay(10);
  //md.flipM1(true);   // Uncomment to flip a motor's direction

/*-------------------------Initiate IMU------------------------------*/
Serial.println("Orientation Sensor Raw Data Test"); Serial.println("");
  if(!bno.begin())      // Initialize IMU
    {
      Serial.print("NO SIGNAL FROM IMU");
      while(1);
    }
delay(1000);
bno.setExtCrystalUse(true);
Serial.println("Calibration status values: 0=uncalibrated, 3=fully calibrated");

/*------------------------Initiate IR--------------------------------*/
irrecv.enableIRIn(); //Start receiver
}

void loop() 
{     
  if(irrecv.decode(&results))
  {
    translateIR();
    irrecv.resume();
  }
    calibrate();
    calibrationDisp();
    headingCorrection();
    delay(100);

}

void translateIR()
{ 
  Serial.println(results.value,DEC);
  switch(results.value)
  {
    case 1637879537:
    thrusterOn();
    break;

    case 1637912177:
    thrusterOff();
    break;
  }
}
  
void calibrate()
{
  imu::Vector<3> euler = bno.getVector(Adafruit_BNO055::VECTOR_EULER); 
  uint8_t system, gyro, accel, mag = 0;
  bno.getCalibration(&system, &gyro, &accel, &mag);
  
/*-----------------------IMU Sensor----------------------------------*/
// -CHANGE VECTOR_ to CHOICE:
// - VECTOR_ACCELEROMETER - m/s^2
// - VECTOR_MAGNETOMETER  - uT
// - VECTOR_GYROSCOPE     - rad/s
// - VECTOR_EULER         - degrees
// - VECTOR_LINEARACCEL   - m/s^2
// - VECTOR_GRAVITY       - m/s^2

 if(gyro == 3 && mag == 3 && system == 3)         //&& accel == 3
  {
        if(runXTimes < N)
        {
           getHeading();
           runXTimes++;
        }
    delay(100);
    Serial.print("Heading: ");
    Serial.print(heading);   
    Serial.println(" Degrees");   
  }
/* Display the floating point data */
Serial.print("X: ");
Serial.print(euler.x());
delay(50);

//  Serial.print(" Y: ");
//  Serial.print(euler.y());
//  Serial.print(" Z: ");
//  Serial.print(euler.z());
//  Serial.print("\t\t");

/* Display calibration status for each sensor. */
bno.getCalibration(&system, &gyro, &accel, &mag);
Serial.print(" CALIBRATION: Sys=");
Serial.print(system, DEC);
Serial.print(" Gyro=");
Serial.print(gyro, DEC);
Serial.print(" Accel=");
Serial.print(accel, DEC);
Serial.print(" Mag=");
Serial.println(mag, DEC);
delay(BNO055_SAMPLERATE_DELAY_MS);

}

void headingCorrection()
{
  imu::Vector<3> euler = bno.getVector(Adafruit_BNO055::VECTOR_EULER); 
  uint8_t system, gyro, accel, mag = 0;
  bno.getCalibration(&system, &gyro, &accel, &mag);
  
rightLimit = heading*-0.05;
leftLimit = heading*0.05;
headError = heading - euler.x();
//variableHeading = headError + heading;

  if(rightLimit < headError && headError < leftLimit)
    {
      Serial.println("Status: On Course");
      Serial.print("Heading Error: ");
      Serial.print(headError);
      Serial.println(" degrees");
      myFinTop.write(finPosition);
      myFinBot.write(finPosition);
      Serial.println(" ");
    }
  else if(headError < rightLimit)
    {
      myFinTop.write(finRight); //Counter Left Drift - Top Fin
      myFinBot.write(finRight); //Counter Left Drift -  Bottom Fin
      Serial.print("Heading Error: ");
      Serial.print(headError);
      Serial.println(" degrees"); 
      Serial.println("Status: Correction left");
      Serial.println(" ");
    }  
  else if(headError > leftLimit)
    {
      myFinTop.write(finLeft); //Counter Left Drift - Top Fin
      myFinBot.write(finLeft); //Counter Left Drift -  Bottom Fin
      Serial.print("Heading Error: ");
      Serial.print(headError);
      Serial.println(" degrees");
      Serial.println("Status: Correction right");
      Serial.println(" ");
    }
  else if(heading < 10 && heading >= 351)
    {
    
    }
    
}

void calibrationDisp()
{
  imu::Vector<3> euler = bno.getVector(Adafruit_BNO055::VECTOR_EULER); 
  uint8_t system, gyro, accel, mag = 0;
  bno.getCalibration(&system, &gyro, &accel, &mag);
  
    if(gyro == 3 && mag == 3 && system == 3)            //&& accel == 3 
    {
      digitalWrite(greenLed,HIGH);
      delay(50);
      digitalWrite(greenLed,LOW);
      digitalWrite(blueLed,LOW);
      digitalWrite(redLed,LOW);
      digitalWrite(redLed2,LOW);
    }
    else if(gyro == 3 && mag == 3)
    {
      digitalWrite(blueLed,HIGH);
      delay(50);
      digitalWrite(blueLed,LOW);
    }
    else if(accel == 3)
    {
      digitalWrite(redLed2,HIGH);
      delay(100);
      digitalWrite(redLed2,LOW);
    }
    else if(system == 3)
    {
      digitalWrite(redLed,HIGH);
      delay(50);
      digitalWrite(redLed,LOW);
    }
    
}

float getHeading()
{
  imu::Vector<3> euler = bno.getVector(Adafruit_BNO055::VECTOR_EULER); 
  uint8_t system, gyro, accel, mag = 0;
  bno.getCalibration(&system, &gyro, &accel, &mag);

  if(gyro == 3 && mag == 3 && system == 3)          //&& accel == 3 
  {
    heading = euler.x();
    return(heading);  
    delay(100);       //This is new 
  }
  
}

void thrusterOn()
{
  md.enableDrivers();
  delay(1);  
  md.setM1Speed(500); 
  Serial.print("M1 current: ");
  Serial.println(md.getM1CurrentMilliamps());
}
  
void thrusterOff()
{
  md.enableDrivers();
  delay(1);  
  md.setM1Speed(0);
  Serial.print("M1 current: ");
  Serial.println(md.getM1CurrentMilliamps());
  irrecv.resume();
}

Our Arduino library for the Dual G2 High Power Motor Driver Shields only uses timer 1 for the PWM signals if you are using a ATmega168, ATmega328P, ATmega328PB, or ATmega32U4 microcontroller. Since the Arduino Mega uses the ATmega2560, our library should be using analogWrite() for the PWM signal, and that shouldn’t be causing any problems with the standard Servo library.

However, it looks like you are trying to use pins 9 and 10 for your servos; those are the pins the G2 Motor Driver Shields use for the PWM signals. If you can swap the servos to different unused pins, that would probably be the easiest solution.

Also, pin 7 is used for motor 1 direction (M1DIR), and it looks like you are trying to use it with an LED, which will cause a conflict and unexpected behavior. You can see which pins are used by the shield and a brief description of their funciton in the “Control and feedback pins” section of the shield’s user’s guide.

An alternative solution would be to remap the pins used by the Dual G2 High-Power Motor Driver Shield, which you can do by following the instructions in the “Remapping the Arduino connections” section of the shield’s user’s guide. Please note that you should choose pins that are capable of analogWrite() and not used for anything else. If you choose this option, you would also need to switch to using the alternate constructor from the library in your code to specify these new pins. You can see the order of the arguements expected by the alternate constructor in the “DualG2HighPowerMotorShield.cpp” file from the library.

Brandon

Hi Brandon,
Thanks very much for your response. It looks like I will need to remap the pins used by the G2 because the Adafruit motorshield uses only pins 9 and 10 as well for driving the servos. Could you explain a little more in detail about what you mean with using the alternate constructor to specify the new pins? I understand I would need to include that in my code at the top the (.cpp), but how do you specify the pins? I guess I just don’t understand the order of arguments expected and what I’m looking for and need to change in that regard.

Thanks again for your time and hats off to Pololu’s customer service.

Sam

Hi Brandon, I think I got something figured out. I was mistaken in thinking I needed to include the .cpp file and found out that I just needed to redesignate the pins in that file. I only remapped pin 9 (M1 PWM) to pin 5 as the instructions stated thinking that I was only using M1 so there was no need to also remap pin 10 a different pin. However, now I still get jitters with the green and red lights flashing extremely fast.

Another thing of note, now I can get one servo to work as well as the motor to work at the same time. The jittery buzz and light flickering is still present, but the motor is turning now. What would you suggest would be the way to proceed from here? I was thinking of remapping pin 10 (M2 PWM) even though I’m not using it, to a different PWM arduino pin and see if that would fix the issue. The only thing stopping me is the signal that is flickering is still on the M1 side so I’m not sure pin 10 and M2 PWM are even correlated.

Thanks again for the help,

Sam

It sounds like you might have figured it out, but the .cpp files is already being referenced when you use the library, so you do not need to include it again. The alternate constructor is the second one listed in the file, and lets you specify the pins being used for each function. The order of the arguments is (M1nSLEEP, M1DIR, M1PWM, M1nFAULT, M1CS, M2nSLEEP, M2DIR, M2PWM, M2nFAULT, M2CS). So, to only change the M1 PWM pin to 5 and leave the rest as the default pins, you would change:

DualG2HighPowerMotorShield24v14 md;

in your code, to:

DualG2HighPowerMotorShield24v14 md( 2, 7, 5, 6, A0, 4, 8, 10, 12, A1);

It sounds like something is still conflicting. Could you post pictures of your board and the modifications you made to remap M1PWM to pin 5? Could you do a continuity test with a multimeter between pin 9 on the Arduino header and M1PWM on the edge of the board (indicated by green circles in the picture below)? You can also check continuity at the 2 pins circled in yellow.

Additionally, it looks like you have a lot of other things in your system (e.g. IR remote and additional sensors). Can you try testing the shield and motors separately from all of your other peripherals with a very simple program? If those work, you could then try adding your servos and seeing if the problem still happens without all of the other devices.

Brandon

Hi Brandon,

Following your advice, I did a continuity test between the portion you circled in yellow above and found there was still a connection that I must have not cut all the way through. After ensuring that connection was severed, the system worked perfectly! No jitters, glitches, or any issues and the DC motor as well as the servos worked in unison. Thanks for all your help you guys at Pololu are outstanding!!

2 Likes

I am glad that you were able to get it all working correctly! Thank you for letting us know.

By the way, your underwater vehicle sounds pretty interesting; you might consider posting more about it in the “Share your projects” section of our forum. I am sure other members here would be interested in it too, especially if you have a video of it in action!

Brandon

Initial testing should be in about a month to 6 weeks from now. The team is just waiting for our parts to arrive to assemble the body, internals, etc. We can then get started with testing and data collection. I will share some results here for sure! Thanks again for the help!

Cheers,

Sam

1 Like