- Sun Apr 30, 2023 9:03 am
#62745
Hi all, I'm attempting to use a modified version of the speedy basic distributor code to read rpm of a motor.
But I get weird results when I approach zero and go back up from there. If i bring the speed up slowly the rpm oscillates between what it should read and half of what it should read. If i do it quickly the reading is perfect
No idea what I've done wrong, Im not very good at programming.
Any help is appreciated.
But I get weird results when I approach zero and go back up from there. If i bring the speed up slowly the rpm oscillates between what it should read and half of what it should read. If i do it quickly the reading is perfect
No idea what I've done wrong, Im not very good at programming.
Any help is appreciated.
Code: Select all
unsigned long curTime;
unsigned long toothLastToothTime = 0;
unsigned int triggerActualTeeth = 8;
volatile unsigned long triggerFilterTime = 0;
volatile unsigned long curGap = 0;
volatile unsigned int rpm = 0; // Initial rpm value
volatile unsigned int cur_rpm = 0;
const byte rpm_in = 2;
bool hasSync = false;
volatile unsigned long toothCurrentCount;
volatile unsigned long toothOneMinusOneTime;
volatile unsigned long toothOneTime;
volatile unsigned long syncLossCounter;
volatile unsigned long startRevolutions;
volatile unsigned long toothLastMinusOneToothTime;
volatile unsigned long currentLoopTime;
unsigned long MAX_STALL_TIME = 500000;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(rpm_in, INPUT); //Interrupt 0
attachInterrupt(digitalPinToInterrupt(rpm_in), triggerPri_BasicDistributor, FALLING);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.print("RPM = ");
Serial.println(rpm);
//Serial.println(" ");
currentLoopTime = micros();
unsigned long timeToLastTooth = (currentLoopTime - toothLastToothTime);
if ( (timeToLastTooth < MAX_STALL_TIME) || (toothLastToothTime > currentLoopTime) ) //Check how long ago the last tooth was seen compared to now. If it was more than half a second ago then the engine is probably stopped. toothLastToothTime can be greater than currentLoopTime if a pulse occurs between getting the latest time and doing the comparison
{
noInterrupts();
if (hasSync == true)
{
rpm = 60000000UL / (curGap * triggerActualTeeth);
}
interrupts();
}
else
{
//We reach here if the time between teeth is too great. This VERY likely means the engine has stopped
toothLastToothTime = 0;
//toothLastMinusOneToothTime = 0;
hasSync = false;
startRevolutions = 0;
rpm = 0;
}
} void triggerPri_BasicDistributor(void)
{
curTime = micros();
curGap = curTime - toothLastToothTime;
if ( (curGap >= triggerFilterTime) )
{
if (hasSync == true) {
triggerFilterTime = (curGap * 3) >> 2; //Recalc the new filter value
}
else {
triggerFilterTime = 0; //If we don't yet have sync, ensure that the filter won't prevent future valid pulses from being ignored.
}
if ( (toothCurrentCount == triggerActualTeeth) || (hasSync == false) ) //Check if we're back to the beginning of a revolution
{
toothCurrentCount = 1; //Reset the counter
toothOneMinusOneTime = toothOneTime;
toothOneTime = curTime;
hasSync = true;
startRevolutions++; //Counter
}
else
{
if ( (toothCurrentCount < triggerActualTeeth) ) {
toothCurrentCount++; //Increment the tooth counter
}
else
{
//This means toothCurrentCount is greater than triggerActualTeeth, which is bad.
//If we have sync here then there's a problem. Throw a sync loss
if ( hasSync == true )
{
syncLossCounter++;
hasSync = false;
}
}
}
toothLastMinusOneToothTime = toothLastToothTime;
toothLastToothTime = curTime;
} //Trigger filter
}