ESP32 Fall Detector

0 2835 Medium

An improvement from my previous fall detector. It can send an email by sensing a fall or with the simple press of a button.

 

ESP32 Fall Detector

 

 

 

Things used in this project

HARDWARE LIST
1 DFRobot ESP32 ESP-WROOM Module
1 Silicon Labs CP2102 USB to UART Bridge
1 MCP73831 Li-Ion Charger IC
1 LM317BD2T Adjustable Regulator
2 0805 4.7uF Capacitor
1 0805 100nF Capacitor
1 0805 1uF Capacitor
1 WS2812b LED
4 1206 LED
1 Micro USB Connector
1 0805 470 ohm Resistor
1 0805 2k ohm Resistor
1 0805 510 ohm Resistor
1 0805 300 ohm Resistor
2 0805 10k ohm Resistor
2 0805 270 ohm Resistor
2 6mm x 6mm Pushbutton
1 SMD 6mm x 6mm Tall Pushbutton

SOFTWARE APPS AND ONLINE SERVICES

· Autodesk EagleCAD
· Autodesk Fusion 360


HAND TOOLS AND FABRICATION MACHINES

· 3D Printer (generic) 
· Soldering iron (generic) 
· Digital Microscope
 

Story

I would like to thank DFRobot for sponsoring this project.

 

 

Previous Project

Back in August of 2017, I imagined a device that could alert users if one of their loved ones experienced a fall or pressed a “panic” button. It used an ESP8266 and was assembled on a piece of perf-board. It had a single LED that would indicate if a fall had occurred. The device also featured a very basic LiPo charging circuit that had no indicators.

 

 

New Idea

Since my last fall detector was so rudimentary, I wanted to make drastic improvements. The first one was making it USB programmable, so I used a CP2102 USB to UART converter IC to handle the USB to UART serial connection.

 

 

I also wanted there to be more indications of the operations, so I added an LED for charging, one for power, and two for the USB status. I chose to use an ESP32 due to its increased power and Bluetooth connectivity, which can allow for future expansion, such as an accompanying app.

 

PCB Design

All these new features would require a lot of additional circuitry, and a simple piece of perf-board would not cut it. This required a PCB, which I designed in EagleCAD. I began by laying out the connections with their schematic editor. Then I moved onto making the actual board and traces.

 

 

Soldering

This was the most difficult part because of the fine-pitched pins. The hardest component to solder was the CP2102, which comes in a QFN-28 package. Each pin is just.5mm apart, and without a stencil, this was fairly tricky to attach. I solved this problem by applying a generous amount of liquid flux to the pads and then running a small amount of solder over the pins.

 

 

 

 

Usage

The device works by checking the acceleration measured by the MPU6050 at set intervals. Once it detects a fall, it sends an email to a set contact. I have found out that the battery lasts about three days, so it must be charged regularly. There is also a button that is connected to a hardware interrupt that can send an email when pressed.

 

 

Schematics

 

 

 

Board Schematic

CODE ESP32 CODE MAIN

CODE
#include <Wire.h>
#include <SimpleTimer.h>

#include <Arduino.h>

#include <WiFi.h>
#include <WiFiMulti.h>

#include <HTTPClient.h>
#include "sendemail.h"

const int MPU_addr=0x68;
int16_t AcX, AcY, AcZ, TmP,GyX,GyY,GyZ;
float AcX_calc, AcY_calc, AcZ_calc;
uint32_t lastTime;

// WiFi network info.
const char* SSID = "ssid";
const char* PASS = "wifi pass";

SendEmail e("stmp.gmail.com", 465, "[email protected]", "password", 5000, true);

#define LED_PIN 14
#define BUTTON_PIN 27

void check_imu(){
  readIMU();
  Serial.print("AcX: "); Serial.print(AcX); Serial.print("g | AcY: "); Serial.print(AcY); Serial.print("g | AcZ: "); Serial.print(AcZ);
  Serial.println("g");
  if(abs(AcX_calc)> 22000 || abs(AcY)> 22000|| abs(AcZ) > 27000){
    Serial.println("Fall detected");
    int button_val = 1;
    lastTime = millis();
    button_val = digitalRead(BUTTON_PIN);
    while(millis()-lastTime<5000){
      button_val = digitalRead(BUTTON_PIN);
      delay(10); //Debounce
      Serial.println(button_val);
      if(!button_val) break;
    }
    if(!button_val){
      Serial.println("Didn't do anything, button was pressed");
      delay(200);
    }
    else{
      alarm();
    }
    delay(50);
  }
  
}

void setup() {
	WiFi.begin(SSID, PASS);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  Wire.begin(4,5);
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);
  Wire.write(0);
  Wire.endTransmission(true);
  Serial.begin(115200);
  Serial.println("Wrote to IMU");
  
}

void loop() {
  int button_state = digitalRead(BUTTON_PIN);
  if(!button_state){
    alarm();
    delay(500);
  }
  check_imu();
}

void readIMU(){
  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)
  GyX=Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
  GyY=Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
  GyZ=Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
}

void alarm(){
  Serial.println("Alarm sent!");
  e.send("<[email protected]>", "<[email protected]>", "ALERT: Fall Detected", "Fall has been detected");
}

 

 

Sendemail.cpp

CODE
#include "sendemail.h"

SendEmail::SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const bool ssl) :
    host(host), port(port), user(user), passwd(passwd), timeout(timeout), ssl(ssl), client((ssl) ? new WiFiClientSecure() : new WiFiClient())
{

}

String SendEmail::readClient()
{
  String r = client->readStringUntil('\n');
  r.trim();
  while (client->available()) r += client->readString();
  return r;
}

bool SendEmail::send(const String& from, const String& to, const String& subject, const String& msg)
{
  if (!host.length())
  {
    return false;
  }
  client->stop();
  client->setTimeout(timeout);
  // smtp connect
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.print("Connecting: ");
  DEBUG_EMAIL_PORT.print(host);
  DEBUG_EMAIL_PORT.print(":");
  DEBUG_EMAIL_PORT.println(port);
#endif
  if (!client->connect(host.c_str(), port))
  {
    return false;
  }
  String buffer = readClient();
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.println(buffer);
#endif
  if (!buffer.startsWith(F("220")))
  {
    return false;
  }
  buffer = F("EHLO ");
  buffer += client->localIP();
  client->println(buffer);
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.println(buffer);
#endif
  buffer = readClient();
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.println(buffer);
#endif
  if (!buffer.startsWith(F("250")))
  {
    return false;
  }
  if (user.length()>0  && passwd.length()>0 )
  {
    buffer = F("AUTH LOGIN");
    client->println(buffer);
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.println(buffer);
#endif
    buffer = readClient();
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.println(buffer);
#endif
    if (!buffer.startsWith(F("334")))
    {
      return false;
    }
    base64 b;
    buffer = user;
    buffer = b.encode(buffer);
    client->println(buffer);
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.println(buffer);
#endif
    buffer = readClient();
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.println(buffer);
#endif
    if (!buffer.startsWith(F("334")))
    {
      return false;
    }
    buffer = this->passwd;
    buffer = b.encode(buffer);
    client->println(buffer);
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.println(buffer);
#endif
    buffer = readClient();
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.println(buffer);
#endif
    if (!buffer.startsWith(F("235")))
    {
      return false;
    }
  }
  // smtp send mail
  buffer = F("MAIL FROM: ");
  buffer += from;
  client->println(buffer);
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.println(buffer);
#endif
  buffer = readClient();
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.println(buffer);
#endif
  if (!buffer.startsWith(F("250")))
  {
    return false;
  }
  buffer = F("RCPT TO: ");
  buffer += to;
  client->println(buffer);
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.println(buffer);
#endif
  buffer = readClient();
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.println(buffer);
#endif
  if (!buffer.startsWith(F("250")))
  {
    return false;
  }
  buffer = F("DATA");
  client->println(buffer);
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.println(buffer);
#endif
  buffer = readClient();
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.println(buffer);
#endif
  if (!buffer.startsWith(F("354")))
  {
    return false;
  }
  buffer = F("From: ");
  buffer += from;
  client->println(buffer);
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.println(buffer);
#endif
  buffer = F("To: ");
  buffer += to;
  client->println(buffer);
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.println(buffer);
#endif
  buffer = F("Subject: ");
  buffer += subject;
  buffer += F("\r\n");
  client->println(buffer);
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.println(buffer);
#endif
  buffer = msg;
  client->println(buffer);
  client->println('.');
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.println(buffer);
#endif
  buffer = F("QUIT");
  client->println(buffer);
#ifdef DEBUG_EMAIL_PORT
  DEBUG_EMAIL_PORT.println(buffer);
#endif
  return true;
}

 

 

Sendemail.h

CODE
#ifndef __SENDEMAIL_H
#define __SENDEMAIL_H

//#define DEBUG_EMAIL_PORT

#include <WiFiClient.h>
#include <WiFiClientSecure.h>
#include <base64.h>

class SendEmail
{
  private:
    const String host;
    const int port;
    const String user;
    const String passwd;
    const int timeout;
    const bool ssl;
    WiFiClient* client;
    String readClient();
  public:
   SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const bool ssl);
   bool send(const String& from, const String& to, const String& subject, const String& msg);
   ~SendEmail() {client->stop(); delete client;}
};

#endif

The article was first published in hackster, March 18, 2019

cr: https://www.hackster.io/gatoninja236/esp32-fall-detector-b8ec6f

author: Evan Rust

License
All Rights
Reserved
licensBg
0