Are there any documentation or resources for programming the Pololu 3pi+ 32u4 (OLED Version) robot? I’m specifically looking to learn how to control its movements, such as moving a certain distance forward and backward, making right and left turns, etc.
If you want to do closed-loop speed/position control you could implement a PID controller that processes the encoder feedback. If you are new to PID control, you might consider the Arduino PID library. This PID speed control tutorial on YouTube might be a good starting point for too (the behaviors you described involve position control instead of speed control, but the overall idea is similar).
I’ve reviewed the GitHub and documentation, but I’m still having trouble figuring out how to make the robot move a specific distance. My goal is to navigate a 5x4 maze by programming the robot to move forward a set distance and turn at precise angles to avoid obstacles, go through gate zones to get bonus points, and reach the target. Could you help me with the steps or code to achieve this?
I suggest breaking the problem down into smaller pieces. First, to make the robot go a set distance, you can calculate how far each tick of the encoder actually moves the wheel. You can start by computing how many counts the encoder gives you per revolution of the wheel by multiplying the gear ratio of the gearbox by 12 (which is the counts per revolution, CPR, of the encoder on the motor shaft).
For example, if you’re using the standard edition of the robot (which uses a gear ratio of 29.86:1, the counts per revolution of the wheel would be 358.3.
Then, if you divide the circumference of the wheel (32mm × π) by the counts per revolution of the wheel, you can get the distance traveled per count of the encoder. Using the standard edition as an example again, this turns out to be around 0.28mm (32π/358.3).
If you’re using the standard edition and want the robot to move 50 cm (i.e. the grid space in your course), you would want to program the robot so both wheels move approximately 1782 encoder counts. You could try doing a simple while loop that runs the motors until the encoder counts reach 1782, but this will likely not be accurate enough and have overshoot (due to inertia and other factors). To get more accurate results, you can use PID controller as I suggested in my previous post to drive the motors more precisely.
Thank you, Brandon! I successfully programmed the robot to move forward. My next question is: how can I make it turn 90 degrees? Do I have to adjust the left and right motor speeds?
Hello Brandon, this is the code I’ve been using to navigate through the maze:
#include <Pololu3piPlus32U4.h>
#include <PololuMenu.h>
using namespace Pololu3piPlus32U4;
// Declare peripherals
OLED display;
Buzzer buzzer;
Motors motors;
Encoders encoders;
ButtonB buttonB;
// Define movement parameters
uint16_t maxSpeed = 400; // Max speed for the Turtle edition
uint16_t turnDurationMsRight = 580; // Adjusted duration for right turn
uint16_t turnDurationMsLeft = 580; // Adjusted duration for left turn
uint16_t turnDurationMsUturn = 850; // Duration for 180-degree turn (U-turn)
// Define distances based on encoder counts (distance cm / 0.011)
uint16_t distance1 = 25 / 0.011; // Encoder counts for 25 cm
// Function to move forward a set distance (in encoder counts)
void moveForward(uint16_t counts)
{
encoders.getCountsAndResetLeft(); // Properly reset encoder counts
encoders.getCountsAndResetRight();
motors.setSpeeds(235, 235); // Move both wheels forward
// Wait until the robot has moved the desired distance
while (encoders.getCountsLeft() < counts && encoders.getCountsRight() < counts)
{
// Continue moving forward
}
motors.setSpeeds(0, 0); // Stop motors
}
// Function to turn 90 degrees to the right
void turnRight90MotorControl()
{
motors.setSpeeds(maxSpeed, 150); // Left motor faster for right turn
delay(turnDurationMsRight); // Duration for turning
motors.setSpeeds(0, 0); // Stop motors after turn
}
// Function to turn 90 degrees to the left
void turnLeft90MotorControl()
{
motors.setSpeeds(150, maxSpeed); // Right motor faster for left turn
delay(turnDurationMsLeft); // Duration for turning
motors.setSpeeds(0, 0); // Stop motors after turn
}
// Function for a 180-degree turn (U-turn)
void turnUturnMotorControl()
{
motors.setSpeeds(maxSpeed, -maxSpeed); // Rotate both motors in opposite directions
delay(turnDurationMsUturn); // Duration for U-turn
motors.setSpeeds(0, 0); // Stop motors after turn
}
void setup()
{
// Welcome sound
buzzer.play(">g32>>c32");
// Display message and wait for button press
display.clear();
display.print(F("Press B to start"));
while (!buttonB.getSingleDebouncedPress());
// Step 1: Move forward 125 cm
moveForward(distance1);
// Wait for half a second before turning
delay(500);
// Turn left 90 degrees
turnLeft90MotorControl();
}
void loop()
{
// No loop logic needed for this task
}
Whenever the robot is turning left or right, it covers horizontal distance as it turns. However, after going straight for a certain amount of distance, I want it to stay in place and then turn either left/right by 90 degrees.
I am not sure how to adjust the code to achieve this. I am not using a PID speed control at the moment, and plan on not using one. Can you please guide me? Thank you!
To turn in place, you can command the motors to spin in opposite directions at the same speed. For example:
motors.setSpeeds(-200, 200);
To turn in the opposite direction, you would just invert the speeds:
motors.setSpeeds(200, -200);
Please note that if your motors are poorly matched, one might spin faster than the other when given the same speed in your code, so you might need to spin one motor slightly faster or slower to account for that, but typically it is close enough for such a short turn. Alternatively, if you need it to be more precise, you can use the encoders to turn each motor a set distance in opposite directions.
The 3Pi+ has an electronic compass (LIS3MDL) which if properly calibrated, can be used to determine the direction of travel, or as an aid in making more accurate 90 degree turns. To learn more about magnetometer calibration, see this post: Correcting the Balboa magnetometer
Likewise, the rate gyro in the onboard IMU (LSM6DS33) can be used to independently measure rotations about the vertical axis.