// The hall sensor pin
static const byte sensor_pin = 2;
// The base for RPM count
uint8_t revolution_halves;
// Here are all supported input type detection types
typedef enum { LOW_LEVEL, BOTH_EDGES, FALLING_EDGE, RISING_EDGE } transition_t;
// We don't wnat to rely upon attachInterrupt, here's our way! At least
// we know if a pin supports external interrupts or not.
//
// TODO: Account for other platforms than just ATmega328 (aka Uno)
inline bool enableTransitions(byte pin, transition_t type)
{
switch (pin)
{
case 2:
EICRA &= _BV(ISC11) | _BV(ISC10);
EICRA |= type << ISC00;
break;
case 3:
EICRA &= _BV(ISC01) | _BV(ISC00);
EICRA |= type << ISC10;
break;
// Unsupported pin ID, no way!
default:
return false;
}
return true;
}
// Return true if a transition has occurred on the given pin
bool testTransition(byte pin)
{
uint8_t state = EIFR;
switch (pin)
{
case 2: state &= ~INTF0; break;
case 3: state &= ~INTF1; break;
// Unsupported pin ID, no way!
default:
return false;
}
// First reset the interrupt bit and return the detected state
EIFR = state;
return state;
}
// Return true if the display was updated. The delay is measured in milliseconds
// and also serves as a base for RPM computation
bool updateDisplay(uint8_t count)
{
// For how many milliseconds we count pulses (also how often the LCD is updated)
static const long interval_millis = 300;
// Keep track of elapsed time and update LCD about 3 times a second
static long prev_millis;
// Wait a small amount of time before updating the display
if (! (millis() - prev_millis >= interval_millis)) return false;
// Now update the display
// Note: we only send through the serial output so adjust to fit your
// requirements (e.g. LCD update)
const uint32_t rpm = 30 * count * 1000 / interval_millis;
Serial.print("Rev=");
Serial.println(count);
// Set the new elapsed time and account for updating the LCD
prev_millis = millis();
return true;
}
void setup()
{
Serial.begin(9600);
pinMode(sensor_pin, INPUT_PULLUP);
pinMode(LED_BUILTIN, OUTPUT);
// Prepare slope detection on sensor pin (2, i.e. INT0)
enableTransitions(sensor_pin, FALLING_EDGE);
Serial.println("Ready!");
}
void loop()
{
// Just a test...
digitalWrite(LED_BUILTIN, digitalRead(sensor_pin) == LOW ? HIGH : LOW);
if (testTransition(sensor_pin))
revolution_halves++;
// Reset the pulse counter after the display was updated
if (updateDisplay(revolution_halves))
revolution_halves = 0;
}
This code should be calculating my RPM, but seems only to be printing the raw amount of counts the sensor picks up during interval_millis
which is set equal to 300. I am using an A3144 Hall sensor. I am using a fidget spinner with a small neodymium magnet.
digitalWrite(LED_BUILTIN, digitalRead(sensor_pin) == LOW ? HIGH : LOW);
^this def seems to work, and just by looking it seems to be flashing every time the magnet passes.
Does anyone see an apparent issue with the code? my project is due Monday, aka June 7th, 2021.
Any help is much appreciated. Thank you in advance
P.S. the LCD is obviously not being used at the moment, waiting for everything to prove accurate before I bother.