What type of hall effect sensor do I need?

I have this gear (image attached) that I'm putting over a metal shaft and I want to measure its rpm from 800-15,000 rpm with a tolerance of +/-10 rpm.

Image

I'm thinking I can do this using a hall effect sensor (the type with a magnet built in so you can measure non magnetic metals moving) and an Arduino.

I need help on what parts I need (digital vs analog hall effect sensor) and if this is a good way to do this.

Thanks.

A link or two to such devices would be great.
Paul

A digital hall effect sensor will give you data as either on or off, great for counting rotations.
15,000 RPM leaves you over 60,000 operations between pulses on a 16MHz Arduino, so that's a very easy range to measure very accurately.
You will need to make a collar for the shaft that has a magnet in it. As the magnet rotates with the shaft and passes over the hall sensor it will raise the output pin of the sensor.
I'd use an interrupt to increment a counter. Then read the counter - last counter reading to get rotations over time.

const byte hall_sensor_pin  = 2;
uint32_t   revolutions      = 0; // rolls over after 198 days @15,000 RPMs
uint32_t   last_revolutions = 0;

uint32_t current_time;
uint32_t rpm_prev_time =   0;
uint16_t rpm_timer     = 250;
uint16_t rpm;
uint16_t time_divisor;

void setup() {
  Serial.begin(57600);
  time_divisor = (uint16_t) 1000 / rpm_timer; // Readings per second
  time_divisor *= 60;                         // Seconds per minute
  pinMode(hall_sensor_pin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(hall_sensor_pin), revolutions_tick, RISING);
}

void loop() {
  current_time = millis();
  if (current_time - rpm_prev_time >= rpm_timer) {
    rpm = (uint16_t) (revolutions - last_revolutions) / time_divisor;
    last_revolutions = revolutions;
    Serial.print(rpm);
    Serial.println(" RPM");
    rpm_prev_time += rpm_timer;
  }
}

void revolutions_tick() {
  revolutions++;
}

I wrote this in the browser so check it carefully, but I think this will do the job.
It could be made better but I think that will get you off the ground.

The variable used in the ISR should be volatile.

You should turn interrupts off while copying the interrupt variable do that it won't be corrupted if the interrupt fires during the copy operation.

I knew I missed a thing or two.
That's what I get for doing it from memory.
Thanks for the correction.
Would you mind fixing it for OP as I'm on my phone now?

const byte hall_sensor_pin    = 2;
volatile uint32_t revolutions = 0; // rolls over after 198 days @15,000 RPMs
uint32_t   last_revolutions   = 0;

uint32_t current_time;
uint32_t rpm_prev_time =   0;
uint16_t rpm_timer     = 250; // <=1000, 1000 % rpm_timer == 0
uint16_t rpm;
uint16_t time_divisor;

void setup() {
  Serial.begin(57600);
  time_divisor = (uint16_t) 1000 / rpm_timer; // Readings per second
  time_divisor *= 60;                         // Seconds per minute
  pinMode(hall_sensor_pin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(hall_sensor_pin), revolutions_tick, RISING);
}

void loop() {
  current_time = millis();
  if (current_time - rpm_prev_time >= rpm_timer) {
    noInterrupts();
    rpm = (uint16_t) (revolutions - last_revolutions) / time_divisor;
    last_revolutions = revolutions;
    interrupts();
    Serial.print(rpm);
    Serial.println(" RPM");
    rpm_prev_time += rpm_timer;
  }
}

void revolutions_tick() {
  revolutions++;
}

That should do.

3 Likes

If you use say an Allegro type A3144 and place a small magnet on the back of it, the hall will register pulses as the gear teeth pass.
These are available as a module with a built in led and resistor so no pullup required.(Ebay etc. KY-003)
Note that you need to use a pullup resistor on the hall effect if it is a discrete device as it is open collector.

Thank you very much for this! : )

Nope, not possible.

No problem, don't forget you need to use a collar with a single magnet as mentioned in reply 4

Also please post your results to help other users after you.

Happy Programming!

Not easy anyway.

He clearly meant "non-magnetised". :grin: