/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial
/* Fill in information from Blynk Device Info here */
#define BLYNK_TEMPLATE_ID "TMPL6FVQINHXz"
#define BLYNK_TEMPLATE_NAME "MotionDetection"
#define BLYNK_AUTH_TOKEN "DZbzrSTI3JSR6oukSryNnstfAdqe3lL7"
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <Wire.h>
#include <NTPClient.h> // NTPClient library by Fabrice Weinberg
#include <WiFiUdp.h>
#include <Adafruit_MPU6050.h> // MPU6050 by Adafruit
#include <Adafruit_Sensor.h>
// #include <Adafruit_ADXL345_U.h> // ADXL345 by Adafruit
#include <math.h>
// *******************
// Configuration
// *******************
// Replace with your WiFi credentials
// Set password to "" for open networks.
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
// Define hardware pin for Magnetic Door Sensor (use internal pull-up)
#define DOOR_SENSOR_PIN 15
// Impact and motion detection thresholds (adjustable)
#define IMPACT_THRESHOLD 1.5 // Threshold in m/s^2 above which an impact is detected
#define MOTION_THRESHOLD 0.2 // Threshold for detecting motion
// Maximum offline records (adjust size based on ESP32 memory constraints)
#define MAX_OFFLINE_RECORDS 50
// *******************
// Global Variables
// *******************
// Sensor status flags
bool doorStatus = HIGH; // Assume door is initially closed (HIGH)
bool motionDetected = false;
bool impactDetected = false;
struct SensorData {
bool doorStatus;
bool motionDetected;
bool impactDetected;
String timestamp;
};
// Offline data storage array
SensorData offlineData[MAX_OFFLINE_RECORDS];
int offlineDataCount = 0; // Track stored records
BlynkTimer timer;
// Blynk transmission rate control (if needed)
unsigned long lastTransmissionTime = 0;
unsigned long transmissionInterval = 1000; // milliseconds
// *******************
// Sensor & Time Objects
// *******************
// MPU6050 sensor (primary for motion & impact)
Adafruit_MPU6050 mpu;
// ADXL345 sensor (secondary accelerometer for validation)
// Adafruit_ADXL345_Unified adxl = Adafruit_ADXL345_Unified(12345);
// NTP setup for timestamping
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 0, 60000); // update every 60 seconds
// *******************
// Function Prototypes
// *******************
void checkDoorSensor();
void checkMotionAndImpact();
void syncOfflineData();
void storeOfflineData();
void sendDataToBlynk();
// *******************
// Setup Function
// *******************
void setup() {
Serial.begin(115200);
// Setup magnetic door sensor pin (using internal pull-up)
pinMode(DOOR_SENSOR_PIN, INPUT_PULLUP);
// Initialize MPU6050 sensor
if (!mpu.begin()) {
Serial.println("Failed to initialize MPU6050!");
while (1)
; // halt if sensor not found
} else {
Serial.println("MPU6050 initialized.");
}
// Initialize ADXL345 sensor
// if (!adxl.begin()) {
// Serial.println("Failed to initialize ADXL345!");
// // while (1)
// // ; // halt if sensor not found
// } else {
// Serial.println("ADXL345 initialized.");
// // Set ADXL345 range to +/- 16g (adjustable if needed)
// adxl.setRange(ADXL345_RANGE_16_G);
// }
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
// Initialize NTP client for timestamping
timeClient.begin();
timeClient.update();
timer.setInterval(1000L, checkDoorSensor);
timer.setInterval(500L, checkMotionAndImpact);
timer.setInterval(5000L, syncOfflineData);
}
void loop() {
Blynk.run();
timer.run();
timeClient.update();
}
// *******************
// Check Door Sensor
// *******************
void checkDoorSensor() {
bool currentDoorStatus = digitalRead(DOOR_SENSOR_PIN);
if (currentDoorStatus != doorStatus) {
doorStatus = currentDoorStatus;
Serial.println(doorStatus ? "Door Closed" : "Door Open");
sendDataToBlynk();
}
}
// *******************
// Check Motion & Impact
// *******************
void checkMotionAndImpact() {
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
float ax = a.acceleration.x;
float ay = a.acceleration.y;
float az = a.acceleration.z;
float mpuAccelMag = fabs(sqrt(ax * ax + ay * ay + az * az) - 9.81);
Serial.print("MPU6050 Acceleration Magnitude:");
Serial.println(mpuAccelMag);
// sensors_event_t event;
// adxl.getEvent(&event);
// float adxlAccelMag = sqrt(event.acceleration.x * event.acceleration.x + event.acceleration.y * event.acceleration.y + event.acceleration.z * event.acceleration.z);
// Serial.print("Adxl345 Acceleration Magnitude:");
// Serial.println(adxlAccelMag);
if (mpuAccelMag > MOTION_THRESHOLD) { //|| (adxlAccelMag > MOTION_THRESHOLD)) {
if (!motionDetected) {
motionDetected = true;
Serial.println("Motion Detected!");
sendDataToBlynk();
}
} else if (motionDetected) {
motionDetected = false;
Serial.println("Motion Stopped.");
sendDataToBlynk();
}
if (mpuAccelMag > IMPACT_THRESHOLD) { // || (adxlAccelMag > IMPACT_THRESHOLD)) {
if (!impactDetected) {
impactDetected = true;
Serial.println("Impact Detected!");
sendDataToBlynk();
}
} else {
impactDetected = false;
}
if (WiFi.status() != WL_CONNECTED) {
storeOfflineData();
}
}
// *******************
// Send Data to Blynk
// *******************
void sendDataToBlynk() {
String timestamp = timeClient.getFormattedTime();
Serial.print("Sending -> Door: ");
Serial.print(doorStatus ? "Closed" : "Open");
Serial.print(", Motion: ");
Serial.print(motionDetected ? "Detected" : "None");
Serial.print(", Impact: ");
Serial.print(impactDetected ? "Detected" : "None");
Serial.print(", Time: ");
Serial.println(timestamp);
// Check if Wifi is connected send data to Blynk
if (WiFi.status() == WL_CONNECTED) {
Blynk.virtualWrite(V1, doorStatus ? "Closed" : "Open");
Blynk.virtualWrite(V2, motionDetected ? "Motion" : "No Motion");
Blynk.virtualWrite(V3, impactDetected ? "Impact" : "No Impact");
Blynk.virtualWrite(V4, timestamp);
} else { // If Wi-Fi is not connected store data offline
storeOfflineData();
}
}
// *******************
// Store Offline Data
// *******************
void storeOfflineData() {
if (offlineDataCount < MAX_OFFLINE_RECORDS) {
offlineData[offlineDataCount] = { doorStatus, motionDetected, impactDetected, timeClient.getFormattedTime() };
offlineDataCount++;
Serial.println("Stored offline data.");
} else {
Serial.println("Offline storage full! Old data will be lost.");
}
}
// *******************
// Sync Offline Data
// *******************
void syncOfflineData() {
if (WiFi.status() == WL_CONNECTED && offlineDataCount > 0) {
Serial.println("Syncing offline data to Blynk...");
for (int i = 0; i < offlineDataCount; i++) {
Serial.print("Sending Stored Data -> Door: ");
Serial.print(offlineData[i].doorStatus ? "Closed" : "Open");
Serial.print(", Motion: ");
Serial.print(offlineData[i].motionDetected ? "Yes" : "No");
Serial.print(", Impact: ");
Serial.print(offlineData[i].impactDetected ? "Yes" : "No");
Serial.print(", Time: ");
Serial.println(offlineData[i].timestamp);
Blynk.virtualWrite(V1, offlineData[i].doorStatus ? "Closed" : "Open");
Blynk.virtualWrite(V2, offlineData[i].motionDetected ? "Yes" : "No");
Blynk.virtualWrite(V3, offlineData[i].impactDetected ? "Yes" : "No");
Blynk.virtualWrite(V4, offlineData[i].timestamp);
delay(30); // wait for 30 milliseconds before sending data again
}
offlineDataCount = 0;
}
}