Washing Machine Notification Sensor

As an At Home Dad, I spend a lot of time doing laundry. I also do cloth diapering, which means I spend a lot of time doing laundry. Often times I don’t hear the washing machine cycle alarms which means the laundry sits until I get curious what’s taking so long and check on it.

Enter the washing machine push notification sensor:

The Problem:

  • I often can’t hear the cycle Alarm on the washer

Solutions:

  • A Timer? Still has the problem of not hearing it go off.
  • Louder Cycle Alarm? Would wake up the sleeping baby.
  • Sensor that sends push notifications when cycle is done.

Materials:

  • Particle Photon – I ordered a ESP8266 Adafruit Huzzah, but it didn’t arrive before I wanted the project done.
  • Piezo Sensor – Also known as a knock sensor
  • 1M Ohm Resistor
  • Pushover Account – There are alternatives, but I use pushover for other projects as well.
  • ThingSpeak Account – Used this for data collection.

Build:
This sensor is very simple in design. We simply hook up the Piezo to the particle with a 1M ohz resistor in parallel.

washer

I ran my hand along the side of the washer until I found a spot that I could feel vibrations through, and then I taped the piezo to the side of the washer.

Code:
Now that we have the sensor built we need data. I setup a ThingSpeak channel and collected data from several washer cycles.

// This #include statement was automatically added by the Spark IDE.
#include "thingspeak/thingspeak.h"

const int PiezoSensor = A1; // the piezo is connected to analog pin 1
const int threshold = 1;
const long interval = 17000;           // interval at which to ping Thingspeak (milliseconds)
unsigned long previousMillis = 0;        // will store last time we reported to thingspeek

int sensorReading = 0; // variable to store the value read from the sensor pin. From 0 to 1023
int ticks = 0;

ThingSpeakLibrary::ThingSpeak thingspeak ("Channel-API-Key");

void setup() {
      pinMode(PiezoSensor, INPUT);
}

void loop() {

    unsigned long currentMillis = millis();
    sensorReading = analogRead(PiezoSensor);

    if (sensorReading >= threshold) {
        bool valSet = thingspeak.recordValue(1, String(sensorReading, DEC));

        if (currentMillis - previousMillis >= interval) {
            ticks = (currentMillis - previousMillis);
            bool valSet = thingspeak.recordValue(2, String(ticks, DEC));
            bool valsSent = thingspeak.sendValues();
            if(valsSent) {
                previousMillis = currentMillis;
                ticks = 0;
            }
        }
    }
    delay(100);

}

Thingspeak gave me a lovely graph of data which I analyzed looking for trends in vibrations.

I noticed that while the washer was running I didn’t get piezo values under 18 and there was a sizable knock at the end of the cycles when my washer’s magnetic lock released.

I also noticed that during the soak cycles I didn’t get any readings for 600 seconds at a time.

With my new data I wrote new firmware.

I setup a particle webhook to send the push notification. You can read about Particle webhooks here.

Edit: Pushover requires a HTTPS connection, and the arduino isn’t powerful enough to encrypt the required data. Normally you’d have to use a middleware script for the arduino to call before the pushover request. The Particle webhook allows the https request to be made from the particle server instead of me having to setup a middleware.

// This #include statement was automatically added by the Spark IDE.
#include "thingspeak/thingspeak.h"

const int PiezoSensor = A1; // the piezo is connected to analog pin 0
const int threshold = 18; 
const int doneThreshhold = 82;
const int cycleThreshhold = 30;
const long interval = 17000;           // interval at which to ping Thingspeak (milliseconds)
const long notificationInterval = 420000; // interval which to determine cycle is done (milliseconds)
unsigned long previousMillis = 0;        // will store last time LED was updated

int sensorReading = 0; // variable to store the value read from the sensor pin. From 0 to 1023
int ticks = 0;
bool notifyDone = 1;
bool notifyStart = 0;
int cycle = 0;
bool done = 0;

ThingSpeakLibrary::ThingSpeak thingspeak ("API-KEY");

void setup() {
    Serial.begin(9600);
      pinMode(PiezoSensor, INPUT);
      Spark.publish("washer", "Washing Monitor Enabled ", 60, PRIVATE);
}

void loop() {

    //Serial.println("Loop start");
    unsigned long currentMillis = millis();
    
    //int rand = random(100);

    sensorReading = analogRead(PiezoSensor);

    if (sensorReading >= threshold) {
        bool valSet = thingspeak.recordValue(1, String(sensorReading, DEC));
          
        if (currentMillis - previousMillis >= interval) {
            ticks = (currentMillis - previousMillis);
           if (ticks <= notificationInterval) {
                cycle++;
            } else {
                cycle =0;
            }
            bool valSet = thingspeak.recordValue(2, String(ticks, DEC));
            bool valSet2 = thingspeak.recordValue(3, String(cycle, DEC));

            bool valsSent = thingspeak.sendValues();
            if(valsSent) {
                previousMillis = currentMillis;
                ticks = 0;
            }
        }
        
        if (cycle >=10 && notifyStart == 0){
            notifyDone = 0;
            notifyStart = 1;
            //Spark.publish("washer", "Washer started!", 60, PRIVATE);
        }
        
        if (sensorReading >=doneThreshhold && cycle >= cycleThreshhold && notifyDone == 0) {
            // Found a knock and Cycles are over 30 Think we can safely assume done instead of having to wait
            done = 1;
        }
        
        
    } else {
        if ((currentMillis - previousMillis >= notificationInterval || done == 1) && (notifyDone == 0)) {
                  Spark.publish("washer", "Washing Done!", 60, PRIVATE);
                  notifyDone = 1;
                  notifyStart = 0;
                  cycle=0;
                  done = 0;
        }
         //Serial.println("Value is " + String(sensorReading, DEC));
    }
    delay(100); //serial output delay. Probably don't need anymore
    
}

5 Comments

  • Can I use an Arduino or a Raspberry pi instead of a Photon ? to send events to Webhook? ( particle)

    • If you wanted to use the arduino you’d need some way for it to connect to the internet. I’d recommend an ESP8266, like the Adafruit Huzzah or NodeMCU.

  • Hi James,
    I’ve been looking for a good solution to detect the washing machine and dryer state and this seems like a great solution. Very simple, cheap and without having to fiddle with the electronics of the actual machine.

    I’m gonna try to create this same setup using a ESP8266.
    Thanks for the idea!

  • “I noticed that while the washer was running I didn’t get piezo values under 18″
    From your chart, how did you arrive at that conclusion?

    My piezo sensor is on average getting a vibration value of 310. In fact, even with your code it is collecting values around 310 when the washing machine is running and when it is finished. I am confused as to how you got 18?

    Thank you

    • Your threshold will be different and should be less than the lowest value you get while the machine is running. You’re looking to ignore all the white noise and only register vibrations from the running washer.

Join the Discussion

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>