In the previous post, we walked through how to turn the motors on for a specific amount of time. In this post, we will turn the motors on for a specific amount of encoder pulses. Like the EV3, encoders count fractions of a rotation. The EV3 uses an optical encoder where it shines a light through a rotating disk. The zumo uses what is called a quadrature magnetic encoder. It senses changes in magnetic field and eddy currents to measure 1/12 of a rotation. For the EV3, it was simple in that each encoder pulse equated to 1 degree of rotation after the gearing of the motor. For the Zumo, it is similar, but the numbers don’t quite match. Each motor rotation produces 12 encoder pulses. However, the gear ratio after the motor is ultimately what determines the number of pulses per rotation. My Zumo has a gear ratio of 75.81:1. That is, for every 75.81 rotations of the motor, the wheel would make 1 rotation. Since each encoder produces 12 pulse for each motor rotation, that means that the encoder measures 75.81 x 12 pulses for each wheel rotation, or about 909.7 pulses.
Anyway, let’s demonstrate how to read the encoders, and how to uses them to make the robot move forward a certain distance, then backwards a certain distance. For the sake of this demonstration, let’s do the following steps:
- Delay 1 second.
- Move forward at a speed of 200 for 2000 encoder counts (a little more than two wheel rotations).
- Stop the Motors and pause for 1 second.
- Move backwards at a speed of 200 for 2000 encoder counts.
- Stop, then repeat.
Like the previous program, we need to include some objects from the Zumo32u4 library. We are creating an instance of the object Zumo32U4Motors, and calling it “motors.” We are also using the Zumo32U4Encoders class, so we need to create an instance of the Zumo32U4Encoders class and call it “encoders.” Therefore, the section before the main body of the program should look something like this:
#include <Zumo32U4.h>
Zumo32U4Encoders encoders;
Zumo32U4Motors motors;
The next section is the Setup(). Like the previous program, there really is nothing to set up for this simple task.
After the setup(), we need the loop() function. One really big difference between C and EV3-G is that all variables have to be declared. In EV3-G, we would just insert a variable anywhere we wanted one, and all variables were global. In C (which Arduino is based from), we have to declare our variables where they will be used, and assign a type to the variable. In this case, we would like to create a variable for the left encoder, and one for the right encoder. The type of variable is “int,” which is short for integer. You declare the variables like below:
int countsLeft;
int countsRight;
Once they are declared, we can use them. The very first operation we should do is measure and reset the encoders. This is done with the following:
countsLeft = encoders.getCountsAndResetLeft();
countsRight = encoders.getCountsAndResetRight();
The command getCountsAndResetLeft() is a member of the class of Zumo32U4Encoders, which we renamed to encoders, and it returns an integer.
The next steps should be similar to the previous post. We need to delay for 1 s, then set the motors to forward at a power of 200.
delay(1000);
motors.setSpeeds(200,200);
Once the motors are set, we need to continuously measure the encoder values until they reach a value of 2000 counts. This is similar to the EV3 loop block. For the Zumo, it is a “do {…. } while ();” statement. This statement does all the commands within the { } while the condition within ( ) is met. We need to put the encoder measurements with the { } brackets. We want to perform this act while both the left and right encoders are less than 2000.
do {
countsLeft = encoders.getCountsLeft();
countsRight = encoders.getCountsRight();
} while(countsLeft<2000&&countsRight<2000);
The above section of code performs these actions. The loop will run as long as the left and right encoders are less than 2000. The “&&” is the logic AND operation. Once the condition is met, we need to turn the motors off and delay for a second.
motors.setSpeeds(0,0);
delay(1000);
Moving the robot in reverse is simply the opposite. You could leave the encoders where they are (at about 2000) and drive while they are greater than 0. I like to go for simplicity and just reset the encoders. To move backwards the code is:
countsLeft = encoders.getCountsAndResetLeft();
countsRight = encoders.getCountsAndResetRight();
motors.setSpeeds(-200,-200);
do {
countsLeft = encoders.getCountsLeft();
countsRight = encoders.getCountsRight();
} while(countsLeft>-2000&&countsRight>-2000);
motors.setSpeeds(0,0);
Putting the whole program together:
#include <Zumo32U4.h>
Zumo32U4Encoders encoders;
Zumo32U4Motors motors;
void setup() {
}
void loop() {
int countsLeft;
int countsRight;
countsLeft = encoders.getCountsAndResetLeft();
countsRight = encoders.getCountsAndResetRight();
delay(1000);
motors.setSpeeds(200,200);
do {
countsLeft = encoders.getCountsLeft();
countsRight = encoders.getCountsRight();
} while(countsLeft<2000&&countsRight<2000);
motors.setSpeeds(0,0);
delay(1000);
countsLeft = encoders.getCountsAndResetLeft();
countsRight = encoders.getCountsAndResetRight();
motors.setSpeeds(-200,-200);
do {
countsLeft = encoders.getCountsLeft();
countsRight = encoders.getCountsRight();
} while(countsLeft>-2000&&countsRight>-2000);
motors.setSpeeds(0,0);
}
The next post will probably be on reading the downward facing light sensors.