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
    
}

Arduino Highlighter Test

This post is to test the syntax highlighter for arduino.

/* This is a multi-line
comment */
#define OUTPIN 11
int thisisavariable = B10011;
boolean isAdvanced = true;
void setup() {
  Serial.begin(9600); // This is an in-line comment
  pinMode(11,OUTPIN);
}
 
void loop() {
  Serial.println("This is a string!");
  if(thisisavariable < 10e4){
    digitalWrite(11,HIGH);
  }
  if(isAdvanced){
    ADCSRA |= (1 << ADSC);
    sei();
  }
}