Page 1 of 1

PIO Pulse Counter

Posted: Tue Feb 16, 2021 2:03 am
by dhylands
I've been learning about the PIO, so I've started creating some little test programs to explore various aspects of the PIO.

My first example is a Pulse Counter. It just counts the number of rising edges on a Pin.
https://github.com/dhylands/upy-example ... counter.py

Code: Select all

# Example using PIO to count pulses on an input pin.
#
# The following assumes Pin 17 is jumper to Pin 16
#
#   pin16 = Pin(16, Pin.IN, Pin.PULL_UP)
#   pin17 = Pin(17, Pin.OUT)
#   pin17.low()
#
#   pc = PulseCounter(0, pin16)
#
#   print("pulse count =", pc.get_pulse_count())
#
#   pin17.high()
#   pin17.low()
#
#   print("pulse count =", pc.get_pulse_count())
#
#   pin17.high()
#   pin17.low()
#
#   print("pulse count =", pc.get_pulse_count())

import rp2

@rp2.asm_pio()
def pulse_counter():
    label("loop")
    # We wait for a rising edge
    wait(0, pin, 0)
    wait(1, pin, 0)
    jmp(x_dec, "loop")  # If x is zero, then we'll wrap back to beginning


class PulseCounter:
    # pin should be a machine.Pin instance
    def __init__(self, sm_id, pin):
        self.sm = rp2.StateMachine(0, pulse_counter, in_base=pin)
        # Initialize x to zero
        self.sm.put(0)
        self.sm.exec("pull()")
        self.sm.exec("mov(x, osr)")
        # Start the StateMachine's running.
        self.sm.active(1)

    def get_pulse_count(self):
        self.sm.exec("mov(isr, x)")
        self.sm.exec("push()")
        # Since the PIO can only decrement, convert it back into +ve
        return -self.sm.get() & 0x7fffffff

Re: PIO Pulse Counter

Posted: Tue Feb 16, 2021 5:51 pm
by JumpZero
Thanks,
tested it works!
just needed to add "from machine import Pin" but was obvious
I'll be curious to see the max frequency this PIO counter can measure. Maybe when I have time, I can try

Re: PIO Pulse Counter

Posted: Mon Feb 22, 2021 4:53 pm
by Georgeskingv
Nice,

I will try to modify it to make a quadrature encoder.

Best regards

Georges

Re: PIO Pulse Counter

Posted: Mon Feb 22, 2021 9:28 pm
by dhylands
Somebody else posted a quadrature encoder, but it puts the pulses in the FIFO and requires the MCU to do the accumulation.

My end goal is also to implement a quadrature encoder where the counter is maintained inside the PIO.

One of the keys is figuring out how to decrement and increment a counter. You can decrement using the JMP statement. Something like:

Code: Select all

    jmp(x_dec, next)
    label(next)
will decrement (the decrement that's part of the jmp always happens whether the jump occurs or not) . And I think if you do an invert, decrement, invert, then that should do an add of 1. Then it just boils down to doing the state machine for the gray codes.

Re: PIO Pulse Counter

Posted: Tue Feb 23, 2021 8:03 am
by Georgeskingv
Hi,

An idea is to decrement X or Y depending of the direction and then take the difference !

Best regards

Georges

Re: PIO Pulse Counter

Posted: Sun Aug 14, 2022 2:06 am
by AlexYeryomin
dhylands wrote:
Mon Feb 22, 2021 9:28 pm
[...] And I think if you do an invert, decrement, invert, then that should do an add of 1.
You are absolutely right. I needed to _increment_ a value, and this code works just fine:

Code: Select all

    mov(x, invert(x))
    jmp(x_dec, "next")
    label("next")
    mov(x, invert(x))