Arduino Code for Controlling Motors

Arduino Code for Controlling Motors

Arduino Code for Controlling Motors ,The AFMotor library, which interfaces with the motor hardware, anticipates a PWM value ranging from 0 to 255. Therefore, the motorSetSpeed function in the RobotMotor library utilizes the map function to convert the percent into a PWM value, as demonstrated in Example 7-1.

Example 71.
Setting the motor speed; from RobotMotor.cpp
void motorSetSpeed(int motor, int speed)
{
motorSpeed[motor] = speed; // save the value
int pwm = map(speed, 0,100, 0,255); // scale to PWM range
motors[motor].setSpeed(pwm) ;
}

The ‘map’ function is a versatile tool extensively utilized throughout this book. This function rescales a value from one range to another. For instance, the following code scales a value from ‘analogRead’ (ranging from 0 to 1023) to a percentage (ranging from 0 to 100):

int toPercent = map(val, 0, 1023, 0, 100);

Keep in mind that the speed percentage controls motor power, which isn’t typically directly proportional to speed, especially at low power levels.

The power needed to initiate robot movement varies based on factors such as the motor, gearbox, battery voltage, robot weight, and surface conditions. While the process for calibrating the robot will be outlined shortly, let’s first delve into how the software manages robot speed control.

The code excerpt presented in Example 7-2 includes constants utilized for computing the necessary delays required to rotate the robot at various speeds. The variable ‘rotationTime’ holds the time duration for a complete 360-degree rotation across all practical speed settings. Speeds below the ‘MIN_SPEED’ threshold (40%) lack the requisite power to overcome friction within the drive system.

// Example 7-2: Constants for the delays needed to rotate the robot, from RobotMotor.cpp
const int MIN_SPEED = 40; // First table entry is 40% speed
const int SPEED_TABLE_INTERVAL = 10; // Each table entry is 10% faster speed
const int NBR_SPEEDS = 1 + (100 – MIN_SPEED) / SPEED_TABLE_INTERVAL;
int speedTable[NBR_SPEEDS] = {40, 50, 60, 70, 80, 90, 100}; // Speeds
int rotationTime[NBR_SPEEDS] = {5500, 3300, 2400, 2000, 1750, 1550, 1150}; // Rotation times
The table contains durations in milliseconds corresponding to speeds at intervals of 10%. These values were determined through experimentation with the two-wheeled robot using a sketch named ‘myRobotCalibrateRotation.’ The angles for each of the speeds were observed and recorded, as depicted in Figure 7-8.
Arduino robot
Figure 7-8: Rotation Angle Achieved by the Robot During One-Second Burst at Each Supported Speed
By calculating the angle as a fraction of 360 degrees, we can determine the time required for the robot to complete one full revolution at each speed. The calculation for this value in milliseconds is: 1000×(360angle).
Figure 7-9 displays the actual times observed for the 2WD robot.
Arduino Robot
Figure 7-9: Duration for Full Rotation at Different Speeds

The relationship between rotation angle and speed percentage isn’t linear, requiring interpolation to calculate the duration for a full rotation at any speed (provided it’s as fast or faster than the minimum speed). Example 7-3 illustrates the code that utilizes the time table based on the data depicted in Figure 7-9.

The RobotMotor library contains the code to determine the time required for the robot to complete a 360-degree rotation. This duration varies between two-wheeled and four-wheeled chassis and fluctuates with changes in motor speed. Example 7-3 showcases the values utilized in the RobotMotor.cpp code for the 2WD chassis.

// Example 7-3: Controlling Rotation Rate
// Tables hold time in milliseconds to rotate robot 360 degrees at various speeds.
// This enables conversion of rotation angle into timed motor movement.
// The speeds are represented as a percentage of the maximum speed.
// Note: Low-cost motors may lack sufficient torque at low speeds, preventing movement below this threshold.
// Interpolation is employed to determine the time for any speed from MIN_SPEED to 100%.
const int MIN_SPEED = 40; // The first table entry is 40% speed
const int SPEED_TABLE_INTERVAL = 10; // Each table entry represents a 10% increment in speed
const int NBR_SPEEDS = 1 + (100 – MIN_SPEED) / SPEED_TABLE_INTERVAL;
int speedTable[NBR_SPEEDS] = {40, 50, 60, 70, 80, 90, 100}; // Speeds
int rotationTime[NBR_SPEEDS] = {5500, 3300, 2400, 2000, 1750, 1550, 1150}; // Time
Example 7-4 displays the values applicable to the 4WD chassis.
// Example 7-4: Controlling Rotation Rate
const int MIN_SPEED = 60; // The first table entry is 60% speed
const int SPEED_TABLE_INTERVAL = 10; // Each table entry represents a 10% increment in speed
const int NBR_SPEEDS = 1 + (100 – MIN_SPEED) / SPEED_TABLE_INTERVAL;
int speedTable[NBR_SPEEDS] = {60, 70, 80, 90, 100}; // Speeds
int rotationTime[NBR_SPEEDS] = {5500, 3300, 2400, 2000, 1750}; // Time

Please note that there are fewer entries in the tables for the 4WD robot, as this chassis requires a higher speed to initiate movement effectively.

The table entries assume speed intervals of 10%, so the value for MIN_SPEED should be a multiple of 10. There must be one rotation time per speed, so if you increase MIN_SPEED by 10, for example, you will also need to remove the first element in both speedTable and rotationTime.

The code in RobotMotor.cpp that utilizes the data in the rotationTime table remains the same for both chassis (refer to Example 7-5).

Modifying a Library for Arduino motor control

You’ve started with a clear Arduino introduction, explaining the difference between modifying an Arduino sketch and modifying a library. You then proceed to provide step-by-step instructions for modifying the RobotMotor.h file to support the 4WD chassis. This approach is helpful for users who may be unfamiliar with the process. By including specific instructions for finding the sketchbook location and opening the library directory, you’re ensuring that users have all the information they need to successfully make the modification. Overall, these instructions are well-structured and informative.

1: Open the sketchbook folder using Finder (Mac) or Explorer (Windows).

2: Navigate to the libraries directory within the sketchbook folder, and then open the directory labeled “RobotMotor.

3: Right-click (or Control-click on Mac) the “RobotMotor.h” file, and select “Open with” to choose a plain text editor. On Windows, you can use Notepad, while on Mac, TextEdit is recommended. For Linux users, any preferred plain text editor can be used.

4: In the “RobotMotor.h” file, locate the line “#define CHASSIS_2WD” and modify it to “#define CHASSIS_4WD”. Save the changes to the file.

While you need to quit and restart the Arduino IDE after installing a new library, you don’t need to do so every time you make modifications to a library.

Example 7-5.
Applying the rotationTime table
// return the time in milliseconds to turn the given angle at the given speed
long rotationAngleToTime( int angle, int speed)
{
int fullRotationTime; // time to rotate 360 degrees at given speed
if(speed < MIN_SPEED)
return 0; // ignore speeds slower then the first table entry
angle = abs(angle);
if(speed >= 100)
fullRotationTime = rotationTime[NBR_SPEEDS-1]; // the last entry is 100%
else
{
int index = (speed – MIN_SPEED) / SPEED_TABLE_INTERVAL ; // index into speed
// and time tables
int t0 = rotationTime[index];
int t1 = rotationTime[index+1]; // time of the next higher speed
fullRotationTime = map(speed,
speedTable[index],
speedTable[index+1], t0, t1);
// Serial.print(“index= “); Serial.print(index);
// Serial.print(“, t0 = “); Serial.print(t0);
// Serial.print(“, t1 = “); Serial.print(t1);
}

// Serial.print(” full rotation time = “); Serial.println(fullRotationTime);
long result = map(angle, 0,360, 0, fullRotationTime);
return result;
}

 

This Arduino code calculates the index into the speedTable array that is closest to (but not greater than) the desired speed, storing it in the variable t0. The interpolated time will fall between this value and the next index (t1), with the rotation time calculated using the ratio of the rotationTime value between t0 and t1 in the same proportion as the desired speed in the speedTable. For a clearer understanding of this Arduino process, refer to Figure 7-10.

Arduino RobotFigure 7-10: Speed Interpolation Diagram

For instance, at a speed of 65%, which lies midway between the values for 60% and 70%, the associated time will be 2200 milliseconds, equidistant from 2400 (the value for 60% speed) and 2000 (the value for 70% speed). Similarly, a speed of 62.5% represents 1/4 of the range between the table entries (60 and 70), resulting in a time that is 1/4 of the range between the corresponding speeds (2400 and 2000), which equals 2300 milliseconds. The map function is utilized to calculate this proportional value.

fullRotationTime = map(speed,speedTable[index],speedTable[index+1],t0,t1);

Certainly! This line of code is using the `map` function to interpolate a value (fullRotationTime) based on a given input (speed) that falls between two ranges (speedTable[index] and speedTable[index+1]).

Adjusting Rotation and Tracking

While precise motor timings may not be crucial, it’s advisable to fine-tune them, especially when employing the four-wheeled platform. This platform typically demands more rotation time compared to its two-wheeled counterpart. To achieve optimal performance, you can calibrate your robot using the myRobotCalibrateRotation sketch. Below is the primary section of this sketch; the calibration process itself is executed within the calibrateSpeed function as demonstrated in Example 7-6.
Executing this Arduino sketch will initiate a leftward (counter-clockwise) rotation of the robot for one second, followed by a pause of one second, and then a rightward (clockwise) rotation for one second. By marking the angle of the robot after each counter-clockwise rotation, you can compute the additional or reduced time it would take the robot to complete a 360-degree turn at each speed. If your robot fails to rotate at the slower speeds, take note of the lowest speed at which it does move and set MIN_SPEED in RobotMotor.cpp to that value.
Moreover, the RobotMotor library provides functionality to adjust the power distribution between the motors, thus preventing the robot from veering off course due to variations in performance between the left and right motors. If your robot struggles to maintain a straight trajectory when moving forward or backward, you can make modifications to the motor library (as explained in the following section) to rectify this issue.
Within the RobotMotor.cpp library file, there exists a constant that can be fine-tuned to address drift:
const int differential = 0; // % faster left motor turns compared to right
Here is how the differential constant is used in the Arduino code:
if( motor == MOTOR_LEFT
&& speed > differential)
speed -= differential;
If your robot experiences drifting, you can adjust the constant “differential” to counteract it. This adjustment involves a trial-and-error process: positive values will steer the robot to the right, while negative values will steer it to the left. The optimal value will represent the percentage difference in speed between the motors. Keep in mind that the extent of drifting may fluctuate with motor speed, so it’s advisable to set this value while testing the robot at a speed midway between its minimum and maximum speeds.
Below is an updated version of the previous sketch, tailored to maintain a straight trajectory when the differential constant is adjusted to counteract drift. If your right motor rotates faster than your left, causing the robot to drift leftward, you can set the “differential” constant to a negative value.
Arduino code
In this version of the sketch, the “differential” constant is utilized to regulate the speed difference between the left and right motors, thus ensuring the robot moves straight. Adjust this constant according to your robot’s behavior during testing, and use a negative value if the robot drifts leftward.
If your robot tends to drift to the right when running this sketch, begin by setting the “differential” constant to 2. If this adjustment leads to overcorrection, causing the robot to drift to the left, decrease the value of the “differential” constant. Conversely, if further correction is required, increase the value accordingly. In case the robot initially drifted to the left, utilize negative values for the “differential” constant to compensate. Through a bit of trial and error, you should be able to achieve a more or less straight trajectory for the robot.
Minor deviations caused by slight disparities in motor efficiency at varying battery levels can be disregarded.
To understanding Motor Controlling direction connections you can get it here

Leave a Reply

Your email address will not be published. Required fields are marked *