KrisKasprzak
Well-known member
All,
I have a fairly reliable pulse counter for measuring RPM. I'm using a Teensy 4.0 and a 3144 hall effect sensor. The sensor reads 4 magnets connected to a PC cooling fan that are evenly placed around the fan (this is just a simple test apparatus). My system counts pulses and measures time between first pulse and last, then dividing the two gives RPM--results are very accurate when compared to a store bought tach. I'm using clock cycles as a basis for time measurement and even if I measure time using micros() to measure pulse times, the results are the same.
I can get a very accurate RPM but is error +/- 4 RPM regardless of the RPM, see the images. However notice the the odd spikes and that they are very predictable making me think it's a timing measure measurement issue--or it simply is what it is... These readings are taken every 200 ms.
If I slow reads to 1000 ms RPM error drops to about +/- 2 RPM. I suspect it's a matter of not enough samples (pulse counts in the measure time period that are causing higher +/- errors. But I would think reading the start and end times would make the error much less.
First image is schematic, second is serial monitor at around 850 RPM, third is serial monitor around 1580 RPM the last image is readings every 1000ms.
Thoughts anyone?
Maybe this is the best I can expect. Any thoughts?
I have a fairly reliable pulse counter for measuring RPM. I'm using a Teensy 4.0 and a 3144 hall effect sensor. The sensor reads 4 magnets connected to a PC cooling fan that are evenly placed around the fan (this is just a simple test apparatus). My system counts pulses and measures time between first pulse and last, then dividing the two gives RPM--results are very accurate when compared to a store bought tach. I'm using clock cycles as a basis for time measurement and even if I measure time using micros() to measure pulse times, the results are the same.
I can get a very accurate RPM but is error +/- 4 RPM regardless of the RPM, see the images. However notice the the odd spikes and that they are very predictable making me think it's a timing measure measurement issue--or it simply is what it is... These readings are taken every 200 ms.
If I slow reads to 1000 ms RPM error drops to about +/- 2 RPM. I suspect it's a matter of not enough samples (pulse counts in the measure time period that are causing higher +/- errors. But I would think reading the start and end times would make the error much less.
First image is schematic, second is serial monitor at around 850 RPM, third is serial monitor around 1580 RPM the last image is readings every 1000ms.
Thoughts anyone?
Maybe this is the best I can expect. Any thoughts?
Code:
#include <avr/io.h>
#define RPM_PIN A0 // pin for the RPM
#define PICKUPS 4.0F
volatile uint32_t PulseStartTime = 0, PulseEndTime = 0, ClockTime = 0;
volatile uint8_t PulseCount = 0;
double PulseTime = 0.0;
double Revs = 0.0;
double RPM = 0.0f;
elapsedMillis Update;
void setup() {
Serial.begin(115200);
pinMode(RPM_PIN, INPUT);
if (ARM_DWT_CYCCNT == ARM_DWT_CYCCNT) {
Serial.println("here");
ARM_DEMCR |= ARM_DEMCR_TRCENA;
ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
}
attachInterrupt(digitalPinToInterrupt(RPM_PIN), ISR_READSPEED, RISING);
ARM_DWT_CYCCNT = 0;
PulseCount = 0;
}
void loop() {
if (Update > 200) {
cli();
Update = 0;
RPM = 0.0;
if (PulseCount > 3) {
// getting RPM will be found by getting the pulses in a time period and dividing by the time between the first and last pulse
// rpm = 1 REC/PICKUPS x Pulses / second x 60 sec / min
Revs = (double) (PulseCount - 1) / PICKUPS; // in revolutions
PulseTime = (double)(PulseEndTime - PulseStartTime) / F_CPU; // in minutes
RPM = (Revs * 60.0)/ PulseTime;
Serial.println(RPM);
}
PulseCount = 0;
ARM_DWT_CYCCNT = 0;
sei();
}
}
void ISR_READSPEED() {
ClockTime = ARM_DWT_CYCCNT;
if (PulseCount == 0) {
PulseStartTime = ClockTime;
} else {
PulseEndTime = ClockTime;
}
PulseCount++;
asm volatile("DSB");
}