Last active
October 27, 2021 02:24
-
-
Save erijpkema/863fa08b5555d7089ba84f506d79444a to your computer and use it in GitHub Desktop.
Washing machine shake sensor MPU-6050 + DHT mqtt home assistant.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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