Overview
Air Tank
A 5 gallon (or bigger!) air tank to store your compressed air. This needs to have a 1/2" threaded port on it -- the tank attached to your typical shop air compressor will likely not work due to having a smaller 1/4" outlet.
You'll also need thread seal tape.
1/4" Pipe Fittings
You'll build the air blaster from a set of pipe fittings (galvanized or black pipe is fine), adapters, couplers, regulators, and cut-off valves.
- 1/4" male brass industrial plug for connecting your compressor for filling the tank
- 1/4" FIP ball valve to shut off the air flow on the inlet side
- 1/4" x 1-1/2" threaded pipe nipple
- 1/4" x 4" threaded pipe nipple (optional)
- 1/4" tee fitting
- 125 PSI 1/4" NPT pressure relief valve
- 1/4" x 1-1/2" threaded pipe nipple
- 150 PSI air compressor regulator with dial gauge 1/4" female threaded to check the filling pressure
- 1/4" x 3" threaded pipe nipple
- 1/2" MIP x 1/4" FIP bushing this adapts us up to 1/2" for the rest of the parts
1/2" Pipe Fittings
This section takes us into the air tank and then out through the solenoid valve, all at 1/2".
- 1/2" tee fitting
- 1/2" x 3-1/2" pipe nipple this connects to the air tank
- 1/2" x 2" pipe nipple to connect the outlet of the tee fitting to the ball valve
- 1/2" FIP full port ball valve to shut off airflow on the outlet side
- 1/2" x 2" pipe nipple to connect the outlet of the ball valve to the solenoid valve (this is the second of two of this size needed)
- 1/2" x 12" pipe nipple to act as the barrel of the blaster
Tools
You'll need an adjustable wrench and a pipe wrench to fasten the fittings tightly enough to be pressurized without leaking. I happened to have a couple of sets of adjustable wrenches and pipe wrenches so I set one for 1/4" and the other for 1/2" to make life easier.
You'll also need a soldering iron to solder the header pins on the Feather, FeatherWing, and FeatherWing Doubler, as well as wire strippers and a small screwdriver.
Page last edited October 18, 2024
Text editor powered by tinymce.
Build the Air Blaster
Tank Prep
The air tank probably came with some fittings in place. They have too small of an outlet diameter to do anything fun and air blaster-y -- Grab your wrench and remove those!
Fitting Prep
Lay out all of the fittings so you have an idea of the assembly order and can double-check you've got all of the parts needed.
- industrial plug (for filling with your compressor line)
- shut-off valve
- pipe nipple
- regulator
- pipe nipple
- tee fitting
- pressure regulator
- pipe nipple
- bushing
- tee fitting
- vertical pipe nipple to tank
- pipe nipple
- shut-off valve
- pipe nipple
- solenoid valve
- long pipe nipple (barrel)
Dry Fit
Before you tape the threads and crank everything on with a pair of wrenches, it's a good idea to dry fit the whole assembly. Thread everything together by hand, just keep it finger-tight.
Here is a dry fit test I did before I had the solenoid valve in place.
Taping
For the final assembly you'll need to seal all of the threads with sealing tape. Wrap it starting at the bottom of the threads going counter-clockwise and overlapping by at least half of the tape width with each turn. Pull to stretch and break the thread from the roll.
Threading
Thread each part together using two wrenches (adjustable and/or pipe as needed) to crank them down hard, otherwise there will be leaks!
Here's the full assembly, minus the tank.
Screw the assembly onto the tank -- it's best to use a pipe wrench on the pipe nipple closest to the tank flange, rather than pulling on the barrel, as tempting as that is, just to avoid bending any fittings.
Page last edited October 18, 2024
Text editor powered by tinymce.
CircuitPython
CircuitPython is a derivative of MicroPython designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Simply copy and edit files on the CIRCUITPY drive to iterate.
CircuitPython Quickstart
Follow this step-by-step to quickly get CircuitPython running on your board.
Click the link above to download the latest CircuitPython UF2 file.
Save it wherever is convenient for you.
To enter the bootloader, hold down the BOOT/BOOTSEL button (highlighted in red above), and while continuing to hold it (don't let go!), press and release the reset button (highlighted in red or blue above). Continue to hold the BOOT/BOOTSEL button until the RPI-RP2 drive appears!
If the drive does not appear, release all the buttons, and then repeat the process above.
You can also start with your board unplugged from USB, press and hold the BOOTSEL button (highlighted in red above), continue to hold it while plugging it into USB, and wait for the drive to appear before releasing the button.
A lot of people end up using charge-only USB cables and it is very frustrating! Make sure you have a USB cable you know is good for data sync.
You will see a new disk drive appear called RPI-RP2.
Drag the adafruit_circuitpython_etc.uf2 file to RPI-RP2.
The RPI-RP2 drive will disappear and a new disk drive called CIRCUITPY will appear.
That's it, you're done! :)
Safe Mode
You want to edit your code.py or modify the files on your CIRCUITPY drive, but find that you can't. Perhaps your board has gotten into a state where CIRCUITPY is read-only. You may have turned off the CIRCUITPY drive altogether. Whatever the reason, safe mode can help.
Safe mode in CircuitPython does not run any user code on startup, and disables auto-reload. This means a few things. First, safe mode bypasses any code in boot.py (where you can set CIRCUITPY read-only or turn it off completely). Second, it does not run the code in code.py. And finally, it does not automatically soft-reload when data is written to the CIRCUITPY drive.
Therefore, whatever you may have done to put your board in a non-interactive state, safe mode gives you the opportunity to correct it without losing all of the data on the CIRCUITPY drive.
To enter safe mode when using CircuitPython, plug in your board or hit reset (highlighted in red above). Immediately after the board starts up or resets, it waits 1000ms. On some boards, the onboard status LED (highlighted in green above) will blink yellow during that time. If you press reset during that 1000ms, the board will start up in safe mode. It can be difficult to react to the yellow LED, so you may want to think of it simply as a slow double click of the reset button. (Remember, a fast double click of reset enters the bootloader.)
In Safe Mode
If you successfully enter safe mode on CircuitPython, the LED will intermittently blink yellow three times.
If you connect to the serial console, you'll find the following message.
Auto-reload is off. Running in safe mode! Not running saved code. CircuitPython is in safe mode because you pressed the reset button during boot. Press again to exit safe mode. Press any key to enter the REPL. Use CTRL-D to reload.
You can now edit the contents of the CIRCUITPY drive. Remember, your code will not run until you press the reset button, or unplug and plug in your board, to get out of safe mode.
Flash Resetting UF2
If your board ever gets into a really weird state and CIRCUITPY doesn't show up as a disk drive after installing CircuitPython, try loading this 'nuke' UF2 to RPI-RP2. which will do a 'deep clean' on your Flash Memory. You will lose all the files on the board, but at least you'll be able to revive it! After loading this UF2, follow the steps above to re-install CircuitPython.
Page last edited October 18, 2024
Text editor powered by tinymce.
Code the Air Blaster
Text Editor
Adafruit recommends using the Mu editor for editing your CircuitPython code. You can get more info in this guide.
Alternatively, you can use any text editor that saves simple text files.
Download the Project Bundle
Your project will use a specific set of CircuitPython libraries and the code.py file. To get everything you need, click on the Download Project Bundle link below, and uncompress the .zip file.
Drag the contents of the uncompressed bundle directory onto your board's CIRCUITPY drive, replacing any existing files or directories with the same names, and adding any new ones that are necessary.
# SPDX-FileCopyrightText: 2024 John Park for Adafruit Industries
#
# SPDX-License-Identifier: MIT
'''
Air Blaster
Feather RP2040 Prop-Maker with Power Relay FeatherWing and VL53L1X distance sensor
'''
import time
import board
import digitalio
import adafruit_vl53l1x
TRIGGER_DISTANCE = 50.0
triggered = False
i2c = board.STEMMA_I2C()
vl53 = adafruit_vl53l1x.VL53L1X(i2c)
vl53.distance_mode = 2
vl53.timing_budget = 100
print("VL53L1X Simple Test.")
print("--------------------")
model_id, module_type, mask_rev = vl53.model_info
print("Model ID: 0x{:0X}".format(model_id))
print("Module Type: 0x{:0X}".format(module_type))
print("Mask Revision: 0x{:0X}".format(mask_rev))
print("Distance Mode: ", end="")
if vl53.distance_mode == 1:
print("SHORT")
elif vl53.distance_mode == 2:
print("LONG")
else:
print("UNKNOWN")
print("Timing Budget: {}".format(vl53.timing_budget))
print("--------------------")
vl53.start_ranging()
relay_pin = digitalio.DigitalInOut(board.D10)
relay_pin.direction = digitalio.Direction.OUTPUT
relay_pin.value = False
def blast(repeat, duration, rate):
for _ in range(repeat):
relay_pin.value = True
print("bang")
time.sleep(duration)
relay_pin.value = False
time.sleep(rate)
distance = None
while True:
if vl53.data_ready:
distance = vl53.distance
print("Distance: {} cm".format(vl53.distance))
vl53.clear_interrupt()
time.sleep(0.1)
if distance:
if distance <= TRIGGER_DISTANCE:
if not triggered :
blast(3, 0.01, 0.1) # adjust repeat, duration, rate here
time.sleep(0.4)
blast(2, 0.01, 0.2) # adjust repeat, duration, rate here
triggered = True
else:
triggered = False
How It Works
The distance sensor continuously measures how far objects are from it. When something moves within 50 cm of the sensor, it triggers the air blaster to fire a few quick blasts. You can control the number of blasts, how long they last, and the rate at which they happen in the code.
Libraries
We start by importing the necessary libraries. board gives us access to the Feather’s pins, digitalio helps us control the relay pin, and adafruit_vl53l1x is the library for the distance sensor.
import time import board import digitalio import adafruit_vl53l1x
Variables
-
TRIGGER_DISTANCEis set to50cm, meaning that when something is closer than this distance, it will activate the air blaster. - The
triggeredvariable keeps track of whether the air blaster has already been activated, preventing it from firing repeatedly when the object stays close.
TRIGGER_DISTANCE = 50.0 triggered = False
Setup
- We initialize the I2C bus for communication with the VL53L1X sensor and set it to long-distance mode (
distance_mode = 2), perfect for larger detection ranges. - The timing budget is set to 100 ms, which controls how quickly the sensor takes measurements. Lower values mean faster readings but slightly reduced accuracy.
- We set up the relay pin (connected to pin D10) that will control the air blaster. By default, the relay is off (
False).
i2c = board.STEMMA_I2C() vl53 = adafruit_vl53l1x.VL53L1X(i2c) vl53.distance_mode = 2 vl53.timing_budget = 100 relay_pin = digitalio.DigitalInOut(board.D10) relay_pin.direction = digitalio.Direction.OUTPUT relay_pin.value = False
blast Function
This function controls how many times the air blaster will fire, how long each blast lasts, and the delay between blasts. You can adjust repeat, duration, and rate to create different blast patterns.
def blast(repeat, duration, rate):
for _ in range(repeat):
relay_pin.value = True # Turn on the relay (blasts air)
print("bang")
time.sleep(duration) # Wait for the duration of the blast
relay_pin.value = False # Turn off the relay
time.sleep(rate) # Wait for the interval before the next blast
Main Loop
In the main loop, the sensor checks if it’s ready to send a distance reading. If it is, it prints the distance in centimeters and then clears the sensor’s interrupt (which tells it to get ready for the next reading).
while True:
if vl53.data_ready:
distance = vl53.distance
print("Distance: {} cm".format(vl53.distance))
vl53.clear_interrupt()
time.sleep(0.1)
Triggering the Air Blaster
- When the distance is less than or equal to
50cm, and the air blaster hasn’t already been triggered (triggered == False), theblastfunction fires the air cannon. - In this example, it blasts three quick shots, pauses for
0.4seconds, and then blasts two more. - The
triggeredvariable is set toTrueto ensure that the blaster doesn’t keep firing while the object remains close. - If the object moves farther than
50cm, the system resets for another trigger.
if distance <= TRIGGER_DISTANCE:
if not triggered:
blast(3, 0.01, 0.1)
time.sleep(0.4)
blast(2, 0.01, 0.2)
triggered = True
else:
triggered = False
Page last edited October 18, 2024
Text editor powered by tinymce.
Air Blaster Circuit
The Air Blaster circuit consists of a Feather RP2040 Prop-Maker that reads a VL53L1X time-of-flight distance sensor over I2C to determine when to fire. The Power Relay FeatherWing connects to the Feather over pin 10 to control the external 12V DC power to the solenoid valve. The solenoid valve is has a capacitor connected across its leads to preven EMF backcharge from resetting the board.
Headers
First, solder male header pins under the Feather and FeatherWing and female header sockets to the top of the FeatherWing Doubler. This guide has more info on soldering headers.
Relay Jumper
Not an exciting new track and field event, but instead, an invitation to solder one of the pads on the underside of the Power Relay FeatherWing.
I've chosen to solder the pin 10 jumper here.
Connect Feather/FeatherWing to Doubler
Press the Feather and FeatherWing into the Doubler as shown here.
Power Connection
Connect a 4" length of 24 ga. stranded hook-up wire, red and black respectively, to the + and - of the DC power jack.
Open the levers on the snap-action block and insert the legs of the capacitor as shown, then snap the levers shut.
Connect the red wire from the DC power jack to the center common screw terminal on the relay FeatherWing.
Then, insert the black wire from the DC power jack into one of the blocks of the snap-action connector that is already connected to the negative leg of the capacitor.
Run an 8" length of red wire from the normally-open (NO) terminal of the relay to a block on the positive wire connector.
Solenoid Connection
Connect one wire from the solenoid valve to the positive side of the snap-action connector block and the other solenoid wire to the negative side. Polarity usually doesn't matter for the solenoid, it should function properly regardless of polarity.
Test Run
Without pressurizing the air tank you can test if the solenoid triggers properly.
Connect the distance sensor to the Feather with the STEMMA QT cable.
Plug in the 12VDC power supply to AC wall power, then plug the barrel jack into the 2.1mm adapter.
Give the Feather power over USB (or battery as shown here for convenience).
Trip the distance sensor and the solenoid should open and close!
Enclosure
You can neaten up the build by placing the circuit in an enclosure.
Disconnect the solenoid from the wire blocks, feed them through a cable gland, and then reconnect as shown.
I sadly lost one cable gland, but if you haven't, use the second one for the STEMMA QT cable, USB C cable, and 12V DC power!
Connect Enclosure
Use zip ties or other fasteners to connect the enclosure to the handle of the air tank.
You can position the distance sensor wherever it makes the most sense for your haunt use. Some Blu-Tack will work fine, or make it a little more secure with double-stick foam tape -- or mount it to a structure with the mounting holes.
Page last edited October 18, 2024
Text editor powered by tinymce.
Use the Air Blaster
Fill the Tank
Connect your compressor hose to the air blaster's inlet and open the valve.
Turn on the compressor an fill the tank to around 80 PSI.
Close the inlet valve and turn off the compressor.
You can remove the hose or leave it connected for quick refilling later.
Prep the Air Blaster
Close the output valve to prevent discharge during setup.
Plug in the USB C power and 12V power plugs.
Place the distance sensor so it will be tripped by your victims, er... guests!
Test tripping the sensor -- you should hear the solenoid valve click open and closed.
Time to arm it -- make sure the barrel is not facing anyone, then open the output valve. It's now armed and ready.
Page last edited October 18, 2024
Text editor powered by tinymce.