Hello all, I'm new into the forum, so I'm sorry if I don't follow the rules properly.
After this, I will explain what is my problem.
I'm using an ESP32 with a GY-521 MPU6050, with the purpose of fall detection. The device has a power comsuption of 80mA while working, as I'm using a 600mAh battery to power it on, I have an autonomy of 7 hours theorically.
I thought of using the sleep mode of the ESP32 as well as the INT pin of the MPU6050 in order to wake up the MCU only when there is a movement. I've been looking all around the different forums but I can't get a clear answer in terms of coding.
Here is my code:
// ----------------------------
// Standard Libraries - Already Installed if you have ESP32 set up
// ----------------------------
#include <WiFi.h>
#include <FS.h>
#include <PubSubClient.h>
// ----------------------------
// Additional Libraries - each one of these will need to be installed.
// ----------------------------
#include <WiFiManager.h>
// Captive portal for configuring the WiFi
// Can be installed from the library manager (Search for "WifiManager", install the Alhpa version)
// https://github.com/tzapu/WiFiManager
#include <ESP_DoubleResetDetector.h>
// A library for checking if the reset button has been pressed twice
// Can be used to enable config mode
// Can be installed from the library manager (Search for "ESP_DoubleResetDetector")
//https://github.com/khoih-prog/ESP_DoubleResetDetector
// -------------------------------------
// ------- Other Config ------
// -------------------------------------
#include <Wire.h>
#include <MPU6050.h>
#define BUZZER_PIN 14
#define BUZZER_CHANNEL 0
#define BEEP_DURATION 5000 // 1 second (in milliseconds)
#include "time.h"
const int PIN_LED = 2;
// Number of seconds after reset during which a
// subseqent reset will be considered a double reset.
#define DRD_TIMEOUT 10
// RTC Memory Address for the DoubleResetDetector to use
#define DRD_ADDRESS 0
// -----------------------------
// -----------------------------
DoubleResetDetector *drd;
unsigned long button_time = 0;
unsigned long last_button_time = 0;
const float fallThreshold = 650000; // Adjust this value to suit your needs (in m/s^3)
const int sampleInterval = 10; // Interval in milliseconds between readings
float prevAccX = 0.0, prevAccY = 0.0, prevAccZ = 0.0;
const char* ntpServer = "in.pool.ntp.org";
const long gmtOffset_sec = 106200;
const int daylightOffset_sec = 0;
char dateTimeStr[30];
bool buttonInterrupted = false;
unsigned long delayStartTime = 0;
const int DOUBLE_PRESS_THRESHOLD = 1500; // Time threshold for double press in milliseconds
bool lastFallDetection = false;
unsigned long lastFallTime = 0;
struct Button {
const uint8_t PIN;
uint32_t numberKeyPresses;
bool pressed;
};
Button button1 = {12, 0, false};
MPU6050 mpu;
void printLocalTime(){
struct tm timeinfo;
if(!getLocalTime(&timeinfo)){
Serial.println("Failed to obtain time");
return;
}
// Print only the current day and time
strftime(dateTimeStr, sizeof(dateTimeStr), "%A, %B %d %Y %H:%M:%S", &timeinfo);
}
void IRAM_ATTR isr() {
button_time = millis();
if (button_time - last_button_time > 250){
button1.numberKeyPresses++;
button1.pressed = true;
last_button_time = button_time;
buttonInterrupted = true; // Set the flag to indicate button press
}
}
///////////AÑADIDOS///////////////
#include <Preferences.h>
//#include <nvs_flash.h>
Preferences preferences;
WiFiClient espClient;
PubSubClient client(espClient);
#define NUMERO_SONDA "1"
#define TOPIC_X "homeassistant/" NUMERO_SONDA "/JerkX"
#define TOPIC_Y "homeassistant/" NUMERO_SONDA "/JerkY"
#define TOPIC_Z "homeassistant/" NUMERO_SONDA "/JerkZ"
#define TOPIC_X_ac "homeassistant/" NUMERO_SONDA "/AceleracionX"
#define TOPIC_Y_ac "homeassistant/" NUMERO_SONDA "/AceleracionY"
#define TOPIC_Z_ac "homeassistant/" NUMERO_SONDA "/AceleracionZ"
#define TOPIC_CAIDA "homeassistant/" NUMERO_SONDA "/caida"
#define TOPIC_SQRT "homeassistant/" NUMERO_SONDA "/raiz"
const char* ssid = "xxxx";
const char* password = "xxxx";
const uint8_t sda = 4;
const uint8_t scl = 5;
void setup()
{
Wire.begin(sda, scl);
// Initialize MPU6050
mpu.initialize();
// Verify the connection
Serial.println(mpu.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
pinMode(button1.PIN, INPUT_PULLUP);
attachInterrupt(button1.PIN, isr, FALLING);
pinMode(PIN_LED, OUTPUT);
Serial.begin(115200);
delay(10);
digitalWrite(PIN_LED, HIGH);
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
preferences.begin("credentials", false); // "credentials" es el espacio de preferencias
String mqttBrokerIP = preferences.getString("mqttBrokerIP","");
// Conectar al broker MQTT
client.setServer(mqttBrokerIP.c_str(), 1883);
}
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);
if (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
}
void reconnect() {
// Loop until we're reconnected
if (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect(NUMERO_SONDA, xxxx, xxxx)) {
Serial.println("connected");
// Subscribe
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void loop()
{
String mqttBrokerIP = preferences.getString("mqttBrokerIP", "");
if (mqttBrokerIP.length() == 0 || Serial.available() > 0) {
// Pedir la dirección IP del broker MQTT por el puerto serie
Serial.println("Introduce la IP del broker MQTT:");
while (!Serial.available()) {
delay(1000);
}
mqttBrokerIP = Serial.readStringUntil('\n');
// Guardar la IP en preferencias
preferences.putString("mqttBrokerIP", mqttBrokerIP);
Serial.print("Broker MQTT IP guardado en preferencias: ");
Serial.println(mqttBrokerIP);
Serial.println("Por favor, reinicie la sonda");
}
static unsigned long lastTime = 0;
// Read accelerometer data
if (millis() - lastTime >= sampleInterval)
{
lastTime = millis();
int16_t ax, ay, az;
mpu.getAcceleration(&ax, &ay, &az);
Serial.print(";Eje X sin correccion; ");
Serial.print(ax);
Serial.println(";");
Serial.print(";Eje Y sin correccion; ");
Serial.print(ay);
Serial.println(";");
Serial.print(";Eje Z sin correccion; ");
Serial.print(az);
Serial.println(";");
delay(1000);
// Convert accelerometer readings from m/s^2 to mg (1 g = 9.8 m/s^2)
float acceleration_mg_x = ax / 9.8;
float acceleration_mg_y = ay / 9.8;
float acceleration_mg_z = az / 9.8;
client.publish(TOPIC_X_ac, String(acceleration_mg_x).c_str());
client.publish(TOPIC_Y_ac, String(acceleration_mg_y).c_str());
client.publish(TOPIC_Z_ac, String(acceleration_mg_z).c_str());
// Calculate jerk by taking the derivative of acceleration with respect to time
float jerkX = (acceleration_mg_x - prevAccX) / (sampleInterval / 1000.0);
float jerkY = (acceleration_mg_y - prevAccY) / (sampleInterval / 1000.0);
float jerkZ = (acceleration_mg_z - prevAccZ) / (sampleInterval / 1000.0);
Serial.print(";Eje X con correccion; ");
Serial.print(acceleration_mg_x);
Serial.println(";");
Serial.print(";Eje Y con correccion; ");
Serial.print(acceleration_mg_y);
Serial.println(";");
Serial.print(";Eje Z con correccion; ");
Serial.print(acceleration_mg_z);
Serial.println(";");
delay(1000);
// Update previous acceleration values for the next iteration
prevAccX = acceleration_mg_x;
prevAccY = acceleration_mg_y;
prevAccZ = acceleration_mg_z;
client.publish(TOPIC_X, String(jerkX).c_str());
client.publish(TOPIC_Y, String(jerkY).c_str());
client.publish(TOPIC_Z, String(jerkZ).c_str());
// Calculate the magnitude of jerk
float jerkMagnitude = sqrt(jerkX * jerkX + jerkY * jerkY + jerkZ * jerkZ);
client.publish(TOPIC_SQRT, String(jerkMagnitude).c_str());
//Serial.println(jerkMagnitude);
// Check for a fall
if (jerkMagnitude > fallThreshold)
{
// Caida detectada
Serial.println("Fall detected!");
client.publish(TOPIC_CAIDA, "true");
// Reset the buttonInterrupted flag
buttonInterrupted = false;
delayStartTime = millis();
while (delayStartTime > 0 && millis() - delayStartTime < BEEP_DURATION)
{
if (button1.pressed)
{
button1.pressed = false;
Serial.println("Buzzer stopped by button press.");
break;
}
}
if (!buttonInterrupted) {
// No se ha presionado el boton, mandando señal de caida
}
delayStartTime = 0;
}
if (button1.pressed)
{
if (delayStartTime > 0)
{
delayStartTime = 0;
}
Serial.printf("Stop Button was pressed %u times\n", button1.numberKeyPresses);
button1.pressed = false;
}
}
if (WiFi.status() != WL_CONNECTED){
setup_wifi();
}
if (!client.connected()) {
reconnect();
}
client.loop();
}
Thanks in advance.