1

I'm trying to measure speed of a fly wheel with a reed switch with one magnet (1 pulse per full rotation). I have an 100nf cap connected to switch to help with debounce.

#include <Arduino.h>

int speedPin = 2; // switch is connected to pin 2
int ledPin = 13;

int debounceTime = 7;

long speedPulseTime = 0;
int speedPulseCount = 0;
int speed = 0;
long speedLastSample = 0;

long serialLastReport = 0;
int serialReportFreq = 40;

void speedPulse()
{
  long time = millis();
  if ((speedPulseTime + debounceTime) < time)
  {
    speedPulseCount++;
    speedPulseTime = time;
  }
}

void setup()
{
  pinMode(ledPin, OUTPUT);

  pinMode(speedPin, INPUT_PULLUP);     // Set the switch pin as input
  attachInterrupt(digitalPinToInterrupt(speedPin), speedPulse, HIGH);

  Serial.begin(115200);
  Serial.println("Ready...");
}


void loop()
{
  long time = micros();
  if (speedPulseCount >= 4 || (speedLastSample + 1500000) < time)
  {
    detachInterrupt(speedPin);
    int tempSpeed = 1000000 / ((time - speedLastSample) / speedPulseCount);
    if (tempSpeed < 0)
    {
      speed = 0;
    }
    else
    {
      speed = tempSpeed;
    }

    //reset sample
    speedLastSample = time;
    speedPulseCount = 0;
    attachInterrupt(digitalPinToInterrupt(speedPin), speedPulse, HIGH);
  }

  if ((serialLastReport + serialReportFreq) < millis())
  {
    Serial.print(millis());
    Serial.print(",");
    Serial.println(speed);
    serialLastReport = millis();
  }
}

Here the code I have so far. The problem I have it jumps around a little bit. What could I change to ensure more accurate readings?

VE7JRO
  • 2,515
  • 19
  • 27
  • 29

1 Answers1

2

It sounds like occasional "misses". Possible causes include:

  • the magnet passing far enough from the reed switch to "only just" trigger it [narrow the gap.];
  • the magnet's passage being too short for the reed switch/capacitor to respond [use a wider magnet or move closer to the center of rotation];
  • Too much capacitance [reduce it or debounce in software];

Update:

Would it be better to debounce in software and what would be the best way to do it.

If you have an oscilloscope available, you could look at the raw switch signal (no capacitor) to find out how long it bounces. I'm guessing that it will be around 10ms for such a small switch. If the entire [make/break/make/break....] sequence takes less than 50% (being conservative) of the wheel rotation time (1/max_RPS), you can probably count the first pulse and ignore the switch for (0.5/max_RPS), or 1/2 of the fastest rotation. You appear to be doing something like this already. If you want to be a little bit more rigorous, you might do:

see a HIGH;
ignore switch for debounce_time;
if still HIGH,
   count++;

Also, don't forget that variables shared between your Interrupt function and the main-line code need to be:

  1. declared as volatile, to tell the compiler not to expect that this variable has the value it had last time the mainline code read it; and

  2. Turn interrupts off briefly while reading or writing such a variable (if it is multi-byte) in your mainline, to prevent it being changed by the interrupt function between byte-reads/writes by the mainline.

JRobert
  • 15,407
  • 3
  • 24
  • 51