Improve your dust collector with this automated smart switch

Using a shop-vac to collect sawdust from your power tools is a great way to keep your woodshop clean and your lungs clear. But only if you remember to turn it on. This guide will teach you how to make a DIY dust-collector switch for half the cost of a store-bought one.
This automated dust-collector switch uses its own WiFi to operate, so your tools don’t have to be plugged into the same box. And you don’t need a connection to the internet.
Check out my DIY automatic shop-vac controller in this video:
Table of Contents
- Project Overview
- Materials
- ESP8266 WiFi Relay Server
- ESP8266 WiFi Current Sensor Client
- Try it out!
- Where’s the Pi?
1. Project Overview
⚡⚡This project involves working with AC wall voltage. If you are not a trained electrician turn back now. The author is not responsible for damages to life and property.⚡⚡
In a nutshell, my shop-vac auto-switch uses two devices; one to sense a change in electrical current, and another to operate a relay. I had originally wanted to use a WeMos D1 Mini for the first device, and a Raspberry Pi Zero for the second.
In the end, I just used two Minis. I’ll explain why at the end of the guide.
One Mini acts as a web server that also controls the relay that turns on the shop-vac. The other is responsible for sensing a change in current from a power tool, sending an HTTP request to the relay server, and sending another request after a delay to turn the relay off.
Although MQTT seems to be the standard communication protocol for home automation gadgets, I chose to use HTTP for two reasons.
First, I can’t rely on cloud-based MQTT brokers because the WiFi in my shop is spotty. Second, the chip that powers the Mini is capable of running an MQTT broker, but it’s really not well-suited for it.
I made this little gif to show how everything is tied together:

2. Materials
- 2 WeMos D1 Minis
- 1 ACS712 current sensor
- 1 solid-state relay
- 1 NPN transistor (optional, but recommended)
- 2 5V power supplies
- 1 momentary switch
- 2 LEDs
- 4 1/4 watt resistors
- 2 enclosures
- 2 AC electrical outlets
- 2 AC electrical plugs
- 1 meter of wire rated for AC voltage
- 1 dozen (approximately) jumper wires
- various sizes of shrink tubing
Notes about materials
Wemos D1 Mini
This is my number one favorite of all time microcontroller because it is small and cheap. You can use any microcontroller for this project, but it needs to have Wi-Fi capabilities, so boards based on the ESP8266 or ESP32 chips are best.

You can use an Arduino but it will have to be one of the few that have WiFi. Alternatively, you could use a plain UNO and add an ESP8266 chip to it.
ASC712 current sensor
These Hall-effect sensor breakout boards are notoriously flakey, but for this project, all it needs to do is detect a change in current, not take an accurate current reading. They come in 5, 20, and 30 amp varieties. The 30 amp one will not be sensitive enough for this project, so choose the five or twenty variant.
⚡⚡ Take note! The solder points for the incoming AC voltage on the bottom of the board are exposed. Do not handle this sensor when it is connected to mains voltage! ⚡⚡

Solid-state relay
I’ve seen a few guides similar to this one that uses one of those blue-box Songle mechanical relays. Even though their rating looks like they should work, power tools use motors that create inductive loads which these relays are not really suitable for.
Solid-state relays, however, have no problem switching on, and more importantly, switching off inductive loads. I’m using a Fotek SSR-40 DA, but you can use any SSR you can find as long as its voltage and amperage ratings are adequate on the AC side, and can be switched on with 12mA or less at 3.3V to 5V on the DC side.

5V power supply
I’m using those little, cube-shaped cell phone chargers as power supplies because they are small and cheap (running theme). Although the power they supply is not the cleanest or the most stable, it’s enough for the D1 Mini.
Momentary switch and LEDs
Any kind of button that only closes a circuit as long as you press it will work. The button will be used when you want to turn your shop-vac on manually, and the LEDs will show the status of the relay.

NPN transistor
To close a solid-state relay, all you have to do is light up an LED. The D1 Mini should have no problem providing enough current directly from its GPIO, but I prefer to stay on the safe side and use a transistor as a relay to control the relay. A relay relay? I used a PN2222a.

If you decide to skip this piece, you should probably put a resistor in series between the dev board and the relay.
Assorted 1/4 watt resistors
You will need a few different resistors. I used a couple of 220Ω, one 1kΩ, and one 10kΩ. Those values will probably work for you too unless you are using a transistor or LEDs that differ a lot from what I used.

Enclosures
You will need two enclosures. Both should have a way to easily mount an electrical outlet in them. One enclosure must be big enough for the D1 Mini, its power supply, and the ACS712 sensor. The other might have to be a little bigger because of the size of the relay.
I used the local equivalent of a single-gang wall-mounted electrical box for the sensor assembly, and a double-gang for the relay assembly. If you use a metal box, make sure to wrap all the components in shrink tubing!
Plugs, outlets, and wire
These will match the tools you are going to use. You might need three-prong plugs or two prongs might be enough. Make sure the wire is rated above what your appliances will draw. If you don’t know what to use, stop here, and find an electrician friend to help you complete this project.
2. ESP8266 WiFi Relay Server
Wiring diagram

The resistor values may vary depending on what parts you use, but I used the following:
- LEDs — 220Ω
- transistor base — 1kΩ
- button pull-down — 10kΩ
Design ideas
The goal is to get everything to fit into the smallest box possible. Unfortunately, because of the size of the relay, I was forced to use a double-gang box.
To reduce the space the D1 Mini took up, I skipped adding a header and soldered the pins of the jumper wires directly to the board. Bending them can save even more space, but don’t bend more than once or they will break!

You can also save some space by taking the plastic case off the power supply you’re using, but don’t do this! It’s dangerous. If hypothetically, you did perform that potentially fire-insurance-voiding technique, you should at least seal the component with shrink tubing. Go ahead and seal the D1 Mini up too.
I used a three-prong plug to house the LEDs and buttons. Try to remove as much of the backside of the plug as you can. The LEDs can go in the slots. After enlarging the ground hole a little, the button will fit in there. I then wrapped the whole thing with shrink tubing to make it look a little better. Here it is pre-face-lift:

Finally, make sure you secure the mains wire to the box somehow. If the wires were to be ripped out of the box somehow, all kinds of bad stuff could happen.
Here is my finished product:

Code
You can download the complete code for the server/shop-vac side of this DIY automated dust-collector switch here:
There’s not much going on in the setup()
loop besides pin declarations and starting and configuring the ESP8266WebServer
instance, so I’m going to skip that.
Here is the main loop()
:
void loop() {
server.handleClient();
overrideButton = digitalRead(overrideButtonPin);
if(overrideButton) {
handle_button();
}
digitalWrite(relayPin, relayStatus);
}
Inside the loop, the D1 Mini is listening for two different types of inputs: a web request or a button-push. There are three specific webpage requests that it is waiting for— /
, /relayOn
and /relayOff
. These pages were connected to their corresponding handlers in the setup()
block.
Here they are:
void handle_OnConnect() {
Serial.println("handling connect");
server.send(200, "text/html", send_HTML(relayStatus));
}
void handle_relayOn() {
Serial.println("handling relay");
relayStatus = true;
server.send(200, "text/html", send_HTML(relayStatus));
}
void handle_relayOff() {
Serial.println("handling relay off");
relayStatus = false;
server.send(200, "text/html", send_HTML(relayStatus));
}
void handle_NotFound(){
server.send(404, "text/plain", "Not found");
}
The last handler is just there for bad requests. The first three handlers are nearly identical. The only difference is that handle_relayOn()
and handle_relayOff()
change the state of the relayStatus
variable.
All of those first three handlers finish up by passing relayStatus
to the send_HTML()
function which looks like this:
String send_HTML(uint8_t relay_stat) {
String pageContent = "<!DOCTYPE html> <html>\n";
pageContent +="<title>Relay Control</title>\n";
pageContent +="<body>\n";
pageContent +="<h1>You Found The Extractor</h1>\n";
if(relay_stat) {
pageContent +="<p>Relay Status: ON</p><a class=\"button button-off\" href=\"/relayOff\">OFF</a>\n";
} else {
pageContent +="<p>Relay Status: OFF</p><a class=\"button button-on\" href=\"/relayOn\">ON</a>\n";
}
pageContent +="</body>\n";
pageContent +="</html>\n";
return pageContent;
}
This function just contains the page content. It uses the parameter passed to it to show the state of the relay on the web page.
Next in the main loop()
is the button handler. If the button is pressed, the handle_button()
function is called. This function uses a timer to combat button bounce and toggles the current state, allowing the shop-vac to be turned on manually with a button press.
The button handler:
void handle_button() {
if(millis() - lastButtonPress > buttonDelay) {
relayStatus = !relayStatus;
lastButtonPress = millis();
}
}
To end the loop, the current relay state is written to the relay pin:
digitalWrite(relayPin, relayStatus);
3. ESP8266 WiFi Current Sensor Client
Wiring Diagram

Wiring up the current sensor is pretty straight-forward, especially considering the ESP8266 only has one analog pin.
Please note, the D1 Mini has a built-in ADC that expands the range of analog input. If you are using a different board this might not be the case. If you are not sure about the board you are using, please ask for help in the comments.
⚡⚡ Don’t touch the current sensor if it is connected to the mains! ⚡⚡
Design ideas
Fitting the components of this side of the automated dust-collector switch into an enclosure is much easier. I was able to use a single-gang box.
Make sure to wrap the current sensor in shrink tubing, electrical tape, or some other insulator. And again, make sure the AC voltage wire is securely connected to the box.

Code
The complete code is available for download here:
Because of the skittery nature of the ACS712, I chose to use a Kalman filter to smooth its readings out. The one I used can be found here. I used these magic numbers to initialize it.
const int e_mea = 2;
const int e_est = 2;
const float q = 0.01;
SimpleKalmanFilter kalman(e_mea, e_est, q);
You can use the following sketch and the serial monitor to test out these values and adjust as necessary:
#include "SimpleKalmanFilter.h"
const int e_mea = 2;
const int e_est = 2;
const float q = 0.01;
SimpleKalmanFilter kalman(e_mea, e_est, q);
int sensorValue;
void setup() {
Serial.begin(9600);
}
void loop() {
sensorValue = analogRead(A0);
int estimatedValue = int(kalman.updateEstimate(sensorValue));
Serial.println(estimatedValue);
delay(250);
}
Hopefully, by this point, you have assembled the current sensing portion of this project (⚡and properly insulated it⚡). Plug in a power tool to the apparatus. Then connect a computer to the D1 Mini, upload the sketch above, and open the serial monitor.

For the dust-collector switch to work, you don’t need to know how much current is being drawn, you just have to be able to detect when there is a significant change.
With the power tool turned off, you should see a stream of values that are more or less steady. For example, I can see values ranging from about 759 to 765 with my sensor.
When the power tool is turned on, the value should move far away from the original value. When I turn my miter saw on, the values jump above 1000 or as low as 300.
If you can reproduce this type of behavior, move on to the code below. If you’re having trouble, please reach out in the comments.
The setup()
block calls a few functions to get the sensor ready before the main loop()
starts.
This is the setup()
block:
void setup() {
Serial.begin(9600);
connect_wifi();
initialize_sensor();
recalibrate();
}
The first few readings from the sensor are always a little low and will cause a false positive, and the shop-vac will be turned on. So, several readings must be taken to give the Kalman filter a chance to stabilize the output.
This is handled in the initialize_sensor()
function:
void initialize_sensor() {
for(int i = 0; i < 20; i++) {
sensorValue = analogRead(A0);
int estimatedValue = int(kalman.updateEstimate(sensorValue));
delay(50);
}
}
Next, it’s time to set the range in which we consider the power tool to be off. The sensitivity is set with the global variable sensitivity
and the upper and lower limits are stored in upperLimit
and lowerLimit.
The recalibrate()
function sets the upper and lower limits:
void recalibrate(){
recalibrateSensorTimer = millis();
sensorValue = analogRead(A0);
int estimatedValue = int(kalman.updateEstimate(sensorValue));
lowerLimit = estimatedValue - sensitivity;
upperLimit = estimatedValue + sensitivity;
}
The main loop()
has three tasks: measure the current, set the state, and re-calibrate the upper and lower limits:
void loop() {
sensorValue = analogRead(A0);
int estimatedValue = int(kalman.updateEstimate(sensorValue));
set_state(estimatedValue < lowerLimit || estimatedValue > upperLimit);
if(!extractorIsOn && millis() - recalibrateSensorTimer > recalibrateSensorInterval){
recalibrate();
}
delay(250);
}
The set_state()
function is called in each loop. If the sensor value is either below the lower limit or above the upper limit, true
gets passed as a parameter. Otherwise, false
is passed.
The set_state()
function uses two boolean variables, global extractorIsOn
and the parameter targetState
, to determine when to call the send_request()
function. Keeping track of the old state with extractorIsOn
prevents sending duplicate HTTP requests.
The set_state()
function:
void set_state(bool targetState) {
if(!extractorIsOn && targetState) {
delay(1000);
startMillis = millis();
extractorIsOn = true;
send_request();
} else if(extractorIsOn && !targetState) {
if(millis() - startMillis > onPeriod) {
extractorIsOn = false;
send_request();
}
}
}
There is a delay before sending the request to turn the shop-vac on to avoid having both it and the power tool turning on at the same time. The global onPeriod
specifies a minimum time to keep the shop-vac on to avoid short-cycling.
Finally, recalibrateSensorInterval
controls how often the recalibrate()
function is called. I find the reading for the ASC712 drifts over time, so re-calibrating the upper and lower limits periodically is necessary. I set this variable to 30 seconds:
if(!extractorIsOn && millis() - recalibrateSensorTimer > recalibrateSensorInterval){
recalibrate();
}
5. Try It Out!
Time to take it for a spin. It’s probably best to plug the server-side in first and wait around 15 seconds. Then plug in the client-side. Do not run the power tool for at least 15 seconds!
I have used my DIY automated dust-collector switch for a few months now. It works like a charm. But be sure to unplug everything when not in use.
I hope you found this guide useful and if you have any questions or comments I’d love to hear them!
6. Where’s the Pi?
When I first thought of this project I thought I would finally have a chance to use MQTT. A Raspberry Pi Zero could act as a WiFi hotspot, a Mosquitto broker, and a controller for the shop-vac relay.
I had everything assembled, installed, programmed, and working. And it worked great! As long as the relay wasn’t activated…
For some reason, the Pi would randomly shut down occasionally. It didn’t happen every time the relay was pulled in, but it happened often enough to make the switch unusable.
I asked for help on the Raspberry Pi Stack Exchange. They pointed towards the power supply. I tried half a dozen power supplies including official Raspberry Pi ones, but the problem persisted.
Can you think of something else I can try? Let me know in the comments.
That’s not to say that I’ve given up on Raspberry Pi. I have around 6 running at home doing various things, and I use them for playing games during my English lesson. They are very capable and can be connected to all kinds of peripherals such as a USB microphone to give them even more functionality.
If you’re looking for more ESP8266 projects, be sure to check out my WiFi LED strip and my internet-capable LED strip!