Robotics‎ > ‎Blimp‎ > ‎

DRV8835

To control DC motors using the DRV8835 dual motor driver carrier, you'll need to create a new tab called DRV8835.h. Once you've done that, add the following code to your newly created file:
#include <Arduino.h>

template <int phasePin, int enablePin>

class DRV8835
{
  public:
    DRV8835()
    {
      pinMode(phasePin,OUTPUT);
      pinMode(enablePin,OUTPUT);
    }
    
    void drive(int velocity)
    {
      if (velocity >= 0)
        digitalWrite(phasePin, LOW);
      else
        digitalWrite(phasePin, HIGH);
      analogWrite(enablePin, abs(velocity));
    }
};
The template is used to relay which pins will be used to control the motors. DC motors can be controlled in many ways, but typically two pins are used to send a signal to a motor driver since most microcontrollers  cannot supply enough current. The DRV8835 motor driver can be used in two ways. The method we are using involves setting one GPIO pin (the phasePin) either high or low to control which direction the motor will turn. A second pin (the enablePin) is controlled using a PWM pin. By varying how often the pin is high or low using the analogWrite command, you control how fast the motor turns. For more information on how this driver works, refer to https://www.pololu.com/product/2135.

Next, you'll have to modify the code within your main file. Start by swapping the line that includes the servo library with the DRV8835 library you just created:
#include <Servo.h> #include "DRV8835.h"

Next, change how the motor objects are created:
Servo leftMotor; DRV8835<16,5> leftMotor;
Servo rightMotor; DRV8835<13,4> rightMotor;

Since your new library defines which pins are used when you create the motor objects, you can now delete the lines of code that attached your servos to pins:
  leftMotor.attach(10);
  rightMotor.attach(D4);

The manner in which we stopped the motors is different too. Instead of passing 1500 to the writeMicroseconds function to get the motors to stop, we now use the drive function in the library we created and send 0.
  leftMotor.writeMicroseconds(1500);  leftMotor.drive(0);
  rightMotor.writeMicroseconds(1500);  rightMotor.drive(0);

To control the motors, we must change the handleRemoteControl() function in a similar fashion.
  leftMotor.writeMicroseconds(1500 - server.arg("L").toInt());   leftMotor.drive(server.arg("L").toInt());
  rightMotor.writeMicroseconds(1500 + server.arg("R").toInt());  rightMotor.drive(server.arg("R").toInt());

Those are all the changes we need to make to your Arduino code, but there are still a few we need to make to the web app you're hosting.

Before we start, you should know that the PWM pins on the esp8266 (the brain behind your Adafruit Huzzah Feather) are 10 bit which means they can accept 1024 distinct values (210 = 1024). Since the first value is a 0 instead of a 1, the range is between 0 and 1023. If we had motors that could handle all the voltage our motor drivers can supply, we would send our motors values that range ±1023. However, since our motors are only designed to handle 3.7 volts at most and our single cell LiPos reach 4.2 volts when fully charged, let's make the values we send ±800 (a little small than needed just to be on the safe side). So go to Cloud9 and pull up your code. To get values that are ±500, we multiplied the accelerometer axis by 60. Now we need to get values that are ±800, so try multiplying by 96 or thereabouts. Remember, you don't want to have to tilt your device 90 degrees to go or turn full speed.
  var power = Math.round(acceleration.z * 60);  var power = Math.round(acceleration.z * 96);
  var steering = Math.round(acceleration.y * 60);  var steering = Math.round(acceleration.y * 96);

One other issue we need to deal with is how to handle values that exceed our desired range. We don't need to worry about this when controlling servos because if we send a signal that is too high, they just continue going as fast as they can. However, if we send a value to our motor drivers that exceeds 1023, the count starts over. For example, if we sent 1025, the power level actually provided to the motors would be 2 since 1025 - 1023 = 2. Why would we need to worry about this if the values we are sending have a range of ±800? Keep in mind the way in which power and steering values are combined to create motor power levels. For the left motor we add them together. If you tilt your device forward and to the right, it is conceivable that you could send it 800 + 800, or 1600, which would yield an incorrect power less than 800 (1600 - 1023 - 577). Sending 600 + 600 would work, but would shorten the life of our motors. So, to prevent values that exceed our desired range, we will created a constrain function directly below the deviceMotionHandler() function. All this function will do is check to see if our motor power levels are too high or too low. If the value exceeds 800, it will bring the value down to 800. If the value is below -800 (for example, -900), it will bring the value up to -800.
        function constrainMotor(motorPower) {
            if (motorPower > 800)
                motorPower = 800;
            else if (motorPower < -800)
                motorPower = -800;
            return motorPower;
        }

To use our newly created constrain function, modify the lines at the bottom of the deviceMotionHanlder() function that set the power levels for your motors:
  leftMotor = power + steering;  leftMotor = constrainMotor(power + steering);
  rightMotor = power - steering;  rightMotor = constrainMotor(power - steering);

Comments