Hall sensor produces too much interrupts



  • Hello,

    I am working on a project which calculates rpm from a hall sensor and for this I use a pin callback.
    However, I get way too high rpm values because the interrupt handler somehow gets run countless times while triggering the hall sensor just one time. Normally it should just add 1 to the counter but somehow it adds between 20 and 100+

    I already searched the web but I could not find any helpful explanation or solution.
    Does anybody face the same issue or know how to solve it?

    Help would be really appreciated!

    Here is my code:

    def begin(self):
            pycom.rgbled(0x000000)
    
            self.chrono.start()
            self.pin_hall.callback(trigger=Pin.IRQ_RISING, handler=self.pin_handler)
    
            print('[OS] Measuring RPM..')
            while(True):
                self.wdt.feed()
    
                if self.n.rtc.now()[0] < 2000:
                    print('[NTP] RTC was reset, syncing...')
                    self.n.establishLTE()
    
                if self.rpmcount >= 2 and self.chrono.read_ms() - self.delayStart >= self.DELAY_TIME:
                    self.delayStart = self.chrono.read_ms()
                    self.delayRunning = False
                    self.pin_hall.callback(trigger=Pin.IRQ_RISING, handler=None)
    
                    print('rpmcount:', self.rpmcount)
    
                    self.rpm = (60000.0 / (self.chrono.read_ms() - self.time_old) * self.rpmcount / 2)
                    self.time_old = self.chrono.read_ms()
    
    
                    self.rpmcount = 0
    
    
                    print('[RPM] Count:', self.rpm)
    
    		self.rpm_old = self.rpm
    		self.data['rpm'] = self.rpm
    		self.data['timestamp'] = time.time() + time.timezone()
    
    		payload = self.basePayload()
    		payload['data'] = self.data
    
    		self.sendPacket(payload)
    
    		self.chrono.reset()
    
                    self.millis_old = self.chrono.read_ms()
                    self.delayRunning = True
    
                    self.pin_hall.callback(trigger=Pin.IRQ_RISING, handler=self.pin_handler)
    
                if self.delayRunning and self.chrono.read_ms() - self.millis_old > self.DELAY_TIME:
                    self.rpm = 0
                    self.rpm_old = 0
                    self.data['rpm'] = self.rpm
                    self.data['timestamp'] = time.time() + time.timezone()
    
                    payload = self.basePayload()
                    payload['data'] = self.data
    
                    self.sendPacket(payload)
                    self.delayRunning = False
            #While End
    
        def pin_handler(self, arg):
            self.rpmcount += 1
            print("Interrupt on pin %s" % (arg.id()))
    
    

    This is the response for triggering the hall sensor ONCE (rising):

    Interrupt on pin P10
    Interrupt on pin P10
    rpmcount: 2
    [RPM] Count: 3.084252
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    Interrupt on pin P10
    rpmcount: 50
    [RPM] Count: 149.0665
    


  • @robert-hh I ordered some A3144's and they are working excellent. Once again, thank you very much for your help!



  • @username What kind of sensor is this? The same mode or a different one?
    Telling what happens is different without knowing, how the signal at the interface between the sensor and the GPy looks like. It could still be the double trigger on slow slopes. It could also be that the sensor creates more than one trigger, but the arduino is too slow to recognize that. So at least you need either a simple logic analyzer or an oscilloscope. Simple logic analyzer are available for about 10 €, like this one: https://www.amazon.de/AZDelivery-⭐⭐⭐⭐⭐-Logic-Analyzer-gratis/dp/B01MUFRHQ2/ref=sr_1_5?__mk_de_DE=ÅMÅŽÕÑ&crid=14X0OB8MUIWEK&dchild=1&keywords=logic+analyzer&qid=1595011961&sprefix=logic%2Caps%2C185&sr=8-5
    It works with the salea logic software https://www.saleae.com/downloads/ . It has a sampling rate of 24MHz, good enough for this purpose.



  • @robert-hh I got my hands on another sensor. I took it from another project so I know that it is working fine.

    With this sensor, the behaviour of the GPy is significantly improved. But it is not as desired yet.

    When connected to an arduino, the sensor triggers exactly one intterupt whenever the magnet moves along it. But with the GPy, it triggers mostly 2 interrupts but sometimes even 5+



  • @username This is a whole family A3141 - A3144 with different sensitivity. The vendor calls them discontinued, with A1101-A1104 as the new type. But the old ones are still on sale, and form the datasheet they look pretty similar, only that the A1101 have a slightly lower lowest Vcc.
    The Vcc is 4.5V-32V for the A314x and 3.8V-30V for the A110x. Since the output is open collector, You can run the sensor at e.g. 5V and connect the output to a 3.3 V device.



  • @robert-hh Okay I think I will just order an A3141 then. Thank you very much for you help!



  • @username Ok. That seems to confirm that the output of the sensor breakout is oscillating in the middle of the transition. Normally the sensor should include a component with a hysteresis characteristics. The A3141 have that built-in. It seems that this board has not. And adding a gate does not help in this case. So you have two choices:
    a) get an A3141. That single chip is sufficient. It is pretty robust and easy to use.
    b) connect an 74Hc14 type gate to the "analog" output to digitize the signal.



  • @robert-hh Just tried and setting the attenuation to 6 or 11db works.
    But unfortunately the analog values are not very useful because I need the interrupt to correctly work.

    Regarding your questions:

    • Yes I did already try but it does not help
    • No I did not yet. I don't quite understand what I should test with this, do you mean if there may be some errors in my code which causes this behaviour?

    When the magnet has a distance where the hall sensor does not trigger and I lower the distance bit for bit until the sensor triggers then the led of the sensor is like one tiny pixel on which keeps flashing on and off. In this state the interrupt handler gets called in an infinte loop (indicating that the sensor output keeps rising and falling.
    If I keep lowering the distance then there suddenly is a point where the led gets full bright and stops flashing. The handler then is not called anymore. But when I release the magnet again the handler is called like 40 times at once again.

    So I think this observation supports your assumption from your first post.



  • @username In that case it's probably not the 3141 or similar digital sensor, but a linear sensor like the SS49E/OH49E ... family. In combination with the other chip on the board that makes sense. The analog output quiet level would be at Vcc/2, which is 1.65V. With the standard ADC setting you get a 4095 reading. YOU might have set the attenuation of the ADC to 11dB to get a meaningful reading.
    Another few questions, when dealing with the digital output:

    • did you try changing the sensitivity of the sensor with the trimming potentiometer?
    • did you test your software with a pulse generator? If you do not have that, you could set a digital output of our device in PWM mode at a low frequency to simulate the output of the sensor.

    If everything fails, you could try to get 314x (e.g.3144) or 110x sensors. You do not need a board. You can connect the sensor directly to your pycom board. At aliexpress you get 10 pieces for less than 1 USD. (same for the SS49E sensors).



  • @robert-hh Strange, the actual sensor is labeled with 49E816BG there is no 3141



  • @username I have seen that description. But I asked for the number that is on the actual sensor in your hand. The hall sensor (black, 3 pin) should have the number printed on it. A A3141 should be labeled with the number 3141.

    If you read 4095 with the ADC, then the voltage is always > 1V.

    About P10: P10 is also assigned to ADC2-4 of the ESP32. Using the ADC2 is not supported by the Pycom firmware.



  • @robert-hh Oh strange, I figured I can use P10 since it is also labeled with adc in the GPy Pinout

    With P13 it is now working, but the value is always 4095, no matter how near the magnet is held. The value is even the same with no magnetical field.

    The description states that it has an A3141 chipset



  • @username ADC is on P13-P18 only. Are you sure the sensor is an A3141 model? It should have 3141 printed on the package. So it looks like without viewing the signal there is little progress possible in that aspect.



  • @robert-hh I am unable to make an anlog pin using ADC and connecting the analog output to a normal digital pin does not work.

    This is the error message when trying to use ADC:

    apin = adc.channel(pin='P10')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    OSError: resource not available
    

    I am also wondering if pin callback is working when using adc



  • @username Did you change to the "analog" output too?



  • @robert-hh I just tried changed to FALLING but unfortunately this doesn't change anything.



  • @username According to the data sheet, the output of the A3141 is a digital output, and it has a built-in schmitt-trigger gate. I used that sensor a few years ago, and from what I recall it had an good fast high->low transient. So at least you should change the trigger to IRQ_FALLING.



  • @robert-hh
    I am using the digital output since I don't need to know exact values, but maybe then I should try to use the anlog one instead.



  • @username Looking at the board, it contains additional circuits, like an amplifier and a comparator. That has always the risk of adding more error sources. I know not know which output of the board you are using. The additional resistor only makes sense when using the analog output, since that seems to be the output of the A3141 sensor.



  • @robert-hh
    Thanks for you reply.

    I'm using the KY-024 (A3141).

    It is using a digital pin with the internal PULL_UP enabled.
    Maybe I should try to use an external pull-up resistor.

    Thanks for this advice!


Log in to reply
 

Pycom on Twitter