Infectious Disease Exposure Alerting Device - BLE Based
Team Members
- Fengrui Zuo (Georgia Tech, BSEE, 21)
- Benjamin Leverett (Georgia Tech, BSEE, 21)
- Rahil Ajani (Georgia Tech, BSEE, 20)
- Kombundit Chitranuwatkul (Georgia Tech, BSEE, 20)
Overview
Due to coronavirus pandemic, hundreds of thousands of people are at risk from being infected with this deadly virus. We wanted to build an effective way to alert people at risk and track the virus to prevent its spread. This project demonstrates the capability of Bluetooth technology to estimate the proximity of infectious persons or zones by using its built-in Received Signal Strength Indicator (RSSI) functionality. A Bluetooth beacon is emulated with an iPhone to be used as an infectious area. A hand-held alerting device is built using a mbed, an uLCD module, a UART BLE module, an SD card logger and a speaker.
Demonstration
Presentation
Slide Deck Link - Google Slide Link
Presentation Link
Hardware
The following are the hardware components that are used in this project with links to purchase the components
- mbed - LPC1768: https://www.sparkfun.com/products/9564
- Adafruit Bluetooth LE UART Friend: https://www.adafruit.com/product/2479
- MicroSD Breakout: https://www.sparkfun.com/products/544
- uLCD: https://www.sparkfun.com/products/11377
- Transistor https://www.sparkfun.com/products/521
- Speaker: https://www.sparkfun.com/products/11089
- Red LED: https://www.sparkfun.com/products/9590
- Yellow LED: https://www.sparkfun.com/products/532
- Green LED: https://www.sparkfun.com/products/9650
Pin Connections
Adafruit Bluetooth LE UART Friend
| mbed | Adafruit BLE |
|---|---|
| GND | GND |
| VU (5V) | VIN (3.3-16V) |
| - | RTS |
| GND | CTS |
| p14 (Serial RX) | TXO |
| p13 (Serial TX) | RXI |
| p18 | MOD |
Wiki Page: Adafruit Bluetooth LE UART Friend
MicroSD Breakout
| mbed | MicroSD |
|---|---|
| p8 (DigitalOut CS) | CS |
| p5 (SPI mosi) | DI |
| VOUT (3.3V) | VCC |
| p7 (SPI sclk) | SCK |
| GND | GND |
| p6 (SPI miso) | DO |
| - | CD |
Wiki Page: MicroSD Breakout
uLCD
| mbed | uLCD Header | uLCD Cable |
|---|---|---|
| VU (5V) | 5V | 5V |
| GND | GND | GND |
| TX=p28 | RX | TX |
| RX=p27 | TX | RX |
| p30 | RES | RES |
Wiki Page: uLCD
Transistor and Speaker
| mbed | Transistor | Speaker |
|---|---|---|
| VOUT (3.3V) | -- | (+) |
| GND | Emitter (1) | -- |
| p21 + (1KOhm) | Base (2) | -- |
| -- | Collector (3) | (-) |
Wiki Page: Class D Audio Amplifier Breakout and Speaker
Green LED
| mbed | Green LED | (Optional) |
|---|---|---|
| p24 | longer leg | |
| GND | shorter leg | 100-300 Ohms Resistor |
Wiki Page: LEDs
Yellow LED
| mbed | Yellow LED | (Optional) |
|---|---|---|
| p25 | longer leg | |
| GND | shorter leg | 100-300 Ohms Resistor |
Wiki Page: LEDs
Red LED
| mbed | Red LED | (Optional) |
|---|---|---|
| p26 | longer leg | |
| GND | shorter leg | 100-300 Ohms Resistor |
Wiki Page: LEDs
Circuit

Program
Import programFinal_Project
Fengrui Zuo, Benjamin Leverett, Rahil Ajani, Kombundit Chitranuwatkul
RTOS Wiki Page: https://os.mbed.com/handbook/RTOS

Sample SD Card Output
Date & time: Tuesday 28, April 2020 10:13:29 Risk Level: 3 47, 44, 45, 48, 57, 52, 57, 47, 49, 44, 61, 73, 68, 79, 83 Date & time: Tuesday 28, April 2020 10:13:47 Risk Level: 1 79, 94, 80, 10, 79, 95, 73, 92, 95, 75, 83, 71, 88, 94, 87 Date & time: Tuesday 28, April 2020 10:14:05 Risk Level: 3 98, 84, 88, 71, 58, 61, 62, 66, 67, 69, 67, 57, 69, 63, 51 Date & time: Tuesday 28, April 2020 10:14:23 Risk Level: 2 57, 61, 56, 51, 57, 62, 61, 57, 52, 58, 49, 51, 59, 60, 54
Project Code
#include "mbed.h"
#include "rtos.h"
#include "ATParser.h"
#include "uLCD_4DGL.h"
#include "SDFileSystem.h"
#include "Speaker.h"
#include <string>
#include <iostream>
using namespace std;
//Hardware setups
DigitalOut cmdMode(p18);
Serial pc(USBTX, USBRX);
BufferedSerial ble(p13,p14);
DigitalOut cmdstuff(p18);
DigitalOut greenLED(p24);
DigitalOut yellowLED(p25);
DigitalOut redLED(p26);
uLCD_4DGL uLCD(p28,p27,p30);
SDFileSystem sd(p5, p6, p7, p8, "sd");
PwmOut speaker(p21);
//AT command data handlers
char delimiter[] = "\r\n";
int buffer_size = 256;
int timeout = 100;
bool debug = false;
ATParser at(ble, delimiter, buffer_size, timeout, debug);
char buffer[10];
//RTOS Mutex Lock
Mutex mutex_lock;
//Global Data points and arrays
volatile int risk_level = 0;
int averageCount = 0;
volatile int datalogged = 0;
volatile int RSSI_array[15];
time_t seconds;
//Responsible for logging on SD card
void log_sd_card()
{
mutex_lock.lock();
FILE *fp = fopen("/sd/mydir/sdtest.txt", "w");
if(fp == NULL) {
error("Could not open file for write\n");
}
int curr_time = (int)ctime(&seconds) % 86400;
int curr_hour = curr_time / 3600;
int curr_min = curr_time / 60;
int curr_sec = curr_time % 60;
fprintf(fp, "Date & time: Tuesday 28, April 2020 ");
fprintf(fp, "%i", curr_hour);
fprintf(fp, ":");
fprintf(fp, "%i", curr_min);
fprintf(fp, ":");
fprintf(fp, "%i", curr_sec);
fprintf(fp, "\n");
fprintf(fp, "Risk Level: ");
fprintf(fp, "%i", risk_level);
fprintf(fp, "\n");
for (int i = 0; i < 15; i++) {
fprintf(fp, "%i", RSSI_array[i]);
if (i < 14) {
fprintf(fp, ", ");
}
}
fprintf(fp, "\n\n");
fclose(fp);
mutex_lock.unlock();
}
//This portion of the code handles RSSI readings
int calculate_average(volatile int *input, int size)
{
int average;
for(int i = 0; i< size; i++) {
average = average + input[i];
}
average = average/size;
return average;
}
void parse_RSSI()
{
mutex_lock.lock();
at.send("AT+BLEGETRSSI") && at.read(buffer, 10);
if(buffer[0] == '-') {
datalogged = 1;
pc.printf("RSSI: ");
pc.putc(buffer[1]);
pc.putc(buffer[2]);
pc.printf("\n");
int digit1 = buffer[1] - 48; //Converts char to int
int digit2 = buffer[2] - 48;
int total = 10*digit1 + digit2;
if (averageCount <= 15) {
RSSI_array[averageCount] = total;
}
averageCount++;
if(averageCount > 15 && buffer[0] == '-') {
averageCount = 0;
int average = calculate_average(RSSI_array, 15);
if(average < 55) {
risk_level = 3;
} else if(average > 55 && average < 70) {
risk_level = 2;
} else if(average > 70 && average < 90) {
risk_level = 1;
} else {
risk_level = 0;
}
log_sd_card();
}
}
mutex_lock.unlock();
}
//Responsible for speaker
void speaker_alarm()
{
while(1) {
if(risk_level == 2 && datalogged) {
for (int i=0; i<10; i=i+2) {
speaker.period(1.0/969.0);
speaker = float(i)/50.0;
wait(.8);
speaker.period(1.0/800.0);
wait(.8);
speaker = 0;
}
} else if(risk_level == 3 && datalogged) {
for (int i=0; i<10; i=i+2) {
speaker.period(1.0/969.0);
speaker = float(i)/50.0;
wait(.25);
speaker.period(1.0/800.0);
wait(.25);
speaker = 0;
}
} else if(risk_level <= 1 && datalogged) {
speaker = 0;
} else {
speaker = 0;
}
}
}
//Code to blink leds based on risk level
void blink_leds()
{
while(1) {
if(risk_level <= 1 && datalogged) {
greenLED = 1;
redLED = 0;
yellowLED = 0;
} else if(risk_level == 2 && datalogged) {
yellowLED = 1;
greenLED = 0;
redLED = 0;
} else if(risk_level == 3 && datalogged) {
redLED = 1;
yellowLED = 0;
greenLED = 0;
} else {
redLED = 0;
yellowLED = 0;
greenLED = 0;
}
}
}
//Displays risk level on uLCD
void display_ulcd()
{
mutex_lock.lock();
uLCD.color(WHITE);
mutex_lock.unlock();
while(1) {
mutex_lock.lock();
if(risk_level <= 1 && datalogged) {
mutex_lock.lock();
uLCD.cls();
uLCD.locate(5, 7);
uLCD.text_width(2);
uLCD.text_height(2);
uLCD.background_color(GREEN);
uLCD.textbackground_color(GREEN);
uLCD.printf("Safe");
mutex_lock.unlock();
} else if(risk_level == 2 && datalogged) {
mutex_lock.lock();
uLCD.cls();
uLCD.locate(1, 7);
uLCD.text_width(2);
uLCD.text_height(2);
uLCD.background_color(0xFFFF00);
uLCD.textbackground_color(0xFFFF00);
uLCD.printf("Cautious");
mutex_lock.unlock();
} else if(risk_level == 3 && datalogged) {
mutex_lock.lock();
uLCD.cls();
uLCD.locate(3, 7);
uLCD.text_width(2);
uLCD.text_height(2);
uLCD.background_color(RED);
uLCD.textbackground_color(RED);
uLCD.printf("Hazard");
mutex_lock.unlock();
}
mutex_lock.unlock();
}
}
//Runs application
int main()
{
cmdstuff = 1;
at.send("AT") && at.recv("OK");
at.send("AT+AB ChangeDefaultBaud [9600]", 3) && at.recv("OK");
ble.baud(9600);
set_time(1588068804);
Thread ULCD_Thread(display_ulcd);
Thread LED_Thread(blink_leds);
Thread Speaker_Thread(speaker_alarm);
while(1) {
parse_RSSI();
}
}
Please log in to post comments.
