I am trying to build a robot that remembers the path that it just passed, to do that I am using two wheel encoders. I bought the wheel encoders form DFrobots (Wheel_Encoders_for_DFRobot_3PA_and_4WD_Rovers__SKU_SEN0038_-DFRobot ) and used the sample code they have to test the encoders here is the code:
#include <AFMotor.h>
AF_DCMotor motor1(1, MOTOR12_64KHZ);
AF_DCMotor motor2(2, MOTOR12_64KHZ);
AF_DCMotor motor3(3, MOTOR12_1KHZ);
AF_DCMotor motor4(4, MOTOR12_1KHZ);
const int pingPin = 19;
#define LEFT 0
#define RIGHT 1
long coder[2] = {
0,0};
int lastSpeed[2] = {
0,0};
void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
motor1.setSpeed(200); // Set the speed for the motors (255 is the maximum)
motor2.setSpeed(200);
motor3.setSpeed(200);
motor4.setSpeed(200);
attachInterrupt(LEFT, LwheelSpeed, CHANGE); //init the interrupt mode for the digital pin 2
attachInterrupt(RIGHT, RwheelSpeed, CHANGE); //init the interrupt mode for the digital pin 3
}
void forward(){ // This function moves the wheels forward
motor1.run(FORWARD);
motor2.run(FORWARD);
motor3.run(FORWARD);
motor4.run(FORWARD);
}
void backward() { // This function moves the wheels backward
motor1.run(BACKWARD);
motor2.run(BACKWARD);
motor3.run(BACKWARD);
motor4.run(BACKWARD);
}
void haltMotors() // This function stops each motor (It is better to stop the motors before changing direction.)
{
motor1.run(RELEASE);
motor2.run(RELEASE);
motor3.run(RELEASE);
motor4.run(RELEASE);
}
void turnRight(){ // This function turns the robot right.
motor1.run(FORWARD);
motor2.run(BACKWARD);
motor3.run(BACKWARD);
motor4.run(FORWARD);
}
void turnLeft(){
motor1.run(BACKWARD);
motor2.run(FORWARD);
motor3.run(FORWARD);
motor4.run(BACKWARD);
}
void loop() {
forward();
delay(500);
haltMotors();
delay (1000);
static unsigned long timer = 0; //print manager timer
if(millis() - timer > 100){
Serial.print("Coder value: ");
Serial.print(coder[LEFT]);
Serial.print("[Left Wheel] ");
Serial.print(coder[RIGHT]);
Serial.println("[Right Wheel]");
lastSpeed[LEFT] = coder[LEFT]; //record the latest speed value
lastSpeed[RIGHT] = coder[RIGHT];
coder[LEFT] = 0; //clear the data buffer
coder[RIGHT] = 0;
timer = millis();
}
}
void LwheelSpeed()
{
coder[LEFT] ++; //count the left wheel encoder interrupts
}
void RwheelSpeed()
{
coder[RIGHT] ++; //count the right wheel encoder interrupts
}
(this is just a test it is not the code for the entire project.)
But the sensors are giving me wrong readings, even when I disconnect the pins it still give me weird readings. Does that mean that is something is wrong with the code or are the encoders bad?
PaulS:
You have interrupt service routines and other functions accessing the same variables, and those variables are not declared volatile.
what do you mean not declared as volatile, which ones? this is my first time working with encoders and I am not sure what you are talking about.
What motor shield are you using? Does it use pins 2 and 3? Are the encoders connected to those pins?
I using the the adafruit motorshield. I am not sure but I think it uses interrupt 2. I tried to connect the encoders to another arduino while running the motion code on the car and it gave me the same weird readings.
Your interrupt service routines are LwheelSpeed() and RwheelSpeed(). These refer to the array coder[], which is not declared volatile.
In loop(), you refer to the same array. Those references do not necessarily get the latest values from the array elements, because the compiler does not know that the values can change outside of loop.
PaulS:
Your interrupt service routines are LwheelSpeed() and RwheelSpeed(). These refer to the array coder[], which is not declared volatile.
In loop(), you refer to the same array. Those references do not necessarily get the latest values from the array elements, because the compiler does not know that the values can change outside of loop.
At the beginning of the code coder is declared as a long I have to change that to volatile?
PaulS:
With 4 motors, pins 3, 5, 6, and 11 are used. You can't then use pin 3 as an interrupt pin, too.
so how I dont use pin 3 as an interrupt?
and is this what you meant by changing the coder to a volatile?
#include <AFMotor.h>
AF_DCMotor motor1(1, MOTOR12_64KHZ);
AF_DCMotor motor2(2, MOTOR12_64KHZ);
AF_DCMotor motor3(3, MOTOR12_1KHZ);
AF_DCMotor motor4(4, MOTOR12_1KHZ);
const int pingPin = 19;
#define LEFT 0
#define RIGHT 1
volatile long coder[2] = {
0,0};
int lastSpeed[2] = {
0,0};
void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
motor1.setSpeed(200); // Set the speed for the motors (255 is the maximum)
motor2.setSpeed(200);
motor3.setSpeed(200);
motor4.setSpeed(200);
attachInterrupt(LEFT, LwheelSpeed, CHANGE); //init the interrupt mode for the digital pin 2
attachInterrupt(RIGHT, RwheelSpeed, CHANGE); //init the interrupt mode for the digital pin 3
}
attachInterrupt(RIGHT, RwheelSpeed, CHANGE); //init the interrupt mode for the digital pin 3
If you mean how can you use another pin as the external interrupt pin, you'd need to rewire the ATMega328 chip internally. I'm not capable of doing that, and I have my doubts about you.
You could use a Mega, which has more external interrupt pins, and different pins.
Are there really 4 independent motors on your robot?
attachInterrupt(RIGHT, RwheelSpeed, CHANGE); //init the interrupt mode for the digital pin 3
If you mean how can you use another pin as the external interrupt pin, you'd need to rewire the ATMega328 chip internally. I'm not capable of doing that, and I have my doubts about you.
You could use a Mega, which has more external interrupt pins, and different pins.
Are there really 4 independent motors on your robot?
If I delete that line wouldn't I lose the information of the right wheel encoder? And yes the robot has 4 independent motors.
I took the interrupt like you said. but the results that the encoder is giving me is too high for just a little bit of movement. here is what I get on the serial monitor
Coder value: 964[Left Wheel] 0[Right Wheel]
Coder value: 885[Left Wheel] 0[Right Wheel]
Coder value: 842[Left Wheel] 0[Right Wheel]
Coder value: 810[Left Wheel] 0[Right Wheel]
Coder value: 2167[Left Wheel] 0[Right Wheel]
Coder value: 2432[Left Wheel] 0[Right Wheel]
Coder value: 2437[Left Wheel] 0[Right Wheel]
Coder value: 2372[Left Wheel] 0[Right Wheel]
Coder value: 214[Left Wheel] 0[Right Wheel]
and the values are not even consistent...
Do you think there is something wrong with the code or is it the hardware?