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

Demo Link

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

Pin Connections

Adafruit Bluetooth LE UART Friend

mbedAdafruit BLE
GNDGND
VU (5V)VIN (3.3-16V)
-RTS
GNDCTS
p14 (Serial RX)TXO
p13 (Serial TX)RXI
p18MOD

Wiki Page: Adafruit Bluetooth LE UART Friend

MicroSD Breakout

mbedMicroSD
p8 (DigitalOut CS)CS
p5 (SPI mosi)DI
VOUT (3.3V)VCC
p7 (SPI sclk)SCK
GNDGND
p6 (SPI miso)DO
-CD

Wiki Page: MicroSD Breakout

uLCD

mbeduLCD HeaderuLCD Cable
VU (5V)5V5V
GNDGNDGND
TX=p28RXTX
RX=p27TXRX
p30RESRES

Wiki Page: uLCD

Transistor and Speaker

mbedTransistorSpeaker
VOUT (3.3V)--(+)
GNDEmitter (1)--
p21 + (1KOhm)Base (2)--
--Collector (3)(-)

Wiki Page: Class D Audio Amplifier Breakout and Speaker

Green LED

mbedGreen LED(Optional)
p24longer leg
GNDshorter leg100-300 Ohms Resistor

Wiki Page: LEDs

Yellow LED

mbedYellow LED(Optional)
p25longer leg
GNDshorter leg100-300 Ohms Resistor

Wiki Page: LEDs

Red LED

mbedRed LED(Optional)
p26longer leg
GNDshorter leg100-300 Ohms Resistor

Wiki Page: LEDs

Circuit

https://os.mbed.com/media/uploads/chenchen2020/circuit.jpg

Program

Import programFinal_Project

Fengrui Zuo, Benjamin Leverett, Rahil Ajani, Kombundit Chitranuwatkul

RTOS Wiki Page: https://os.mbed.com/handbook/RTOS https://os.mbed.com/media/uploads/chenchen2020/program_diagram.jpg

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.