Hello,
I hope everyone is doing well. I am working on a robot using the DRV8833 to power two motors. For some reason, the left motor will sometimes move slower than the right motor. We use a PID system to make the bot move straight, but the inconsistency poses problems (Sometimes, it will go straight, and other times it does not). Below is the schematic:
Hardware
- Parts:
- Waveshare esp32 zero, driving the motor driver.
- Polulu DRV8833 motor driver, powered by a boost regulator from 3.7V to 6V.
- U3V40F9 voltage step-up regulator
- step up is powered by 1 3.7 850 mah battery.
Software
Driving the Motor
static char Rcurrentdirection = '\0';
static void actualMoveRightMotor(uint8_t rightPWM, char direction) {
if(direction == 'N') { //moving forward relative to front of robot
if(Rcurrentdirection != direction){
digitalWrite(BIN1_RIGHTMOT, LOW);
digitalWrite(BIN2_RIGHTMOT, HIGH);
Rcurrentdirection = direction;
}
analogWrite(BIN2_RIGHTMOT, rightPWM);
} else {
if(Rcurrentdirection != direction){
digitalWrite(BIN1_RIGHTMOT, HIGH);
digitalWrite(BIN2_RIGHTMOT, LOW);
Rcurrentdirection = direction;
}
analogWrite(BIN1_RIGHTMOT, rightPWM);
}
}
To move the motor forward/backward, we specify the direction. I also have a condition that if the current motor direction is different from the previous motor direction, do the digital writes to change the direction of the motor driver. The logic is similar for the left motor.
PID Control
- We are using the Adafruit bno055 IMU to ensure the bot goes straight. We know this approach works correctly, as we have used this approach on previous bots. It moves the bot at the Angle specified.
#define DIA 32
#define PI 3.1415926535897932384626433832795
double maxSpeed = 175;
double minSpeed = 100;
void straight(char direction, int distance)
{
// ratio for the Angle PID
double AKp = 1.0; /* Angle proportion scale constant */
double AKd = 0.0;
// ratios for the Encoder PID
double LEKp = 1; /* Left encoder proportion scale constant */
double LEKd = 0.0;
double REKp = 1; /* Right encoder proportion scale constant */
double REKd = 0.0;
//Angle variables
double AngleError = 0.0;
double PreviousAngleError = 0.0;
double currentAngle = angle();
double targetDirection = 0.0;
switch (direction)
{
case 'N':
targetDirection = 0;
break;
case 'S':
targetDirection = 180;
break;
case 'E':
targetDirection = 90;
break;
case 'W':
targetDirection = 270;
break;
}
// encoder values
double numTicks = (102 * distance) / (DIA * PI); // Num ticks that we need to travel
double EncoderLeftError = numTicks;
double EncoderRightError = numTicks;
// clear the encoder count
encLeft.clearCount();
encRight.clearCount();
// final motor speeds
double LeftMotorSpeed = 0.0;
double RightMotorSpeed = 0.0;
// time values (for derivative)
unsigned long PreviousTime = millis();
unsigned long CurrentTime = millis();
/* stall detection variables */
// Variables for destination check
bool isAtDestination = false;
const double encoderTolerance = 5.0; // Consider arrived if within this many ticks
double basespeed = 135;
while (1)
{
AngleError = targetDirection - Angle (); //Angle () gets the Angle the bot is at.
//normalize the angle error
while (AngleError > 180) AngleError -= 360;
while (AngleError <= -180) AngleError += 360;
// Calculate encoder errors
EncoderLeftError = numTicks - getLeftEncoder();
EncoderRightError = numTicks + getRightEncoder();
//constrain the max encoder error to the base speed.
EncoderLeftError = constrain(EncoderLeftError, 0, basespeed);
EncoderRightError = constrain(EncoderRightError, 0, basespeed);
/* Calculate the motor speeds based on the error*/
LeftMotorSpeed = (LEKp * EncoderLeftError) + (AKp * AngleError);
RightMotorSpeed = (REKp * EncoderRightError) - (AKp * AngleError);
LeftMotorSpeed = constrain(LeftMotorSpeed, 0, maxSpeed);
RightMotorSpeed = constrain(RightMotorSpeed, 0, maxSpeed);
/* Stalling logic (not relevant here) */
// Apply motor speeds
moveLeftMotor(LeftMotorSpeed);
moveRightMotor(RightMotorSpeed);
// Update time for next iteration
PreviousTime = CurrentTime;
CurrentTime = millis();
}
// Stop motors
moveLeftMotor(0);
moveRightMotor(0);
delay(100);
// turnTo(direction);
}
- I know there is a lot to this question, but I look forward to a response.
TDLR: We are experiencing inconsistencies with the motor speeds. What are some potential causes and remedies for this? If there are any questions, I’d love to clarify anything. Thanks for the help, cheers!