COVID-19 (also called novel coronavirus) is a deadly disease that has infected over 24 million people and has killed over 800 thousand people.
In the USA alone, there have been 6 million cases. According to Worldometers.info, COVID-19 cases have been increasing lately.
CDC suggests social distancing, which is a procedure in which people stand 6 feet apart unless they are part of the same family. So how do we, as a community, use technology to enforce this procedure? That was the motive for this project.
CostIn order to make this project accessible to everyone, we wanted to ensure the cost is as low as possible.
The cost of one device:
- Arduino Nano--10 for $36.49 so each is $3.65
- HC-05--2 for $12.5 so each is $6.25
- LCD--2 for $6.49 so each is $3.25
- Active Buzzer--20 for $9.59 so each is $0.48
- 10K ohm potentiometer--20 for $6.39 so each is $0.32
- 220 ohm resistor- 100 for $5.69 so each is $0.06
- 9V battery-- 8 for $10.99 so each is $1.37
- 9V battery connecter breadboard--40 for $6.48 so each is $0.16
This totals up to $15.54. This is very impressive since this can save numerous lives.
Prep Step: Install librariesThe first step is to install the LCD library, both of which you will need. This might be pre-installed on Arduino IDE but it may not on some versions.
Go to the Tools>ManageLibraries. Here, search "LiquidCrystal".
The library we are looking for is the first one on the list. Install it if you have not already.
The SoftwareSerial library is also used, but that is already pre-installed.
Step 1: Configure HC-05 to AT modeThe first step is to configure the HC-05 to AT mode. Here, we can execute the AT+INQ command to scan for other devices.
Two or more devices are needed in order to scan for each other. One "device" is described in the parts needed.
For this step, a device should be wired like this:
There are two kinds of HC-05 devices: one with a "KEY" pin without button and one with an "EN" pin with button
AT mode HC-05 without button:
If the KEY pin is connected to +5V DC, it should automatically be in AT mode.
AT mode HC-05 with button
In this case, EN pin should be connected to +5V DC. When plugging in the Arduino Nano, push down the button, plug the device in, and release it. This should active AT mode.
Copy and paste this code into Arduino IDE.
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10,11);
void setup()
{
Serial.begin(9600);
mySerial.begin(38400);
Serial.println("Enter AT commands:");
delay(2000);
}
void loop()
{
// Keep reading from HC-05 and send to Arduino Serial Monitor
if (mySerial.available()){
Serial.write(mySerial.read());}
// Keep reading from Arduino Serial Monitor and send to HC-05
if (Serial.available()){
mySerial.write(Serial.read());}
}
Esentially, this takes anything you type in the Serial monitor and prints it to HC05, waits for a message and prints that message.
Run the code.
Runningcode:
Open the serial monitor.
When "Enter AT commands:" appears, type "AT" and press enter. You should get a message saying "OK"
Type "AT+NAME" and the name appears.
Rssivalues
To obtain distance between devices, we needed the rssi values. To obtain the rssi values, we needed to execute AT+INQ command. However, there are a few commands to execute before that, one by one:
- AT+RESET
- AT+INIT
- AT+IAC=9e8b33
- AT+CLASS=0
- AT+INQM=1, 9, 48
- AT+INQ
Here is how the serial monitor should look after all 6 commands are executed. (Step by Step)
Notice when we executed the AT+INQ command, it says +INQ followed by the Address, Class, followed by the RSSI value. The RSSI value is the last 4 characters. Note that this is in hexadecimal; to convert it to decimal, we need to use signed two's complement format.
If the RSSI value you get is 7FFF, try executing the commands above again.
If the rssi value starts with F, then you are good.
Step 2: Convert Rssi valuesTo convert the rssi values, we need to make a new function to do so.
Copy and paste this code into Arduino IDE
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10,11);
void setup()
{
Serial.begin(9600);
mySerial.begin(38400);
Serial.println("Enter AT commands:");
delay(2000);
}
unsigned int hexToDec(String hexString) {
unsigned int decValue = 0;
int nextInt;
for (int i = 0; i < hexString.length(); i++) {
nextInt = int(hexString.charAt(i));
if (nextInt >= 48 && nextInt <= 57) nextInt = map(nextInt, 48, 57, 0, 9);
if (nextInt >= 65 && nextInt <= 70) nextInt = map(nextInt, 65, 70, 10, 15);
if (nextInt >= 97 && nextInt <= 102) nextInt = map(nextInt, 97, 102, 10, 15);
nextInt = constrain(nextInt, 0, 15);
decValue = (decValue * 16) + nextInt;
}
return decValue;
}
void loop()
{
// Keep reading from HC-05 and send to Arduino Serial Monitor
if (mySerial.available()){
String x = String(mySerial.readString());
int slashn = x.indexOf("\n");
Serial.println(slashn);
int xlen = x.length()/(slashn+1);
if (x.endsWith("OK\r\n")) {
x = x.substring(0, x.length() - 4);
}
for (int i = 0; i < xlen; i++) {
if (i != 0) {
x = x.substring(slashn+1);
}
slashn = x.indexOf("\n");
String rssi = x.substring(slashn-5, slashn-1);
int decNO = hexToDec(rssi);
Serial.println(decNO);
}
// Keep reading from Arduino Serial Monitor and send to HC-05
if (Serial.available()){
mySerial.write(Serial.read());
}
}}
Howdoes this program work
First, it detects if data is available. Then, it copies the data into a string (X) and detects the end of a INQ line (notice all the INQ data is all one string, this needs to be separated into different strings for single-line INQ data).
Please note a line is +INQ:ADDR, CLASS, RSSI\r\n
Through the for loop, it is detecting separate lines and deleting the ones already detected. The RSSI values is sixth to third to last (including the \r\n) so that is substring(slashn-5, slashn-1); we called the end "slash n" because that is the end, a slash n.
When you run this program, you should get the RSSI value as a decimal after the +INQ.... This should be a negative number. The greater the number, the closer the two devices are.
In the next step, we will show you how to report this data to an LCD. We will also see how to detect a family member
Step 3: detecting family membersIt is possible to detect a family member through the address of the device. The address starts from the 5th index and ends 13th to last which is substring(5, slashn-11).
With this given, we can also count the number of outsiders and family members.
With the outsiders, the distance can be measured to see if it is 6 ft. After a series of trials by putting the devices at 6ft, we determined it is 76.91.
Here is the code.
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX
void setup() {
Serial.begin(9600);
Serial.println("Enter AT commands:");
mySerial.begin(38400);
}
unsigned int hexToDec(String hexString) {
unsigned int decValue = 0;
int nextInt;
for (int i = 0; i < hexString.length(); i++) {
nextInt = int(hexString.charAt(i));
if (nextInt >= 48 && nextInt <= 57) nextInt = map(nextInt, 48, 57, 0, 9);
if (nextInt >= 65 && nextInt <= 70) nextInt = map(nextInt, 65, 70, 10, 15);
if (nextInt >= 97 && nextInt <= 102) nextInt = map(nextInt, 97, 102, 10, 15);
nextInt = constrain(nextInt, 0, 15);
decValue = (decValue * 16) + nextInt;
}
return decValue;
}
void loop()
{
while (!mySerial.available()) {}
while (mySerial.available()) {
String x = String(mySerial.readString());
int slashn = x.indexOf("\n");
Serial.println(slashn);
int nod = 0;
int countf = 0;
int counto = 0;
int countd = 0;
int xlen = x.length()/(slashn+1);
if (x.endsWith("OK\r\n")) {
x = x.substring(0, x.length() - 4);
}
for (int i = 0; i < xlen; i++) {
if (i != 0) {
x = x.substring(slashn+1);
}
slashn = x.indexOf("\n");
String rssi = x.substring(slashn-5, slashn-1);
int decNO = hexToDec(rssi);
Serial.println(x.substring(5,slashn-11));
if (x.substring(5, slashn-11) == "FAMILYADDR") {
countf++;
}
else {
counto++;
if (decNO > -76.91) {
countd++;
}
}
if (decNO > -76.91) {
Serial.println("near");
}
else {
Serial.println("far");
}
Serial.println(decNO);
}
Serial.println("Family: " + String(countf) + " Outsider: " + String(counto) + " Danger: " + String(countd));
}
delay(100);
}
Countf is the count of family members, counto is the count of outsiders, and countd is the count of dangerous outsiders that are less than 6ft.
Replace FAMILYADDR with the device which you are trying to scan that is the "famiily". Any outsider devices will automatically count as an outsider. For more than one device, use the || operation to list more than one device.
When you run this, you will see the addresses of the device listed as well as the converted RSSI. After all is scanned, it will show Family, Outsider, and Danger count.
Step 4: Report to LCDWhen this device is implemented in the real world, there must be a way for the device holder to know the rssi value as well as if they are in danger of getting COVID-19.
Wire the LCD as shown:
Next, copy and paste this code into Arduino IDE. Run it.
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
int buttonstate = 0;
void setup() {
lcd.begin(16, 2);
Serial.begin(9600);
Serial.println("Enter AT commands:");
}
unsigned int hexToDec(String hexString) {
unsigned int decValue = 0;
int nextInt;
for (int i = 0; i < hexString.length(); i++) {
nextInt = int(hexString.charAt(i));
if (nextInt >= 48 && nextInt <= 57) nextInt = map(nextInt, 48, 57, 0, 9);
if (nextInt >= 65 && nextInt <= 70) nextInt = map(nextInt, 65, 70, 10, 15);
if (nextInt >= 97 && nextInt <= 102) nextInt = map(nextInt, 97, 102, 10, 15);
nextInt = constrain(nextInt, 0, 15);
decValue = (decValue * 16) + nextInt;
}
return decValue;
}
void loop()
{
while (!mySerial.available()) {}
while (mySerial.available()) {
String x = String(mySerial.readString());
int slashn = x.indexOf("\n");
Serial.println(slashn);
int nod = 0;
int countf = 0;
int counto = 0;
int countd = 0;
int xlen = x.length()/(slashn+1);
if (x.endsWith("OK\r\n")) {
x = x.substring(0, x.length() - 4);
}
for (int i = 0; i < xlen; i++) {
if (i != 0) {
x = x.substring(slashn+1);
}
slashn = x.indexOf("\n");
String rssi = x.substring(slashn-5, slashn-1);
int decNO = hexToDec(rssi);
lcd.setCursor(0, 1);
lcd.print("RSSI:" + String(decNO));
Serial.println(x.substring(5,slashn-11));
if (x.substring(5, slashn-11) == "20:2:2011FB") {
countf++;
}
else {
counto++;
if (decNO > -76.91) {
countd++;
}
}
if (decNO > -76.91) {
Serial.println("near");
}
else {
Serial.println("far");
}
Serial.println(decNO);
}
Serial.println("Family: " + String(countf) + " Outsider: " + String(counto) + " Danger: " + String(countd));
if (counto/2<countd) {
lcd.setCursor(10, 1);
lcd.print("DANGER");
Serial.println("DANGER");
}
else {
lcd.setCursor(10, 1);
lcd.print(" ");
Serial.println("Fine");
}
}
delay(100);
}
We feel we need to explain the logic behind counto/2<countd
. Notice that 76.91 is the average rssi value, This means half of the values are over and half are under. This ensures that no more than 5 values are under 76.91; else it says "DANGER".
It is dangerous to look at the device in scenarios like crossing a road. We used an active buzzer to sound an alarm if the distance is less than 6 ft. This only turns off if either person steps more than 6 ft away from the other. Wire the buzzer to D13, as shown:
Copy and paste the code as shown
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
int buttonstate = 0;
void setup() {
pinMode(13,OUTPUT);
lcd.begin(16, 2);
Serial.begin(9600);
Serial.println("Enter AT commands:");
mySerial.begin(38400);
}
unsigned int hexToDec(String hexString) {
unsigned int decValue = 0;
int nextInt;
for (int i = 0; i < hexString.length(); i++) {
nextInt = int(hexString.charAt(i));
if (nextInt >= 48 && nextInt <= 57) nextInt = map(nextInt, 48, 57, 0, 9);
if (nextInt >= 65 && nextInt <= 70) nextInt = map(nextInt, 65, 70, 10, 15);
if (nextInt >= 97 && nextInt <= 102) nextInt = map(nextInt, 97, 102, 10, 15);
nextInt = constrain(nextInt, 0, 15);
decValue = (decValue * 16) + nextInt;
}
return decValue;
}
void loop()
{
while (!mySerial.available()) {}
while (mySerial.available()) {
String x = String(mySerial.readString());
int slashn = x.indexOf("\n");
Serial.println(slashn);
int nod = 0;
int countf = 0;
int counto = 0;
int countd = 0;
int xlen = x.length()/(slashn+1);
if (x.endsWith("OK\r\n")) {
x = x.substring(0, x.length() - 4);
OK = 1;
}
for (int i = 0; i < xlen; i++) {
if (i != 0) {
x = x.substring(slashn+1);
}
slashn = x.indexOf("\n");
String rssi = x.substring(slashn-5, slashn-1);
int decNO = hexToDec(rssi);
lcd.setCursor(0, 1);
lcd.print("RSSI:" + String(decNO));
Serial.println(x.substring(5,slashn-11));
if (x.substring(5, slashn-11) == "20:2:2011FB") {
countf++;
}
else {
counto++;
if (decNO > -76.91) {
countd++;
}
}
if (decNO > -76.91) {
Serial.println("near");
}
else {
Serial.println("far");
}
Serial.println(decNO);
}
Serial.println("Family: " + String(countf) + " Outsider: " + String(counto) + " Danger: " + String(countd));
if (counto/2<countd) {
lcd.setCursor(10, 1);
lcd.print("DANGER");
Serial.println("DANGER");
digitalWrite(13,HIGH);
}
else {
lcd.setCursor(10, 1);
lcd.print(" ");
Serial.println("Fine");
digitalWrite(13,LOW);
}
}
delay(100);
}
When you run the code, the device will buzz if the distance is less than 6 ft and become regular once it is more than 6 ft.
Step 6: Device Independence (without computer)If implemented in the real world, this device must be running and sending commands without a computer.
This being said, a 9V battery must provide the voltage necessary.
Note that a little bit of scotch tape might be necessary to tape the battery to the back of the breadboard. This makes the device easier to hold.
Commands must be sent letter by letter through integer form using int()
The code is in the "Code" area of the documentation.
Demo Video
Comments