Overview
You can use the IoT friendly Adafruit FunHouse board, combined with a fast-vibration switch, to set up an a smart washing machine timer, triggered by the spin cycle, and never forget to hang out your clothes again!
Get a notification at a set time after the spin cycle is detected, along with being able to glance at the onboard display for details.
Get reminders until the washing is hung out, signified by pressing one of the onboard buttons (or remotely), updating the display message and stopping the notification routine.
Although not required, you can setup a "Start Cycle" button action to avoid any false starts, which can also be used during testing to help establish the time between start/spin/end points of the wash cycle.
Grab appropriate cables or wires, for simplicity the JST-PH connectors are the most robust, but quite short.
Either use the JST 3-Pin ports on the FunHouse and an appropriate JST-PH 3-pin cable, or jumper wires with the 2.54mm female sockets at the top of the board designed for the PIR sensor.
Here is the recommended alligator/crocodile clips version of the JST-PH 3-pin cable:
Or, instead of the JST-PH to alligator/crocodile clips, you might prefer to solder some header pins onto the vibration switch, and then use female-male DuPont connectors to the female PIR headers or a JST cable.
Next pick up one or two Fast vibration sensor switches, although one should be enough for this project.
Additional Tools
- Mounting tape - Double sided adhesive tape, or some other way of attaching the switch to the washing machine (or to the FunHouse as it'll vibrate too).
Finally, the FunHouse includes a built in display and buttons, which we'll take advantage of, but if using another board, then you'll ideally want a button or two and a compatible display.
Now to move on to setting up the board with the WipperSnapper firmware, configuring the components on the device page, and then setting up Actions to automate the notifications and reset the state.
Page last edited December 03, 2025
Text editor powered by tinymce.
WipperSnapper Setup
What is WipperSnapper
WipperSnapper is a firmware designed to turn any WiFi-capable board into an Internet-of-Things device without programming a single line of code. WipperSnapper connects to Adafruit IO, a web platform designed (by Adafruit!) to display, respond, and interact with your project's data.
Simply load the WipperSnapper firmware onto your board, add credentials, and plug it into power. Your board will automatically register itself with your Adafruit IO account.
From there, you can add components to your board such as buttons, switches, potentiometers, sensors, and more! Components are dynamically added to hardware, so you can immediately start interacting, logging, and streaming the data your projects produce without writing code.
Sign up for Adafruit.io
You will need an Adafruit IO account to use WipperSnapper on your board. If you do not already have one, head over to io.adafruit.com to create a free account.
Add a New Device to Adafruit IO
Log into your Adafruit IO account. Click the New Device button at the top of the page.
After clicking New Device, you should be on the board selector page. This page displays every board that is compatible with the WipperSnapper firmware.
In the board selector page's search bar, search for the FunHouse. Once you've located the board you'd like to install WipperSnapper on, click the Choose Board button to bring you to the self-guided installation wizard.
Follow the step-by-step instructions on the page to install Wippersnapper on your device and connect it to Adafruit IO.
If the installation was successful, a popover should appear displaying that your board has successfully been detected by Adafruit IO.
Give your board a name and click "Continue to Device Page".
You should be brought to your board's device page.
Feedback
Adafruit.io WipperSnapper is in beta and you can help improve it!
If you have suggestions or general feedback about the installation process - visit https://io.adafruit.com/support, click "Contact Adafruit IO Support" and select "I have feedback or suggestions for the WipperSnapper Beta".
Troubleshooting
If you encountered an issue during installation, please try the steps below first.
If you're still unable to resolve the issue, or if your issue is not listed below, get in touch with us directly at https://io.adafruit.com/support. Make sure to click "Contact Adafruit IO Support" and select "There is an issue with WipperSnapper. Something is broken!"
First, make sure that you selected the correct board on the board selector.
Next, please make sure that you entered your WiFi credentials properly, there are no spaces/special characters in either your network name (SSID) or password, and that you are connected to a 2.4GHz wireless network.
If you're still unable to connect your board to WiFi, please make a new post on the WipperSnapper technical support forum with the error you're experiencing, the LED colors which are blinking, and the board you're using.
Try hard-resetting your board by unplugging it from USB power and plugging it back in.
If the error is still occurring, please make a new post on the WipperSnapper technical support forum with information about what you're experiencing, the LED colors which are blinking (if applicable), and the board you're using.
"Uninstalling" WipperSnapper
WipperSnapper firmware is an application that is loaded onto your board. There is nothing to "uninstall". However, you may want to "move" your board from running WipperSnapper to running Arduino or CircuitPython. You also may need to restore your board to the state it was shipped to you from the Adafruit factory.
Moving from WipperSnapper to CircuitPython
Follow the steps on the Installing CircuitPython page to install CircuitPython on your board running WipperSnapper.
- If you are unable to double-tap the RST button to enter the UF2 bootloader, follow the "Factory Resetting a WipperSnapper Board" instructions below.
Uploading this sketch will overwrite WipperSnapper. If you want to re-install WipperSnapper, follow the instructions at the top of this page.
Moving from WipperSnapper to Arduino
If you want to use your board with Arduino, you will use the Arduino IDE to load any sketch onto your board.
First, follow the page below to set up your Arduino IDE environment for use with your board.
Then, follow the page below to upload the "Arduino Blink" sketch to your board.
Uploading this sketch will overwrite WipperSnapper. If you want to re-install WipperSnapper, follow the instructions at the top of this page.
Factory Resetting a WipperSnapper Board
Sometimes, hardware gets into a state that requires it to be "restored" to the original state it shipped in. If you'd like to get your board back to its original factory state, follow the guide below.
Page last edited December 03, 2025
Text editor powered by tinymce.
Adafruit IO Configuration
Assuming you have already gone through the WipperSnapper Setup page and connected your board(s) to WipperSnapper, navigate to the WipperSnapper board list. You should see your newly connected FunHouse board listed here.
If you do not see your FunHouse listed - go back to the WipperSnapper Setup Page and make sure its registered with Adafruit.io
On the device page, quickly check that your device is online and is running the latest version of the WipperSnapper firmware.
The device tile on the left indicates the version number of the firmware running on the connected board.
- If the firmware version is green with a checkmark - continue with this guide.
- If the firmware version is red with an "X" - update to the latest WipperSnapper firmware on your board before continuing.
Adding Components
From the FunHouse device page, click the Auto-Config button, which can be used to automatically set up all of the various buttons, LEDs, and sensors built into the FunHouse.
On the pop-up, select Import Config to have Adafruit IO do all of the heavy lifting.
Use this file to add just the components for this project (later try out Magic Config):
Your FunHouse built in components should all be set up and configured, and the the display initializes, showing the WipperSnapper logo followed by the status bar.
You can do a quick test to confirm it is all working as it should by pressing the Down and Up buttons. The corresponding button component should instantly react.
Make sure you press the Down button at least once! You'll use the press event timestamp later.
The next step sets up Adafruit IO Actions to get all of this to work.
Page last edited December 03, 2025
Text editor powered by tinymce.
Wiring and Assembly
Always ensure your board is unplugged when doing any wiring changes, it reduces the risk of damage.
Connect one end of the JST cable to A0 (the top STEMMA / JST-PH socket).
Wire up the vibration switch by connecting one leg with an alligator clip to the black wire of the JST cable, or to a ground pin with DuPont jumper wires if not using a JST cable.
The other leg will be the signal connection, and should be connected to the White wire of the JST cable, which internally connects to the named GPIO Pin, A0, or alternatively using jumper wires to your desired pin.
Be careful to avoid short circuits if using the JST cable with alligator clips!
Make sure to pull the shrouded insulation hood down towards the tips beforehand as the chance of bridging them together is high.
Consider adding an insulating separator, although the insulating hoods are enough protection as seen to the left.
The thinnest leg of the vibration switch easily slips out of the alligator clips (and female jumper sockets). Maybe remove the shroud from that one croc clip as they can restrict the closing a little bit too much for tiny wires.
Avoid the red alligator clip touching anything else and damaging it! Try covering it up with insulating tape.
Alternatively you might find it's enough to gently shorten the cable with a simple loop and tuck it away.
The vibration switch has two wires, one of those is very thin and harder to solder due to the spring material.
It's not impossible to solder to, but is a bit more challenging than normal, so make sure to 'Tin' everything first (apply a thin coating / pre-application of solder).
Ideally use flux, and quickly tin the leads to avoid the plastic switch housing melting. Leave time or blow air between soldering attempts to allow the housing to cool (similarly with tinning the header pins).
To avoid accidentally damaging the thin connection, add hot glue or heat shrink like shown in the image.
Assembly
Attach the magnetic feet to the back side of the FunHouse using the four corner threaded nuts in the PCB.
Consider the cable length when mounting the FunHouse to the Washing Machine, as you'll need to mount the vibration switch relatively close using some thick backed double sided adhesive mounting tape.
The angle and orientation of the vibration switch can affect it's responsiveness, so experiment by rotating the mounting angle, or position (front vs. side/top). You can mount it by just the legs for even more bounce.
Page last edited December 03, 2025
Text editor powered by tinymce.
Cycle Timer Action
Here you'll setup a single action to help with recording how long a washing machine cycle takes to complete, after the vibration is detected (usually in the final spin cycle). You'll handle notifications later in the guide.
Create a new feed to store notification status
Before creating the Action, you need a new feed to hold the notification status. You'll set the value of the feed to "almost-washed", "washed", or "hungout", depending on the state of the system, and respond to that in another action.
Visit the Feeds page using the navigation menu, or by visiting https://io.adafruit.com/feeds/, and then use the New Feed button to create a new feed.
Give it an unambiguous name and description for your future benefit, like "washer-notify".
Create the Cycle Monitoring Action
Start by visiting the Actions page using the navigation menu, or going to https://io.adafruit.com/actions/.
Then click the New Action button and fill in a useful name like 'Washing Cycle Timer' & description.
You'll be taken to the new action's edit page, and be presented with the Actions workspace.
Visit the documentation site regularly for the latest guidance on the available block types and usage.
From the toolbox panel on the left side of the workspace, open the Triggers category, and then drag the "When feed data matching = 0" trigger block onto the main workspace area.
The trigger block you've just dragged + dropped actually goes in the Triggers section of the Root block, and the top connectors lock together along with the target block gaining a yellow highlight when correctly placed.
Then use the feed dropdown, inside the trigger block, to select the Vibration Switch feed, probably called "Adafruit FunHouse: Round Vibration Switch"
Now, as you've got buttons and a display, you'll set the action to use the last button press time.
Then depending if that button is pressed more recently than the last detected vibration, you'll update the display to one of two message templates, along with setting the value of the 'washing-notify' feed.
Start by adding a new variable from the Variables toolbox category called vibrated, then dropping a Set Variable block into the Actions: section.
Then from the Text category, drag the Text Template block ({{ label) and use it to replace the value of the Set Variable block.
Update the text of the template block to this, but with your feed's key instead of mine (details below).
It fetches the updated_at time in seconds for the vibration feed:{{
feeds['funhouse1782526.ws-003'].updated_at
| date: '%s'
}}
To find your feed key visit the Feed Page for your feed and click Feed Info.
Get there quickly either by clicking the graph icon from the device page, or searching the Feeds List page (where on larger displays the second column also shows the feed key).
Then copy the feed key from the Feed Info dialog, under "Show detailed feed JSON record", or from the last path segment of the URL for the feed page.
Create a second variable, to store the time of the start button press, called started.
Exactly the same template as before, but use the FunHouse: Up Button feed key.
Create a third variable called ended, exactly the same template again, and this time use the Down Button feed key.
Your action should look like this before continuing.
Next it's on to the logic section. If you only use one button then you'll need to make minor adjustments.
Start by adding an If/Else/Else-If block from the Logic category of the toolbox into the Actions: section.
Next grab a Numerical Comparison block ( 0 = 0 ) from the Maths toolbox category and replace the IF comparison block (the 'True' dropdown).
Drop a Get Variable block into each half of the new comparison block.
Update the comparison to be "started" > "vibrated".
Click the + next to the phrase "Else If" to add a new Else-If section to the logic block.
Do the same with the Else section to add a third (fallback) option.
Next, replace the Else-If conditional block (another 'true' dropdown) with a Numeric Comparison block, and utilize the Get Variable blocks to do another similar comparison of "ended" > "started".
At this point, it's worth adding in two extra Trigger blocks, to capture When Any Data arrives for both the Up and Down buttons on the FunHouse, and then update the screen message.
Your Action should look like this before continuing:
Now for the Display templates! There's one minor caveat that will improve in the near future when we add Time related blocks, but for now this template includes a hard-coded timezone offset (5h x 3600s = 18000) to render times in GMT instead of EST. You could instead use a variable or feed and update it more easily.
Drop a Set Feed block into the first nested do section beneath the IF.
Replace the child value block of the set feed block with a Text Template block.
Set the template to be this (with the 18000s offset adjusted for your timezone):
Started:
{{ vars.started | plus: 18000 | date: '%H:%M:%S' }}
No Cycle
recorded.
<-- Hung/End
Update the feed dropdown for the Set Feed block to point to the Display.
Repeat for the nested do section of the Else If, using this template:
<-- Start
Started:
{{vars.started | plus: 18000 | date: '%H:%M:%S' }}
Last Cycle:
{{vars.vibrated | plus: 18000 | date: '%H:%M:%S' }}
Ended/Hung:
{{vars.ended | plus: 18000 | date: '%H:%M:%S' }}
And again for the final do section of the Else, using this template:
Started:
{{vars.started | plus: 18000 | date: '%H:%M:%S' }}
Last Cycle:
{{vars.vibrated | plus: 18000 | date: '%H:%M:%S' }}
<-- Hung/End
Add another Set Feed block to the Else-If section. Publish the value "hungout" to the washer-notify feed.
Do the same again for the Else section, but send the value of "almost-washed" to the same feed.
To avoid any issues with a second wash straight after, add another publish block for the If section, setting the washer-notify feed to "not-washed" (it doesn't matter as long as it isn't the two above which we track).
Your action should look like this before using the Save & Run button and continuing on to the next page.
Page last edited December 03, 2025
Text editor powered by tinymce.
Notifications + Remote Reset
Now to create a simple action to send a notification every 30 minutes until you hang out the washing.
First, as a form of debouncing, you'll create an extra action to switch the washer-notify feed from "almost-washed" to "washed" after a 30 minute resettable delay. Resettable so extra vibrations mean the same run.
Create a new action called "Washing Almost Ready", and add a When Data Matching = 0 trigger.
Set the feed dropdown of the trigger block to the washer-notify feed.
In the Triggers category is the Text Matcher block ( =" ). Use it to replace the trigger block's numerical comparator block.
Update the value of the text matcher to be "almost-washed".
Now use the blue settings gear (⚙️) on the root block, adjust the Delay Settings to be 30minutes, and ensure "reset" existing delays is selected.
Click the gear again to close+save the Delay Settings.
The output of the action should be to update the washer-notify feed to "washed".
To ensure the feed value is still "almost-washed" after the delay expires, it's best to recheck the value in the Actions: section of the workspace.
Add an If/Else-If/Else block, and use the Text Compare block ( " = " ) for the IF conditional.
Drop a Get Feed Value block into one half of the comparison block, and enter the value "almost-washed" into the other side.
Inside the do section of the If block add a Set Feed Value block, with the value "washed" being sent to the washer-notify feed.
Your action should look similar to the image above before continuing on with this guide.
washer-notify feed.
Use the Add Data button on the feed page, or a Dashboard widget to send a pre-populated message.
Now it's on to the main notification action, which sends an Email/SMS at regular intervals.
Start by creating a new action with an appropriate name and description, like "Hang clothes notifier".
Add a Data Match Changing trigger for washer-notify STARTS = "washed".
This will only trigger when a Starts transition occurs (check was false with old value, and now true).
Add a Scheduled trigger block to the diagram.
Configure the time + date segments using the Blue gear icons (⚙️ - see the help page for more info).
Set it to match your desired reminder frequency (Every 30minutes).
Next add a conditional IF/Else-If/Else block to the Actions: section, and for the IF comparator use the Textual Comparison block ( "" = "" ) listed under the Text and Logic toolbox categories.
Drop a Get Feed Value block into one side of the comparison, pointed at the washer-notify feed, and then enter the text value washed for the second side of the comparison. Leave the operator on Equals (=).
Add a Send Email block from the Notifications toolbox category (or use SMS if IO+ and based in USA/CA).
Place it into the do section of the IF block, and update with an appropriate message body / reminder.
Your action should look the same as above. Now go and test your Action / System!
Page last edited December 03, 2025
Text editor powered by tinymce.
Testing and Usage
Testing
Most washing machines have a drain + spin cycle, which doesn't actually wash anything, but is a useful test to see if the vibration sensor detects it. Mine takes 10 minutes with spin, and only detects 3/4 of the way.
Press the Up Button on the FunHouse to signify the loading of the machine and start of a cycle.
The display should update with a new Start Time, and show no cycle detected yet by the vibration switch.
Begin the washing machine cycle.
Wait for the washing machine cycle to finish, then press the Down Button on the FunHouse and the end time will be updated.
Take a quick photo, to record the detected cycle time compared to the manual start and end times.
If the end time is more than 30 minutes after the spin cycle was detected then modify the delay time of the "Washing Almost Ready" action (mentioned at the top of previous page).
Usage
If you don't "end" the cycle, by pressing the Down button, then soon you'll be receiving an Email reminding you to hang out the washing.
They'll keep being sent until you finally do the good deed, or pull the emergency rip cord by changing the washer-notify feed to a value that isn't almost-washed or washed.
SMS Text Messages?
If you prefer using SMS messages (and are USA / Canada based with an IO+ subscription) then you can easily swap the Email block for an SMS block instead.
Just make sure you have set up your number and verified it in the Accounts->Services->IO SMS settings:
https://accounts.adafruit.com/settings/phone
Prefer Discord / Slack notifications?
You could do that too!
Go and checkout the plant watering notification guide that details how to setup Slack + Discord:
Page last edited December 03, 2025
Text editor powered by tinymce.