# No-Touch Hand Wash Timer for Circuit Playground Express and CLUE

## Overview

https://youtu.be/M8Fh9-bwPKc

This guide will show two ways to build a hand washing timer. Bored of singing "Happy Birthday"? This countdown timer will help you scrub your hands with soap for a full 20 seconds with confidence, as outlined by the US Centers For Disease Control and Prevention [handwashing guidelines](https://www.cdc.gov/handwashing/when-how-handwashing.html).

Plus, there's no need to touch the timer, in order keep it clean.

Two different version of the project here -- one in MakeCode for Circuit Playground Express, the other in CircuitPython for the CLUE. Use a loud sound, such as a clap or snap to activate the CPX timer, or a wave of a hand to start the CLUE.

**This is a great beginner project to show how to make a real product with a few 'blocks' of code!**

https://youtu.be/_Ui1HS6LiPA

## Parts
### Circuit Playground Express

[Circuit Playground Express](https://www.adafruit.com/product/3333)
 **Circuit Playground Express** is the next step towards a perfect introduction to electronics and programming. We've taken the original Circuit Playground Classic and made it even better! Not only did we pack even more sensors in, we also made it even easier to...

In Stock
[Buy Now](https://www.adafruit.com/product/3333)
[Related Guides to the Product](https://learn.adafruit.com/products/3333/guides)
![A Black woman's manicured hand holds a round microcontroller with lit up LEDs.](https://cdn-shop.adafruit.com/640x480/3333-05.jpg)

### Adafruit Circuit Playground Express or Bluefruit Enclosure

[Adafruit Circuit Playground Express or Bluefruit Enclosure](https://www.adafruit.com/product/3915)
We've got nice cases for many of our beloved boards, but the [Circuit Playground Express](https://www.adafruit.com/product/3333)&nbsp;and [Circuit Playground&nbsp;Bluefruit](https://www.adafruit.com/product/4333) has been left out of couture enclosure...

In Stock
[Buy Now](https://www.adafruit.com/product/3915)
[Related Guides to the Product](https://learn.adafruit.com/products/3915/guides)
![Top down view of a clear acrylic Adafruit Circuit Playground Express or Bluefruit Enclosure.](https://cdn-shop.adafruit.com/product-videos/640x480/3915-06.jpg)

### Adafruit CLUE - nRF52840 Express with Bluetooth® LE

[Adafruit CLUE - nRF52840 Express with Bluetooth® LE](https://www.adafruit.com/product/4500)
Do you feel like you just don't have a CLUE? Well, we can help with that - get a CLUE here at Adafruit by picking up this sensor-packed development board. We wanted to build some projects that have a small screen and a lot of sensors. To make it compatible with existing projects, we made...

In Stock
[Buy Now](https://www.adafruit.com/product/4500)
[Related Guides to the Product](https://learn.adafruit.com/products/4500/guides)
![Animated GIF showing CLUE board  displaying data from the many on-board sensors.](https://cdn-shop.adafruit.com/product-videos/640x480/4500-04.jpg)

### USB cable - USB A to Micro-B

[USB cable - USB A to Micro-B](https://www.adafruit.com/product/592)
This here is your standard A to micro-B USB cable, for USB 1.1 or 2.0. Perfect for connecting a PC to your Metro, Feather, Raspberry Pi or other dev-board or microcontroller

Approximately 3 feet / 1 meter long

In Stock
[Buy Now](https://www.adafruit.com/product/592)
[Related Guides to the Product](https://learn.adafruit.com/products/592/guides)
![USB cable - USB A to Micro-B - 3 foot long](https://cdn-shop.adafruit.com/640x480/592-01.jpg)

# No-Touch Hand Wash Timer for Circuit Playground Express and CLUE

## Circuit Playground Express Timer

![](https://cdn-learn.adafruit.com/assets/assets/000/089/820/medium800/makecode_cpxsink.jpg?1585090707)

The Circuit Playground Express (CPX) hand wash timer will be created with MakeCode. If you're new to MakeCode, check out [this guide](https://learn.adafruit.com/makecode) on getting started.

We'll use MakeCode's graphical, block-based interface to create the code that runs on the CPX.

![](https://cdn-learn.adafruit.com/assets/assets/000/089/831/medium800thumb/makecode_wash_sim.jpg?1585150876)

[MakeCode Hand Wash Timer](https://makecode.com/_ToW9ppdgmT1T)
Click the link above to open the MakeCode file -- be sure to use an approved browser, such as Chrome or Edge.

Once you have the code open, click on the Edit button.

![makecode_mc1.png](https://cdn-learn.adafruit.com/assets/assets/000/089/821/medium640/makecode_mc1.png?1585091232)

![](https://cdn-learn.adafruit.com/assets/assets/000/089/808/medium800/makecode_handwashMC.jpg?1585088053)

The key features of the code are the **on start** block, the **on loud sound** block, and the three functions:

- **blink**
- **prep\_countdown**
- **countdown**

## On Start

When the CPX is first powered on or reset, the **on start** block will run. In it we set the NeoPixel **brightness** to **10** , call the **blink** function with arguments of **1** for **color** and **2** for **times** (more on **blink** below).

Then the pixels are turned of and the on-board red LED is turned on by setting the pin **high.**

## On Loud Sound

When a lound sound is detected, the code in the **on loud sound** block runs. This calls the **prep\_countdown** function and the **countdown** function. More on those below.

![makecode_start.png](https://cdn-learn.adafruit.com/assets/assets/000/089/822/medium640/makecode_start.png?1585092141)

## Blink

The **blink** function is called, along with two arguments, **color** and **time.**

The **repeat** loop will iterate however many times it is called, for example the startup loop blink calls it twice.

Inside the repeat, the pixels are first turned off, then after a short pause the color argument is checked -- if it is a **0** then the pixels will be set to **red** , if not, **green**.

This could be expanded to include more colors.

Then, there is a short **pause** and the process repeats, thus creating the blinking pattern.

![makecode_blink.png](https://cdn-learn.adafruit.com/assets/assets/000/089/824/medium640/makecode_blink.png?1585092442)

## Prep Countdown

The **prep\_countdown** function is used to put a certain number of seconds "on the clock" by lighting up the NeoPixels one at a time in a counterclockwise direction. It is called along with an argument of a number of seconds.

The **for index** loop iterates whatever code is contained within it the number of times specified by the **seconds** value. Additionally, the **index** variable's value will start at **0** and increase by one for each iteration through the loop.

On the first ten iterations (0-9) the corresponding NeoPixel will be lit up cyan, thanks to the **if index \< 10** check.

Once **index** is greater than 9, the pixels will loop around the circle a second time, this time being lit up green.

Since the value of **index** will be 10-20 and there are no NeoPixels on the CPX with those values, we need to do a bit of modulo math to loop back around to 0-9 again. That is how the **remainder of index / 10** block is used.

![makecode_prep.png](https://cdn-learn.adafruit.com/assets/assets/000/089/825/medium640/makecode_prep.png?1585092867)

## Countdown

The **countdown** function works similarly to the **prep\_countdown** function, running back from **seconds** to **0,** and with a one second pause between each NeoPixel call.

To run backwards, a variable called **counter** is created, and is set to equal the **seconds** variable minus the **index + 1.** So, for example, **seconds is 20, index is 0** on the first loop through, so **counter = 20 - (0 + 1)** or 19.

For the first ten seconds, **counter \> 10,** so after a one second pause the appropriate pixel is set to magenta for each iteration. Again, a modulo function is used to light the proper NeoPixel.

On the second ten seconds through, the **counter** is less than or equal to ten, so the pixels are set to blue when its their turn.

After the **20** seconds elapse, the whole ring is set to red and blinks red three times to tell you its OK to stop scrubbing!

![makecode_count.png](https://cdn-learn.adafruit.com/assets/assets/000/089/826/medium640/makecode_count.png?1585094058)

# No-Touch Hand Wash Timer for Circuit Playground Express and CLUE

## CLUE Hand Wash Timer

https://youtu.be/z08mbxTqGJo

The CLUE version of this project is a bit more sophisticated than the CPX one, since we have a TFT display to work with and a proximity sensor.

We'll set up the board with CircuitPython and the necessary libraries first, and then code it.

## Setup

First, [follow this guide](https://learn.adafruit.com/adafruit-clue/circuitpython) on getting CircuitPython and the on your CLUE board. Then, [use these instructions](https://learn.adafruit.com/adafruit-clue/clue-circuitpython-libraries) to add the libraries you'll need.

Once you've gotten the board set up, click Download: Project Zip below in the code guide. Expand the .zip file and then drag the two **.bmp** images and the **font** folder to your CLUE's **CIRCUITPY** drive via USB.

Your CLUE's **CIRCUITPY** drive should look like this.

![makecode_washcluelibs.png](https://cdn-learn.adafruit.com/assets/assets/000/090/006/medium640/makecode_washcluelibs.png?1585669538)

## Code

Copy the code from the code-block below and paste it into the Mu editor and save it to your CLUE as **code.py** (or copy **code.py** from the zip file and place on the **CIRCUITPY** drive).

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/CLUE/CLUE_Hand_Wash_Timer/code.py

## What the code is doing

The code does a few fairly simple things. First, we import the necessary libraries.

```python
import time
import board
from adafruit_clue import clue
from adafruit_display_text import label
from adafruit_bitmap_font import bitmap_font
import displayio
import pulseio
```

### Display and Images

Next, we set the display brightness and then use the **clue\_display** commands to set up the **displayio** group that will hold the bitmap images and text.

We then draw both images onto the screen, one on top of the other. (The reason we do this is for speed. By loading both images into memory at startup, it will be fast to later move the top image out of the way to reveal the bottom image.)

```python
clue.display.brightness = 0.8
clue_display = displayio.Group()

# draw the background image
WASH_ON_FILENAME = "wash_on.bmp"

# CircuitPython 6 &amp; 7 compatible
wash_on_file = open(WASH_ON_FILENAME, "rb")
wash_on_bmp = displayio.OnDiskBitmap(wash_on_file)
wash_on_sprite = displayio.TileGrid(
    wash_on_bmp,
    pixel_shader=getattr(wash_on_bmp, 'pixel_shader', displayio.ColorConverter())
)

# # CircuitPython 7+ compatible
# wash_on_bmp = displayio.OnDiskBitmap(WASH_ON_FILENAME)
# wash_on_sprite = displayio.TileGrid(wash_on_bmp, pixel_shader=wash_on_bmp.pixel_shader)

clue_display.append(wash_on_sprite)

# draw the foreground image
WASH_OFF_FILENAME = "wash_off.bmp"

# CircuitPython 6 &amp; 7 compatible
wash_off_file = open(WASH_OFF_FILENAME, "rb")
wash_off_bmp = displayio.OnDiskBitmap(wash_off_file)
wash_off_sprite = displayio.TileGrid(
    wash_off_bmp,
    pixel_shader=getattr(wash_off_bmp, 'pixel_shader', displayio.ColorConverter())
)

# # CircuitPython 7+ compatible
# wash_off_bmp = displayio.OnDiskBitmap(WASH_OFF_FILENAME)
# wash_off_sprite = displayio.TileGrid(wash_off_bmp, pixel_shader=wash_off_bmp.pixel_shader)

clue_display.append(wash_off_sprite)
```

### Text Labels

Then we add groups for each line of text we'll be displaying. This involves specifying bitmap fonts (learn how to make your own [in this guide](https://learn.adafruit.com/custom-fonts-for-pyportal-circuitpython-display)!)

Again, to speed things up later, we'll preload the glyphs (a.k.a., characters) now. Notice that we're loading only the glyphs we intend to use to save time.

We also specify the text to be displayed, the colors, and positions in x/y screen space, and then append each text label to the **text\_group**.

The `clue.display.root_group = clue_display` command finally tells the screen to display the bitmaps and text lines.

```python
# Create text
# first create the group
text_group = displayio.Group()
# Make a label
title_font = bitmap_font.load_font("/font/RacingSansOne-Regular-38.bdf")
title_font.load_glyphs("HandWashTimer".encode('utf-8'))
title_label = label.Label(title_font, text="Hand Wash", color=0x001122)
# Position the label
title_label.x = 10
title_label.y = 16
# Append label to group
text_group.append(title_label)

title2_label = label.Label(title_font, text="Timer", color=0x001122)
# Position the label
title2_label.x = 6
title2_label.y = 52
# Append label to group
text_group.append(title2_label)

timer_font = bitmap_font.load_font("/font/RacingSansOne-Regular-29.bdf")
timer_font.load_glyphs("0123456789ADSWabcdefghijklmnopqrstuvwxyz:!".encode('utf-8'))
timer_label = label.Label(timer_font, text="Wave to start", color=0x4f3ab1)
timer_label.x = 24
timer_label.y = 100
text_group.append(timer_label)

clue_display.append(text_group)
clue.display.root_group = clue_display
```

## Countdown Function

We'll create a separate function called `countdown()` to handle the hand washing countdown process after the CLUE has been triggered.

It will accept an argument for the number of `seconds` you intend, which makes it easier to adjust if you like versus a hard coded value.

The function iterates through a loop for the number of `seconds`, incrementing the value of `i` each time. During each run through this loop it will buzz the buzzer, displaying the scrub time remaining in seconds, pause a second, and repeat.

When the loop finishes the last iteration (20 seconds, say), the **wash\_off.bmp** sprite is moved into place, and the timer label resets to say " **Wave to start**".

```python
def countdown(seconds):
    for i in range(seconds):
        buzzer.duty_cycle = 2**15
        timer_label.text = ("Scrub time:  {}".format(seconds-i))
        buzzer.duty_cycle = 0
        time.sleep(1)
    timer_label.text = ("Done!")
    wash_off_sprite.x = 0
    buzzer.duty_cycle = 2**15
    time.sleep(0.3)
    buzzer.duty_cycle = 0
    timer_label.x = 24
    timer_label.y = 100
    timer_label.text = ("Wave to start")
```

## Buzzer Setup

The buzzer is setup to use the `pulsio()` command and buzz the onboard speaker using a pulse wave modulation signal (PWM) set to a frequency of 1000.

When the `buzzer.duty_cycle = 2**15` we'll hear the buzzing, and when the `duty_cycle = 0` it will stop. These commands are found inside the `countdown()` function.

```python
buzzer = pulseio.PWMOut(board.SPEAKER, variable_frequency=True)
buzzer.frequency = 1000
```

## Main Loop

Finally, we have finished setting things up and can run the main loop.

Here, we'll use `clue.proximity` to check the value of the CLUE's on-board proximity sensor. The value will read 0 when nothing is in front of the sensor. When an object -- such as your hand -- is about 8cm or closer, the sensor will report a value greater than 1 and trip the rest of the conditional statement to run.

In this case, we'll move the timer label to the bottom, replacing the text with " **Scrub Away!**", move the "off" bitmap out of the way to reveal the hand washing "on" bitmap, wait two seconds and then call the `countdown` function for 20 seconds.

```python
while True:
    # print("Distance: {}".format(clue.proximity))  # use to test the sensor
    if clue.proximity &gt; 1:
        timer_label.x = 12
        timer_label.y = 226
        timer_label.text = "Scrub Away!"
        wash_off_sprite.x = 300
        time.sleep(2)
        countdown(20)
```

Now, you can mount the CLUE over your sink, run a USB power cable to it from an outlet, and wash your hands to a stylish timer!

https://youtu.be/_Ui1HS6LiPA


## Featured Products

### Circuit Playground Express

[Circuit Playground Express](https://www.adafruit.com/product/3333)
 **Circuit Playground Express** is the next step towards a perfect introduction to electronics and programming. We've taken the original Circuit Playground Classic and made it even better! Not only did we pack even more sensors in, we also made it even easier to...

In Stock
[Buy Now](https://www.adafruit.com/product/3333)
[Related Guides to the Product](https://learn.adafruit.com/products/3333/guides)
### Adafruit Circuit Playground Express or Bluefruit Enclosure

[Adafruit Circuit Playground Express or Bluefruit Enclosure](https://www.adafruit.com/product/3915)
We've got nice cases for many of our beloved boards, but the [Circuit Playground Express](https://www.adafruit.com/product/3333)&nbsp;and [Circuit Playground&nbsp;Bluefruit](https://www.adafruit.com/product/4333) has been left out of couture enclosure...

In Stock
[Buy Now](https://www.adafruit.com/product/3915)
[Related Guides to the Product](https://learn.adafruit.com/products/3915/guides)
### Adafruit CLUE - nRF52840 Express with Bluetooth® LE

[Adafruit CLUE - nRF52840 Express with Bluetooth® LE](https://www.adafruit.com/product/4500)
Do you feel like you just don't have a CLUE? Well, we can help with that - get a CLUE here at Adafruit by picking up this sensor-packed development board. We wanted to build some projects that have a small screen and a lot of sensors. To make it compatible with existing projects, we made...

In Stock
[Buy Now](https://www.adafruit.com/product/4500)
[Related Guides to the Product](https://learn.adafruit.com/products/4500/guides)
### USB cable - USB A to Micro-B

[USB cable - USB A to Micro-B](https://www.adafruit.com/product/592)
This here is your standard A to micro-B USB cable, for USB 1.1 or 2.0. Perfect for connecting a PC to your Metro, Feather, Raspberry Pi or other dev-board or microcontroller

Approximately 3 feet / 1 meter long

In Stock
[Buy Now](https://www.adafruit.com/product/592)
[Related Guides to the Product](https://learn.adafruit.com/products/592/guides)

## Related Guides

- [Adafruit Circuit Playground Express](https://learn.adafruit.com/adafruit-circuit-playground-express.md)
- [Introducing Adafruit CLUE](https://learn.adafruit.com/adafruit-clue.md)
- [Wind Blowing Emoji Prop](https://learn.adafruit.com/wind-face-emoji.md)
- [CLUE BLE MIDI Glove](https://learn.adafruit.com/clue-midi-glove.md)
- [Drone Claw](https://learn.adafruit.com/drone-claw.md)
- [CircuitPython BLE Libraries on Any Computer](https://learn.adafruit.com/circuitpython-ble-libraries-on-any-computer.md)
- [Drama Piñata](https://learn.adafruit.com/customizable-reusable-pinata.md)
- [Interactive Map with Circuit Playground Express](https://learn.adafruit.com/interactive-map-with-cpx.md)
- [Light Paintbrush with Circuit Playground](https://learn.adafruit.com/lightpaint-cplay.md)
- [Machine Learning with Marshmallows and Tiny Sorter](https://learn.adafruit.com/machine-learning-with-marshmallows-and-tiny-sorter.md)
- [Personal UV HotSpot Parasol](https://learn.adafruit.com/personal-blacklight-uv-parasol.md)
- [Secret Hollow Book Intrusion Detector](https://learn.adafruit.com/secret-hollow-book.md)
- [BLE Thermal "Cat" Printer with CircuitPython](https://learn.adafruit.com/ble-thermal-cat-printer-with-circuitpython.md)
- [Make It Pulse](https://learn.adafruit.com/make-it-pulse.md)
- [Getting Started With Steven Universe](https://learn.adafruit.com/getting-started-with-steven-universe.md)
- [The MonkMakes Plant Monitor and CircuitPython](https://learn.adafruit.com/monkmakes-plant-monitor-and-circuitpython.md)
- [Fireflies with MakeCode](https://learn.adafruit.com/circuit-playground-fireflies-makecode.md)
