Jhong Barien
Published © MIT

RemindMe!: A Smart Tag That Reminds You

Stay safe with the smart tag that reminds you to wear a face mask when you'll go outside and sanitize yourself upon returning home.

IntermediateFull instructions provided8 hours910

Things used in this project

Hardware components

ESP32
Espressif ESP32
×1
SparkFun Triple Axis Accelerometer Breakout - ADXL335
SparkFun Triple Axis Accelerometer Breakout - ADXL335
×1
Jumper wires (generic)
Jumper wires (generic)
×1
500 mAh Li-Poly Battery
×1

Software apps and online services

Blynk
Blynk

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free

Story

Read more

Schematics

Schematic Diagram

Code

RemindME! Code

Arduino
//deep sleep
#include "esp_sleep.h"
#include "sys/time.h"
RTC_DATA_ATTR static time_t last;
RTC_DATA_ATTR static uint32_t bootcount;
RTC_DATA_ATTR int previousState = 2;
#define GPIO_DEEP_SLEEP_DURATION     15
struct timeval now;
//for wifi
#include <WiFi.h>
#include <WiFiClient.h>
char ssid[] = "PLDT_Home_CDC2D";
char pass[] = "14325garciA";
int attempts = 1;
//gy-61 pins. remember that *use only adc1 pins beacuse wifi is messing up the adc2 pins*
const int xpin = 32, ypin = 33, zpin = 35;
//calibrate variables
int totalx, totaly, totalz, calibratex, calibratey, calibratez;
//acceleration
float totalAcce, initialAcce, difference;
int motionCounter;
//blynk
int timer = 0;
#define BLYNK_PRINT Serial
#include <BlynkSimpleEsp32.h>
char auth[] = "dofF8fFiA3ex4tOVDnsfFXKhOCmVZQAL";



void setup()
{
  Serial.begin(9600);
  gettimeofday(&now, NULL);
  last = now.tv_sec;
  Serial.println(previousState);
  WiFi.begin(ssid, pass);
  //check if the tag is inside the house
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
    Serial.println(attempts);
    attempts++;
    //since the tag can't connect to home wifi and our previous states indicates that it was picked earlier, we'll change its state to 0 to indicate that it's outside
    if (attempts == 5 && previousState == 1) {
      previousState = 0;//indicates that it was outside the house
      Serial.printf("out! enter deep sleep for 10 mins\n"); //the device will go to deep sleep for 10minutes
      esp_deep_sleep(1000000LL * 15);
      Serial.printf("in deep sleep\n");
    }
    //there are chances that we'll lost connection in the wifi even tho we didn't go outside. In that case we'll just go to deep sleep for 1 min and try to reconnect again. State wont be change.
    if (attempts == 5) {
      Serial.printf("wifi not detected! enter deep sleep for 2 mins\n"); //the device will go to deep sleep for 2minutes
      esp_deep_sleep(1000000LL * 60);
      Serial.printf("in deep sleep\n");
    }
  }
  //if the tag is inside the house it will proceed to the following
  calibrateSensor();
  getInitialAcce();
  //determine whether the tag is in motion or at rest
  for (int i = 0; i <= 10; i++) {
    getMotionChange();
    if (difference >= 70) {
      motionCounter++;
    }
    Serial.println(motionCounter);
  }
  //if the tag was previously outside and went inside and not in motion, it means that the owner just went home so we'll notify him to wash his/her hands
  if (previousState == 0 && motionCounter < 3) {
    previousState = 2; //indicates that the tag is now inside the house
    Serial.println("Please Wash Your Hands");
    notifyIn();
    //go to deep sleep
    Serial.printf("in! enter deep sleep for 10 mins\n");
    esp_deep_sleep(1000000LL * 600);
    Serial.printf("in deep sleep\n");
  }
  //if the tag was inside the house and set in motion, it means that the owner just picked the tag because maybe he'll go outside so we'll notify him to wear a facemask
  if (motionCounter >= 3 && previousState == 2 || previousState == 1) {
    previousState = 1; //indicates that the tag was picked
    Serial.println("Please don't forget to wear mask");
    notifyOut();
    //go to deep sleep for 5mins and upon restart will check if the owner was outside
    Serial.printf("picked! enter deep sleep for 5 mins\n");
    esp_deep_sleep(1000000LL * 15);
    Serial.printf("in deep sleep\n");
  }
  //since the tag is already inside and w/o motion, we'll check the timer from the blynk, to see if it's late at night so the tag can go to deep sleep until morning to save power
  if (previousState == 2 && motionCounter < 3) {
    checkTime();
    if (timer == 1) {
      //i set the timer in the blynk app to go to sleep when it's 8pm until 6 am, thats 10 hours so the tag will sleep for 36000 seconds.
      Serial.printf("sleep! enter deep sleep for 10 hours\n");
      esp_deep_sleep(1000000LL * 36000);
      Serial.printf("in deep sleep\n");
    }
    //if it's not between 8pm and 6 am, the tag shouldn't sleep and just continue to see if it will be picked up by the owner. So we'll just set it to sleep for 30sec
    else {
      Serial.printf("enter deep sleep for 30secs\n");
      esp_deep_sleep(1000000LL * 30);
      Serial.printf("in deep sleep\n");
    }
  }
}

void loop()
{
}

void notifyIn() {
  Blynk.config(auth);
  while (Blynk.connect() == false) {
    Serial.print("x");
  }
  Blynk.notify("Hey, Rod! Please ensure to clean and sanitize your body.");
  delay(500);
}
void notifyOut() {
  Blynk.config(auth);
  while (Blynk.connect() == false) {
    Serial.print("x");
  }
  Blynk.notify("Hey, Rod! Don't forget to wear mask before going outside.");
  delay(500);
}
void checkTime() {
  Blynk.config(auth);
  while (Blynk.connect() == false) {
    Serial.print("x");
  }
  for (int i = 0; i <= 5; i++) {
    Blynk.run();
    Blynk.syncAll();
  }
}
BLYNK_CONNECTED() {
  //get data stored in virtual pin V0 from server
  Blynk.syncVirtual(V1);
}
BLYNK_WRITE(V1) {
  Serial.println(param.asInt());
  timer = param.asInt();
}

//calculate the difference between the initial total acceleration and current total acceleration to determine if there is motion change
void getMotionChange() {
  int x = (analogRead(xpin) - calibratex);
  int y = (analogRead(ypin) - calibratey);
  int z = (analogRead(zpin) - calibratex);
  totalAcce = pow(pow(x, 2) + pow(y, 2) + pow(z, 2), 0.5);
  Serial.print(totalAcce);
  Serial.println( "total acc");
  Serial.print(x); //print x value on serial monitor
  Serial.print("\t");
  Serial.print(y); //print y value on serial monitor
  Serial.print("\t");
  Serial.print(z); //print z value on serial monitor
  Serial.print("\n");
  delay(200);
  difference = abs(initialAcce - totalAcce);
  Serial.print(difference);
  Serial.println(" Motion Change");
}

//get the initial average reading from the sensor for calibration
void calibrateSensor() {
  for (int i = 0; i <= 200; i++) {
    int x = analogRead(xpin);
    totalx += x;
    int y = analogRead(ypin);
    totaly += y;
    int z = analogRead(zpin);
    totalz += z;
  }
  calibratex = totalx / 200;
  calibratey = totaly / 200;
  calibratez = totalz / 200;
}

//get the initial total acceleration of the device in all axis
void getInitialAcce() {
  int x = (analogRead(xpin) - calibratex);
  int y = (analogRead(ypin) - calibratey);
  int z = (analogRead(zpin) - calibratex);
  totalAcce = pow(pow(x, 2) + pow(y, 2) + pow(z, 2), 0.5); //compute the total acceleration in all axis
  Serial.print(totalAcce);
  Serial.println( "initial acce");
  initialAcce = totalAcce;
}

Credits

Jhong Barien

Jhong Barien

1 project • 0 followers

Comments