The Silent Killer is how people in the medical field refer to High Blood Pressure or Hypertension. They also give the same title to diabetes, prostate cancer, and even Carbon Monoxide. Today we will only focus on Hypertension because according to American Heart Association, if left undetected (or uncontrolled), high blood pressure can lead to many things including heart disease. That in turn, according to the Centers for Disease Control and Prevention (CDC), is the Leading Cause of Death in the United States of America. Among other organizations, the International Society of Hypertension (ISH) also echoed those findings and the importance of accurate measurement.
Now that I got your attention, my imaginary legal team advised me to give the following disclaimer:
Statements made here have not been evaluated by the Food and Drug Administration. This product is not intended to diagnose, treat, cure, or prevent any disease.
I'm not a Doctor, and I've never even played one on TV. I should also mention that any resemblance to reality is purely coincidental.
We're all waivered-up, let's get this show on the road.
Game PlanWhen I applied for the free hardware, I was planning to use MAX30102 Pulse Oximeter and Heart-Rate sensor to measure blood oxygen level. I got the sensor to work with Sony Spresense then AVR-IoT WG. However, the sensor readings were all over the place, and I found out later that even industry experts here and here couldn't get a straight answer from that sensor.
To create a reliable product and the whole thing we mentioned earlier about "The Silent Killer" I decided to build a Google Cloud Platform (GCP) IoT Core Blood Pressure Monitor (BPM) instead.
If you recall in the introduction we talked about "the importance of accurate measurement". The National Center for Biotechnology Information of National Library of Medicine of National Institutes of Health of U.S. Department of Health & Human Services studied the effect of ambient temperature on blood pressure:
Therefor, we will not only send Systolic, Diastolic, and Heart Rate values, we will also send the ambient temperature along with a timestamp to give our data some context for more accurate interpretation by healthcare professionals. Finally, to make data more accessible, we will present it in Google Sheets format.
Couple of things to note before we dive in:
- Topics will be introduced in this tutorial in the order they became relevant to the evolution of the product
- Text Fragments, i.e. "<URL>#:~:text=<first word>, <last word>" are used to highlight a single point, and that should not be taken out of context
The AVR-IoT WG development board combines a powerful ATmega4808 AVR® MCU, an ATECC608A CryptoAuthentication™ secure element IC and the fully certified ATWINC1510 Wi-Fi® network controller - which provides the most simple and effective way to connect your embedded application to Google’s Cloud IoT core platform. The board will be used to take data from non-smart BPM and send it to Google cloud.
While waiting for my BPM to arrive, I stumbled upon a video on YouTube where Circuit Desolator took apart three different BPMs. His goal was to tap into Electrically Erasable Programmable Read-Only Memory (EEPROM) via Inter-Integrated Circuit (I2C) bus on each device. Once a device finishes measuring, it will save the results in EEPROM then data can be easily retrieved. This method requires some disassembly and precision soldering. For me that would be plan B.
My idea is slightly different. I took apart my BPM as soon as I received and tested it then I looked for a Serial Port. Best case scenario, I'll find the four holes of Universal Asynchronous Receiver/Transmitter (UART) next to each other and I'll have to find out which one is Vcc, GND, Tx, and Rx.
The second challenge is figuring out the voltage level. It is unlikely the voltage level would be 5 Volts since this BPM operates on two 1.5 Volts batteries. I measured 3.3 Volts and now I'm ready for the next challenge which is finding the Baud Rate. I used my FTDI and the following Python script to answer that question:
import serial.tools.list_ports as ports
import serial
BaudRates=[110, 150, 300, 600, 1200, 2400, 4800, 9600,
14400, 19200, 28800, 31250, 38400, 57600,
115200, 128000, 230400, 256000, 460800, 921600]
for p in ports.comports():
for b in BaudRates:
with serial.Serial(p.device,b,timeout=3) as s:
print(s.name + ' ' + str(s.baudrate) + ' ' +
s.read(100).decode('unicode_escape'))
exit()
I had to turn the BPM on to start reading from UART. The baud rate that gave me readable text was 38400. That number will be used by one of AVR-IoT WG's USARTs to read data from BPM.
If you feel uncomfortable around Python (ophidiophobic), you could also reach the same conclusion by using Arduino IDE Serial Monitor and try all Baud Rates in the lower right corner of the window.
Before we leave this section I wanted to point out that I preferred to use UART over I2C because I wanted to have the ability to expand on this project in the future. In addition to reading from the device, we can also write to the device via UART. For now, we just connect power and ground of AVR-IoT WG to BPM, and Tx of BPM to Rx of AVR-IoT WG. One more connection is needed between AVR-IoT WG and BPM On/off button. We need that because as soon as we supply BPM with power it goes into settings mode. Therefore, we need to get out of that mode then turn the device on to commence the measurement process.
Software - MPLAB X IDEI liked using MPLAB X IDE. I struggled in the beginning with MPLAB Code Configurator (MCC), but I found lots of documentations and videos on how to use it. AVR-IoT WG is shipped with AVR IoT Google Sensor Node demo firmware on it. So, to get back to factory settings we can drag and drop the HEX file, download MPLAB X IDE project, import Atmel START atzip file, or my favorite, create it from MCC with steps detailed here.
When I plugged AVR IoT WG to my Windows 10 machine it showed up as a drive named CURIOSITY. That drive has a file named CLICK-ME.HTM which took me to the page above. Once again, more than one way to setup Wi-Fi three of them are documented in this video. I connected to Wi-Fi and started getting light and temperature data immediately.
It was easy to follow the three tutorials under "What's Next" on the same page. The last button I clicked on that page was a red one towards the bottom with white "Graduate" text on it. Finally, I'm at a Leverege GitHub repository.
Software - FirebaseMuch of the process have been automated by Leverege. I followed the steps they posted on GitHub, but had to make few deviations to create something reproducible by anyone. We started by creating a project in Firebase.
Upgraded billing from Spark to Blaze.
Created Realtime Database (RTDB).
Two things we need to get from here before leaving Firebase. First, we need the URL which will be on the same page after creating RTDB.
We also need to get a database secret from Settings > Service accounts > Database secrets.
Keep in a safe place or at least remember how to get to them. We will need this information to setup Google Apps Script.
Software - GCPHave you ever wondered what people really mean when they say "steep learning curve"? Do they mean it is like a steep hill that is "hard" to climb? or they gain a lot of knowledge in a shot period of time as in "easy"? Working with the cloud was a steep learning curve for me (whatever that means). Maybe because my first exposure was with a platform that I would not wish on anyone. GCP was different though. You may see tutorials and documentations that go out of date because of the fast evolution; however, Google seem to be having a better control over things. I started by typing the following in Google Cloud Shell:
git clone https://github.com/Leverege/microchip-avr-iot.git && cd microchip-avr-iot/setup && bash setup.sh
Entered my Device UID and accepted the default registry name. I also had to provide authorization.
After few minutes the script finished successfully, and the last URL took me to a page that looked familiar.
We're getting close, but we need to click on the URL before the last to tell GCP about the device's Public key which is also saved on CURIOSITY drive.
Now we can go back to MPLAB X IDE and update the same project we created from MCC to publish to a private account. Click Ctrl+Shift+F then type CFG_PROJECT_ID.
The first hit was in "cloud_config.h" so we replaced "avr-iot" with our Project ID. Loaded the code and still no data showing up even though the yellow light is flashing. As it turned out, the script didn't create Google Cloud Function needed to send data to Firebase.
Running the script again may result in creating some duplicates so we just ran the missing part.
firebase deploy --only functions:recordMessage
Sometimes that needs to be done more than once until it succeeds.
Now our data is in Firebase.
We need to change the structure of the data to make it easier to retrieve later by Google Apps Script and displayed on Google Sheets.
The easiest way to change the data structure is to edit that stubborn Google Cloud Function.
The first file we need to edit is index.js. Just comment out two lines and add a line like so:
//-//const time = Date.now();
//-//msg = Object.assign({}, msg, { time });
msg = Object.assign({},msg);//-//
We're done editing the first file. We also need to edit the file right above it; FirebaseWriter.js. We needed to add the timestamp we removed from the previous file then send data to the root so we don't have to dig for it. For each device, we will send data down two paths the first is cumulative for history, and the second is overwriting old data with the latest.
Click deploy and watch how data structure change in Firebase.
When you make an appointment with a doctor, they ask you to show up 15 minutes early to fill out three sets of paper with the same information you already provided when you registered online. That is, you write down your name, address, phone number, and you Social Security Number three times on papers that nobody will ever look at. If you didn't have Hypertension before you walked in, now you do.
Seriously though, it is unrealistic to expect people with that level of technology awareness to transition straight from paper to the cloud. That's why I created a Google Sheets interface to query Firebase on demand. Originally, I tried to make Google Cloud Function send the data (push) to Google Sheets at the same time the data is sent to Firebase. Then I had a better idea, as soon as the sheet is open, Apps Script should fetch latest data (pull) very quickly from Firebase RTDB. There was also the option to use Google Sheets API, but it was going to add unnecessary complexity to the project.
Three things we need to do to make this work. First, we need to add FirebaseApp library by going to Resources > Libraries... in Apps Script.
The second thing we need to do is create a trigger because the code will not run with onOpen function. Click on the clock between the floppy disk and Run buttons to add a trigger.
The last thing we need to do is replace <url>, and <optSecret> in Code.gs
var db = FirebaseApp.getDatabaseByUrl("<url>", "<optSecret>")
Bring it all togetherTo summarize what has been accomplished till this point:
- Made physical connection between AVR-IoT WG and BPM
- Created AVR-IoT Google Sensore Node using MCC
- Published temperature and light to sandbox
- Published temperature and light to private cloud
- Change the data structure in Firebase
- Google Sheets retrieves from Firebase on-demand
Now that all the mechanics work in a known state we can move on to publishing Systolic, Diastolic, Heart Rate, ambient temperature, and timestamp.
Back to the MPLAB X IDE, use MCC to add USART1. Change the baud rate to the value we found using Python then click Generate to add the needed files to our project.
One C source file and one header file are also required to be added to the project. These two files are not included in MCC, and they are needed to read BPM text via UART. Once that's done, we can edit application_manager.c by adding #include "../BPM.h" at the top. In the sendToCloud function we need to update json data like so:
len = sprintf(json, "{\"SYS\":%d,\"DIA\":%d,\"PPM\":%d,\"Temp\":%d.%02d}", SYS, DIA, PPM, rawTemperature / 100, abs(rawTemperature) % 100);//-//
We need to add the following lines before anything else in receivedFromCloud:
DELAY_milliseconds(60000);//-//
wdt_enable(WDTO_30MS);//-//
while (1);//-//
Finally, we need to add bpm();//-// as the last line in application_init.
ConclusionWe may not be able to use BPM as a lie detector like Dwight Schrute claimed. Nonetheless, we were able to use AVR-IoT WG to send BPM readings to Google Sheets by an easy and secure process.
This device can be used by patients in the days or weeks leading up to a doctor visit. It can also be used when changing medication is critical to blood pressure. The last use case we want to mention here is the use in epidemiological surveys like the one highlighted the effect of ambient temperature on blood pressure readings.
DemoFull disclosure: Hackster kindly sent me only one AVR-IoT WG device. I had to create 6 more readings in the database to simulate entries from multiple devices. At the end of each line, I added a color based on my interpretation of chart below.
Comments