Adding a Touch Button to GurgleApps Word Clock Using RP2040/RP2350 Programmable IO (PIO)

by kevinjwalters in Circuits > Microcontrollers

136 Views, 3 Favorites, 0 Comments

Adding a Touch Button to GurgleApps Word Clock Using RP2040/RP2350 Programmable IO (PIO)

gawordclock-captouch-title-43.jpg

The GurlgeApps Word Clock is an open-source digital clock which shows the time as words in English. This small USB-powered desktop clock has letters in an 8x8 grid layout which can be individually illuminated in any colour. It can be controlled from a web interface but it has no buttons for local interaction.

This article shows the simple addition of an unobtrusive button to the front panel of the clock. The clock isn't designed for this but a few options are explored and capacitive touch is pursued. The RP2040 microcontroller on the Pi Pico W (and RP2350 on the Pi Pico 2 W) do not have hardware support for capacitive touch but this can be implemented using the simple but powerful Programmable I/O (PIO). Fortunately, this low-level feature is fully accessible from MicroPython making it easy to use.

The new TouchPad class is easily introduced into the Word Clock software using the asyncio primitive Pushbutton.

Assembling the Word Clock involves some simple soldering. This project involves some additional simple soldering.

Supplies

  1. GurgleApps Word Clock : Etsy (select Full Kit if you want to build it or Fully Built if you don't)
  2. Soldering iron and solder.
  3. A single male header pin. Two small pairs of pliers might be needed to break one off cleanly from a longer row.
  4. A short wire.
  5. Epoxy resin or hot glue gun to hold the pin in place.
  6. Optional: a fine metal file to dull the point of the header pin and something hefty to hold the pin during filing.

Touch Measurement

noritake-self.png
noritake-mutual.png

The two diagrams above are taken from Noritake's summary of touchscreen sensing.

Resistance Measurement

Resistive touch pads can be implemented with two conductive pads measuring the (tiny) current which will pass through a finger pressed against both pads. A multimeter can be used to show how high this resistance is.

Another more common approach is to detect the resistance change of two electrodes with a separator compressed by finger pressure.

Self-Capacitance Measurement

Capacitive touch pads can use a single connection which may have a high value (megaohm) pull-down (or pull-up) resistor. Some microcontrollers have a built-in hardware feature to provide capacitive touch efficiently. For microcontrollers without this feature either an extra chip like the Microchip AT42QT1070 or Analog Devices AD7147 on a breakout board can be used or the feature can be implemented in software in compiled** code.

The NXP MPR121 is often used by hobbyists and while this is still stocked it is a discontinued product. The Tontek TTP223 is popular for single touch pads.

Mutual Capacitance Measurement

Capacitive touch pads can also use two electrodes rather than one. The Microchip Technology AT42QT2160 implements this and can be seen in action on the Kitronik :KLEF piano.

** Capacitive touch is challenging to reliably implement purely in an interpreted language, see the Adafruit PyRuler's CircuitPython demonstration program for one attempt in read_caps().

Button Candidates

gurgleapps-assembly-frontbackcomposite-annotated-43.jpg
  1. Touch button using one of the four bolt heads on the front of the case.
  2. Touch button using the GurgleApps metal logo.
  3. Touch button using something conductive through one of the two holes** for RGB LED matrix alignment.
  4. BOOTSEL button accessed on the rear of case.
  5. Proximity/light sensors.

1) The bolts aren't accessible from inside of the case. They might be difficult to solder to and for the black ones they would need testing to check if they work with capacitive touch. If there's room then fork/hook/ring terminals might work well on the bolt thread with a pair of additional nuts clamping them.

2) The GurgleApps logo is very tempting to use as a touch pad. This isn't accessible from the reverse side of the face plate but the PCB could be very carefully milled away to reveal a small patch of it. See next page.

3) The simplest solution is to use one or two small pieces of metal poking through one of the existing unused holes. These are intended to align the RGB LED matrix with the letters on the face plate but the plastic frame does a good job of this on its own. For resistive touch two would be need, for capacitive touch only one would be needed.

4) The BOOTSEL button is also a possibility. It's only used as the Pi Pico W powers up, after that it can be repurposed. It's not directly connected to the microcontroller making it difficult to use. Its position on the rear of the case makes it non-ideal for most interactive use.

5) Proximity sensors (e.g. using infrared) and simple light sensors detecting blockage of ambient light weren't explored.

** Alternatively, hole(s) could be made in the spacer frames for touch buttons on the side or top of the Word Clock.

Grinding a PCB With a Precision Drill by Hand

pcb-grind-underside-1.jpg
pcb-grind-copperside-1.jpg

The second option of connecting a wire to the GurgleApps metal logo was briefly explored. An experiment with a Dremel-like drill on a piece of stripboard** showed it was possible to gradually grind away the PCB by hand but even with care the copper strips were damaged. The copper is likely to be far thicker than the logo making the face plate logo near impossible to access with this tool and technique.

Drilling the full stop of the GurgleApps.com with a 1mm drill in a pillar drill and then soldering the end of a wire to the surface of the logo and accepting some visible silver-coloured solder might work.

This idea was abandoned in favour of adding a new metal pin.

** Protective eyewear, a face mask and dust extraction are wise precautions for dealing with the fine dust created from this form of PCB abrasion.

Selecting and Testing Capacitive Touch PIO Code

pipico-jtouch-gp12-demo-anim-1.gif

The first Programmable I/O (PIO) example found by an Internet search didn't appear to work from a quick test. The second one, James Brown's jtouch, worked very well and came with a useful MicroPython class and integrated test program. This was tested on a bare Pi Pico and with a 10cm wire connected to a pad (recreation shown above), both worked well. This provided a high level of confidence for moving forward with the capacitive touch solution in software.

The library uses one PIO state machine per pin. This provides 8 touch pads on the RP2040-based Pi Pico W and 12 on the RP2350-based Pi Pico 2 W.

Some capacitive touch solutions rely on an external high value pull-down (or pull-up) resistor per pad but this library does not need this.

Adding a Metal Pin for Capacitive Touch

captouch-pin-wire-header.jpg
captouch-pipico2w-soldered-pinglued-1.jpg
gawordclock-touchpinaddition-1.jpg

The bottom right hole is the easiest one to use as no existing cabling goes near it. The instructions for adding a metal touch pin follow.

  1. Break off one header pin. Two small pairs of pliers are useful here.
  2. Consider filing** the end of the longer part of the pin which will protrude out of the case slightly to make it less sharp.
  3. Check the pin fits and can just be felt through the front panel with a finger.
  4. Cut a wire to appropriate length and strip ends.
  5. Solder to the short part of the single header pin. Check the plastic on the pin has not moved during soldering as it can soften with the heat.
  6. Hot glue the pin in place on the back of the RGB LED matrix. Ensure it's reasonably central in the hole and perpendicular to the PCB. Allow time for the glue to solidify, at least a minute.
  7. Solder to a convenient GPIO pad on the Pi Pico W. GP12 was used in the example shown above.

Note: this particular Word Clock is using a Pi Pico 2 W.

** These pins are typically tin-plated, depending on the quality of the underlying metal they may tarnish a little if filed, try to use a header pin which is not attracted to a magnet.

Word Clock Software Additions

button_classes.png

TouchPad class in captouch_rp2.py

The jtouch library was tweaked and renamed to captouch_rp2.py, the differences are described below.

  1. Channel becomes TouchPad, Device class wasn't needed and was removed.
  2. The CPU clock frequency isn't changed. The PIO runs at 125MHz which is the default frequency on the Pi Pico W. On the Pi Pico 2 W at the default 150MHz the PIO does runs at 125MHz - it does this by skipping occasional pulses - the minor jitter introduced does not affect the capacitive touch measurements.
  3. The collection period is reduced from 16.7ms to 10.0ms.
  4. The @micropython.native decorator is no longer used (not sure of pros & cons here).
  5. The window of 64 is now larger of 100 and warmup range * multiplier - this is used to ignore noise.
  6. New boolean is_pressed() method calculates using a value which is based on highest measured value and does not dynamically vary but can be specified in the constructor with press_value.
  7. Objects are now callable for compatibility with asyncio primitve Pushbutton. This always waits for a fresh measurement.
  8. PIO code now "free" runs with non-blocking PIO push to let it collect data continuously. The most recent value is normally returned immediately but if the FIFO full then all of the values need to be discarded as they may be stale and a new value needs to be waited for.
  9. The FIFO is doubled up via the join feature. It's now 8 words rather than 4 - this gives 8 * 10ms = 80ms of data in FIFO.
  10. Simple dynamic assignment of PIO state machine numbers.

Using TouchPad with Pushbutton in Word Clock software

The button is created if the TouchPad class has been imported.

button = None if touch_pin is None or globals().get("TouchPad") is None else TouchPad(touch_pin)

If the button has been created then a Pushbutton object is conditionally created. Anything which returns a boolean value when it's called (i.e. implements __call__() method) can be used with Pushbutton if sense=False (or sense=True) is supplied.

pb = Pushbutton(button, sense=False, suppress=True)
pb.release_func(lambda : set_display_mode(next_display_mode(), save=False))
pb.long_func(button_long, (pb,))

The two callbacks implement:

  1. short press (0.4s)- changes the display mode without saving;
  2. long press (1.0s) - changes the background mode without saving, also detects very long presses;
  3. very long press (3.0s) - saves the configuration.

Touch Button Demonstration Video

GurgleApps Word Clock - capacitive touch demonstration

The video above shows the capacitive touch pad being tested. A short press changes the display mode, a long press changes the background mode, a very long press saves the configuration.

  1. 00:00 Single Colour mode with Minutes Digit background at 7:22
  2. 00:15 Short press - Word Colours mode.
  3. 00:20 Short press - Random mode.
  4. 00:24 Short press - Rainbow mode.
  5. 00:27 Long press - Blank background.
  6. 00:30 Long press - Digital Rain background.
  7. 00:44 Long press - Minutes Offset background.
  8. 00:48 Very long press to save configuration.
  9. 00:51 Configuration saved - S briefly appears on the display.
  10. 00:55 Clock advances to 7:23.

The touch pad calibrates itself when the clock is turned on and the software starts-up. It's important not to touch the pad at this time.

Capacitive Touch Pulses on Oscilloscope

GurgleApps Word Clock - oscilloscope view of capacitive touch

The video above shows an oscilloscope view of the pulses used to implement the capacitive touch feature. A 10x passive probe was used together with a 10k resistor to probe the touch pad. This probing registers as a touch which isn't ideal for an attempt at observing the signal! A finger appears and the increased period of the pulses can be seen and later in the video the frequency can be read from the oscilloscope's measurement panel.

  1. 00:00 Word clock running.
  2. 00:06 Probe with 10k resistor, pulse frequency approximately 1.9MHz.
  3. 00:15 Probe touch combined with finger, pulses lengthen.
  4. 00:18 Probe removed.
  5. 00:30 Probe with 10k resistor, 1.9MHz
  6. 00:40 Probe touch combined with finger with clear view of oscilloscope.
  7. 00:46 Probe touch with finger, pulse frequency approximately 0.9MHz
  8. 00:52 Prove removed.

A USB lead with a Y splitter for 2.1mm barrel jack power was used to access a common ground for the oscilloscope.

Capacitive Touch Raw Values From PIO Code

gawordclock-captouch-scope-noreszoom-43.jpg

Some raw cycle count values are listed below from the PIO code. These are not shown in the video in the previous page.

  1. Untouched: 23400
  2. Light touch: 20800
  3. Firm touch: 17700
  4. Oscilloscope 10x passive probe with 10k resistor (1.9MHz): 18900
  5. Oscilloscope 10x passive probe with 10k resistor and finger (0.9MHz): 9000
  6. Oscilloscope 10x passive probe (1.0MHz): 10100

The photograph above shows the final reading and gives a reasonable view of what the waveform looks like on this low-end oscilloscope. The PIO code sets the GPIO output to low (0V) and then after a few cycles changes the GPIO to a digital input pulled high by the internal pull-up. This (CMOS) digital input will interpret a voltage approximately above the mid-point (1.65V) as a 1. The presence of a touching object affects the gradient of the rise changing the period of the sawtooth wave and this is reflected in the cycle count per sampling period.

The frequency can be seen to be related to the cycle count from the PIO code. It runs over a 9.96ms sampling period meaning the frequency is approximately 100x the value. The frequency when the touch pad isn't touched cannot be measured with this oscilloscope but based on the cycle count it will be 2.35MHz.

These values vary considerably, a very steady finger might be +/- 200. These will also vary with the hardware and touch pad wiring preventing the use of fixed values and making it important for the device to be calibrated. The touch pad object performs a calibration itself when it's instantiated, i.e. when the clock is powered on. The code currently selects the highest value to represent the untouched value.

Capacitive touch can be sensitive to whether the power supply's ground is earthed. This means battery power can change the values above. The Word Clock does not offer battery power but for any device that can seamlessly switch between USB power from an (earthed) desktop and battery power it must be tested. It may need to recalibrate capacitive touch for transitions like this.

Installing the Software on Pi Pico 2 W

gawordclock-filesystem-captouch.png

The normal software installation process using Thonny is described in Software Setup: Configuring Your Wifi Word Clock. The capacitive touch feature is currently only in a forked (from main) branch. The capacitive touch library is in captouch_rp2.py and a subset of the asyncio primitives library is in the lib directory.

The config.json file needs an extra line to enable the use of capacitive touch. For a wire connected to GP12 add the line below.

"TOUCH_PIN": 12,

MicroPython v1.26.1 was used for this article.

One Issue to Fix - Drift Compensation

The current library only partially tracks the cycle count value for the untouched value over time. This value is the maximum for all measurements (bar a few in the "warm up" phase) which means it can be non-representative due to

  1. insufficient warm up period and/or
  2. a single high outlier values and/or
  3. gradual change (drift) to a lower value.

All of those could cause a false press detection.

Going Further

arturia-microfreak-fromvideo.jpg

The photograph above is an Arturia MicroFreak synthesiser which has an advanced capacitive keybed and a touch strip (ribbon controller).

Some ideas to explore:

  1. See if the four case bolts can be accessed in some way and used as touch pads.
  2. Study the effect of ambient temperature using CapTouch.
  3. Improve the baseline tracking in CapTouch to cater for drift.
  4. Evaluate the usefulness of the debounce logic in Pushbutton for CapTouch. Investigate whether hysteresis is beneficial.
  5. Experiment with very thin metal plates/foil sandwiched between the spacer frames to see if these can be used for touch detection.
  6. Fabricate your own face plate with touch pads. These could be as small as discreet PCB vias or as large as the current logo.

Libraries:

  1. CircuitPython's touchio library. This library is available on many microcontrollers including the RP2040 and will use hardware of software implementations of touch depending on the microcontroller. This needs external passive hardware, typically a 1Mohm resistor to GND, although the RP2350 (Pi Pico 2) needs the resistor to go to 3.3V instead.
  2. Arduino: CapacitiveSensor library - this requires two pins and at least one high value inline resistor between the "sending" GPIO and the conductive touch pad.
  3. Hackster.io: Turn Any Pico Pin Into a Capacitive Touch Sensor with This Simple Code - a brief article on the jtouch library.

A small selection of products offering/using capacitive touch:

  1. Adafruit Circuit Playground Express (CPX) and Circuit Playground Bluefruit (CPB)
  2. BBC micro:bit V2 - the V2 is the one with the gold oval logo and non-straight edge connector.
  3. Kitronik :KLEF piano - an attractive one octave keyboard using Mircochip Technology AT42QT2160 intended for BBC micro:bit but can be used with other microcontrollers.
  4. PicoTouch Synth - Pico-based MIDI synth & keyboard

Interesting projects featuring capacitive touch:

  1. Instructables: DIY 3D Controller - replicated by Make Magazine.
  2. Jay Silver: MaKey MaKey - An Invention Kit for Everyone (YouTube) - banana space bar and more.
  3. Instructables: Ever Blooming Mechanical Tulip

Further reading:

  1. DigiKey: TechForum: Touch Sensors: Types, Applications and Selection Tips
  2. Noritake: What are the different types of touchscreens and how are they used?
  3. Creative Computing Institute: Using an MPR121 capacitive touch sensor
  4. Microchip Technology: Capacitive Touch Sensor Design Guide Application Note AN2934 (pdf).
  5. Infineon: Proximity sensing with CAPSENSE Application Note AN92239 (pdf)
  6. Texas Instruments: FDC1004: Basics of Capacitive Sensing and Applications (Application Report) (pdf)
  7. BBC micro:bit: Touch sensing on the micro:bit - explains how the V1 micro:bit only offers resistive touch but V2 offers capacitive touch on the new logo pad and both on the three traditional large pads.
  8. Arduino Blog: Rapidly create your own capacitive multi-touch sensors with this kit about the Multi-Touch Kit which runs on many Arduino platforms including Arduino UNO R3 (ATmega328P), Arduino Mega (ATmega2560), and (discontinued) Arduino LilyPad (ATmega328P), described in more detail in the research paper Pourjafarian, Narjes & Withana, Anusha & Paradiso, Joseph & Steimle, Jürgen. (2019). Multi-Touch Kit: A Do-It-Yourself Technique for Capacitive Multi-Touch Sensing Using a Commodity Microcontroller. 1071-1083. 10.1145/3332165.3347895 (pdf).
  9. Zimmerman, Thomas & Smith, Joshua & Paradiso, Joseph & Allport, David & Gershenfeld, Neil. (1995). Applying Electric Field Sensing to Human-Computer Interfaces. 10.1145/223904.223940.