Skip to content

Instantly share code, notes, and snippets.

@erijpkema
Last active October 27, 2021 02:24
Show Gist options
  • Save erijpkema/863fa08b5555d7089ba84f506d79444a to your computer and use it in GitHub Desktop.
Save erijpkema/863fa08b5555d7089ba84f506d79444a to your computer and use it in GitHub Desktop.
Washing machine shake sensor MPU-6050 + DHT mqtt home assistant.
#include <DHT.h>
#include <EEPROM.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#define DHTPIN 2 // D4 what digital pin we're connected to
#define DHTTYPE DHT11 // DHT 11
bool debug = false;
// DHT humidity sensor
DHT dht(DHTPIN, DHTTYPE);
//Wifi stuff
const char* ssid = "";
const char* password = "";
WiFiClient espClient;
//mqtt stuff
const char* mqtt_user = "";
const char* mqtt_pass = "";
const char* clientId = "";
const char* MQTTtopic = "";
IPAddress server(192, 168, 1 ,42);
PubSubClient client(server, 1883, espClient);
//MPU-6050 stuff
const int MPU_addr=0x68; // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
// Vars for an average of the gyro readings.
const int numReadings = 6;
const int threshold = 20000; // Shakiness at which we consider the washing machine to be running
unsigned int readIndex = 0; // the index of the current reading
unsigned long shakiness = 0; // Commulative fluctuation in XYZ acc
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
randomSeed(micros());
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a random client ID
// Attempt to connect
if (client.connect(clientId, mqtt_user, mqtt_pass)) {
Serial.println("connected");
// Once connected, publish an announcement...
// client.publish(MQTTTopic, "Starting...");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setup_gyro(){
Wire.begin();
Wire.beginTransmission(MPU_addr);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
}
void setup() {
Serial.begin(115200);
dht.begin();
setup_wifi();
setup_gyro();
client.setServer(server, 1883);
}
void read_gyro(){
/*
We consider the washing machine to be shaking, when there's much fluctuation in the X, Y, Z readings.
*/
int16_t Old_AcX,Old_AcY,Old_AcZ;
shakiness = 0;
readIndex = 0;
for (readIndex; readIndex < numReadings; readIndex++) {
Old_AcX = AcX; Old_AcY = AcY; Old_AcZ = AcZ;
Wire.beginTransmission(MPU_addr);
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU_addr,14,true); // request a total of 14 registers
AcX=Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
AcY=Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
AcZ=Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
Tmp=Wire.read()<<8|Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
Tmp=(Tmp/340.00+36.53);
// add the reading to the total:
if (readIndex > 0) {
shakiness = shakiness + abs(AcX - Old_AcX) + abs(AcY - Old_AcY) + abs(AcZ - Old_AcZ);
}
delay(333);
}
// calculate the average:
Serial.print("AcX: "); Serial.print(AcX); Serial.print(" AcY: "); Serial.print(AcY);Serial.print(" AcZ: "); Serial.println(AcZ);
Serial.print("shakiness: "); Serial.println(shakiness);
}
void loop() {
delay(2000);
read_gyro();
// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h = dht.readHumidity();
// Read temperature as Celsius (the default)
float t = dht.readTemperature();
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
// Compute heat index in Celsius (isFahreheit = false)
float hic = dht.computeHeatIndex(t, h, false);
// battery connected wiyth 100kOHM resistor to A0
pinMode(A0, INPUT);
unsigned int raw = analogRead(A0);
float volt = raw * 4.2 / 1023.0;
bool running = false;
if (shakiness > threshold) {
running = true;
}
// reserve 1 byte of eeprom
EEPROM.begin(2);
byte romstore[2];
romstore[0] = EEPROM.read(0);
romstore[1] = EEPROM.read(1);
// 123 in [0] is a marker to detect first use
if (romstore[0] != 123) {
romstore[0] = 123;
// romstore[1] is a marker of how many cycles ago we were running.
// Only 1-10 is of real interest...
romstore[1] = 254;
}
// Only report that whe are running when we measure running for the second time.
bool report_running = false;
if (running and romstore[1] == 0) {
report_running = true;
}
if (running) {
romstore[1] = 0;
} else if (romstore[1] < 254) {
romstore[1]++;
}
// system_rtc_mem_write(64, rtcStore, 2);
EEPROM.write(0, romstore[0]);
EEPROM.write(1, romstore[1]);
EEPROM.end();
// ------------------------ Send message
if (!client.connected()) {
reconnect();
}
client.loop();
String payload = "{\"Humidity\":" + String(h) +
",\"Temp\":" + String(t) +
",\"GyroTemp\":" + String(Tmp) +
",\"Hic\":" + String(hic) +
",\"Volt\":" + String(volt) +
",\"Shakiness\":" + String(shakiness) +
//",\"AcX\":" + String(AcX) +
//",\"AcY\":" + String(AcY) +
//",\"AcZ\":" + String(AcZ) +
",\"running\":" + String(report_running) +
"}";
delay(2000);
Serial.println(payload);
int succ = false;
int attempts = 10;
while (succ == false && attempts-- > 0) {
succ = client.publish(MQTTtopic, payload.c_str());
Serial.print('Sending: ');
Serial.println(succ);
delay(500);
}
// we're checking if the machine starts again every minute for ten minutus
// after the last detection of movement.
if (debug != true) {
if (romstore[1] < 10) {
ESP.deepSleep(60e6);
}
// sleep 10 minutes.
ESP.deepSleep(600e6);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment