Code RPM with Hall Sensor but without wait/sleep

CircuitPython on hardware including Adafruit's boards, and CircuitPython libraries using Blinka on host computers.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
christofeugster
 
Posts: 29
Joined: Sun Jan 02, 2022 2:46 am

Code RPM with Hall Sensor but without wait/sleep

Post by christofeugster »

Hi Guys

Im searching for a Code example to read from Hall effect Sensor to get RPMs.
But i would like to achive this without a sleep/wait command,
because i have some other things going on and need a fast loop.

Has anybody somthing to share?
That would save me a lot of time.
Thanks a lot!
Chris

Feather2040 - CircuitPython - VSC - Hall Sensor on GPIO (3.3 - 0V)

User avatar
mikeysklar
 
Posts: 13824
Joined: Mon Aug 01, 2016 8:10 pm

Re: Code RPM with Hall Sensor but without wait/sleep

Post by mikeysklar »

You can look into asyncio with CircuitPython if you wish to run multiple things at once.

https://learn.adafruit.com/cooperative- ... o/overview

The fidget spinner guide provides from code for determinig revolutions per second / minute.

https://learn.adafruit.com/fidget-spinn ... cuitpython

User avatar
CircuitFlyer
 
Posts: 21
Joined: Thu Sep 17, 2020 11:01 pm

Re: Code RPM with Hall Sensor but without wait/sleep

Post by CircuitFlyer »

I use pulseio.Pulsein https://docs.circuitpython.org/en/lates ... io.PulseIn to measure the period of a tachometer input. Just let it do its thing in the background and when you are ready, pause it, total up the pulses and calculate RPM then resume.

User avatar
christofeugster
 
Posts: 29
Joined: Sun Jan 02, 2022 2:46 am

Re: Code RPM with Hall Sensor but without wait/sleep

Post by christofeugster »

mikeysklar wrote: Thu Nov 17, 2022 7:42 pm You can look into asyncio with CircuitPython if you wish to run multiple things at once.

https://learn.adafruit.com/cooperative- ... o/overview

The fidget spinner guide provides from code for determinig revolutions per second / minute.

https://learn.adafruit.com/fidget-spinn ... cuitpython
Thanks for your answer.
I need something that lets the loop flowing.
As far is i understand asyncio, it waits for multiple tasks to start simultaneously. But then
i also have to wait for each task.
I want a loop that constantly ask if some condition is met and only execute if true.
I guess i have to play with time.

User avatar
christofeugster
 
Posts: 29
Joined: Sun Jan 02, 2022 2:46 am

Re: Code RPM with Hall Sensor but without wait/sleep

Post by christofeugster »

CircuitFlyer wrote: Thu Nov 17, 2022 9:28 pm I use pulseio.Pulsein https://docs.circuitpython.org/en/lates ... io.PulseIn to measure the period of a tachometer input. Just let it do its thing in the background and when you are ready, pause it, total up the pulses and calculate RPM then resume.
Thanks, that is actually helping a lot. I will try to combine pulseio with time.monotonic and ask how long it took since the last pulse.
Thanks

User avatar
christofeugster
 
Posts: 29
Joined: Sun Jan 02, 2022 2:46 am

Re: Code RPM with Hall Sensor but without wait/sleep

Post by christofeugster »

CircuitFlyer wrote: Thu Nov 17, 2022 9:28 pm I use pulseio.Pulsein https://docs.circuitpython.org/en/lates ... io.PulseIn to measure the period of a tachometer input. Just let it do its thing in the background and when you are ready, pause it, total up the pulses and calculate RPM then resume.
Is it possible to send me this section of code from you. That would probably save me a ton of time as the documentation on adafruit isnt that detailed as i could wish.
That would be very kind.

I get pulses but two each pass?

Thanks

User avatar
CircuitFlyer
 
Posts: 21
Joined: Thu Sep 17, 2020 11:01 pm

Re: Code RPM with Hall Sensor but without wait/sleep

Post by CircuitFlyer »

You can collect as many pulses as you like. It records the length of each pulse in microseconds. So if you have one magnet then it should record one high pulse length and one low pulse length for each revolution.

I’ll see if I can dig up a code snippet for you. In the meantime, there is some useful info here https://learn.adafruit.com/ir-sensor/circuitpython.

User avatar
CircuitFlyer
 
Posts: 21
Joined: Thu Sep 17, 2020 11:01 pm

Re: Code RPM with Hall Sensor but without wait/sleep

Post by CircuitFlyer »

Here is the code I used to test my set-up. I was measuring the RPM of a DC brushless motor that had 14 magnet poles. In my case I have 14 highs & lows/revolution so you may need to change the math for your use case. Note: my signal conditioning circuit allowed some short duration spikes to get through. I chose to just ignored them. It didn't effect what I was trying to accomplish.

Hope it makes sense.

Code: Select all

# RPM sensor test output using Pulseio
# using QTPy RP2040

from board import D10
import pulseio
from time import monotonic

def getRPM():

    global RPM, valid_samples, now  # needed function updates these
    global total  # although local use only it needs to be initiated at a value of 0
    global number_of_poles  # not needed as function only references this value
    global start_time  # needed, function updates this

    if (now - start_time) > .02:  # set max sample time to collect all required samples at the desired resolution 
        pulses.pause() 
        if (len(pulses) >= 6):  # if there is the minimum number of samples
            for i in range(len(pulses)):  # If the RPM conditioining circuit is unable to filter out some short spikes they get summed and throw the calculation off.
                if pulses[i] < 40:  # this throws out any short spikes that make it through.  Test sample had spikes up to 28usec long.
                    #print(pulses[i])  # test print to show invalid pulse lengths
                    pass
                else:
                    total += pulses[i]  # only valid pulses totaled up
                    valid_samples += 1  # only the number of valid samples to be used in RPM calculation to give true RPM numbers.
            try:
                RPM = (int(((1_000_000/total)*60)/(number_of_poles/valid_samples)/10))*10  # need to divide by number of motor poles here.  Minimum resolution 10RPM
            except ZeroDivisionError:
                RPM = 0
            if (RPM > 60_000):  # needed to read 0 RPM (if total = 1 then RPM is 60,000,000)
                RPM = 0
        if (len(pulses) < 6):  # minimum samples
            RPM = 0
        total = 0
        valid_samples = 0
        pulses.clear()
        start_time = now
        pulses.resume()
        print((RPM,))  # for plotting the results
        return RPM
    else:
        return  # if maximum sample time has not finished yet then return None

number_of_poles = 14
total = 0
RPM = 0
valid_samples = 0
start_time = 0
samples = 14

pulses = pulseio.PulseIn(D10, maxlen=samples, idle_state=False)

while True:
    now = monotonic()
    getRPM()

User avatar
Rcayot
 
Posts: 321
Joined: Sat Feb 08, 2020 6:48 pm

Re: Code RPM with Hall Sensor but without wait/sleep

Post by Rcayot »

I prefer using:

Code: Select all

pin_counter = countio.Counter(board.GP13, edge=countio.Edge.RISE)
The counter counts pin rises or falls. The difference is that you cn count for a long time, in the example below, it collects pin counts for 180 seconds.

Code: Select all

async def fanspeed(interval):
    now = time.monotonic()
    while True:
        lapsed_time = time.monotonic() - now
        print("elapsed time = ", lapsed_time)
        if lapsed_time >= fan_speed_time:
            fan_count = pin_counter.count
            print("count = ", fan_count)
            rpm = ((fan_count/2)/(lapsed_time))*60
            print("rpm = ", rpm)
            F2tag = str(8)
            F2packet = (F2tag + str(rpm))
            print(F2packet)                                                                        
            pin_counter.reset()
            print(pin_counter.count)
            now = time.monotonic()
            if not rfm9x.send_with_ack(F2packet.encode("utf-8")):
                print("No Ack F")            
        await asyncio.sleep(interval)
you can set the time for counting pulses as short or long as you want, just keep track of the elapsed time for the time part of the function.

Altyhough it looks like you did a great job using pulsein.

Roger

User avatar
Rcayot
 
Posts: 321
Joined: Sat Feb 08, 2020 6:48 pm

Re: Code RPM with Hall Sensor but without wait/sleep

Post by Rcayot »

here is the noctura white paper
Noctua_PWM_specifications_white_paper.pdf.zip
(915.14 KiB) Downloaded 5 times

User avatar
christofeugster
 
Posts: 29
Joined: Sun Jan 02, 2022 2:46 am

Re: Code RPM with Hall Sensor but without wait/sleep

Post by christofeugster »

Thanks a lot!
CircuitFlyer wrote: Sat Nov 19, 2022 3:49 pm Here is the code I used to test my set-up. I was measuring the RPM of a DC brushless motor that had 14 magnet poles. In my case I have 14 highs & lows/revolution so you may need to change the math for your use case. Note: my signal conditioning circuit allowed some short duration spikes to get through. I chose to just ignored them. It didn't effect what I was trying to accomplish.

Hope it makes sense.

Code: Select all

# RPM sensor test output using Pulseio
# using QTPy RP2040

from board import D10
import pulseio
from time import monotonic

def getRPM():

    global RPM, valid_samples, now  # needed function updates these
    global total  # although local use only it needs to be initiated at a value of 0
    global number_of_poles  # not needed as function only references this value
    global start_time  # needed, function updates this

    if (now - start_time) > .02:  # set max sample time to collect all required samples at the desired resolution 
        pulses.pause() 
        if (len(pulses) >= 6):  # if there is the minimum number of samples
            for i in range(len(pulses)):  # If the RPM conditioining circuit is unable to filter out some short spikes they get summed and throw the calculation off.
                if pulses[i] < 40:  # this throws out any short spikes that make it through.  Test sample had spikes up to 28usec long.
                    #print(pulses[i])  # test print to show invalid pulse lengths
                    pass
                else:
                    total += pulses[i]  # only valid pulses totaled up
                    valid_samples += 1  # only the number of valid samples to be used in RPM calculation to give true RPM numbers.
            try:
                RPM = (int(((1_000_000/total)*60)/(number_of_poles/valid_samples)/10))*10  # need to divide by number of motor poles here.  Minimum resolution 10RPM
            except ZeroDivisionError:
                RPM = 0
            if (RPM > 60_000):  # needed to read 0 RPM (if total = 1 then RPM is 60,000,000)
                RPM = 0
        if (len(pulses) < 6):  # minimum samples
            RPM = 0
        total = 0
        valid_samples = 0
        pulses.clear()
        start_time = now
        pulses.resume()
        print((RPM,))  # for plotting the results
        return RPM
    else:
        return  # if maximum sample time has not finished yet then return None

number_of_poles = 14
total = 0
RPM = 0
valid_samples = 0
start_time = 0
samples = 14

pulses = pulseio.PulseIn(D10, maxlen=samples, idle_state=False)

while True:
    now = monotonic()
    getRPM()
[/quote]

Locked
Please be positive and constructive with your questions and comments.

Return to “Adafruit CircuitPython”