Make a cheap and easy DIY WiFi automated dust-collector switch with ESP8266

Picture of the shop-vac side of a DIY automated dust collection switch
Half of the project

Hello! If you are coming from Medium you can download the two sketches for the dust-collector switch here:

Or scroll down the page a bit and you can directly copy and paste.

If you found this page by some other means, please check out my guide on how to make a DIY dust-collector switch on Medium. Especially if you’re a Medium member, I’d really appreciate some read time and some claps. Or, just check out the diagrams and code here at MakerWS.


DIY Automated Dust-collector Switch Shop-vac Relay

Wiring diagram for a DIY automated dust-collector switch
The shop-vac gets plugged into this
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

/* Put your SSID & Password */
const char* ssid = "dustcollector";  // Enter SSID here
const char* password = "securepassword";  //Enter Password here

/* Put IP Address details */
IPAddress local_ip(192,168,7,1);
IPAddress gateway(192,168,7,1);
IPAddress subnet(255,255,255,0);

ESP8266WebServer server(80);

uint8_t powerLEDPin = D6;

uint8_t relayPin = D5;
bool relayStatus = LOW;

uint8_t overrideButtonPin = D8;
int overrideButton = LOW;

long lastButtonPress = 0;
long buttonDelay = 500;

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;
}

void handle_button() {
  if(millis() - lastButtonPress > buttonDelay) {
    relayStatus = !relayStatus;
    lastButtonPress = millis();
  }
}

void flash_LED(uint8_t pin, int flashes) {
  bool state = true;
  for(int i = 0; i < flashes; i++) {
    state = !state;
    digitalWrite(pin, state);
    delay(300);
  }

}

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");
}


void setup() {
  Serial.begin(9600);
  Serial.println("Extractor hub started");
  pinMode(powerLEDPin, OUTPUT);
  pinMode(relayPin, OUTPUT);
  pinMode(overrideButtonPin, INPUT);
  
  flash_LED(powerLEDPin, 7);
  digitalWrite(powerLEDPin, HIGH);

  WiFi.softAP(ssid, password);
  WiFi.softAPConfig(local_ip, gateway, subnet);
  delay(100);
  
  server.on("/", handle_OnConnect);
  server.on("/relayOn", handle_relayOn);
  server.on("/relayOff", handle_relayOff);
  server.onNotFound(handle_NotFound);
  
  server.begin();
  Serial.println("HTTP server started");

}

void loop() {
  server.handleClient();
  overrideButton = digitalRead(overrideButtonPin);
  
  if(overrideButton) {
    handle_button();
  }

  digitalWrite(relayPin, relayStatus);
  
}

DIY Automated Dust-collector Switch Current Sensor

Wiring diagram for the power tool side of a DIY automated dust-collector switch
The power tool gets plugged into this
#include <Arduino.h>
#include "ESP8266WiFi.h"
#include "ESP8266HTTPClient.h"
#include "SimpleKalmanFilter.h"

// The following needs to match the ssid in the shopvacserver.cpp file
const char* ssid = "dustcollector";
// The following needs to match the password in the shopvacserver.cpp file
const char* wifi_password = "securepassword";

int sensorValue = 0;
int sensitivity = 8;
int lowerLimit;
int upperLimit;

unsigned long onPeriod = 10000;
unsigned long startMillis = 0;

unsigned long recalibrateSensorInterval = 30000;
unsigned long recalibrateSensorTimer = 0;

bool extractorIsOn = false;

const int e_mea = 2;
const int e_est = 2;
const float q = 0.01;
SimpleKalmanFilter kalman(e_mea, e_est, q);

WiFiClient wifiClient;

void initialize_sensor(){
  for(int i = 0; i < 20; i++) {
    sensorValue = analogRead(A0);
    int estimatedValue = int(kalman.updateEstimate(sensorValue));
    delay(50);
  }
}

void recalibrate(){
  recalibrateSensorTimer = millis();
  sensorValue = analogRead(A0);
  int estimatedValue = int(kalman.updateEstimate(sensorValue));
  lowerLimit = estimatedValue - sensitivity;
  upperLimit = estimatedValue + sensitivity;
}

void connect_wifi(){
  WiFi.begin(ssid, wifi_password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void send_request() {
  if (WiFi.status() != WL_CONNECTED) {
    connect_wifi();
  }

  HTTPClient http;
  if(extractorIsOn) {
    http.begin("http://192.168.7.1/relayOn");
  } else {
    http.begin("http://192.168.7.1/relayOff");
  }
  int httpCode = http.POST("");
  if(httpCode == 200) {
    http.end();
  } else {
    http.end();
    send_request();
  }
}

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();
    }
  }
}

void setup() {
  Serial.begin(9600);
  connect_wifi();
  initialize_sensor();
  recalibrate();
}

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);
}

Leave a Comment

Your email address will not be published. Required fields are marked *