Hi,
I'm controlling the speed of a 12VDC motor using PWM via potentiometer input on my Arduino Uno. The motor is connected to an H bridge module. I'd like to read the motor rpm which is in the range of 0-6000 max. Accuracy at lower rpm (below 1000) is not that important for my application. The ultimate goal is to use this rpm input for PID to maintain the speed of the motor.
For the rpm reading i'm using the slotted LM393 IR speed sensor module to read a disc with a single slot.
I've added a 100nf - 250v capacitor between GND and the DO pin on the speed sensor module as advised on this page
If I set the speed of the motor via the pot, the rpm given in the serial monitor appears stable-ish, then jumps a couple of hundred rpm, remains there for a few more readings, only to then drop back to a similar reading to before. Does this stability need to be improved for using it with PID? If so, is there something which can be done to improve it? I've attached the code below.
The sketch i'm using is said to be an improved version of the rpm code found in the Arduino Playground. See the last post in this thread. I've deleted the associated code for the LCD, as I don't have one to use. I've then combined it with my basic speed control code for the motor.
Any help on improving the stability of the readings would be much appreciated.
Thanks
Michael
/*
This code measures the RPM of a DC motor (or anything really) using a HALL sensor connected to PIN 21 and outputs data on a LCD display and also some debugging info on the serial
if I ever want to create a nice chart based on the measurements.
I made quite a bit of an effort to make it as precise as possible. The RPM is sampled with 4 microsecond resolution so it should be enough for any household DC motor.
*/
int potPin=A0; // Assign potentiometer to pin A0
int RPWM_Output=5; // Assign RPWM to Arduino PWM output pin 5
int LPWM_Output=6; // Assign LPWM to Arduino PWM output pin 6
int readPotValue; // Declare potentiometer read value variable
int writePotValue; // Variable to write motor speed
volatile byte rev;
volatile long dTime, timeold;
unsigned int rpm, freq;
void setup(){
Serial.begin(9600);
pinMode(potPin,INPUT); // Set potentiometer as an input
pinMode(RPWM_Output,OUTPUT); // set RPWM as a PWM output
pinMode(LPWM_Output,OUTPUT); // set LPWM as a PWM output
attachInterrupt(0, revInterrupt, RISING); //pin 2 is our interrupt
dTime=0, rev=0, rpm=0, freq=0;
timeold=0;
}
void loop(){
readPotValue = analogRead(potPin); // Read potentiometer and put value in readPotValue
writePotValue = map(readPotValue,0,1023,0,255); // Use map function to calculate writePotValue
analogWrite(RPWM_Output, 0); // Write a PWM value of zero to LPWM (Pin6)
analogWrite(LPWM_Output, writePotValue); // Write PWM signal to RPWM (Pin5)
if (rev > 20)
{
cli(); //disable interrupts while we're calculating
if (dTime > 0) //check for timer overflow
{
rev-=1; //subtract one since the first revolution is not measured
rpm=(60000000*rev)/(dTime);
freq=rpm/60;
Serial.print(rev);
Serial.print(" ");
Serial.print(rpm); //a bit of serial for the debugging (not really needed at this point, perhaps one day for some graphs)
Serial.print(" ");
Serial.println(dTime);
rev=0;
}
sei(); //re-enable interrupts
}
}
void revInterrupt (){
if (rev == 0)
{
timeold=micros(); //first measurement is unreliable since the interrupts were disabled
rev++;
}
else
{
dTime=(micros()-timeold); //'micros()' is not incrementing while inside the interrupt so it should be safe like this right?
rev++;
}
}
