49E Hall Effect with Arduino Interrupt - Page 1
Forum section: electronics / beginners

author: metrologist
author_rank: Super Contributor
timestamp: June 18, 2020, 05:43:04 pm
content: Hi All,I bought a bunch of 49E hall effect sensors and am looking to improve interrupt performance for RPM measurements. It seems to be working ok on the breadboard, but I feel it is marginal due to the HES output wiggles around 1.6V to 2.3V with both poles of a magnet passing by, and sometimes I get erroneous readings. Arduino only triggers on one pole. The 49E goes directly to the D2 port.I have an LT1078 and modeled the attached circuit. I was wondering if there is a better approach? I tried modeling an NPN transistor but it seems too sensitive as far as resistor selection. Same thing with the op amp - it's supply voltage sensitive due to how the 49E works (outputs Vcc/2 without magnetic field).

author: alsetalokin4017
author_rank: Super Contributor
timestamp: June 19, 2020, 05:05:41 am
content: Can your application get away with smoothing, that is, averaging the sensor's output over several pulses? Calculate a moving average over, say, 10 magnet pulses or revolutions and let that be the value used for the RPM calculation?

author: mikerj
author_rank: Super Contributor
timestamp: June 19, 2020, 09:09:24 am
content: 1) Use a comparator rather than an op-amp.2) Low pass filter the sensor output to get the DC level and use this to set the common mode voltage.2) Add some positive feedback to give hysteresis. Without this you are likely to get multiple triggers near the zero crossing point.

author: metrologist
author_rank: Super Contributor
timestamp: June 19, 2020, 05:32:10 pm
content: I tried playing with the simulation some more and increased my frequency since I'll have an application that could go up to 50k rpm (which I don't have a way to test right now). First is low frequency for an anemometer. I could not get positive feedback to work.And the code, I rather like the simple implementation with just the one hardware component and thought a software solution with an analog read instead of an interrupt, and then figure out the max or min point to determine a single cycle duration. The program logic is not coming to me though... and I always get an erroneous first reading.I took out the rest of the weather station code and data outputs, so this is just the hall sensor bits.Code://hall sensorint encoder = 2;float rps;float rpm;float mph;float gust;float gustm;volatile byte pulses;unsigned long timeold;unsigned long timegustold;void setup() {pinMode(LED_BUILTIN, OUTPUT);//hall sensorpinMode(encoder, INPUT);delay (2000); //try delay to avoid erroneous first reading - does not work...attachInterrupt(0, counter, FALLING); //attaching the interrupt and declaring the variables, one of the interrupt pins on Nano is D2, and has to be declared as 0 herepulses = 0;rps = 0;rpm = 0;mph = 0;gust = 0;gustm = 0;timeold = 0;}void loop() {if (millis() - timebme > 1000) {timebme = millis();bme01();}hall01();serial01();oled01();}//this subprogram will run when interrupt is triggeredvoid counter() {pulses++; //every time this subprogram runs, the number of pulses is increased by 1}void hall01() {if (pulses >= 1) { //this part of the code calculates the rpm and rps in a way that every time the magnet passes by the sensor, the time between the pulses is measured and rpm and rps is calculateddetachInterrupt(0);rpm = 60000.0 / (millis() - timeold) * pulses;timeold = millis();pulses = 0;digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); //toggle LEDattachInterrupt(0, counter, FALLING);}if (millis() - timeold >= 5000) rpm = 0; //resets rpm to zero if no pulses after xx secs//mph = rpm * 0.020825 * 2.5; // based on rpm, 7 inch diameter (= rpm*0.020825) and empirical cal factor (/0.711) (or wiki says *2 to just over 3)//mph = rpm * 0.372823; //empirical 10m/s = 60 rad/s 1 rps from https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6539519/mph = rpm * 0.020825 * 4.5; //circumference * k where k = radius of center rotation / radius of cupsif (mph > gustm) {gustm = mph;}if (mph > gust) {timegustold = millis();gust = mph;}if (millis() - timegustold > 300000) { //reset gust every xxx msgust = mph;}}Also added a scope shot of the D2 pin and the updated simulation.