Hello everybody,
I bought a 12V brushed DC motor with a 18.75:1 metal gearbox and an integrated quadrature encoder that provides a resolution of 64 counts per revolution of the motor.
In my application I want to control the position of the motor. Most of time it will not turn more than 360° degrees.
I tried to read the value from the two encoder outputs by using the Interrupt example uses both interrupt pins, but I'm not able to have a correct value (one tour = 64 or 64x19).
I check on the scope the outputs and they are fine.
This is the code I used :
// MD03A_Motor_basic + encoder
#define InA1 10 // INA motor pin
#define InB1 11 // INB motor pin
#define PWM1 3 // PWM motor pin
#define encoder0PinA 5 // encoder A pin
#define encoder0PinB 6 // encoder B pin
#define LOOPTIME 100 // PID loop time
#define FORWARD 1 // direction of rotation
#define BACKWARD 2 // direction of rotation
unsigned long lastMilli = 0; // loop timing
unsigned long lastMilliPrint = 0; // loop timing
long count = 0; // rotation counter
long countInit;
long tickNumber = 0;
boolean run = false; // motor moves
volatile unsigned int encoder0Pos = 0;
void setup()
{
Serial.begin (9600);
pinMode(InA1, OUTPUT);
pinMode(InB1, OUTPUT);
pinMode(PWM1, OUTPUT);
pinMode(encoder0PinA, INPUT);
pinMode(encoder0PinB, INPUT);
digitalWrite(encoder0PinA, HIGH); // turn on pullup resistor
digitalWrite(encoder0PinB, HIGH);
// attachInterrupt(1, rencoder, FALLING);
attachInterrupt(0, doEncoderA, CHANGE);
// attachInterrupt(1, doEncoderB, CHANGE);
}
void loop() {
// moveMotor(FORWARD, 100, 464*2); // direction, PWM, ticks number
moveMotor(FORWARD, 100, 2000);
delay(3000);
// moveMotor(BACKWARD, 100, 464*2); // 464=360°
moveMotor(BACKWARD, 100, 2000);
delay(3000);
}
void moveMotor(int direction, int PWM_val, long tick)
{
// countInit = count; // abs(count)
countInit = encoder0Pos; // abs(count)
tickNumber = tick;
if(direction==FORWARD) motorForward(PWM_val);
else if(direction==BACKWARD) motorBackward(PWM_val);
}
void motorForward(int PWM_val) {
analogWrite(PWM1, PWM_val);
digitalWrite(InA1, LOW);
digitalWrite(InB1, HIGH);
run = true;
}
void motorBackward(int PWM_val) {
analogWrite(PWM1, PWM_val);
digitalWrite(InA1, HIGH);
digitalWrite(InB1, LOW);
run = true;
}
void motorBrake() {
analogWrite(PWM1, 0);
digitalWrite(InA1, HIGH);
digitalWrite(InB1, HIGH);
run = false;
}
void doEncoderA()
{
// look for a low-to-high on channel A
if (digitalRead(encoder0PinA) == HIGH) {
// check channel B to see which way encoder is turning
if (digitalRead(encoder0PinB) == LOW) {
encoder0Pos = encoder0Pos + 1; // CW
}
else {
encoder0Pos = encoder0Pos - 1; // CCW
}
}
else // must be a high-to-low edge on channel A
{
// check channel B to see which way encoder is turning
if (digitalRead(encoder0PinB) == HIGH) {
encoder0Pos = encoder0Pos + 1; // CW
}
else {
encoder0Pos = encoder0Pos - 1; // CCW
}
}
Serial.println (encoder0Pos, DEC);
// use for debugging - remember to comment out
}
void doEncoderB()
{
// look for a low-to-high on channel B
if (digitalRead(encoder0PinB) == HIGH) {
// check channel A to see which way encoder is turning
if (digitalRead(encoder0PinA) == HIGH) {
encoder0Pos = encoder0Pos + 1; // CW
}
else {
encoder0Pos = encoder0Pos - 1; // CCW
}
}
// Look for a high-to-low on channel B
else {
// check channel B to see which way encoder is turning
if (digitalRead(encoder0PinA) == LOW) {
encoder0Pos = encoder0Pos + 1; // CW
}
else {
encoder0Pos = encoder0Pos - 1; // CCW
}
}
}
The motor turns weel and changes side, but however the number of tick I want he will always do 2,5 turn.
I have for objective to do an application like that :
360°degrees of amplitude. When the analog input is 0V motor doesn't move. When the input is 2,5V, the motor goes to 180° degree, etc... And it moves through 0 to 360° according to the analog input voltage.
Thanks for your help. (Sorry if there are grammatical english mistakes, I come from France )
Regards
Simon