# No-Code Counters and Email Reports with Adafruit IO Actions

## Overview

![](https://cdn-learn.adafruit.com/assets/assets/000/137/825/medium800thumb/adafruit_products_VID_20250613_174934_1-ezgif.com-resize.jpg?1750184153)

Ladyada is so busy making exciting new products for us all, that she needs an extra pairs of eyes at her disposal to catch all the things going on that day. Occasionally she doesn't have time for the latest potty training session with her little one... Now that Adafruit IO Actions have new superpowers, she's getting new reports setup to help keep her informed!

Do you want to track as important events are occurring, like your child's potty training progress? Learn the basics of Adafruit IO Actions with this "Potty Training Report" project.

Use Adafruit IO **Actions** to send a scheduled report, control LEDs, count button events / progress and reset the counters each day. Use your existing data feeds or follow this arcade button journey for inspiration.

With a wireless microcontroller running&nbsp;WipperSnapper, Adafruit's no-code platform (an [open source Arduino firmware](https://github.com/adafruit/Adafruit_Wippersnapper_Arduino)) which can easily send data to the cloud, and a couple of buttons to generate events. You'll be firing data to the cloud and getting those daily training reports as quick as a flash.

This project is a great demo for how to use Blockly-based Actions to create full-featured apps that don't require you to write a single line of code or host any services.

## Why WipperSnapper and Adafruit IO Actions?

Adafruit IO can accept data in&nbsp;[many ways](https://learn.adafruit.com/welcome-to-adafruit-io), but there is a special Devices page for easy installation and configuration of WipperSnapper based devices.&nbsp;

It allows [any supported Wireless microcontroller](https://github.com/adafruit/Adafruit_Wippersnapper_Arduino?tab=readme-ov-file#supported-platforms) to easily install the needed software, using the web browser, and then to configure any of over 100 components that may be attached, like sensors and buttons. There's even an automatic configuration option for any onboard components!

As well as accepting data, Adafruit IO can generate data too. Using **Actions**. IO can&nbsp;automatically respond and calculate, or with the [IO+ paid upgrade](https://io.adafruit.com/upgrade) you also gain access to Apple WeatherKit data (and [other benefits](https://io.adafruit.com/plus)).

## Required Parts

In this project a Wi-Fi enabled Raspberry Pi Pico has been used (with headers for no soldering), mounted on a Terminal PiCowbell to give 40 screw terminals along with a reset button and Stemma QT connector!

### Raspberry Pi Pico WH - Pico Wireless with Headers Soldered

[Raspberry Pi Pico WH - Pico Wireless with Headers Soldered](https://www.adafruit.com/product/5544)
The Raspberry Pi foundation changed single-board computing [when they released the Raspberry Pi computer](https://www.raspberrypi.org/archives/723), now they're ready to do the same for microcontrollers with the release of the brand new **Raspberry Pi Pico WH**....

In Stock
[Buy Now](https://www.adafruit.com/product/5544)
[Related Guides to the Product](https://learn.adafruit.com/products/5544/guides)
![Angled shot of green rectangular microcontroller with a Wi-Fi module and pre-soldered headers.](https://cdn-shop.adafruit.com/640x480/5544-02.jpg)

### Adafruit Terminal PiCowbell for Pico with Pre-Soldered Sockets

[Adafruit Terminal PiCowbell for Pico with Pre-Soldered Sockets](https://www.adafruit.com/product/5907)
Ding dong! Hear that? It's the PiCowbell ringing, letting you know that the new **&nbsp;Adafruit Terminal PiCowbell** &nbsp;is finally in stock and ready to assist your&nbsp;[Raspberry Pi Pico](https://www.adafruit.com/product/4864)&nbsp;and&nbsp;<a...></a...>

In Stock
[Buy Now](https://www.adafruit.com/product/5907)
[Related Guides to the Product](https://learn.adafruit.com/products/5907/guides)
![Angled Shot ](https://cdn-shop.adafruit.com/640x480/5907-02.jpg)

For this project you'll want **4x Illuminated Push buttons** , also known as [Arcade Buttons](https://learn.adafruit.com/arcade-buttons) (51mm Square version), and then either solder wires directly to the metal contacts on the arcade button switch units, or use four wires with spade connectors per switch unit.

Info: If you only plan on using the **free tier** of Adafruit IO then you are **limited to ten feeds**. This guide uses 12 feeds, so you could use less Arcade Buttons, like 3 instead of 4, which would remain under the limit.

### Part: LED Illuminated Push Button - 51mm Square Arcade Button
quantity: 4
This 51mm square button is cute, inviting, and ready for all sorts of pressing and pushing
[LED Illuminated Push Button - 51mm Square Arcade Button](https://www.adafruit.com/product/6270)

### Part: Adafruit IO+ Subscription Pass – One Year
quantity: 1
The all-in-one Internet of Things service from Adafruit you know and love is now even better with IO+. The 'plus' stands for MORE STUFF!
[Adafruit IO+ Subscription Pass – One Year](https://www.adafruit.com/product/3792)

Or purchase individual Arcade buttons:

### LED Illuminated Push Button - 51mm Square

[LED Illuminated Push Button - 51mm Square](https://www.adafruit.com/product/6270)
This 51mm square button is cute, inviting, and ready for all sorts of pressing and pushing. We've seen these in some games of skill in arcades. They're easy to mount on nearly any kind of enclosure. They're not...

In Stock
[Buy Now](https://www.adafruit.com/product/6270)
[Related Guides to the Product](https://learn.adafruit.com/products/6270/guides)
![A white hand pressing an index finger on a push-button.](https://cdn-shop.adafruit.com/product-videos/640x480/6270-07.jpg)

If you prefer to not solder wires directly to the metal contacts of the switch unit, use 0.25inch (~6.3mm) sized Spade connectors for the LED connection tabs, and 0.187" (~4.8mm) spade connectors for the button switch tabs, although I found the 6.3mm spades also worked fine for both as the switch tab increases width further back.

Adafruit sells some cables in packs of ten pairs, and you'll need a pair of both sizes for each arcade button.

The JST connectors on the other end are not used and will be cut off, but do offer a quick no-soldering solution. They are designed for the&nbsp;[Arcade button STEMMA QT breakout](https://www.adafruit.com/product/5296) (support coming to WipperSnapper Q4 2025).

### Arcade Button and Switch Quick-Connect Wires - 0.25" (10-pack)

[Arcade Button and Switch Quick-Connect Wires - 0.25" (10-pack)](https://www.adafruit.com/product/3838)
Quick connector wire sets make wiring up our arcade-style or metal buttons quicky-quick. Each wire comes as a 'pair' with two 0.25" quick-connects pre-crimped. The wires are terminated together in a JST 2.5mm 2-pin connector. This connector will fit in 0.1" headers,...

In Stock
[Buy Now](https://www.adafruit.com/product/3838)
[Related Guides to the Product](https://learn.adafruit.com/products/3838/guides)
![Angled shot of ten ~8.5" long quick-connect wire pairs in white and blue. ](https://cdn-shop.adafruit.com/640x480/3838-02.jpg)

### Arcade Button and Switch Quick-Connect Wires - 0.187" (10-pack)

[Arcade Button and Switch Quick-Connect Wires - 0.187" (10-pack)](https://www.adafruit.com/product/3835)
Quick connector wire sets make wiring up our arcade-style or metal buttons quicky-quick. Each wire comes as a 'pair' with two 0.187" quick-connects pre-crimped. The wires are terminated together in a JST 2.5mm 2-pin connector. This connector will fit in 0.1" headers,...

In Stock
[Buy Now](https://www.adafruit.com/product/3835)
[Related Guides to the Product](https://learn.adafruit.com/products/3835/guides)
![Angled shot of Arcade Button and Switch Quick-Connect Wires - 0.187" (10-pack)](https://cdn-shop.adafruit.com/640x480/3835-08.jpg)

# No-Code Counters and Email Reports with Adafruit IO Actions

## Wiring

If you're happy creating your own circuit for the LEDs and button switches, as it's often one of the first things you learn in electronics, then skip over this page. Otherwise read on!

This project uses a lot of wires, so color coding or labelling them can help (tape / pen / colored heat-shrink). It uses&nbsp; **all** of the ground connections available on the Raspberry Pi Pico, but other configurations are possible.

In fact, only one wire on each switch needs careful management: the positive line of the LED, as the LED has a fixed polarity (direction).

First find the LED direction / polarity.

Starting with just one arcade button for now, connect the larger sized (0.25" / 6.3mm) **spade connectors** onto the metal tabs at the two larger sides of the switch unit (marked LED in the image).

![LED connections shown on sides of switch unit, Button connections shown top and front.](https://cdn-learn.adafruit.com/assets/assets/000/137/309/medium640/adafruit_io_components_connections.png?1748893648)

The other ends of the wires need to be cut and stripped (\>2mm), then insert one of the two wires into a ground connection on the board. To make life easier, the back of the Terminal PiCowbell has big white bands labelling the ground connections. Make sure you have undone the screw gate first! Tighten the wire screw gate.

Take the second wire and insert it into the 3.3 volt connection on the Raspberry Pi Pico, and then power the Pico using a USB cable. If the LED is illuminated then you got lucky, otherwise the wires need to be swapped around.

Unplug the board from USB power, and also the LED wire connected to 3.3 volts, then label the two wires you've just identified as positive (3v3) and negative (ground). The button switch connections are not polarised, so the direction doesn't matter, just connect wires to them.

Your arcade buttons switch unit should now have four wires connected, with one of those routed to ground.

Repeat this procedure for four all of the arcade buttons.

## Fritzing Circuit Diagram
![](https://cdn-learn.adafruit.com/assets/assets/000/137/450/medium800/adafruit_io_picowh-arcade-buttons-wired_bb.png?1749639669)

Wire up the circuit as described (shown above). You _can_ vary the pins as they don't need special functionality.

Connect the positive wires for the LEDs to pins GPIO 2 onwards (3, 4, 5) ideally keeping them in button order.

Later, during testing of the lights, it'll be easier to identify which is which again and swap wires if needed.

Turn the Pico Terminal board 180 degrees around so you're now looking at pins GPIO 18-21. It's not necessary, but I found it easier to hold and wire up this way.

Connect the first wire from each of the button switches to GPIO 18 onwards (19, 20, 21).

Finally, wire the remaining four switch wires to ground pins.

Warning: This layout uses the default I2C pins (GPIO 4+5), so use others if you plan to connect I2C devices!

# No-Code Counters and Email Reports with Adafruit IO Actions

## Button Labels and Enclosures

Having light up buttons _without_ custom labels feels like a wasted opportunity, and tying back in with the Potty Training theme, I've used some appropriate Emoji labels (recommended to me 😁) for the buttons.

This project will count number 1's (💦) and number 2's (💩), when nothing came (❌), and "told an adult" (🔔).

Grab your emojis, or images, then paste them in a document or your favourite graphics program. You can copy them from a webpage (they're in the paragraph above) or another page / app.

&nbsp;

You can also hand type emojis! I used the **Windows Key and Period (.)** to bring up the Emoji keyboard ( **Command + Control + Space** on mac), and then searched for the emojis. Try searching for 'sweat', 'poo', 'cross', and 'bell'.

&nbsp;

Issues? Try emailing yourself emojis using your mobile phone, and then copy from the email once back on the computer.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/897/medium640thumb/adafruit_products_XnW8ZYz1UM.jpg?1750291226)

Use a large font size (I used 80pt) and print them out.

&nbsp;

If you find the characters/emojis are not displaying correctly in your software then try changing the font, or switching software.

&nbsp;

You're aiming for images/labels that are a maximum of 37.4mm (1.472" or 1 15/32") width and height, but you can make them with a larger edge and use the inside diffuser piece of the button as a template for cutting.

![Graphics software showing the font dialog, where only the top 3 fonts supported emoji characters when tested.](https://cdn-learn.adafruit.com/assets/assets/000/137/354/medium640/adafruit_io_CJSuWAYiKA.png?1749162474)

Simple printed paper works fine, as do sticky labels, but transparent versions might block less light.&nbsp;  
I've used whole A4 or Letter sheet sized labels suitable for inkjet printers and added some extra emojis for later projects.

## Assembling the Buttons
Read the guide (linked below) for details on how to safely remove the button from it's case.

I **used a plastic dental spatula (like a spudger) to help the clips over the inner lip, and to then carefully split the inner button to remove the transparent lid and reveal the label location.**

**Place the label into the transparent button lid** , or apply the sticker to the inner button light diffuser (with the domed back side, resting on the tweezers in this image), then reassemble the arcade button.&nbsp;

It can a be a tight fit if the label is poorly trimmed, so use a moderate amount of force if needed. It will then be extra hard to remove again, but not impossible if you carefully lift from the corners.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/357/medium640/adafruit_io_IMG_20250606_010655_871_%28Custom%29.jpg?1749169746)

If you need a bit of help with assembly and disassembly of the buttons, then check this guide dedicated to Arcade Buttons:

### Arcade Buttons - Disassembly 

[Arcade Buttons](https://learn.adafruit.com/arcade-buttons)
[Disassembly ](https://learn.adafruit.com/arcade-buttons/disassembly)
## Make a case - 3D Print / Laser cut / Drill

If you're making your own case then you'll need to mark out a template for the holes to cut, or use CAD.

The arcade buttons have two nubs / pegs approximately 4 mm in diameter and 42 mm from furthest edge to furthest edge (38 mm center to center). They stop the button being rotated, but can be cut off.

Then you need a 26mm hole for the big screw thread, or 23.5-24 mm with a chamfered edge at the front.

&nbsp;

The spade terminals add a few extra millimeters to an already deep bolt and switch unit, approximately 60mm from the back of the button to the end of the spade plus a sharply bent (almost 90 degree) wire.

While reassembling later (after dealing with mounting to the wall), it may be easier to remove one or two spade connectors that are close to the struts.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/361/medium640/adafruit_io_IMG_20250606_052746_557_%28Custom%29.jpg?1749184407)

![](https://cdn-learn.adafruit.com/assets/assets/000/137/431/medium640/adafruit_io_k1ndoFmEKn.png?1749589228)

![](https://cdn-learn.adafruit.com/assets/assets/000/137/445/medium640/adafruit_io_IMG_20250610_180405_529_%28Custom%29.jpg?1749594100)

 **Prototyping is important** , as it's a risky idea to assume everything will work out perfectly first attempt.

A friend and I had great fun testing a single button version of the potty trainer. It's top is too flexible, although that is still strangely enjoyable!

Initially I used the laser cutter, due to its rapid speed, to see how the fit and spacing felt. A quick project box followed, with top plate for hygiene reasons.

Switching back to PETG for 3D printing, and using a Brim for support, the case prints on it's side for maximum strength **,** with the Terminal PiCowbell clips closest to the bed. I printed with a 0.6mm nozzle.

Here is the 3D model in STL format, oriented correctly:

![](https://cdn-learn.adafruit.com/assets/assets/000/137/434/medium640thumb/adafruit_io_IMG_20250610_174737_7-ezgif.com-crop.jpg?1749590037)

![](https://cdn-learn.adafruit.com/assets/assets/000/137/441/medium640/adafruit_io_IMG_20250610_225741_978_%28Custom%29.jpg?1749592787)

![](https://cdn-learn.adafruit.com/assets/assets/000/137/433/medium640/adafruit_io_iE1CNROpOe.png?1749589884)

[Potty Training Arcade Button Assembly.stl](https://cdn-learn.adafruit.com/assets/assets/000/137/440/original/Potty_Training_Arcade_Button_Assembly.stl?1749592287)
My first clips for the Terminal PiCowbell worked well, but self-destructed in the CAD model when I moved them.

It's important to be thoughtful about relative references in parametric CAD designs. Use offset planes and variables based on other dimensions if possible.

The second version now works when the PiCowbell is moved in the design, but I initially forgot the offset for easy insertion. Now it has that satisfying ease and a good snap into place.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/446/medium640thumb/adafruit_io_IMG_20250610_234158_3.jpg?1749595416)

You can&nbsp;[modify the model configuration](https://cad.onshape.com/documents/ebe81d707319c1643471acd4/w/0709122f62153637ef0157a9/e/b373fbccec6550052c3fa22a?renderMode=0&uiState=6848a831f172846f39f5980d), but you'll need to setup an OnShape account (free for public designs).

## Attaching to the wall

_Listen_ when **Ladyada** says something! She told me under no circumstances use double sided tape for the project, as people have so many problems with poor quality tape or humidity affecting stickiness.&nbsp;

It's quite a heavy project to be sticking on the bathroom wall, so Ladyada suggested using&nbsp; **strong magnetic strips** , or magnetic tape, instead of risking it with double-sided tape.

Using the magnet strips is a great idea as they are really easy to apply and super strong, while also being removable!

They usually arrive in pairs, magnetically attracted to each other, with sticky on the back sides.

Simply leave the two magnetic strips attracted together with the sticky side on the outside / backs, then remove one piece of backing paper and stick that side to the project enclosure.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/421/medium640/adafruit_io_IMG_20250610_180952_828_%28Custom%29.jpg?1749582669)

Locate the first pair of strips at the top edge of the back side.

Use a second pair too, along the bottom edge this time.

Leaving the backing paper in place is a good idea until final installation.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/423/medium640/adafruit_io_IMG_20250610_181215_478_%28Custom%29.jpg?1749582384)

Now bring your project into the final installation location. Remember that this project is only splash resistant, so should be positioned accordingly. Remove the remaining backing paper, and stick the project to the wall.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/425/medium800/adafruit_io_IMG_20250610_181629_113_%28Custom%29.jpg?1749582122 Yay, project successfully stuck to the wall🥳 Remember it's only splash resistant!)

Apply a good amount of force and squidging where the sticky magnetic strips are located. I like to imagine squeezing bubbles out of the newly applied sticky magnetic tape. I also removed the wiring first!

Leave it for a minute or so before testing the removal.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/426/medium800/adafruit_io_IMG_20250610_182038_146_%28Custom%29.jpg?1749582037 Enclosure safely removed after the magnetic strips had a moment to cure)

Info: If you're in rented accommodation then you'll need to remove the sticky magnetic strip eventually, but don't worry as there is a Sticker Removal spray which can make a light job of such things.

After you're done potty training, the same enclosure can be turned on its back, some grippy feet attached, and you have a wonderful table-top button console! Why not try CircuitPython and [make a custom controller](https://learn.adafruit.com/qtpy-lemon-mechanical-keypad-macropad)!

![](https://cdn-learn.adafruit.com/assets/assets/000/137/435/medium800/adafruit_io_IMG_20250610_222627_542_%28Custom%29.jpg?1749590857)

# No-Code Counters and Email Reports with Adafruit IO Actions

## WipperSnapper Setup

Installing [WipperSnapper](https://learn.adafruit.com/quickstart-adafruit-io-wippersnapper) should be a quick and easy process, but it's still under development so [tell us](https://io.adafruit.com/support) if you run into issues. If you know how to use a Serial Monitor, the device spits out useful info over the serial port!

Head to the [**Devices**](https://io.adafruit.com/devices) page on Adafruit IO, and click the **New Device** button.

Select your board from the list of compatible boards, then follow the instructions to get the software and secrets (WiFi and Adafruit IO credentials) copied to your board.

Using a Chromium based browser works best with the web installer (Chrome / Edge), but local installation using UF2 files (or esptool) is supported too!

If your board isn't listed in the board selector then you can request support by&nbsp;[creating an issue on GitHub](https://github.com/adafruit/Wippersnapper_Boards/issues/new?template=board-request.md) (or just try the most compatible looking boards by chipset and pin count).

![Arrow pointed at the New Device button on the Adafruit IO Devices page](https://cdn-learn.adafruit.com/assets/assets/000/137/528/medium640/wippersnapper_setup__project_guides_page__adafruit_io_Z1h7LUJkfk.png?1749675779)

![A search box in the new device page shows Pico, then three boards are visible with an arrow pointing to the Raspberry Pi Pico W](https://cdn-learn.adafruit.com/assets/assets/000/137/530/medium640/wippersnapper_setup__project_guides_page__adafruit_io_d3khbzSlFN.png?1749675832)

After installation and copying the secrets (not required for boards without USB Mass storage device support), the board should reboot itself.

If not then reset it manually (using a reset button or by reconnecting power).

Make sure you have an Adafruit IO webpage open, as it's required to receive the Registration message, and then name the device once it connects.

If you missed this registration / board naming step, don't worry, just reset the board and try again.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/537/medium640/wippersnapper_setup__project_guides_page__adafruit_io_Screenshot_2025-06-11_164648.png?1749676110)

![](https://cdn-learn.adafruit.com/assets/assets/000/137/538/medium640/wippersnapper_setup__project_guides_page__adafruit_io_qWK9akM1Bg.png?1749676175)

After registration you're taken to the Device page for the newly registered board. From here you can view the Online Status, WipperSnapper version installed, previous connection events, and any components you've added to the device. There is also a Settings button to change the device name, or delete the device (and data).

![](https://cdn-learn.adafruit.com/assets/assets/000/137/541/medium800/wippersnapper_setup__project_guides_page__adafruit_io_393HTOB2EK.png?1749676309)

Info: To learn more about using WipperSnapper with your board, and "uninstalling" WipperSnapper (replace with Arduino blink sketch or CircuitPython), find the WipperSnapper page on your board's Learn Guide by using the Docs link beneath it's online status. It'll be similar to [this one for the ESP32-S2 feather](https://learn.adafruit.com/adafruit-esp32-s2-feather/wippersnapper-setup#uninstalling-wippersnapper-3121738)

&nbsp;

Adding components is a simple process, click&nbsp;`+` or the **New Component** button, then search for the component you're looking for.

The search isn't perfect, so in addition to searching for the name or family, try other similar words, the type of data, the I2C address, or the categories like `PWM`,&nbsp;`analog`,&nbsp;`i2c`,&nbsp;`uart`,&nbsp;`pin`,&nbsp;`digitalio`.

You'll then be asked to configure any options for your component, such as pin/address, brightness, any pull-up resistors, or at least the name.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/544/medium640/wippersnapper_setup__project_guides_page__adafruit_io_11g7uxrXBc.png?1749677859)

![](https://cdn-learn.adafruit.com/assets/assets/000/137/545/medium640/wippersnapper_setup__project_guides_page__adafruit_io_fBABS2UD7r.png?1749677889)

![](https://cdn-learn.adafruit.com/assets/assets/000/137/546/medium640/wippersnapper_setup__project_guides_page__FnadwyI4qW.png?1749678081)

Each new component has it's own row, and an automatically associated data [Feed](https://learn.adafruit.com/adafruit-io-basics-feeds/overview), one per data type (e.g. temperature + humidity).

It's worth noting that some **additional display related options** are present in the **component settings** after creation, like the on/off state labels and icons for buttons.

The components feed page is linked via the **Graph icon** at the end of the row, next to the component's **Settings cog icon**.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/549/medium640/wippersnapper_setup__project_guides_page__RCO8fWiHu1.png?1749683853)

![](https://cdn-learn.adafruit.com/assets/assets/000/137/550/medium640/wippersnapper_setup__project_guides_page__DLXz1D3Vlq.png?1749683912)

Once you've configured a device, you can&nbsp; **Export** the configuration so it can be shared or easily recreated / duplicated.

There's a complimentary&nbsp; **Import** config option too, and if the board doesn't match, or component addresses are in use, then you may be asked to unselect those incompatible components before import.

Almost all boards have some built in components, like an on-board LED, NeoPixel, or boot button.

Most of these are useable by WipperSnapper, and can be automatically setup using the **Auto-Config** button, then **Magic Configuration**.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/578/medium640thumb/wippersnapper_setup__project_guides_page__adafruit_io_chrome_fqiyeTH3Mw_1.jpg?1749740066)

## Configure Project Components

You need to add&nbsp; **eight&nbsp;** components to your new device. Each Arcade Button needs setting up as a&nbsp; **button&nbsp;** component with a&nbsp; **pull-up resistor** , with an additional component for each button LED (pick dimmable LEDs although setting them up as normal LEDs is also fine). You can do this really easily by importing a config file!

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Adafruit_IO_Template_Emails/rpi-pico-w-potty-training.json

Use this configuration file to easily import all the needed components for this project, the four buttons plus their dimmable LEDs. Find the&nbsp; **Import** &nbsp;button by using the&nbsp; **Auto-Config** &nbsp;button on the device page.

If you'd prefer to set the components up manually, then have a look at the&nbsp; **Usage page** &nbsp;of the&nbsp; **Quick Start Guide for Using The Raspberry Pi Pico With WipperSnapper** &nbsp;which covers most types of components:

### Quick Start: Pico W / 2W with WipperSnapper - Usage

[Quick Start: Pico W / 2W with WipperSnapper](https://learn.adafruit.com/quick-start-the-pico-w-with-wippersnapper)
[Usage](https://learn.adafruit.com/quick-start-the-pico-w-with-wippersnapper/usage)
After setting up the components, they can be configured further using the&nbsp; **Settings cog** &nbsp;at the end of the row.

You can view the feed page and data associated with each component by clicking the **Graph icon** there too.

Before continuing on to create your Actions, ensure you're device page looks similar to the image below, with all four buttons and dimmable LEDs configured.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/583/medium800/adafruit_io_vV1y0FPatr.png?1749741508)

# No-Code Counters and Email Reports with Adafruit IO Actions

## Create Adafruit IO Actions

In this project, you'll create a whole bunch of actions, but don't worry, it's only three plus a bit of repetition:

- When the first button is pressed, turn on the LED, and increase the first "Counter" feed by 1
- When the first button is pressed, delay a few seconds (3), then turn the LED off.
- Repeat previous two actions for remaining buttons (each with their own counter feed)
- At a scheduled time each day, collect the counter feeds and use in an email template, then reset.

Hopefully that doesn't sound too complex, and it's worth noting you can do similar with any data on Adafruit IO.

## Create the Counter feeds

When counting things on Adafruit IO you'll need somewhere to store that count. It's possible to use a variable as a temporary count holder, but variables only live inside the action briefly as that action executes, and are then destroyed again. Alternatively using another Feed is a more permanent storage option.

As you'll want to interact with the counter from more than one action it needs to be stored in a Feed.

**Go to the [Feeds page](https://io.adafruit.com/feeds)**

Use the&nbsp; **New Feed** &nbsp;button, and then enter a memorable&nbsp; **Name&nbsp;** for the feed (the only restriction is length). I've used **"💩 Poo Counter"** as the name, which gives me a feed key of `poo-counter`.

&nbsp;

The new feed will show up in the Default group at the top of the feeds list (which I've renamed to "My Feeds").

&nbsp;

Repeat the process to create the remaining counter feeds (one per button). For simplicity name them&nbsp;`wee-counter`,&nbsp;`nothing-counter`, and&nbsp;`informed-counter`.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/362/medium640/adafruit_io_arrow_Screenshot_2025-06-06_141617.png?1749215911)

Initially the feeds have no data, which will cause errors to display during the first run of the email template. If you'd prefer you can go and manually add data to the counter feeds (like zero, or some other test number).

## Add a new Action

Start by visiting the [Actions page](https://io.adafruit.com/actions) using the link in the navigation menu, where you'll see a list of your actions.&nbsp;  
It shows their names, descriptions, enabled status, and an information icon button with more details.

Click the **New Action** button, enter a suitable name and optional description, e.g. "Button #1 pressed - increase counter", then submit.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/334/medium800/adafruit_io_image.png?1749018151)

You'll be brought to the new Action page and see a workspace in the centre with a single "root block" and toolbox.&nbsp;

&nbsp;

It's a diagram based "programming" tool, similar to other low-code/no-code platforms.

&nbsp;

There is a toolbox and a main workspace area where you compose your Action, attaching blocks to the **root block** to form your idea.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/488/medium640/adafruit_io_uRgxD1eOPO.png?1749660808)

## Triggers and Cooldowns

The root block has a `Triggers:` section that defines the different events which can trigger the action. You can use multiple if you like, and the action will fire when _any_ of the triggers match their condition (schedule or data).

The root block also has a **Settings button** (an icon with a grey cog in blue background), used for configuring delayed execution (which can also optionally reset existing delays to create a dead man's switch / fail-safe).

The other crucial bit of information is about **cooldown periods**. After a trigger matches, and then the action is executed, a cooldown period is activated (currently five seconds) during which all triggers are ignored.

## Create Actions for the Arcade Buttons
Start by opening the Triggers category in the toolbox, and pick the trigger that says&nbsp;`When FEED receives data that STARTS matching = 0`.

Drag and drop it onto the&nbsp;`Triggers:` section of the root block, making sure to line up the puzzle piece edges (the notches and tabs) until the root block shows a yellow highlight.

Then to configure the block, use the Feed selector drop-down menu to select the first button Feed.

Next leave the comparison&nbsp; **Operator** selected on equals, and set the Value to `1`.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/489/medium640thumb/adafruit_io_chrome_UK3rOJo8rO-ezgif.com-optimize.jpg?1749661005)

Great, that's the trigger done. Now onto the `Actions:` section of the root block, where you'll select the "doing" blocks for your action.

Start with a **Set Feed** block from the Feeds category in the toolbox, drag + drop it into the&nbsp;`Actions:` section.

&nbsp;

Select the first buttons LED feed from the Feed selection drop-down.

&nbsp;

Enter the value&nbsp;`1` into the Set Feed blocks value textbox.

&nbsp;

If using a Dimmable LED component, instead of plain LED, then use the value `255` for max brightness.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/492/medium640thumb/adafruit_io_chrome_DSdf6FvxKA-ezgif.com-optimize.jpg?1749662030)

Next you'll be setting the first button's **counter feed** to increase, using the **Set** / **Get Feed** blocks and a block from the Maths category of the toolbox.

Start by grabbing a **Set Feed** block and dropping it beneath the previous one.

Select the appropriate counter feed created earlier in the Set Feed blocks feed selector drop-down menu.

Now go to the Maths category in the toolbox, and grab the block that shows the plus/addition operator, then place that maths block into the Value section of the Set Feed block you've just placed.

Enter the value `1` into one of the two value text boxes inside the Maths block, and leave the operator as Plus (+).

Now grab a **Get Feed Value** block from the Feeds toolbox category, and finally drop it into the remaining value box of the maths block just placed.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/493/medium640thumb/adafruit_io_chrome_cIEFe3ErQv.jpg?1749662367)

Your action should look like this before continuing. Save the action, and choose enable if asked.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/499/medium800/adafruit_io_zrS8xfQZkM.png?1749663247)

For the next action, to turn off the LED again, it's nearly identical to the first steps of the last one. The only difference is related to delayed execution, which you can configure using the root blocks Settings dialog.

Create a new action, called something like "#1 Button - LED off after 3seconds".

Setup the same trigger as before, **When&nbsp;`Button 1` receives a value that `Starts` matching `= 1`.**

Use the same **Set Feed** block to change the `#1 Button LED` feed value to&nbsp;`0`.

Now comes the interesting part, setting the delay for the Action.

Start by clicking the grey settings cog on the root block, and a new dialog opens, it's like a mini Blockly workspace just for configuring the delay options.

Drag the block for&nbsp;`1 Seconds` over to the right-hand side (the mini workspace area), to replace `No Delay`.

Pick an appropriate amount of time in the drop-down menu for the seconds, like `3`.

Finally close the delay settings dialog by clicking on the same settings cog again.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/498/medium640thumb/adafruit_io_chrome_V6c2tY0Q4I.jpg?1749663281)

You action should look like this, and can now be saved.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/496/medium800/adafruit_io_image.png?1749662989)

Repeat the previous two actions for each of the remaining buttons, using their dedicated LED + Counter feeds.

Before continuing, double check that the Actions page now shows the 8 Actions just created, enabled in the list.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/500/medium800/adafruit_io_xS7NmKmXzR.png?1749664259)

On the next page you'll create the Action to send the scheduled email report, and then on the subsequent page learn about templates and the specifics for this project.

# No-Code Counters and Email Reports with Adafruit IO Actions

## Email Action with Variables

An action needs a trigger. Let's use the **Schedule** trigger block to activate daily at 20:15.

 **Drag the Schedule block from the Triggers category of the toolbox** , snapping it into place inside the `Triggers:` section of the root block.

&nbsp;

Use the **Settings cog** (grey cog in blue background) for each of the Schedule block's time and date segments **to build the schedule**.

&nbsp;

Change the month and day segments to&nbsp; **Every Day** and **Every Month** , and the hour and minute segments to suitable time values like 8:15 PM.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/502/medium640thumb/adafruit_io_chrome_hNpYCSmAQp.jpg?1749665705)

That's the trigger section done! Now you'll setup the rest of the action, but with no explanation of the template. This is to save overcomplicating things in one mega page, instead you'll learn about templates afterwards.

## Variables
Before adding the email block to the `Actions:` section of the workspace you'll create some variables, doing some seemingly pointless maths to make it easier to be referred to later in the email body. This is for two reasons, firstly because all data in Adafruit IO is effectively stored as text strings, explained later on the next page.

Secondly, it&nbsp;_is_ possible to use feed values directly in templates as you'll see later, but crucially the **feed has to be _used_ in a block,** somewhere in the action, to then be available for templates.

There are a few things in the template that could also be calculated as variables first, like total events.  
The example template calculates everything in the template, unwisely, just to show how it can be done.

Start by creating a new variable using the button at the top of the&nbsp; **Variables&nbsp;** category in the toolbox.

&nbsp;

Call it `poo_progress`, then create the remaining 3 variables,&nbsp;`wee_progress`,&nbsp;`nothing_progress`&nbsp;and&nbsp;`informed_progress`.

&nbsp;

Drag a **Set Variable** block into the main `Actions:` section of the workspace diagram, and select the variable.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/763/medium640thumb/adafruit_io_ezgif.com-optimize.jpg?1750086991)

Grab one of the Addition blocks from the Maths category in the toolbox, and drop it into the value section of the Set Variable block. Leave the operator as plus / addition (`+`), and the values untouched at zero.

&nbsp;

Use the **Get Feed** block from the Feeds category, and drop into one of the the value sections of the Maths block.&nbsp;

&nbsp;

Select the feed for the first counter (e.g. `poo_counter`) from the feeds dropdown in the Get Feed block.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/617/medium640thumb/adafruit_io_chrome_JZnR7A7KlQ.jpg?1749771689)

Now grab a second Set Variable block and drop it beneath the first, selecting the `wee_progress` variable, and add the maths and feed blocks for the associated counter feed `wee-counter`.

Repeat this process for the remaining counter feeds, at which point your action should look like this:

![](https://cdn-learn.adafruit.com/assets/assets/000/137/820/medium800/adafruit_io_image.png?1750182354)

Next it's time to reset the counter feeds. You'll use the Set Feed block to set the counter values to zero.

Start by adding a **Set Feed** block beneath the previous blocks, then select the&nbsp;`poo-counter` feed from the dropdown, setting the value to `0`.

Repeat for the remaining counter feeds. Your action should look like this before continuing:

![](https://cdn-learn.adafruit.com/assets/assets/000/137/821/medium800/adafruit_io_image.png?1750182429)

Add an **Email block** from the **Notifications** category in the toolbox. Enter a subject for the email.

From the Text toolbox category select the Template block (with the `{{` label) and drop it into the value section of the second Set Variable block.

Update the Template's child **Paragraph** text block, by clicking inside it and updating the value to use the following template body text. Then click outside the text area to finish setting the block content.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Adafruit_IO_Template_Emails/template.liquid

Before continuing, your action should now look nearly identical to this:

![](https://cdn-learn.adafruit.com/assets/assets/000/137/822/medium800/adafruit_io_image.png?1750182493)

Warning: Templates are so new that we're still getting the error messaging and validation sorted, so for now if your template has a serious error then it just won't product any output (no new entry in Previous Runs).

 **Save and Run** &nbsp;the action, then check your email for the sample report, it should look something like this:

![](https://cdn-learn.adafruit.com/assets/assets/000/137/472/medium800/adafruit_io_pEAhIQO6bJ.png?1749655634)

Now head on over to the final page to learn more about the template, and how you can craft your own!

# No-Code Counters and Email Reports with Adafruit IO Actions

## "Liquid" Templates

Templates in Adafruit IO Actions are done using the Liquid templating language. It has built in support for some helper functions, or "filters" as they are known in liquid parlance.

All template blocks require a child block to be attached, with either a text string block, or paragraph block, or something else text compatible (like a Get Feed value block).

Every line in the template gets whitespace (line-breaks) at the end of it, but that can be prevented by adding the dash (`-`) syntax to any placeholders (`{{- placeholder -}}`) or commands (`{%- assign t = vars.now -%}`).&nbsp;

It can be used to trim / collapse the whitespace from just the beginning, or end, or both. For example `{{ vars.now }}` prints the time with a newline afterwards, but using `{{- vars.now -}}` removes whitespace before and afterwards. Alternatively` {{ vars.now -}}` would just remove from the end.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/515/medium800/adafruit_io_NtJndUnrYA.png?1749667413 Log blocks showing the template placeholder values for {{user}}, {{vars}}, and {{feeds}})

Using feed values as part of a template allows you to easily add units and symbols, or display messages, to dramatically improve the user experience. Templates can be used in place of text values for any of the blocks.

The classic example is to add a prefix and suffix for a dashboard label, or sending an email report, to yourself, based on some triggering condition (reacting to incoming data) or schedule.

There are a few built-in Adafruit IO custom template "placeholders". These allow easy insertion of the user related properties (like name) using `{{ user }}`, variables created inside the action using&nbsp;`{{ vars }}`, and any feeds used in the action under `{{ feeds }}`. Of course the variable must be set before use in a template.

Accessing the sub-properties of these placeholders is done with the dot-notation, e.g.&nbsp;`{{ user.name }}`, or square bracket indexing / accessors like python uses, e.g.&nbsp;`{{ user["name"] }}`.

Bracket notation is preferred, as it supports any properties with unusual characters (like dots `.` and spaces).

For the `feeds` placeholder, you access each feed as a sub-property using the feed key (dash separated lowercase), e.g. a feed called Feed-Key in a group named Group-Key would be `feeds["group-key.feed-key"]`

Then you want to access the sub-property&nbsp;`.value`, or another like `name`, `last_value`, `updated_at`, etc.  
e.g. `{{ feeds["group-key.feed-key"].value }}` would be replaced with the feed value inside a template.

The feed key can be found using the URL when visiting the feed page, or using the feed info button, or lastly by logging/emailing the value of `{{ feeds }}`. See this guide on Editing Feeds for details on feed keys:

[https://learn.adafruit.com/adafruit-io-basics-feeds/editing-a-feed](https://learn.adafruit.com/adafruit-io-basics-feeds/editing-a-feed)

With templates referring to feed values the syntax can become very long and almost unreadable, but you can help yourself by creating variables first from the needed feeds, and then refer to the variables instead.

## Using Filters and basic logic in Liquid templates

Spend a few minutes reading about basic usage and the list of filters on the official Liquid help documentation:

[Liquid template docs](https://shopify.github.io/liquid/)
The template uses a couple of filters to do some basic arithmetic (`plus:`), repeating characters using `for`-loops (based on the counter value), and printing phrases of encouragement based on certain `if` conditions.

Filters are quite simple at their most basic usage level, and chained together using Pipes (vertical bar `|`), for example to make your name a lowercase version: `{{ user.name | downcase }}`&nbsp; [[Docs for downcase]](https://shopify.github.io/liquid/filters/downcase/)

The idea for this template was to repeat an emoji the same number of times as the counter, as a sort of bar graph / progress indicator. With a small nearly-identical section of the email template for each of the counters.

Finally the template totals all the events recorded by the counters, along with a hypothetical success rate. Then based on some predefined ranges, gives an appropriate summary and phrase of encouragement. Of course after the daily report is sent the counters should be reset to zero.

Some of these might be clearer if calculated as variables first, like total events, and then used in the template.  
The example template calculates everything in the template, unwisely, just to show how it can be done.

Primary: If you've not read the previous pages, and seen the [template contents](https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Adafruit_IO_Template_Emails/template.liquid), then know that there are 4 counters stored in feeds. Those feed values have been placed into Variable blocks, and then a daily summary report is emailed, composed from the sections below.

## Explaining the sections of the template
The first piece of the template matching the counter for button 1 (did a wee) has two simple bits, print the value, then repeat emoji X times.

`🚽 Successful Wees: {{ vars["wee_progress"] }} {% for i in (1..(vars["wee_progress"])) %}💧{% endfor %} `

Here you can probably tell that the first line outputs the current value of the variable, and the second line repeats the character 💧 up to the number of times in the variable's value with a " **for i = 1 to X, repeat** 💧".

If you want to have a summary phrase in each section of the report, then you can add lines like these too:

`{% if vars.wee_progress == 0 %}Slow progress is still progress, keep that encouraging reinforcement going!{% elsif vars.wee_progress <= 2 %}Getting the hang of this, keep up the amazing work! 🎯{% else %}SUPERSTAR ALERT! 🌟 Absolutely crushing it! You've got a potty champion! 🏆{% endif %}`

This section is then repeated for the remaining progress variables, with slightly different phrases & thresholds.

You'll no doubt notice that the template is doing numeric comparison of the variables (that you added zero to).

All feed data on Adafruit IO is stored as strings (text encased in speech marks). We previously did a bit of automatic conversion in some places, but now with the new Actions we leave the power (and complexity) in your hands...

Having all data as text strings is normally fine to use in templates, however if doing comparisons it gets tricky, but there are a couple of methods for converting (casting) text data to numerical data instead.

Firstly, Maths blocks in the toolbox allow you to manipulate numbers, automatically casting strings, so use `+ 0`.

Secondly, liquid templates support [their own form of variables](https://shopify.github.io/liquid/tags/variable/), both capturing and assigning, using the syntax&nbsp;`{% capture name %}value{% endcapture %}`(captured as strings), and&nbsp;`{% assign name = value %}`. Some maths filters convert text strings automatically, like `plus:`, as does the range syntax `(1..number)` used in the template.

This template uses `capture` for a few extra template variables, calculating the total tries versus successes, creating a percentage bar of success from repeating ASCII greyscale characters.

![](https://cdn-learn.adafruit.com/assets/assets/000/137/457/medium800/adafruit_io_5OwkaSK7Mi.png?1749650142)

Then finally, the **total\_events** is divided by 3 and the remainder then assigned to **event\_mod** using `| modulo: 3`. The last phrase is conditional based on the remainder in **event\_mod** , a bit like "Quote of the Day".

![](https://cdn-learn.adafruit.com/assets/assets/000/137/455/medium800/adafruit_io_C9IjTbxs0o.png?1749642782)

Now imagine if you will, saving the value of **total\_events** and **successes** , to new feeds, using Variables for the templated values, then the Set Feed block. You could even have total\_events\_last\_week, 2weeks ago, etc.

Your report could include your sensor data or weather data too, maybe that dramatically impacts productivity...

Then with weekly, monthly, etc, hopefully your mind also begins to play with other non potty ideas...

Remember that you get all sorts of benefits with [IO Plus](https://io.adafruit.com/plus), like unlimited feeds and devices! And don't forget to checkout the Weather block, exposing the full Apple® WeatherKit data for your [added locations](https://io.adafruit.com/services/weather).

## A Real Liquid Template Debugger

If you wish to experiment with liquid templates in a more constructive environment, then try this online liquid template editor and debugger (I've included the variables with the template for easier testing):

[Liquid Template in Editor](https://liquidjs.com/playground.html#PGI+8J+MnyBEYWlseSBQb3R0eSBUcmFpbmluZyBSZXBvcnQg8J+MnzwvYj4NCkhpIHRoZXJlISBIZXJlJ3MgaG93IG91ciBsaXR0bGUgc3VwZXJzdGFyIGRpZDoNCi0tLQ0KPGI+8J+avSBTdWNjZXNzZnVsIFdlZXM6IHt7IHZhcnMud2VlX3Byb2dyZXNzIH19PC9iPg0KeyUgZm9yIGkgaW4gKDEuLnZhcnMud2VlX3Byb2dyZXNzKSAlffCfkqd7JSBlbmRmb3IgJX0NCnslIGlmIHZhcnMud2VlX3Byb2dyZXNzIDw9IDUgLSV9DQpHcmVhdCBzdGFydCEgRXZlcnkgc3VjY2VzcyBjb3VudHMsIGFuZCB0aGV5J3JlIGJ1aWxkaW5nIGdvb2QgaGFiaXRzIG9uZSB3ZWUgYXQgYSB0aW1lISDwn4yxDQp7JSBlbHNpZiB2YXJzLndlZV9wcm9ncmVzcyA8PSAxNSAtJX0NCkZhbnRhc3RpYyBwcm9ncmVzcyEgVGhleSdyZSByZWFsbHkgZ2V0dGluZyB0aGUgaGFuZyBvZiB0aGlzIC0ga2VlcCB1cCB0aGUgYW1hemluZyB3b3JrISDwn46vDQp7JSBlbHNlIC0lfQ0KU1VQRVJTVEFSIEFMRVJUISDwn4yfIEFic29sdXRlbHkgY3J1c2hpbmcgaXQgd2l0aCB0aG9zZSB3ZWUgc3VjY2Vzc2VzISBUaGV5J3JlIGEgcG90dHkgY2hhbXBpb24hIPCfj4YNCnslIGVuZGlmICV9LS0tDQoNCjxiPvCfkqkgU3VjY2Vzc2Z1bCBQb29zOiB7eyB2YXJzLnBvb19wcm9ncmVzcyB9fTwvYj4NCnslIGZvciBpIGluICgxLi52YXJzLnBvb19wcm9ncmVzcykgJX3wn5+keyUgZW5kZm9yICV9DQp7JSBpZiB2YXJzLnBvb19wcm9ncmVzcyA9PSAwIC0lfQ0KUG9vcyBjYW4gYmUgdHJpY2t5LCBidXQgdGhleSdyZSBiZWluZyBzbyBicmF2ZSEgRXZlcnkgdHJ5IGlzIGEgc3RlcCBmb3J3YXJkISDwn5KqDQp7JSBlbHNpZiB2YXJzLnBvb19wcm9ncmVzcyA8IDIgLSV9DQpMb29rIGF0IHRoZW0gZ28hIFRoZXkncmUgYmVjb21pbmcgYSByZWFsIHBvbyBwcm8gLSB0aGF0J3MgYXdlc29tZSBwcm9ncmVzcyEg8J+OiQ0KeyUgZWxzZSAtJX0NClBPTyBDSEFNUElPTiEg8J+PhSBUaGV5J3ZlIG1hc3RlcmVkIG9uZSBvZiB0aGUgdHJpY2tpZXN0IHBhcnRzIC0gc28gcHJvdWQhIPCfjooNCnslIGVuZGlmICV9LS0tDQoNCjxiPvCfpJ0gVG9sZCBhbiBBZHVsdDoge3sgdmFycy5pbmZvcm1lZF9wcm9ncmVzcyB9fTwvYj4NCnslIGZvciBpIGluICgxLi52YXJzLmluZm9ybWVkX3Byb2dyZXNzKSAlffCfl6PvuI97JSBlbmRmb3IgJX0NCnslIGlmIHZhcnMuaW5mb3JtZWRfcHJvZ3Jlc3MgPD0gNSAtJX0NCkNvbW11bmljYXRpb24gaXMga2V5ISBLZWVwIHByYWN0aWNpbmcgc2F5aW5nIHdoZW4gdGhleSBuZWVkIHRvIGdvIC0gVGhleSdyZSBkb2luZyBncmVhdCEg8J+Tog0KeyUgZWxzaWYgdmFycy5pbmZvcm1lZF9wcm9ncmVzcyA8PSAxNSAtJX0NCldvbmRlcmZ1bCBjb21tdW5pY2F0aW9uIHNraWxscyEgVGhleSdyZSByZWFsbHkgZ29vZCBhdCBsZXR0aW5nIHVzIGtub3cgLSB0aGF0J3Mgc28gaGVscGZ1bCEg8J+Rjw0KeyUgZWxzZSAtJX0NCkNPTU1VTklDQVRJT04gU1VQRVJTVEFSISDwn4yfIFRoZXkncmUgYW1hemluZyBhdCB0ZWxsaW5nIGFkdWx0cyAtIHRoYXQncyBzdWNoIGEgYmlnIGtpZCBza2lsbCEg8J+Orw0KeyUgZW5kaWYgJX0tLS0NCg0KPGI+8J+RuyBOb3RoaW5nIEhhcHBlbmVkOiB7eyB2YXJzLm5vdGhpbmdfcHJvZ3Jlc3MgfX08L2I+DQp7JSBmb3IgaSBpbiAoMS4udmFycy5ub3RoaW5nX3Byb2dyZXNzKSAlfeKtlXslIGVuZGZvciAlfQ0KeyUgaWYgdmFycy5ub3RoaW5nX3Byb2dyZXNzIDw9IDMgLSV9DQpUaGF0J3Mgb2theSEgVHJ5aW5nIGlzIHdoYXQgbWF0dGVycywgYW5kIHRoZWlyIGJvZHkgd2lsbCBsZXQgdGhlbSBrbm93IHdoZW4gaXQncyByZWFkeSEg8J+MiA0KeyUgZWxzZSAtJX0NClNvIHBhdGllbnQgYW5kIHBlcnNpc3RlbnQhIEV2ZW4gd2hlbiBub3RoaW5nIGhhcHBlbnMsIHRoZXkga2VlcCB0cnlpbmcgLSB0aGF0J3MgcmVhbCBkZXRlcm1pbmF0aW9uISDwn5KrDQp7JSBlbmRpZiAlfS0tLQ0KDQo8Yj7wn5OKIERhaWx5IFN1bW1hcnk6PC9iPg0KeyUgY2FwdHVyZSB0b3RhbF90cmllcyAtJX17eyB2YXJzLndlZV9wcm9ncmVzcyB8IHBsdXM6IHZhcnMucG9vX3Byb2dyZXNzIHwgcGx1czogdmFycy5ub3RoaW5nX3Byb2dyZXNzIH19eyUgZW5kY2FwdHVyZSAtJX0NCnslIGNhcHR1cmUgc3VjY2Vzc2VzIC0lfXt7IHZhcnMud2VlX3Byb2dyZXNzIHwgcGx1czogdmFycy5wb29fcHJvZ3Jlc3MgfX17JSBlbmRjYXB0dXJlIC0lfQ0KeyUgY2FwdHVyZSBzdWNjZXNzX3JhdGUgLSV9eyUgaWYgdG90YWxfdHJpZXMgIT0gIjAiIC0lfXt7IHN1Y2Nlc3NlcyB8IHRpbWVzOiAxMDAgfCBkaXZpZGVkX2J5OiB0b3RhbF90cmllcyB9fXslIGVsc2UgLSV9MTAweyUgZW5kaWYgLSV9eyUgZW5kY2FwdHVyZSAtJX0NCnslIGNhcHR1cmUgYmFyX2ZpbGxlZCAtJX17eyBzdWNjZXNzX3JhdGUgfCBkaXZpZGVkX2J5OiAxMCB9fXslIGVuZGNhcHR1cmUgLSV9DQp7JSBjYXB0dXJlIGJhcl9lbXB0eSAtJX17eyAxMCB8IG1pbnVzOiBiYXJfZmlsbGVkIH19eyUgZW5kY2FwdHVyZSAtJX0NClRvdGFsIHBvdHR5IHZpc2l0czoge3sgdG90YWxfdHJpZXMgfX0NClN1Y2Nlc3MgcmF0ZToge3sgc3VjY2Vzc19yYXRlIH19JSBbeyUtIGZvciBpIGluICgxLi5iYXJfZmlsbGVkKSAtJX3iloh7JS0gZW5kZm9yIC0lfXslLSBmb3IgaSBpbiAoMS4uYmFyX2VtcHR5KSAtJX3ilpF7JS0gZW5kZm9yIC0lfV0NCnslLSBhc3NpZ24gdG90YWxfZXZlbnRzID0gdmFycy53ZWVfcHJvZ3Jlc3MgfCBwbHVzOiB2YXJzLnBvb19wcm9ncmVzcyB8IHBsdXM6IHZhcnMubm90aGluZ19wcm9ncmVzcyB8IHBsdXM6IHZhcnMuaW5mb3JtZWRfcHJvZ3Jlc3MgLSV9DQogKHt7IHRvdGFsX2V2ZW50cyB9fSBldmVudHMgdG9kYXkgKQ0KeyUgaWYgdG90YWxfZXZlbnRzIDw9IDMgJX0NCvCfkp0gPGI+VG9kYXk6PC9iPiBUaGV5J3JlIGRvaW5nIHN1Y2ggYSBncmVhdCBqb2IgbGVhcm5pbmchIEV2ZXJ5IGRheSBnZXRzIGEgbGl0dGxlIGVhc2llci4uLg0KeyUgZWxzaWYgdG90YWxfZXZlbnRzIDw9IDUgJX0NCvCfjJ8gPGI+VG9kYXk6PC9iPiBBeWVlISBUaGV5J3JlIHJlYWxseSBnZXR0aW5nIHRoZSBoYW5nIG9mIHRoaXMgcG90dHkgdHJhaW5pbmcgdGhpbmchIEtlZXAgaXQgdXAhDQp7JSBlbHNpZiB0b3RhbF9ldmVudHMgPD0gOCAlfQ0K8J+MnyA8Yj5Ub2RheTo8L2I+IFdPVyEgTG9vayBhdCBhbGwgdGhhdCBwcmFjdGljZSEgVGhleSdyZSBiZWNvbWluZyBzdWNoIGEgcG90dHkgZXhwZXJ0Lg0KeyUgZWxzZSAlfQ0K8J+PhiA8Yj5Ub2RheTo8L2I+IElOQ1JFRElCTEUgREFZISBUaGV5J3JlIGFic29sdXRlbHkgcm9ja2luZyB0aGlzIHBvdHR5IHRyYWluaW5nIGpvdXJuZXkhIPCfjorwn46JDQp7JS0gZW5kaWYgJX0NCg0KS2VlcCBiZWluZyBhd2Vzb21lIQ0KV2l0aCBsb3ZlIGFuZCBoaWdoLWZpdmVzISDwn5mMDQotLS0NCnslLSBhc3NpZ24gZXZlbnRfbW9kID0gdG90YWxfZXZlbnRzIHwgbW9kdWxvOiAzICV9DQp7JSBpZiBldmVudF9tb2QgPT0gMCAtJX0NCjxpPlAuUy4gUmVtZW1iZXI6IEV2ZXJ5IGV4cGVydCB3YXMgb25jZSBhIGJlZ2lubmVyIC0gdGhleSdyZSBkb2luZyBicmlsbGlhbnRseSEg8J+MnzwvaT4NCnslIGVsc2lmIGV2ZW50X21vZCA9PSAxIC0lfQ0KPGk+UC5TLiBGdW4gZmFjdDogRXZlbiBzdXBlcmhlcm9lcyBoYWQgdG8gbGVhcm4gdG8gdXNlIHRoZSBwb3R0eSEg8J+muDwvaT4NCnslIGVsc2UgLSV9DQo8aT5QLlMuIFJlbWVtYmVyOiBhY2NpZGVudHMgYXJlIGp1c3QgcHJhY3RpY2UgaW4gZGlzZ3Vpc2UhIFRoZXkncmUgZG9pbmcgYW1hemluZ2x5ISDwn5KVPC9pPg0KeyUgZW5kaWYgJX0=,ewogICJ2YXJzIjogewogICAgIndlZV9wcm9ncmVzcyI6NiwKICAgICJwb29fcHJvZ3Jlc3MiOjIsCiAgICAibm90aGluZ19wcm9ncmVzcyI6MiwKICAgICJpbmZvcm1lZF9wcm9ncmVzcyI6NH0KfQo=)
Warning: Templates are so new that we're still getting the error messaging and validation sorted, so for now if your template has a serious error then it just won't product any output (no new entry in Previous Runs).

Try breaking it down into smaller template chunks for testing, and assign the templates to variables or use log blocks in combination with the Run button (but mind the 5 second cooldown).

If it's valid in the liquid template editor above then it probably should work so [tell us if it doesn't](https://io.adafruit.com/support)!

# No-Code Counters and Email Reports with Adafruit IO Actions

## Downloads

[WipperSnapper configuration file for Pico (JSON)](https://raw.githubusercontent.com/adafruit/Adafruit_Learning_System_Guides/main/Adafruit_IO_Template_Emails/rpi-pico-w-potty-training.json)
[Potty Training Enclosure (3D Printing STL Model)](https://cdn-learn.adafruit.com/assets/assets/000/137/447/original/Potty_Training_Arcade_Button_Assembly.stl?1749596536)
[Fritzing Circuit Diagram (Zipped)](https://cdn-learn.adafruit.com/assets/assets/000/137/451/original/picowh-arcade-buttons-wired.zip?1749639786)
[Square Arcade Buttons - Fritzing part (zipped)](https://cdn-learn.adafruit.com/assets/assets/000/137/452/original/square_arcade_buttons_fritzing_part.zip?1749639878)
[Adafruit CAD Parts repository on GitHub](https://github.com/adafruit/Adafruit_CAD_Parts)
[OnShape model of Enclosure](https://cad.onshape.com/documents/ebe81d707319c1643471acd4/w/0709122f62153637ef0157a9/e/b373fbccec6550052c3fa22a?renderMode=0&uiState=6848ba76f172846f39f5abc2)
[OnShape Model of Pico + Terminal PiCowbell + Clips](https://cad.onshape.com/documents/8e0452d58184bb3bfdf6f588/w/4d111422315834e3493638f4/e/b735d15426eb85a3af83878d?configuration=Inner_PCB_Edge_Offset%3D4.0E-4%2Bmeter%3Bclip_top_thickness%3D0.0015%2Bmeter%3Bclip_wall_offset%3D0.002%2Bmeter%3Bdraft_angle%3D0.6108652381980153%2Bradian%3Boffset_clip_to_board_bottom%3D5.0E-4%2Bmeter%3Boffset_from_board_edge%3D8.0E-4%2Bmeter%3Boffset_mate_to_bottom%3D0.003%2Bmeter%3Btop_offset%3D2.0E-4%2Bmeter&renderMode=0&uiState=6848b9fab4d8bd6a38a48f85)

## Featured Products

### Adafruit Terminal PiCowbell for Pico with Pre-Soldered Sockets

[Adafruit Terminal PiCowbell for Pico with Pre-Soldered Sockets](https://www.adafruit.com/product/5907)
Ding dong! Hear that? It's the PiCowbell ringing, letting you know that the new **&nbsp;Adafruit Terminal PiCowbell** &nbsp;is finally in stock and ready to assist your&nbsp;[Raspberry Pi Pico](https://www.adafruit.com/product/4864)&nbsp;and&nbsp;<a...></a...>

In Stock
[Buy Now](https://www.adafruit.com/product/5907)
[Related Guides to the Product](https://learn.adafruit.com/products/5907/guides)
### Raspberry Pi Pico WH - Pico Wireless with Headers Soldered

[Raspberry Pi Pico WH - Pico Wireless with Headers Soldered](https://www.adafruit.com/product/5544)
The Raspberry Pi foundation changed single-board computing [when they released the Raspberry Pi computer](https://www.raspberrypi.org/archives/723), now they're ready to do the same for microcontrollers with the release of the brand new **Raspberry Pi Pico WH**....

In Stock
[Buy Now](https://www.adafruit.com/product/5544)
[Related Guides to the Product](https://learn.adafruit.com/products/5544/guides)
### LED Illuminated Push Button - 51mm Square

[LED Illuminated Push Button - 51mm Square](https://www.adafruit.com/product/6270)
This 51mm square button is cute, inviting, and ready for all sorts of pressing and pushing. We've seen these in some games of skill in arcades. They're easy to mount on nearly any kind of enclosure. They're not...

In Stock
[Buy Now](https://www.adafruit.com/product/6270)
[Related Guides to the Product](https://learn.adafruit.com/products/6270/guides)
### Adafruit IO+ Subscription Pass – One Year

[Adafruit IO+ Subscription Pass – One Year](https://www.adafruit.com/product/3792)
The all-in-one Internet of Things service from Adafruit you know and love is now _even better_ with IO+. The 'plus' stands for MORE STUFF! More feeds, dashboards, storage, speed. Power up your [Adafruit IO](https://io.adafruit.com/) with the $99 pass for 1 year of the...

In Stock
[Buy Now](https://www.adafruit.com/product/3792)
[Related Guides to the Product](https://learn.adafruit.com/products/3792/guides)
### Arcade Button and Switch Quick-Connect Wires - 0.25" (10-pack)

[Arcade Button and Switch Quick-Connect Wires - 0.25" (10-pack)](https://www.adafruit.com/product/3838)
Quick connector wire sets make wiring up our arcade-style or metal buttons quicky-quick. Each wire comes as a 'pair' with two 0.25" quick-connects pre-crimped. The wires are terminated together in a JST 2.5mm 2-pin connector. This connector will fit in 0.1" headers,...

In Stock
[Buy Now](https://www.adafruit.com/product/3838)
[Related Guides to the Product](https://learn.adafruit.com/products/3838/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

Out of Stock
[Buy Now](https://www.adafruit.com/product/592)
[Related Guides to the Product](https://learn.adafruit.com/products/592/guides)
### Adafruit IO+ 1 Year Subscription Card

[Adafruit IO+ 1 Year Subscription Card](https://www.adafruit.com/product/3980)
It's the Internet of the Things!&nbsp;[Adafruit IO+](https://io.adafruit.com/plus) is the easiest way to stream, log, and interact with your data. Whether you're interesting in&nbsp;datalogging or communicating with your microcontroller over the web, Adafruit IO is our cloud...

In Stock
[Buy Now](https://www.adafruit.com/product/3980)
[Related Guides to the Product](https://learn.adafruit.com/products/3980/guides)
### Adafruit IO+ Subscription Card

[Adafruit IO+ Subscription Card](https://www.adafruit.com/product/4443)
These are for freebies only! If you like to purchase one for yourself, here's the store version! https://www.adafruit.com/product/3980

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

## Related Guides

- [Adafruit Terminal PiCowbell for Pico](https://learn.adafruit.com/adafruit-terminal-picowbell-for-pico.md)
- [Ikea Vindriktning Hack with QT Py ESP32-S3 and Adafruit IO](https://learn.adafruit.com/ikea-vindriktning-hack-with-qt-py-esp32-s3-and-adafruit-io.md)
- [Arcade Stick Conversion](https://learn.adafruit.com/arcade-stick-conversion.md)
- [IoT Bird Feeder with Camera](https://learn.adafruit.com/iot-window-bird-feeder-with-camera.md)
- [Use Apple HomeKit Devices with itsaSNAP and Adafruit IO](https://learn.adafruit.com/use-apple-homekit-devices-with-itsasnap.md)
- [All the Internet of Things - Episode Four: Adafruit IO](https://learn.adafruit.com/all-the-internet-of-things-episode-four-adafruit-io.md)
- [No-Code Battery Monitoring with WipperSnapper](https://learn.adafruit.com/no-code-battery-monitoring-with-wippersnapper.md)
- [Adafruit IO Basics: Feeds](https://learn.adafruit.com/adafruit-io-basics-feeds.md)
- [Adafruit IO Basics: Analog Input](https://learn.adafruit.com/adafruit-io-basics-analog-input.md)
- [Monitor Your Greenhouse with a No-Code Environmental Sensor](https://learn.adafruit.com/monitor-your-greenhouse-with-a-no-code-environmental-sensor.md)
- [No-Code Rain Sensing Smart Desktop Umbrella Stand](https://learn.adafruit.com/no-code-rain-sensing-smart-desktop-umbrella-stand.md)
- [Using Piezo Buzzers with WipperSnapper](https://learn.adafruit.com/using-piezo-buzzers-with-wippersnapper.md)
- [Quickstart: Adafruit IO WipperSnapper ](https://learn.adafruit.com/quickstart-adafruit-io-wippersnapper.md)
- [Integrating Color Sensors with itsaSNAP and HomeKit](https://learn.adafruit.com/integrating-color-sensors-with-itsasnap-and-homekit.md)
- [Memento Photo Capture with itsaSNAP](https://learn.adafruit.com/memento-photo-capture-with-itsasnap.md)
