Stress is a significant contributor to various health issues such as heart disease, high blood pressure, diabetes, and mental health conditions. This project aims to develop a real-time wearable stress monitoring device that uses sensors to track physiological parameters such as heart rate, skin conductivity (GSR), and body temperature. The device leverages an Arduino R4 Wi-Fi board, which is a powerful microcontroller capable of wireless communication, to send the collected data to a Telegram bot for real-time monitoring.
Impact Statement
This wearable stress monitoring device leverages real-time sensors to track key physiological indicators such as heart rate, skin conductivity, and body temperature, providing users with immediate feedback on their stress levels. Through wireless communication with a Telegram bot, it allows for continuous, remote monitoring, empowering users to manage their stress more effectively and proactively. Designed with a 3D-printed casing and powered by a rechargeable Li-ion battery, this compact, portable solution promotes mental well-being by making stress management accessible anytime, anywhere.
Objectives
The primary objectives of this project are as follows:
Develop a Wearable Device: Build a portable and comfortable wearable band to monitor stress levels continuously.
Real-Time Data Collection and Transmission: Measure heart rate, skin conductivity (GSR), and body temperature as indicators of stress.
Wireless Communication: Use the Arduino R4 WiFi board to wirelessly transmit the data to a Telegram bot for remote monitoring.
Personalized Stress Insights: Provide immediate feedback and long-term insights into stress levels.
Components and Hardware Setup
The key components used in this project were selected for their compatibility, portability, and accuracy in measuring physiological parameters. Here's a breakdown of the components:
Arduino R4 Wi-Fi: The central microcontroller responsible for reading data from sensors, processing the data, and transmitting it to the Telegram bot over Wi-Fi.
MAX30105 Heart Rate Sensor: Measures heart rate using photoplethysmography (PPG) by detecting blood volume changes.
BME280 Temperature Sensor: Measures ambient temperature, which can correlate with stress as stress can affect body temperature.
GSR Sensor: Measures skin conductivity, which varies with stress levels and emotional arousal.
OLED Display (0.96-inch): Displays real-time data, including heart rate, skin conductivity, and body temperature.
Battery: A 3.7V 1500mAh rechargeable Li-ion battery provides the power for the device, ensuring portability and long usage times. The battery is rechargeable and provides sufficient capacity for continuous monitoring.
Telegram Bot: A communication platform that receives real-time sensor data from the device and notifies users.
Additional Components
3D Printed Casing: The casing for the device was designed using SolidWorks and 3D printed to house all the components, making the device compact and wearable. The design was optimized for comfort, durability, and ease of access to the sensors and display.
Charging Circuit: A TP4056 lithium battery charging module is used for safely charging the 3.7V Li-ion battery, providing an easy and efficient charging solution.
Navigate to This YouTube Video for Full Demonstration of the Project
These components are connected as described in the following circuit diagram:
Let's look at the circuit diagram.
This wearable stress monitoring device combines a set of carefully chosen sensors—heart rate (MAX30105), skin conductivity (GSR), and temperature (BME280)—to offer real-time tracking of stress-related physiological parameters. By using I2C communication, the device is able to efficiently integrate multiple sensors onto the Arduino R4 Wi-Fi board connected on A4 and A5 of board as SDA and SCL. The GSR has a signal pin which is attached on pin A0 to read the data from the sensor. simplifying the wiring and making the system compact and portable. The GSR sensor is connected to the analog pin for continuous skin conductivity measurement, while the data is displayed on a 0.96-inch OLED screen and transmitted wirelessly to a Telegram bot, offering easy, remote monitoring.
To make the device truly portable, I’ve powered it using a 3.7V 1500mAh rechargeable Li-ion battery paired with a TP4056 charging module, allowing for convenient, on-the-go usage. The design is enclosed in a custom 3D-printed casing created in SolidWorks, ensuring a lightweight and ergonomic form factor suitable for everyday wear. This compact, accessible solution empowers users to monitor and manage their stress levels effectively, anytime and anywhere, supporting proactive mental well-being management.
CAD Model
For the casing of the device, I designed a custom 3D model using SolidWorks, taking precise measurements of all the components—like the Arduino R4 Wi-Fi board, MAX30105 heart rate sensor, BME280 temperature sensor, OLED display, GSR sensor, and the Li-ion battery. Once the design was complete, I 3D printed the casing to ensure a snug fit for all the parts.
The design prioritized compactness, portability, and comfort, as the device is intended to be worn. I carefully positioned all components inside the casing, ensuring everything fits securely while keeping the device lightweight and wearable. The 3D printing process allowed me to quickly iterate and make adjustments, and the result is a durable, functional enclosure that protects the electronics while being easy to wear and use on a daily basis.
Data Transmission and Telegram Setup
To enable real-time data transmission, I created a Telegram bot through BotFather, which is a simple and powerful tool provided by Telegram for bot creation. The bot was named "Stress Monitoring", specifically designed to send stress-related data such as heart rate (BPM), body temperature, and GSR (Galvanic Skin Response) readings to my personal Telegram account.
After creating the bot, I obtained its API key, a unique identifier that allows the Arduino R4 board to securely communicate with the Telegram servers. Additionally, I retrieved my Telegram chat ID, which is required to specify where the data should be sent within the app. This chat ID corresponds to my personal Telegram account, allowing me to receive notifications directly to my phone.
Using this API key and chat ID, I programmed the Arduino R4 Wi-Fi board to send data over the internet. The Arduino board, with its built-in Wi-Fi capability, connects to the internet and establishes a communication link with the Telegram servers. It sends periodic updates regarding the monitored stress parameters (such as BPM, temperature, and GSR) via Telegram messages, ensuring I can monitor my stress levels remotely at any time.
The UniversalTelegramBot library, used in the Arduino code, provides the necessary functionality to send these messages. It handles the API calls and message formatting, making it easy to send real-time data to the Telegram bot. By integrating the Telegram Bot API into the project, I have enabled a simple and reliable way to transmit the device’s health data without the need for a complex app interface.
Demo Results
The project successfully captures and displays real-time stress-related data. Heart rate, temperature, and GSR values are continuously monitored and displayed on the OLED screen, providing immediate feedback to the user. The data is also transmitted to the Telegram app, where it can be viewed remotely, offering additional convenience.
Here are some screenshots of the live data being displayed on oled with Arduino:
The data collected can be used for future analytics, potentially integrating machine learning algorithms to predict stress levels and offer personalized insights.
Code
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <WiFiS3.h>
#include <WiFiSSLClient.h>
#include <UniversalTelegramBot.h>
#include "MAX30105.h"
#include "heartRate.h"
#include <Adafruit_GFX.h> // OLED Library
#include <Adafruit_SSD1306.h> // OLED Library
// GSR reading and percentage
int GSR;
int GSR_percentage;
// WiFi credentials
#define WIFI_SSID "LAVKUSH_CHAUDHARI "
#define WIFI_PASSWORD "8108491665"
// Telegram bot token
#define BOT_API_TOKEN "7534847312:AAEmhLTw7KuXPPPt9pWi00ePsqpilst1zdo"
// BME280 sensor configuration
Adafruit_BME280 bme; // I2C
// MAX30105 sensor configuration
MAX30105 particleSensor;
// OLED display configuration
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); //Declaring the display name (display)
const byte RATE_SIZE = 4; // Increase for more averaging
byte rates[RATE_SIZE]; // Array of heart rates
byte rateSpot = 0;
long lastBeat = 0; // Time of the last beat
float beatsPerMinute;
int beatAvg;
String chat_id = ""; // Chat ID for Telegram
int message_id = -1; // Message ID for Telegram
unsigned long last_call = 0; // Last call time for checking messages
const unsigned long interval = 1000; // Interval between message checks
// Object for secure WiFi client management
WiFiSSLClient securedClient;
// Object for managing the Telegram bot
UniversalTelegramBot bot(BOT_API_TOKEN, securedClient);
// Function to handle incoming messages from Telegram
void handleMessages(int num_new_messages) {
for (int i = 0; i < num_new_messages; i++) {
message_id = bot.messages[i].message_id;
chat_id = bot.messages[i].chat_id;
String text = bot.messages[i].text;
// Command handling
if (text == "/GSR") {
// Send the GSR value and mapped percentage to the chat
bot.sendMessage(chat_id, "Mapped GSR: " + String(GSR_percentage) + "%", "Markdown");
} else if (text == "/TEMP") {
float temperature = bme.readTemperature(); // Read temperature
bot.sendMessage(chat_id, "Temperature: " + String(temperature, 2) + " °C", "Markdown");
Serial.print("Temperature: ");
Serial.print(temperature, 2);
Serial.println(" °C");
} else if (text == "/BPM") {
bot.sendMessage(chat_id, "Average BPM: " + String(beatAvg), "Markdown");
} else if (text == "/start") {
bot.sendMessage(chat_id, "Use /GSR Value to get the GSR value, /TEMP to get the temperature, and /BPM to get the average heart rate.", "Markdown");
}
}
}
// Function to connect to WiFi network
void connectToWiFi() {
Serial.print("Connecting to WiFi network ");
Serial.println(WIFI_SSID);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting...");
}
Serial.print("WiFi connected. IP Address: ");
Serial.println(WiFi.localIP());
}
// Initialization function
void setup() {
Serial.begin(115200); // Start serial communication
pinMode(A0, INPUT); // Set GSR pin as input
randomSeed(analogRead(A1)); // Use an unconnected pin (A1) for better random seed initialization
connectToWiFi(); // Connect to WiFi
// Initialize BME280 sensor
if (!bme.begin(0x76)) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1); // Stop execution if sensor is not found
}
// Initialize MAX30105 sensor
if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) { // Use default I2C port, 400kHz speed
Serial.println("MAX30105 was not found. Please check wiring/power.");
while (1); // Stop execution if sensor is not found
}
Serial.println("Place your index finger on the sensor with steady pressure.");
particleSensor.setup(); // Configure sensor with default settings
particleSensor.setPulseAmplitudeRed(0x0A); // Turn Red LED to low to indicate sensor is running
particleSensor.setPulseAmplitudeGreen(0); // Turn off Green LED
bot.sendMessage(chat_id, "BOT Started", "Markdown"); // Notify that the bot has started
// Initialize the OLED display
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Check the display initialization
Serial.println(F("SSD1306 allocation failed"));
while (1);
}
display.clearDisplay(); // Clear the display
display.setTextColor(SSD1306_WHITE); // Set text color to white
display.setTextSize(2); // Set larger text size
display.display(); // Display initial settings
delay(2000); // Wait for 2 seconds to let the user see "Initializing" message
}
// Main loop
void loop() {
GSR = analogRead(A0); // Read the GSR sensor value (0-1023 range)
// Map the GSR value from 700-300 to 0-100%
GSR_percentage = map(GSR, 300, 700, 0, 100);
if (GSR_percentage < 0) GSR_percentage = 0; // Ensure percentage does not go below 0
if (GSR_percentage > 100) GSR_percentage = 100; // Ensure percentage does not go above 100
// Check for new messages from Telegram
if (millis() - last_call > interval) {
int num_new_messages = bot.getUpdates(bot.last_message_received + 1);
while (num_new_messages) {
handleMessages(num_new_messages); // Handle incoming messages
num_new_messages = bot.getUpdates(bot.last_message_received + 1);
}
last_call = millis(); // Update the last call time
}
// Update the OLED display with sensor data
display.clearDisplay();
// Display GSR data
display.setCursor(0, 0); // Set the cursor to top-left corner
display.print("GSR: ");
display.print(GSR_percentage);
display.print("%");
// Display temperature data
float temperature = bme.readTemperature();
display.setCursor(0, 24); // Set cursor for next line
display.print("Temp: ");
display.print(int(temperature));
display.print("C");
// Check heart rate data
long irValue = particleSensor.getIR();
if (irValue > 50000) {
if (checkForBeat(irValue) == true) {
long delta = millis() - lastBeat;
lastBeat = millis();
beatsPerMinute = 60 / (delta / 1000.0);
if (beatsPerMinute < 255 && beatsPerMinute > 20) {
rates[rateSpot++] = (byte)beatsPerMinute; // Store reading in the array
rateSpot %= RATE_SIZE; // Wrap variable
// Take average of readings
beatAvg = 0;
for (byte x = 0; x < RATE_SIZE; x++)
beatAvg += rates[x];
beatAvg /= RATE_SIZE;
}
// Display the heart rate (BPM) on OLED
display.setCursor(0, 48); // Set cursor for heart rate
display.print("BPM: ");
display.print(beatAvg);
}
}
// Check if all conditions are met: GSR > 400, Temp > 39°C, BPM > 90
if (GSR_percentage > 40 && temperature > 39.0 && beatAvg > 90) {
bot.sendMessage(chat_id, "Try to relax, you are stressed!", "Markdown");
}
// Show the display contents
display.display();
// Print to serial for debugging
Serial.print("GSR: ");
Serial.print(GSR);
Serial.print(" | Mapped GSR: ");
Serial.print(GSR_percentage);
Serial.print(" | Temp: ");
Serial.print(temperature);
Serial.print(" | BPM: ");
Serial.println(beatAvg);
}
The code for this project is written in C++ using the Arduino IDE. It has been thoroughly tested for each individual component, and I have uploaded the complete code, along with detailed testing and explanations, to GitHub for easy access. The code is well-structured and includes comprehensive comments throughout, making it easy to understand for anyone, even those who are new to the project. Each section of the code is clearly documented to explain its purpose and functionality, ensuring that others can easily follow along and replicate the setup if needed.
Conclusion and Future Improvements
This project has demonstrated how sensors can be used to monitor stress indicators and transmit real-time data for visualization and analytics. The device could be expanded in the future to include additional parameters, such as blood pressure or oxygen levels, for more comprehensive health monitoring. Improvements to the data transmission system could also be made, such as adding Bluetooth functionality or improving Wi-Fi stability in areas with poor connectivity.
Further, the integration of machine learning models on the Telegram platform could provide predictive analytics, helping users manage their stress more effectively. Data collected over time can be analyzed to detect trends, providing insights into factors that trigger stress and enabling better stress management strategies.
Click on the GitHub Image to view or download code