Created
February 26, 2023 19:23
-
-
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"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For more fully-developed version of this idea, see: https://github.com/todbot/picotouch/tree/main/circuitpython/picotouch_grid/picotouch_grid