Capacitive Touch Sensor using PIO - how to set jmp_pin? [solved]

RP2040 based microcontroller boards running MicroPython.
Target audience: MicroPython users with an RP2040 boards.
This does not include conventional Linux-based Raspberry Pi boards.
Post Reply
cebersp
Posts: 22
Joined: Mon Feb 08, 2021 12:07 pm

Capacitive Touch Sensor using PIO - how to set jmp_pin? [solved]

Post by cebersp » Tue Feb 16, 2021 5:21 pm

Edit: See post 3 for working code!

Hi, I would like to do a cap-sensor again but with PIO for better resolution.
viewtopic.php?f=5&t=9829

Two GPIOs are used. One (16) is output and coupled via a 1 Megaohms resistor to the metal pad. The second (17) is coupled directly to the metal pad. The time needed to charge the capacity of the pad is measured. With increased capacity a longer time is needed.


I need to jump on pin state. Something like

jmp(pin, "target_label")

Where can I find the docu about PIO assembler?
Thank you very much!
Christof

Code: Select all

title= "pioTouchA"
# from Example of using PIO for PWM, and fading the brightness of an LED

from machine import Pin
from rp2 import PIO, StateMachine, asm_pio
from time import sleep

@asm_pio(sideset_init=PIO.OUT_LOW)
def cap_prog():
    mov(y, osr) .side(1) # ISR must be preloaded with max
    #mov(x, osr) .side(1) # ISR must be preloaded with max
    
    label("test_pin") # count down y, until inPin is high
    nop()
    jmp(pin, "is_set") # does not work!
    #nop() [5]
    jmp(y_dec, "test_pin") # tested
    
    label("is_set")        
    mov(isr, y) .side(0) # pin low
    push(block)

    


class PIOCAP:
    def __init__(self, sm_id, outPin, inPin, max_count, count_freq):
        self._sm = StateMachine(sm_id, cap_prog, freq=2 * count_freq, sideset_base=Pin(outPin), jmp_pin=Pin(inPin))
        # Use exec() to load max count into ISR
        self._sm.put(max_count)
        self._sm.exec("pull()")
        #self._sm.exec("mov(isr, osr)")
        self._sm.active(1)
        self._max_count = max_count



# Pin 16 is output
#cap = PIOCAP(0, 16, 17, max_count=(1 << 16) - 1, count_freq=10_000_000)
cap = PIOCAP(0, 16, 17, max_count=(1000), count_freq=10_000_000)

while True:
    print(cap._sm.get())
    sleep(0.01)

Last edited by cebersp on Tue Feb 16, 2021 7:28 pm, edited 4 times in total.

Online
User avatar
dhylands
Posts: 3593
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: PIO how to set jmp_pin?

Post by dhylands » Tue Feb 16, 2021 7:03 pm

The documentation for the PIO assembler can be found in the RP2040 datasheet. https://datasheets.raspberrypi.org/rp20 ... asheet.pdf starting at page 324.

I haven't seen any documentation on the Micropython assembler syntax. I've use the examples found in the micropython/examples/rp2 directory, and https://hackspace.raspberrypi.org/books ... ython-pico has some examples/verbage in Appendix C (page 130)

I've also found looking at: https://github.com/micropython/micropyt ... les/rp2.py to be useful. If you're looking for jmp modifiers (like !x is really not_x) or mov modifiers (like invert) you'll find them in this file.

It also has the assembler functions (i.e. jmp/mov/wait/...) and you can see what arguments all of the functions expect.

There is an example of jmp(pin, "target") in the pio_uart_rx.py file: https://github.com/micropython/micropyt ... _rx.py#L58

cebersp
Posts: 22
Joined: Mon Feb 08, 2021 12:07 pm

Re: PIO how to set jmp_pin?

Post by cebersp » Tue Feb 16, 2021 7:16 pm

Thank You very much Dave!
Yes I did have a close look into the datasheet.

I learned, how to do it here:
https://www.raspberrypi.org/forums/view ... 6&t=303606

I do not at all understand it, but the following code works now!
I did learn how to get the result from your code.

Christof


Code: Select all

title= "pioTouchB"
# from Example of using PIO for PWM, and fading the brightness of an LED

from machine import Pin
from rp2 import PIO, StateMachine, asm_pio
from time import sleep

maxTime=10000

@asm_pio(sideset_init=PIO.OUT_LOW)
def cap_prog():
    mov(y, osr) .side(1) # OSR must be preloaded with max
    mov(x, osr) .side(1) 
    
    label("test_pin") # count down y, until inPin is high
    jmp(pin, "is_set") # does work
    jmp(y_dec, "test_pin") # tested
        
    label("is_set")
    mov(isr, y) .side(0) # save result pin low
    
    label("delayLow")
    nop()
    jmp(x_dec, "delayLow") # tested    

    


class PIOCAP:
    def __init__(self, sm_id, outPin, inPin, max_count, count_freq):
        self._sm = StateMachine(sm_id, cap_prog, freq=2 * count_freq, sideset_base=Pin(outPin), jmp_pin=Pin(inPin,Pin.IN))
        # Use exec() to load max count into ISR
        self._sm.put(max_count)
        self._sm.exec("pull()")
        #self._sm.exec("mov(isr, osr)")
        self._sm.active(1)
        self._max_count = max_count
        
    def getCap(self):
        self._sm.exec("push()")
        # Since the PIO can only decrement, convert it back into +ve
        return self._sm.get()



# Pin 16 is output
#cap = PIOCAP(0, 16, 17, max_count=(1 << 16) - 1, count_freq=10_000_000)
cap = PIOCAP(0, 16, 17, max_count=(maxTime), count_freq=10_000_000)

while True:
    print(maxTime-cap.getCap())
    sleep(0.01)


Post Reply