#include <TinyGPS++.h>
#include <Wire.h>
#include <WiFi.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ThingSpeak.h>
#include <HTTPClient.h>
#include "base64.h"
// GPS Configuration
#define GPS_BAUDRATE 9600
TinyGPSPlus gps;
// ThingSpeak Configuration
const char* WIFI_NAME = "Wokwi-GUEST";
const char* WIFI_PASSWORD = "";
const int myChannelNumber = 2527670;
const char* myApiKey = "4GUFVO761V2M6QVY";
const char* server = "api.thingspeak.com";
// OLED Display Configuration
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Pin Definitions
#define RELAY 19
#define PULSE_PIN 35
#define alertLed 32
// Twilio Configuration
const char* accountSid = "AC574c8ac9da6d95d130a441fdaface639";
const char* authToken = "0c406fcdada6b04db18ce894536ee0c6";
const char* fromPhoneNumber = "+17693009297";
const char* toPhoneNumber = "+918838080465";
// Heart Rate Thresholds
int minHeartRate = 50;
int maxHeartRate = 120;
WiFiClient client;
void setup() {
Serial.begin(9600);
Serial2.begin(GPS_BAUDRATE);
Wire.begin(16, 17);
pinMode(alertLed, OUTPUT);
pinMode(RELAY, OUTPUT);
// Initialize OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
while(1);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
// Connect to WiFi
WiFi.begin(WIFI_NAME, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print("Connecting to WiFi...\n");
}
Serial.println("\nWiFi connected");
Serial.println("IP Address: " + String(WiFi.localIP()));
WiFi.mode(WIFI_STA);
ThingSpeak.begin(client);
Serial.println("Heart Rate and GPS Monitor Started");
}
void displayGPSData() {
display.clearDisplay();
display.setCursor(0, 0);
if (gps.location.isValid()) {
display.print("Lat: ");
display.println(gps.location.lat(), 6);
display.print("Lng: ");
display.println(gps.location.lng(), 6);
} else {
display.println("GPS: No Fix");
}
display.display();
}
void processHeartRate() {
int16_t pulseValue = analogRead(PULSE_PIN);
float voltage = pulseValue * (5 / 4095.0);
int heartRate = (voltage / 3.3) * 675;
ThingSpeak.setField(1, heartRate);
ThingSpeak.writeFields(myChannelNumber, myApiKey);
if (heartRate > maxHeartRate) {
sendTwilioAlert(heartRate);
digitalWrite(alertLed, HIGH);
digitalWrite(RELAY, HIGH);
} else {
digitalWrite(alertLed, LOW);
digitalWrite(RELAY, LOW);
}
// Display heart rate on second half of OLED
display.setCursor(0, 40);
display.print("HR: ");
display.print(heartRate);
display.println(" bpm");
display.display();
}
void sendTwilioAlert(int heartRate) {
String messageBody = "ALERT: Heart Rate is " + String(heartRate) + " bpm";
String credentials = String(accountSid) + ":" + String(authToken);
String encodedCredentials = base64::encode(credentials);
String url = "https://api.twilio.com/2010-04-01/Accounts/" + String(accountSid) + "/Messages.json";
String postData = "To=" + String(toPhoneNumber) + "&From=" + String(fromPhoneNumber) + "&Body=" + messageBody;
HTTPClient http;
http.begin(url);
http.addHeader("Authorization", "Basic " + encodedCredentials);
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
int httpCode = http.POST(postData);
http.end();
}
void loop() {
// Process GPS data
while (Serial2.available() > 0) {
if (gps.encode(Serial2.read())) {
displayGPSData();
}
}
// Check GPS module connection
if (millis() > 5000 && gps.charsProcessed() < 10) {
Serial.println(F("No GPS data received: check wiring"));
}
// Process heart rate
processHeartRate();
delay(2000);
}
Loading
ssd1306
ssd1306