#define BLYNK_TEMPLATE_ID "TMPL4mhud2_gw"
#define BLYNK_TEMPLATE_NAME "IoT in GIS"
#define BLYNK_AUTH_TOKEN "zuLUQu7kWSfAjKSJVo9IZeexKPoU0co4"
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <TinyGps++.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// ------ Pin Definitions ------
const int motionSensorPin = 13; // PIR sensor input pin
const int ledPin = 2; // ON indicator LED
const int buzzerPin = 4; // Buzzer output pin
// ------ OLED Display ------
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// ------ Motion Detection ------
bool motionDetected = false;
BlynkTimer timer; // Built-in timer in Blynk library
// ------ WiFi Credentials ------
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
// ------ Nigeria Bounding Box Coordinates ------
const float minLat = 4.0;
const float maxLat = 14.0;
const float minLon = 3.0;
const float maxLon = 15.0;
// ------ Function Prototypes ------
void checkMotion();
void sendRandomLocation();
void initializeOLED();
void connectToWiFiAndBlynk();
void setup() {
Serial.begin(115200);
pinMode(motionSensorPin, INPUT);
pinMode(ledPin, OUTPUT);
pinMode(buzzerPin, OUTPUT);
// Indicate device power with LED
digitalWrite(ledPin, HIGH);
// Initialize OLED Display
initializeOLED();
// Connect to WiFi and Blynk
connectToWiFiAndBlynk();
// Set a timer to check motion every 2 seconds
timer.setInterval(2000L, checkMotion);
}
void initializeOLED() {
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x64
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Don't proceed, hang in an infinite loop
}
// Clear the buffer
display.clearDisplay();
// Text settings
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 10);
display.println("Device ON");
display.display();
}
void connectToWiFiAndBlynk() {
Serial.println("Connecting to WiFi...");
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
Serial.println("Connected to Blynk!");
}
void checkMotion() {
int motionState = digitalRead(motionSensorPin);
if (motionState == HIGH) {
if (!motionDetected) { // Trigger only once per motion event
Serial.println("Motion detected!");
motionDetected = true;
// Activate buzzer with tone function
tone(buzzerPin, 1000, 500); // 1 kHz for 500ms
// Send "Motion Detected" message to Blynk
Blynk.virtualWrite(V2, "Motion Detected!");
// Generate and send random location
sendRandomLocation();
}
} else {
motionDetected = false; // Reset motion flag
// Clear "Motion Detected" message on Blynk when no motion
Blynk.virtualWrite(V2, "");
}
}
void sendRandomLocation() {
// Generate random latitude and longitude within the defined boundaries
float randomLat = random(minLat * 1000000, maxLat * 1000000) / 1000000.0;
float randomLon = random(minLon * 1000000, maxLon * 1000000) / 1000000.0;
// Output the coordinates to Serial Monitor
Serial.printf("Latitude: %.6f, Longitude: %.6f\n", randomLat, randomLon);
// Display the coordinates on OLED
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.println("Motion Detected!");
display.print("Lat: ");
display.println(randomLat, 6); // Print with 6 decimal places
display.print("Lon: ");
display.println(randomLon, 6); // Print with 6 decimal places
display.display();
// Send to Blynk (ensure exact values without approximation)
Blynk.virtualWrite(V0, randomLat);
Blynk.virtualWrite(V1, randomLon);
}
void loop() {
Blynk.run();
timer.run(); // Run the timer to check motion
}