Pololu Dual VNH5019 Motor Driver Shield for Arduino controlled with Processing Firmata

The goal is to create a rectangle in Processing that increases the speed up to max at the top of the y coordinate max reverse speed at the bottom of the y coordinate. The servo fimata aspect works fine as the servo swings from 180 to 0 degrees based on the position of the mouse within the rectangle.

Right now the dc motor goes in the correct direction based upon if the mouse is above or below the middle of the rectangle but it jumps and is not consistent.

The use for this is for a phone controlled rover due in three weeks. I’m freaking out this is my ME senior design project. I think something is wrong with my arduino sketch.

Thanks,
Lucas

// Send numeric data to Arduino through Firmata library using a reserved pin.
// The data received on the reserved pin is handled as needed
// In this example, the mouse position is sent to the Arduino and controls the brightness of an RGB LED


import processing.serial.*; 
import cc.arduino.*;


int input1 = 5;
int input2 = 6;
Arduino arduino; // Setup an arduino object to communicate with Firmata firmware

// variables for the sampling
long time;
int servoDelay = 2;

// variables for the servo position
int xPos;
int yPos;
int changePosX,changePosY;

// sets a maximum change of 5 degrees
int deltaMax = 5;

void setup()
{
  size(180, 800); 
  //println(Serial.list());   
  // Using Firmata library
  arduino = new Arduino(this, Arduino.list()[0], 57600);

  // initializes variables
  time = millis();
  xPos = mouseX;
  yPos = mouseY;
}
/*void userevent() {
  
  if (key=='1') {
    arduino.analogWrite(input1, 1);
    changePosX = xPos;
      changePosY = yPos;
    
    println("forward");
  } else if (key=='2') {
    arduino.analogWrite(input1, 0);
    changePosX = 180-xPos;
      changePosY = 180-yPos;
    
     println("backward");
  }
}*/



  void draw() {
    // local variables for the change in servo positions
    //int changePosX, changePosY;
   // print(millis() +","+(time +servoDelay)+"---");

    // timer check statement to make the servo update at a lower frequency
    if (millis() > (time + servoDelay)) {
      // constrains the servo angle change to +/- deltaMax
      changePosX = constrain((mouseX-xPos), -deltaMax, deltaMax);
      changePosY = constrain((mouseY-yPos), -deltaMax, deltaMax);
      println(changePosX+","+changePosY);

      // sets the new motor positions
      xPos += changePosX;
      yPos += changePosY;

      //resets timer
      time = millis();
    }

    //Writes to Arduino pins for it to intercept and transfer to servo motion
    arduino.analogWrite(input1, yPos);
    delay(2);
    arduino.analogWrite(input2, xPos);
    delay(2);
    println(xPos+","+yPos);
  }

The arduino code is

#include <Wire.h>
//#include <Adafruit_MotorShield.h>
//#include "utility/Adafruit_PWMServoDriver.h"
#include <Servo.h>
#include <Firmata.h>
#include "DualVNH5019MotorShield.h"

//Adafruit_MotorShield AFMS = Adafruit_MotorShield();
//Adafruit_DCMotor *myMotor = AFMS.getMotor(1);


Servo servo1;
DualVNH5019MotorShield md; //Servo servo2;


int input1 = 5;
int input2 = 6;

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

}

void setup() {
  Serial.begin(9600);
  Serial.println("Dual VNH5019 Motor Shield");
  md.init();
  servo1.attach(9);


  //  servo2.attach(10);
  //  myMotor->setSpeed(0);
  //  myMotor->run(FORWARD);
  // turn on motor
  //  myMotor->run(RELEASE);

  Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
  Firmata.attach(ANALOG_MESSAGE, analogWriteCallback); // Call this function when analog writes are received

  Firmata.begin(57600);

}

void analogWriteCallback(byte pin, int value)
{

  // If data is sent to reserved pin, execute code
  if (pin == input1) {
    if ( value > 410 || value < 390) {
      md.setM1Speed((400 - value)); //speed max is 400
      stopIfFault();


    }


    else {
      md.setM1Speed(0);

      stopIfFault();


    }
  }
  else if (pin == input2) {

    servo1.write(value);
  }
}


void loop() {
  while (Firmata.available()) { // Handles Firmata serial input
    Firmata.processInput();
  }

}

Hello.

It looks like your servo is attached to pin 9, which the VNH5019 uses for PWM on motor driver 1, which might explain the jumping. You might consider using a different pin for that servo, or using motor driver 2, which uses pin 10 for PWM. You can see what pins the VNH5019 shield uses (and for what purpose) under the “Default Arduino Pin Mappings” table inside the “Shield Connections” section of the shield’s user’s guide. You can find the user’s guide under the “Resources” tab of the shield’s product page.

-Jon

thanks for getting back to me Jonathon. so i altered the arduino code so that the servo was using pin 10 which works and i simplified the motor input to just take the value 0-255 from the analog write in the processing firmata code.

  #include <Wire.h>
#include <Servo.h>
#include <Firmata.h>
#include "DualVNH5019MotorShield.h"

Servo servo1;
DualVNH5019MotorShield md; //Servo servo2;

int input1 = 5;
int input2 = 6;

int dcspeed = 0;

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

}
*/
void setup() {
  Serial.begin(9600);
  Serial.println("Dual VNH5019 Motor Shield");
  md.init();
  servo1.attach(10);
  md.setM1Speed(dcspeed);




  Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
  Firmata.attach(ANALOG_MESSAGE, analogWriteCallback); // Call this function when analog writes are received

  Firmata.begin(9600);

}

void analogWriteCallback(byte pin, int value)
{

  // If data is sent to reserved pin, execute code
  if (pin == input1) {
    if (value <= 115) {
      dcspeed = (400 - value * 3.48);
      md.setM1Speed((dcspeed)); //speed max is 400
    }
    else if (value >= 140) {
      dcspeed = (400 - value * 3.13);
      md.setM1Speed((dcspeed)); //speed max is 400
    }
    else {
      dcspeed = 0;
      md.setM1Speed((dcspeed));

    }

    else if (pin == input2) {

      servo1.write(value);
    }
  }


  void loop() {
    while (Firmata.available()) { // Handles Firmata serial input
      Firmata.processInput();
    }

  }

And I made the processing code just a 180 by 255 rectangle that should write the speed to motor 1. The motor does nothing. I made an adafruit motorshield work with a very similar sketch in a previous rover project. Do I need to designate which pin I want to talk to? Do I need to create a for loop in arduino like in the demo sketch? that doesn’t seem to make sense.

import processing.serial.*; 
import cc.arduino.*;


int input1 = 5;
int input2 = 6;
Arduino arduino; // Setup an arduino object to communicate with Firmata firmware

// variables for the sampling
long time;
int servoDelay = 2;

// variables for the servo position
int xPos;
int yPos;
int changePosX,changePosY;

// sets a maximum change of 5 degrees
int deltaMax = 5;

void setup()
{
  size(180, 255); 
  //println(Serial.list());   
  // Using Firmata library
  arduino = new Arduino(this, Arduino.list()[0], 9600);

  // initializes variables
  time = millis();
  xPos = mouseX;
  yPos = mouseY;
}




  void draw() {
    // local variables for the change in servo positions
    //int changePosX, changePosY;
   // print(millis() +","+(time +servoDelay)+"---");

    // timer check statement to make the servo update at a lower frequency
    if (millis() > (time + servoDelay)) {
      // constrains the servo angle change to +/- deltaMax
      changePosX = constrain((mouseX-xPos), -deltaMax, deltaMax);
      changePosY = constrain((mouseY-yPos), -deltaMax, deltaMax);
     // println(changePosX+","+changePosY);

      // sets the new motor positions
      xPos += changePosX;
      yPos += changePosY;

      //resets timer
      time = millis();
    }

    //Writes to Arduino pins for it to intercept and transfer to servo motion
    arduino.analogWrite(input1, yPos);
    delay(2);
    arduino.analogWrite(input2, xPos);
    delay(2);
    println(xPos+","+yPos);
  }

Sorry, my mistake. I just realized that the Arduino Servo library disables the use of the analogWrite() functionality on pins 9 and 10, whether or not there is a Servo attached to either of those two pins. So, the solution is not as simple as switching to another pin.

Here are a few of the options I can see:

  1. Remap the motor shield to use different pins (instead of the timer1 pins) for PWM. This would mean modifying our VNH5019 library.

  2. Use a different library or code for controlling the servo that doesn’t rely on timer 1. For example, you could use the code in the “controlling a servo” section of the Zumo shield user’s guide.

  3. Use a different shield and library that don’t rely on timer1 (like how you got your Adafruit motor shield working with a similar sketch).

-Jon

Thanks for your suggestions.

I got it to work but without variable speed control.

Processing

import processing.serial.*; 
import cc.arduino.*;


int input1 = 5;
int input2 = 6;
Arduino arduino; // Setup an arduino object to communicate with Firmata firmware

// variables for the sampling
long time;
int servoDelay = 2;

// variables for the servo position
int xPos;
int yPos;
int changePosX,changePosY;

// sets a maximum change of 5 degrees
int deltaMax = 5;

void setup()
{
  size(180, 255); 
  //println(Serial.list());   
  // Using Firmata library
  arduino = new Arduino(this, Arduino.list()[2], 9600);

  // initializes variables
  time = millis();
  xPos = mouseX;
  yPos = mouseY;
}




  void draw() {
    // local variables for the change in servo positions
    //int changePosX, changePosY;
   // print(millis() +","+(time +servoDelay)+"---");

    // timer check statement to make the servo update at a lower frequency
    if (millis() > (time + servoDelay)) {
      // constrains the servo angle change to +/- deltaMax
      changePosX = constrain((mouseX-xPos), -deltaMax, deltaMax);
      changePosY = constrain((mouseY-yPos), -deltaMax, deltaMax);
     // println(changePosX+","+changePosY);

      // sets the new motor positions
      xPos += changePosX;
      yPos += changePosY;

      //resets timer
      time = millis();
    }

    //Writes to Arduino pins for it to intercept and transfer to servo motion
    arduino.analogWrite(input1, yPos);
    delay(2);
    arduino.analogWrite(input2, xPos);
    delay(2);
    println(xPos+","+yPos);
  }`

ARDUINO

#include <Wire.h>
#include <Servo.h>
#include <Firmata.h>
#include "DualVNH5019MotorShield.h"

Servo servo1;
DualVNH5019MotorShield md; //Servo servo2;

int M1INA =2;
int M1INB =4;
int M1PWM =9;

int input1 = 5;
int input2 = 6;

//int dcspeed = 0;

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

}

void setup() {
  Serial.begin(9600);
  Serial.println("Dual VNH5019 Motor Shield");
  md.init();
pinMode(M1INA, OUTPUT);
pinMode(M1INB, OUTPUT);
pinMode(M1PWM, OUTPUT);
  
 servo1.attach(3);

  Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);
  Firmata.attach(ANALOG_MESSAGE, analogWriteCallback); // Call this function when analog writes are received
  Firmata.begin(9600);

}

void analogWriteCallback(byte pin, int value)
{

  // If data is sent to reserved pin, execute code
  if (pin == input1) {
    if (value <= 115) {
//      dcspeed = (400 - value * 3.48);
      digitalWrite(M1INA, HIGH);
  digitalWrite(M1INB, LOW);
  analogWrite(M1PWM,255);
    }
    else if (value >= 140) {
   Serial.println("Motor Reverse");
digitalWrite(M1INA, LOW);
digitalWrite(M1INB, HIGH);
  analogWrite(M1PWM,255);
    }
    else {
      //dcspeed = 0;
      md.setM1Brake((0));

    }
  }
    else if (pin == input2) {

      servo1.write(value);
    }
    
  }
  


  void loop() {
    while (Firmata.available()) { // Handles Firmata serial input
      Firmata.processInput();
    }

  }`

I can’t get variable speed control to work correctly but i’m guessing i could just make 3 different regions to make the pwm sin wav bigger or smaller. I don’t need that wide range of variability but the system is going to be attached to a wheel chair motor so it might go kindof fast and max speed with the momentum of our frame might be kindof dangerous.

Also How do I write a command to turn this motor off when i stop the processing sketch… Any ideas? when i turn off processing the motor continues to run.

Thanks for your help

As the Arduino reference states, using the Servo library means that analogWrite() will not work properly on pins 9 and 10, so that is probably why you are having trouble with variable speed control. If you remap the shield connections and use a different pin for the motor PWM, it will probably work.

It looks like one way to perform an operation when a Processing sketch exits is to add a shutdown hook, as described here. This is where you can stop the motor with a call like analogWrite(M1PWM, 0) (allowing it to coast) or setM1Brake(400) (applying maximum braking). For example, you could add the following code to your setup() function:

Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
    public void run() {
        analogWrite(M1PWM, 0);
    }
}));

Edit: Actually, setM1Brake() will not work as expected for the same reason you can’t use pins 9 and 10 for PWM, but you can get the same effect with a different PWM pin by setting the INA and INB pins appropriately to brake the motor.

-Jon