Raspberry Pi Pico Capacitive Touch

I’ve now done a number of projects using capacitive touch, using a range of methods from native IO handling to the use of the MPR121 and off-the-shelf boards.  Typically native IO methods require testing a response between a signal on one IO pin being received on another, with the timing of that response affected by the capacitance in the circuit, which will change if touched.

Recently, I’ve been looking at the touchio library for CircuitPython and noticed a number of projects that show the use of just one IO pin with it connected to GND via a large (typically 1MΩ) resistor and some of those use a Raspberry Pi Pico, so this post is a bit of a deep dive into how that works.

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

These are the key tutorials for the main concepts used in this project:

If you are new to microcontrollers, see the Getting Started pages.

Single Pin Touch IO

My first task was actually to find out what was going on. When using an Arduino, as I say, it was typically to require the use of two IO pins – one to send a signal out, and one to receive it back, but everything I’ve read about Touch IO suggests that a single pin is fine.

What I couldn’t pin down though was that most of the tutorials for the CircuitPython touchio related to boards using microcontrollers that include specific hardware for touchpads. For the SAMD21 based boards this means using the “Qtouch PTC” or “peripheral touch controller”.

But the only reference to how to do this on the Raspberry Pi was several posts in the forums suggesting using the “two GPIO pin” method, in some cases utilising the PIO, so what was going on?

The clue ended up being the touchio bindings for CircuitPython. In the shared module file “TouchIn.c” is the following comment:

// This is a capacitive touch sensing routine using a single digital
// pin.  The pin should be connected to the sensing pad, and to ground
// via a 1Mohm or thereabout drain resistor.  When a reading is taken,
// the pin's capacitance is charged by setting it to a digital output
// 'high' for a few microseconds, and then it is changed to a high
// impedance input.  We measure how long it takes to discharge through
// the resistor (around 50us), using a busy-waiting loop, and average
// over N_SAMPLES cycles to reduce the effects of noise.

The code goes on to implement that algorithm hence providing the interface now available via the CircuitPython touchio module.

In the case of the SAMD21 port, there is an alternative TouchIn.c which provides the hardware “native” touch IO using the PTC and I guess other ports may include more specific hardware drivers if supported too.

One upshot of all this is that it might not be immediately obvious which IO pins support touch and which do not. There is a test script here (with more explanation here) that will list all touch valid IO pins from CircuitPython. In the case of the Raspberry Pi Pico, with no direct hardware support for touch, it is all GPIO pins.

Aside: Two alternative approaches for the Arduino for capacitive sensing that I found and might explore at some point are:

Note that neither of these seems to be the same algorithm or implementation as the CircuitPython TouchIO though. Anyway, with that all cleared, up, on to the circuit.

Parts list

  • Raspberry Pi Pico.
  • 1MΩ resistor per touch pad.
  • Conductive sensor (e.g. aluminium foil, copper tape, other such conducting object).
  • Breadboard and jumper wires.
  • Optional: 3V3 MIDI OUT circuit.

The Circuit

Each GPIO pin can act as a touch pin if connected to GND via a 1MΩ resistor. The pin can then be connected to any conductive surface to use as a sensor.

An optional 3V3 MIDI OUT circuit can be connected to GP0 (UART TX) if serial MIDI is required, otherwise it is assumed that USB MIDI will be used.

The list of GPIO pins used is thus:

  • GP0 (TX) – MIDI OUT
  • GP12 – Touchpad 1
  • GP13 – Touchpad 2

The Code

Adafruit have made using capacitive touch pretty straightforward. Typically one would have to worry about thresholds, false triggers, and so on, but with the use of the adafruit_debouncer and touchio libraries (both from the Adafruit CircuitPython Library Bundle), it can all be abstracted away, and it basically “just works”.

Here is the basic code to handle a debounced, touch pad:

import board
import touchio
from adafruit_debouncer import Debouncer, Button

THRESHOLD = 1000
t = touchio.TouchIn(board.GP12)
t.threshold = t.raw_value + THRESHOLD
touchpad = Button(t, value_when_pressed=True)

while True:
    touchpad.update()
    if touchpad.rose:

        print("Touch On")
    if touchpad.fell:
        print("Touch Off")

The value used as the THRESHOLD is slightly higher than the default (which I think would be around 100). A bit of experimentation should find a value that seems to work for your setup.

When combined with the Adafruit MIDI library this can be used to send MIDI NoteOn and NoteOff messages over USB and serial MIDI in response to touching and releasing the touch pads.

The final code has a list of touch pins to be configured and corresponding MIDI notes to be played, one for each pin.

Find it on GitHub here.

Closing Thoughts

This has turned out to be fairly straight forward, so with the basics out of the way, I’m now thinking about how to modify my Touch Keyboard PCB to include built-in resistors (for example) as well as additional MIDI applications.

Kevin

One thought on “Raspberry Pi Pico Capacitive Touch

Leave a comment