MarkT:
Firstly you must use INPUT_PULLUP mode on the Due, the trick with digitalWrite only works on ATmega
processors.
Secondly you are powering your encoder with 5V and sending its outputs direct to the Due pins which
are instantly destroyed by 5V... I would be more circumspect with this even if the outputs are open-collector
which is liekly - perhaps the encoder works at 3.3V anyway?
Thirdly if you want accurate position feedback you need a PID loop(*), you can't just hope the motor stops
instantly, because they don't. However if such accuracy isn't an issue the naive "brake now" approach may
be OK (depending on inertia in the system not being too high).
(*) Such a loop takes as input the difference in actual encoder count from desired encoder count,
and its output drives the motor bidirectionally. This means it can handle any overshoot and end up
in the right place.
Hi MarkT,
Thank you for your input. I have recently played about with my code and removed the motor control section and just tried to ensure that I could get results for my encoder counting and this code I have now does this.
// MD03A_Motor_basic + encoder
#define InA1 2 // INA motor pin
#define InB1 4 // INB motor pin
#define PWM1 6 // PWM motor pin
#define encodPinA1 18 // encoder A pin
#define encodPinB1 19 // 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
volatile long count = 0; // rotation counter
long countInit;
long tickNumber = 0;
boolean run = false; // motor moves
int aLastState;
int aState;
int counter = 0;
void setup() {
Serial.begin(9600); // baud rate
//Serial.flush();
pinMode(InA1, OUTPUT);
pinMode(InB1, OUTPUT);
pinMode(PWM1, OUTPUT);
pinMode(encodPinA1, INPUT);
pinMode(encodPinB1, INPUT);
digitalWrite(encodPinA1, HIGH); // turn on pullup resistor
digitalWrite(encodPinB1, HIGH);
attachInterrupt(2, rencoder, FALLING); // 2 is pin 18
aLastState = digitalRead(encodPinA1);
}
void loop() {
aState = digitalRead(encodPinA1); // Reads the "current" state of the outputA
// If the previous and the current state of the outputA are different, that means a Pulse has occured
if (aState != aLastState){
// If the outputB state is different to the outputA state, that means the encoder is rotating clockwise
if (digitalRead(encodPinB1) != aState) {
counter ++;
} else {
counter --;
}
Serial.print("Position: ");
Serial.println(counter);
}
aLastState = aState; // Updates the previous state of the outputA with the current state
// delay(1000);
/*
moveMotor(FORWARD, 255, 211.2*10); // direction, PWM, ticks number
delay(2000);
moveMotor(BACKWARD, 255, 211.2*10); // 211.2=360°
delay(2000);
Serial.print("countInit : " );
Serial.println(count);
*/
}
void moveMotor(int direction, int PWM_val, long tick) {
countInit = count; // abs(count)
tickNumber = tick;
if(direction==FORWARD) motorForward(PWM_val);
else if(direction==BACKWARD) motorBackward(PWM_val);
}
// ********* Encoder counting ********
void rencoder() { // pulse and direction, direct port reading to save cycles NB so this might be the bit that tells if the motor is going forwards or backwards
if (encodPinB1 & 0b00000001) { count++; } //if (digitalRead(encodPinB1)==HIGH) count ++;
else { count--; } // if (digitalRead(encodPinB1)==LOW) count --;
if(run)
if((abs(abs(count)-abs(countInit))) >= tickNumber) motorBrake();
}
// ****Code for forward backward and brake ****
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;
}
Regards to your second point, I am using the 3.3V pin in the Due and you are right, the encoder works just fine with this.
I was wondering if you could help me with your third point about using PID loop? I need the motor to stop where I want it to and to know where it is positioned when it begins rotating again after each loop. The inertia in my setup will be relatively high as the motor will be spinning at 1600rpm. Thanks for any help you can give me.