Hello. I made a simple robot which uses a DC motor (driven by an h-bridge, controlled by the PWM from the Arduino) for driving and a servo motor for steering. The DC motor is a Pololu motor with a quadrature encoder Pololu - 19:1 Metal Gearmotor 37Dx52L mm 12V with 64 CPR Encoder (No End Cap).
In my code, the steering angle is a function of the encoder count. The problem is that the servo jitters when I use the interrupt to "read" the encoder output and increment the encoder counter. I think it's because the encoder's interrupt handler prevents the Servo library's interrupt handler from sending the control signal, hence the jitter.
Would enabling the interrupts by placing "interrupts()" in "handleEncAInterrupt()" solve my problem? Or will it cause problems because "handleEncAInterrupt()" will become re-entrant?
#include <digitalWriteFast.h>
#include <Servo.h>
float sm[] = {0,3148.1199,8647.021};
float targetAlpha[] = {1535,1677.3481};
float tacc = 1000;
float tconst = 5000;
int tASize = 2;
//outputs
Servo steering;
//variables for reading encoder
volatile bool encAState; //volatile so it can be changed outside the interrupt
volatile bool encBState;
volatile long count = 0;
//variables needed by computeSteeringAngle()
const float vmax=50000; //counts/sec
const float wmax=20000; //micros/second
float s1,s2;
float alpha;
float alphaAbs;
int i=1; //counter for computeSteeringAngle()
const float accel=2.5;
float velocity;
float velocityConst;
float tAccStart,tConstStart,tDecStart,tEnd;
boolean chk=true;
void setup(){
steering.attach(9);
Serial.begin(115200);
//steering angle variables
alphaAbs = abs(targetAlpha[i]-targetAlpha[i-1]);
s1=sm[i]-alphaAbs*vmax/(2*wmax);
s2=sm[i]+alphaAbs*vmax/(2*wmax);
//for the output
pinMode(11,OUTPUT);
pinMode(12,OUTPUT);
pinMode(13,OUTPUT);
digitalWrite(12,LOW);
digitalWrite(13,HIGH);
//for the quadrature encoder
pinMode(2, INPUT);
pinMode(4, INPUT);
digitalWrite(2, LOW);
digitalWrite(4, LOW);
attachInterrupt(0, handleEncAInterrupt, CHANGE);
computeSteeringAngle(count);
steering.writeMicroseconds(alpha);
delay(2000);
analogWrite(11,60);
}
void loop(){
computeSteeringAngle(count);
if(count>=18340.656){
analogWrite(11,0);
}
}
void computeSteeringAngle(long s){
if(i<tASize){
if(s<s1 && chk){
alpha=targetAlpha[i-1];
steering.writeMicroseconds((int)alpha);
chk=false;
}
else if(s>=s1 && s<s2){
if((targetAlpha[i]-targetAlpha[i-1])>0)
alpha=s*(wmax/vmax)-sm[i]*(wmax/vmax)+(targetAlpha[i]+targetAlpha[i-1])/2;
else
alpha=s*(-wmax/vmax)-sm[i]*(-wmax/vmax)+(targetAlpha[i]+targetAlpha[i-1])/2;
steering.writeMicroseconds((int)alpha);
}
else if(s>=s2){
i=i+1;
alphaAbs = abs(targetAlpha[i]-targetAlpha[i-1]);
s1=sm[i]-alphaAbs*vmax/(2*wmax);
s2=sm[i]+alphaAbs*vmax/(2*wmax);
alpha=targetAlpha[i-1];
chk=true;
steering.writeMicroseconds((int)alpha);
}
}
}
void handleEncAInterrupt(){
encAState = digitalReadFast(2);
encBState = digitalReadFast(4);
count+= encAState==encBState ? 1 : -1;
}