Skip to content

Instantly share code, notes, and snippets.

@todbot
Created February 26, 2023 19:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save todbot/d585f7de31e1fa263f06dbfda58dcb8c to your computer and use it in GitHub Desktop.
Save todbot/d585f7de31e1fa263f06dbfda58dcb8c to your computer and use it in GitHub Desktop.
Capacitive Touch Sensing using Pico / RP2040 PIO using similar API to CircuitPython's "touchio"
# touchpio.py -- Capacitive Touch Sensing using Pico / RP2040 PIO using similar API to CircuitPython's "touchio"
# 24 Feb 2023 - @todbot / Tod Kurt
# # Uses ideas from "# PIO Capsense experiment / -scottiebabe 2022" from
# https://community.element14.com/products/raspberry-pi/f/forum/51242/want-to-create-a-capacitance-proximity-touch-sensor-with-a-rp2040-pico-board-using-pio/198662
#
import time, array
import board
import rp2pio
import adafruit_pioasm
from supervisor import ticks_ms
class touchpio:
capsense_pio_code = adafruit_pioasm.assemble(
"""
pull block ; trigger a reading, get maxcount value from fifo, OSR contains maxcount
set pindirs, 1 ; set GPIO as output
set pins, 1 ; drive pin HIGH to charge capacitance
set x,24 ; wait time for pin charge
charge: ; wait (24+1)*31 = 1085 cycles = 8.6us
jmp x--, charge [31]
mov x, osr ; load maxcount value (10_000 usually)
set pindirs, 0 ; set GPIO as input
timing:
jmp x--, test ; decrement x until timeout
jmp done ; we've timed out, so leave
test:
jmp pin, timing ; loop while pin is still high
done:
mov isr, x ; load ISR with count value in x
push ; push ISR into RX fifo
""")
def __init__(self, touch_pin, max_count=10_000):
self.max_count = max_count
self.pio = rp2pio.StateMachine( touchpio.capsense_pio_code,
frequency=125_000_000,
first_set_pin = touch_pin,
jmp_pin = touch_pin )
self.max_count = 10_000
self.buf_send = array.array("L", [max_count] ) # 32-bit value
self.buf_recv = array.array("L", [0] ) # 32-bit value
self.base_val = self.raw_read()
print("base_val:",self.base_val)
if self.base_val == 0xffffffff: # -1
raise ValueError("No pulldown on pin; 1Mohm recommended")
def raw_read(self):
self.pio.write( self.buf_send )
self.pio.readinto( self.buf_recv )
return self.buf_recv[0] # return 32-bit number from PIO
@property
def raw_value(self):
return self.max_count - self.raw_read()
import touchio # to compare against
touch_pins = ( board.GP8, board.GP9, board.GP10, board.GP11 )
touchs = [touchpio(p) for p in touch_pins] # try with touchpio
#touchs = [touchio.TouchIn(p) for p in touch_pins] # try with touchio
vals = [0] * len(touchs)
while True:
t = ticks_ms()
for i in range(len(touchs)):
vals[i] = touchs[i].raw_value
dt = ticks_ms() - t
print("\n",dt, end=' ')
for v in vals:
print(v, end=' ')
time.sleep(0.05)
# touch1 = touchpio( board.GP10 )
# while True:
# t = ticks_ms()
# val = touch1.raw_read()
# dt = (ticks_ms() - t)
# dval = (touch1.base_val-val)
# print(dt, hex(val), dval, "*" * int(dval/30) )
# time.sleep(0.05)
# NOTE:
# this is too slow (1msec per pin)
# def read_pin(self, apin):
# apio = rp2pio.StateMachine( touchpio.capsense_pio_code,
# frequency=125_000_000,
# first_set_pin = apin,
# jmp_pin = apin )
# apio.write( self.buf_send )
# apio.readinto( self.buf_recv )
# apio.deinit()
# return self.buf_recv[0] # return 32-bit number from PIO
@todbot
Copy link
Author

todbot commented Feb 26, 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment