Projects Research & Design Hub

IoT Device Measures Key Health Stats

Figure 1 The MyPulse device
Written by Andrei Florian

The MyPulse Project

Wouldn’t it be cool to build your own device that precisely tracks your heart rate and blood oxygen (SpO2) levels with the press of a button? Andrei did just that with MyPulse, an IoT application that’s integrated with Microsoft Azure IoT allowing the collected data to be streamed to the platform from where it is displayed on a dashboard.

These days many of us wear an array of sensors on our wrist all the time, keeping track of various vitals such as heart rate and stress levels. Although the heart rate depends heavily on the individual’s age, generally, a resting heart rate of 60bpm (beats per minute) to 100bpm is normal. Anything below or above this indicates signs of a possible disease like diabetes or atrial fibrillation.

Blood oxygen levels do not vary with age and a healthy person would have a saturation of over 95%. Anything below can indicate that there is not enough oxygen pumped around the body meaning that there may be a problem with anything from the lungs to the production of red blood cells in the individual. Diseases include emphysema, bronchitis and pneumonia.

Wouldn’t it be interesting to build your own device that precisely tracks your heart rate and blood oxygen (SpO2) levels with the press of a button? With just that in mind, MyPulse (Figure 1) is an IoT application that allows users to measure their heart rates and SpO2 levels by pressing a button and softly putting their finger on the device for 30 seconds. MyPulse is directly integrated with Microsoft Azure IoT allowing the collected data to be securely streamed to the platform from where it is beautifully illustrated on a dashboard.

Figure 2 and Figure 3 illustrate the dashboard. Through the use of Microsoft Power Bi, the data collected from the device is illustrated beautifully online and accessible from any device, anywhere. The dashboard shows the most recent heart rate and blood oxygen level alongside graphs that show these values over time. The dashboard is easily sharable with anyone allowing your doctor to have direct access to the data collected in seconds.

Figure 1 The MyPulse device
Figure 1
The MyPulse device
Figure 2 MyPulse mobile dashboard
Figure 2
MyPulse mobile dashboard
Figure 3 MyPulse web dashboard
Figure 3
MyPulse web dashboard
TECHNOLOGY STACK

The application can be split into the frontend and the backend. The frontend of the application refers to the actual device that collects the heart rate and blood oxygen values from the user while the backend refers to the data storage and dashboard.

I chose to make use of the Microsoft Azure Sphere development kit to power the project, available from Seeed Studio. The Azure Sphere supports Mikro Bus interfaces. These allow for the connection of MikroElektronika (MikroE) extension boards. MikroE has hundreds of extension boards offering a wide variety of functionality. Each board is essentially a module that snaps on the device in a Mikro Bus. These boards make prototyping and developing an application very simple and fast, making them a great choice for our application. In this project, I make use of the MikroE Heart Click 4. This is a heart rate and blood oxygen module that can easily be plugged into a Mikro Bus on the Azure Sphere device. It is also officially supported by the Azure Sphere community.

— ADVERTISMENT—

Advertise Here

Some quick facts: Studies correlate temperature and barometric pressure with the chance of stroke. A study by NCBI [1] states that the chances of acute stroke increase by 2.4% per a 1°C change in temperature. Another study by NCBI [2] relates that the majority of people rushed to the doctor with a stroke have been exposed to fluctuations in barometric pressure. In light of this, I decided to also collect the barometric pressure and temperature data. These data are collected by onboard sensors meaning that we don’t have to connect any external components to get this functionality.

The Azure Sphere also has support for typical components. I connected a buzzer and RGB LED to the device to provide user feedback. Microsoft Azure is directly integrated with the Azure Sphere device. Azure IoT Hub is used in the backend. Azure IoT Hub provides us with an endpoint to send the data from the Azure Sphere. The data is collected in the IoT Hub. The hub allows for thousands of devices to stream data.

A stream analytics job is used to periodically check for new data in the IoT Hub. When new data is detected, the job will push this data into a Power Bi dataset. Finally, Microsoft Power Bi is used to visualize the data. Power Bi allows us to create a beautiful dashboard by dragging and dropping elements on a canvas.

PROJECT ARCHITECTURE

Figure 4 illustrates the project architecture in the frontend and the backend. The Azure Sphere is put into sleep mode and is woken up by the press of the button on the device. The button being pressed signals that the user wishes to take a sample.

Figure 4 Project architecture diagram
Figure 4
Project architecture diagram

The device will turn the MikroE heart rate sensor on and start sampling it. The device will attempt to detect a pulse for a couple of seconds. If a pulse is detected, it will measure it together with the blood oxygen levels, otherwise the device will send an error and prompt the user to try again. If the data is collected successfully. The device will sample the room temperature and barometric pressure and then compile the data and send it over an internet connection to IoT Hub.

The data will arrive in IoT Hub in seconds. In another few seconds, the stream analytics job set up will identify the presence of new data in IoT Hub and extract it. The job will then inject the data into a Power Bi report. When the user opens the Power Bi report, the dashboard will showcase the data. The user can take as many samples as wished a day using the device. All the data collected is reflected live in the online dashboard.

FRONTEND IN-DEPTH

I chose to make use of the Microsoft Azure Sphere development kit (Figure 5) to power the project. I made this decision because the Azure Sphere is an industry-grade development board that is really easy to work with. It offers plug-and-play capabilities that allow for rapid development of applications. The device is also vertically integrated with Microsoft Azure IoT offering easy and secure access to an industry leading IoT provider.

I believe that security is very important to ensure that the application is running smoothly and undisturbed by outside sources. The Azure Sphere device is as secure as it gets when it comes to IoT. From the Pluton chip ensuring that the device’s code can only be modified by users with access to the specificity needed in the app manifest, this device will ensure that the application is running smoothly and securely.

The Azure Sphere supports Mikro Bus interfaces. These allow for the connection of MikroE extension boards. These boards make development easier and faster. The Azure Sphere also has integrated Wi-Fi support making it very easy to connect to the internet. Microsoft Azure is directly integrated with the Azure Sphere device making connecting to the backend secure and seamless.

— ADVERTISMENT—

Advertise Here

The application makes use of three separate sensors to collect data. All the sensors used by the application are listed and explained in Table 1. Data is collected by the device from various sensors after the user presses the button. To save resources, the temperature and atmospheric pressure are only collected if a successful heart rate and SpO2 are taken. Table 2 shows all the data fields collected by the application.

I decided to also incorporate a buzzer and an RGB LED into the project to provide the user with feedback. The buzzer will buzz whenever the user should place their finger on the heart rate sensor and when the sensor completes its measurement to notify them that they can lift their finger. Table 3 describes what the different colors of the LED signify for the user.

Table 1 Sensors
Table 1
Sensors
Table 2 Data collected
Table 2
Data collected
Table 3 LED color significance
Table 3
LED color significance

The application will report all the data collected to the backend if the device successfully collected a heart rate sample. All the sensor data is collated and sent in an encrypted package to IoT Hub over an internet connection.

Figure 6 shows a rendering of the device’s enclosure. I personally made it out of acrylic and glued it together but I have the STL files in the GitHub repository [3] if you wish to 3D print the enclosure together with drawings with dimensions. The enclosure consists of a box shape with three holes at the top; one for the RGB LED, one for the button and the other for the heart rate module. Make sure the material used is as thin as possible so that the user’s finger will be able to touch the sensor through the hole. Between 3mm and 5mm is fine.

Figure 5 Azure Sphere development kit
Figure 5
Azure Sphere development kit
Figure 6 Rendering of the enclosure
Figure 6
Rendering of the enclosure
BACKEND IN-DEPTH

Figure 7 illustrates an overview of the backend architecture. Each part of the backend is described in more detail in this section. All the data that is sent to the backend is received by the Azure IoT Hub. This acts as a gateway for sending data from an IoT device to Azure Cloud. The service allows devices to be authenticated and then saves the data streamed temporarily. Figure 8 illustrates the connected device in the IoT Hub.

Stream Analytics is a glue service provided by Azure. It is separate from the IoT Hub. This service runs all the time and periodically checks to see if there is new data present in the IoT Hub. Whenever the device sends data to the hub, it takes a couple of seconds for the job to detect the new data. When this happens, the job will extract the data from the IoT Hub and inject it into a Power Bi Dataset.

Power Bi is the last stop for the data. Power Bi allows us to create a dashboard, which can be populated with the data injected by the job into the dataset. Whenever a user opens the dashboard on any device, it will refresh the data and display the newest data from the dataset. On average it takes about 30 seconds to a minute for the data to get from the device to the dashboard. The dashboard (Figure 9) illustrates all the data collected by the device.

Figure 7 Backend architecture overview
Figure 7
Backend architecture overview
Figure 8 IoT Hub devices
Figure 8
IoT Hub devices
Figure 9 Web MyPulse dashboard
Figure 9
Web MyPulse dashboard

As I was creating the project, I came across a lot of ideas that I did not get a chance to implement. The list below goes through them in case you want to add them:

  • The frontend device can be equipped with an OLED display that will inform the user about their heart rate and SpO2 levels as well as the temperature and barometric pressure when the sample is successful.
  • The device could have a background function that reads the temperature and barometric pressure while the device is in stand-by and prints them on the OLED display.
  • The data could be streamed into Cosmos DB for safekeeping.

CONSTRUCTING THE PROJECT

This section will walk through the construction of the project.

Step 1: Required materials: Table 4 lists all the components needed for the products together with links to the stores and their prices. Figure 10 shows all the components that I used.

Table 4 List of the components needed for the products together with links to the stores and their prices
Table 4
List of the components needed for the products together with links to the stores and their prices

Step 2: Prerequisites: Before we start building the project. You will need to ensure that you have access to a Windows 10 PC with Visual Studio 2017 or 2019 installed. You will also need the Azure Sphere SDK installed on your PC. Note that I’m working on version 19 and not the most recent version. Although there should be no problem loading project files using the new SDK, some bugs can occur.

You will then need to follow the well laid out guide at [6] provided by Microsoft to get started with your development board and set it up. When your device is in debug mode and connected to Wi-Fi, you can continue with the guide.

Step 3: Connecting the circuit: The next thing to do is wire the circuit. I used a breadboard for prototyping, but the final device should be soldered together. Please reference Figure 11 for the wiring connections. Be sure to connect the MikroE heart click to MikroE socket 1.

Figure 10 Required materials
Figure 10
Required materials
Figure 11 Fritzing diagram showing the MyPulse electronics and connections
Figure 11
Fritzing diagram showing the MyPulse electronics and connections

Step 4: Acknowledging the code: The project’s code is composed of four main sections:

— ADVERTISMENT—

Advertise Here

  • Get Button State
  • Get Heart Rate
  • Analyse Data
  • Send Data to Azure

(Editor’s note: In order to be consisted with the author’s code section name and code, we’ve maintained the British English spelling “analyse” when the section name is used.)

The function in the Get Button State code section (Listing 1) samples the button and checks if it is pressed. The Get Heart Rate section (Listing 2) is literally the heart of the program, no pun intended. As shown in that code, the device will wait until the button is pressed and then take a 30 second sample of the heart rate and SpO2 levels. The device will then compile the values and check if they are valid. It will then move on to the next function.

The function in the Analyse Data section (Listing 3) analyzes the vitals to see if the values are OK or out of health limits. The device will then alert the user respectively. Finally, the function in the Send Data to Azure code section (Listing 4) appends all the data collected together in a buffer and sends it to Azure IoT.

Listing 1
The Get Button State code section. This function samples the button and checks if it is pressed.

int getButton() // this loop checks if the button is pressed
{
    GPIO_Value_Type newButtonAState;
    int result = GPIO_GetValue(buttonAOpen, &newButtonAState); 
				// read the GPIO value
    if (result < 0) // if read was not allowed
    {
        Log_Debug(“ [ERROR] Access to Pin Denied \n”);
        return -1;
    }
    return newButtonAState;
}
Listing 2
This is the Get Heart Rate section of the code. As shown in this code, the device will wait until the button is pressed and then take a 30 second sample of the heart rate and SpO2 levels. The device will then compile the values and check if they are valid moving on to the next function.

// wait until button is pressed and then sample Hr
bool getHeartRate()
{
    println(“[Program] Preapring Sample”);
    float n_spo2 = 0;
    float ratio = 0;
    float correl = 0;
    int8_t  ch_spo2_valid = 0;   //indicator to show if the SPO2 calculation is valid
    int32_t n_heart_rate = 0;    //heart rate value
    int8_t  ch_hr_valid = 0;     //indicator to show if the heart rate calculation is valid
    uint32_t aun_ir_buffer[BUFFER_SIZE]; //infrared LED sensor data
    uint32_t aun_red_buffer[BUFFER_SIZE]; //red LED sensor data
    int32_t i = 0;
    int32_t average_hr = 0;
    float average_spo2 = 0;
    int32_t nbr_readings = 0;
    struct timeval time_start;
    struct timeval time_now;
    bool turn = false;
    memset(aun_ir_buffer, 0, 128);                                        (continued on p.22)
    (continued from p.21)
    
    memset(aun_red_buffer, 0, 128);
    println(“[Program] Press Button to get heart rate”);
    while (!getButton())      // wait until the button is pressed.
    {
        dowork();             // buffer events in the meanwhile
        delay(100);
    }
    buzz(1000);               // buzzer
    ledBlue();
    println(“[Program] Initialising MikroE Device”);
    maxim_max30102_i2c_setup(read_i2c, write_i2c);
    maxim_max30102_init();    // initialise the sensor and send the on command    
    Log_Debug(“[Program] Running test for %d seconds\n”, run_time);
    println(“[Program] Place Finger on Sensor - Starting in 5 seconds”);
    delay(5000);
    println(“”);
    println(“[Program] Reading Heart Rate”);
    // get the start time of the sampling
    gettimeofday(&time_start, NULL);
    time_now = time_start;
    average_hr = nbr_readings = 0;
    average_spo2 = 0.0;
    while (difftime(time_now.tv_sec, time_start.tv_sec) < run_time) // run for defined time
    {
        // blink the blue LED
        if (turn)
        {
            ledBlue();
            turn = false;
        }
        else
        {
            ledOff();
            turn = true;
        }
        GPIO_Value_Type intVal;
        for (i = 0; i < BUFFER_SIZE; i++)
        {
            do
            {
                GPIO_GetValue(intPinFd, &intVal);
            } while (intVal == 1);  //wait until the interrupt pin asserts
            maxim_max30102_read_fifo((aun_red_buffer + i), (aun_ir_buffer + i));  
                                    //read from MAX30102 FIFO
            Log_Debug(“.”);
        }
        Log_Debug(“\n”);
//calculate heart rate and SpO2 after BUFFER_SIZE samples (ST seconds of samples) using Robert’s method
        rf_heart_rate_and_oxygen_saturation(aun_ir_buffer, BUFFER_SIZE, aun_red_buffer, 
          &n_spo2, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid, &ratio, &correl);
        if (ch_hr_valid && ch_spo2_valid)   // if sample is valid
        {
            println(“[Program] Success - Sample is Good”);
            Log_Debug(“Blood Oxygen Level %.2f%% \n”, n_spo2);
            Log_Debug(“Heart Rate %d BPM \n”, n_heart_rate);
            println(“”);
            average_hr += n_heart_rate;
            average_spo2 += n_spo2;
            nbr_readings++;                                                 (continued on p.23)


// wait until button is pressed and then sample Hr
bool getHeartRate()
{
    println(“[Program] Preapring Sample”);
    float n_spo2 = 0;
    float ratio = 0;
    float correl = 0;
    int8_t  ch_spo2_valid = 0;   //indicator to show if the SPO2 calculation is valid
    int32_t n_heart_rate = 0;    //heart rate value
    int8_t  ch_hr_valid = 0;     //indicator to show if the heart rate calculation is valid
    uint32_t aun_ir_buffer[BUFFER_SIZE]; //infrared LED sensor data
    uint32_t aun_red_buffer[BUFFER_SIZE]; //red LED sensor data
    int32_t i = 0;
    int32_t average_hr = 0;
    float average_spo2 = 0;
    int32_t nbr_readings = 0;
    struct timeval time_start;
    struct timeval time_now;
    bool turn = false;
    memset(aun_ir_buffer, 0, 128);                                        (continued on p.22)
    (continued from p.21)
    
    memset(aun_red_buffer, 0, 128);
    println(“[Program] Press Button to get heart rate”);
    while (!getButton())      // wait until the button is pressed.
    {
        dowork();             // buffer events in the meanwhile
        delay(100);
    }
    buzz(1000);               // buzzer
    ledBlue();
    println(“[Program] Initialising MikroE Device”);
    maxim_max30102_i2c_setup(read_i2c, write_i2c);
    maxim_max30102_init();    // initialise the sensor and send the on command    
    Log_Debug(“[Program] Running test for %d seconds\n”, run_time);
    println(“[Program] Place Finger on Sensor - Starting in 5 seconds”);
    delay(5000);
    println(“”);
    println(“[Program] Reading Heart Rate”);
    // get the start time of the sampling
    gettimeofday(&time_start, NULL);
    time_now = time_start;
    average_hr = nbr_readings = 0;
    average_spo2 = 0.0;
    while (difftime(time_now.tv_sec, time_start.tv_sec) < run_time) // run for defined time
    {
        // blink the blue LED
        if (turn)
        {
            ledBlue();
            turn = false;
        }
        else
        {
            ledOff();
            turn = true;
        }
        GPIO_Value_Type intVal;
        for (i = 0; i < BUFFER_SIZE; i++)
        {
            do
            {
                GPIO_GetValue(intPinFd, &intVal);
            } while (intVal == 1);  //wait until the interrupt pin asserts
            maxim_max30102_read_fifo((aun_red_buffer + i), (aun_ir_buffer + i));  
                                    //read from MAX30102 FIFO
            Log_Debug(“.”);
        }
        Log_Debug(“\n”);
//calculate heart rate and SpO2 after BUFFER_SIZE samples (ST seconds of samples) using Robert’s method
        rf_heart_rate_and_oxygen_saturation(aun_ir_buffer, BUFFER_SIZE, aun_red_buffer, 
          &n_spo2, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid, &ratio, &correl);
        if (ch_hr_valid && ch_spo2_valid)   // if sample is valid
        {
            println(“[Program] Success - Sample is Good”);
            Log_Debug(“Blood Oxygen Level %.2f%% \n”, n_spo2);
            Log_Debug(“Heart Rate %d BPM \n”, n_heart_rate);
            println(“”);
            average_hr += n_heart_rate;
            average_spo2 += n_spo2;
            nbr_readings++;                                                 (continued on p.23)

(continued from p.22)
        
        }
        else
        {
            println(“[Program] Sample is Bad”);
        }
            gettimeofday(&time_now, NULL); // refresh the time
    }
    println(“”);
    println(“”);
    println(“[Program] Samples Collated”);
    // process the sample
    avgOxygen = average_spo2 / (float)nbr_readings;
    avgRate = average_hr / nbr_readings;
    // playing around with the values for testing
    //avgOxygen = 66;
    //avgRate = 40;
    buzz(1000);
    Log_Debug(“Blood Oxygen Level %.2f%% \n”, avgOxygen);
    Log_Debug(“Heart Rate %d BPM \n”, avgRate);
    max301024_shut_down(1);
    // ensure that the data is not corrupted again
    println(“[Program] Veryfying Data”);
    if (avgOxygen != 0 && avgRate != 0)
    {
        delay(1000);
        println(“”);
        println(“[Program] Sample is Good”);
        println(“[Program] Moving On”);
        println(“”);
        max301024_shut_down(1);
        return true;
    }
    else
    {
        delay(1000);
        println(“[Program] Error - All Samples are Corrupted”);
        println(“[Program] Not sending data to Azure”);
        for (int i = 0; i < 2; i++)
        {
            ledOff();
            buzz(1000);
            ledPurple();
            delay(1000);
        }
        max301024_shut_down(1);
        return false;
    }
}
Listing 3
The Analyse Data code section. This function analyzes the vitals to see if the values are okay or out of health limits. The device will then alert the user respectively.

// analyse the data to check if vitals are OK
void analyseData()
{
    println(“[Program] Checking Vitals against WHO healthy standards”);
    println(“[Program] Checking Heart Rate”);
    int problem = 0;
    if (avgRate < minRate || avgRate > maxRate) // compare heart rate with WHO standards
    {
        println(“[Warning] Heart Rate is not normal [60bpm - 100bmp]”);
        problem = 1;
    }
    else
    {
        println(“[Info] Heart Rate is normal”);
    }
    delay(1000);
    println(“[Program] Checking Oxygen”);
    if (avgOxygen < minOxygen) // compare SpO2 with WHO standards
    {
        println(“[Warning] SpO2 is not normal [95 - 100]”);
        if (problem == 1)
        {
            problem = 2;
        }
        else
        {
            problem = 3;
        }
    }
    else
    {
        println(“[Info] SpO2 is normal”);
    }
    // check if there was a problem
    if (problem == 0)
    {
        ledGreen();
    }
    else
    {
        for (int i = 0; i < 5; i++)
        {
            ledOff();
            buzz(1000);
            ledRed();
            delay(1000);
        }
    }
delay(2000);
}
Listing 4
The Send Data to Azure code section. This function appends all the data collected together in a buffer and sends it to Azure IoT.

// parse the data to Azure
void sendDataToAzure()
{
    delay(1000);
    println(“[Program] Formatting Data to Send to Azure”);
    char *pjsonBuffer = (char *)malloc(JSON_BUFFER_SIZE); // format a buffer
    if (pjsonBuffer == NULL)
    {
        Log_Debug(“ERROR: not enough memory to send telemetry”);
        for (int i = 0; i < 2; i++)
        {
            ledOff();
            buzz(1000);
            ledPurple();
            delay(1000);
        }
    }
    // append data to the buffer
    // snprintf(bufferToSend, 128, JSON Payload Config (defined above), dataLable, dataValue);
    snprintf(pjsonBuffer, JSON_BUFFER_SIZE, jsonFormat, “Oxygen”, avgOxygen, “HeartRate”, avgRate, “Temperature”, temp, “Pressure”, atmoPressure);
    Log_Debug(“[Info] Sending telemetry %s\n”, pjsonBuffer);
    AzureIoT_SendMessage(pjsonBuffer); // send the message
    free(pjsonBuffer); // clear the JSON buffer
}

Step 5: Setting up Azure IoT: This guide will walk you through setting up the Azure side of the application. Make sure you have a Microsoft Azure account [7] before proceeding with this section.

  1. Sign into the Azure Portal.
  2. Select the Create a Resource button from the home screen.
  3. Search for “IoT Hub” and select that option.
  4. Click on the Create button to create a new IoT Hub.
  5. From the options on the next page, select your subscription and create a new resource group for the project. Make sure to select your region accordingly. Finally, give your IoT Hub a name.
  6. Click on the Size and Scale tab. You can create a free IoT hub in Azure. Do this by selecting the F1 tier. S3 tier is perfect for adding multiple devices.
  7. Click on Create and wait for the resource to deploy.
  8. Select the resource. You can find it in the All Resources tab from the menu on the left of the screen.
  9. Scroll on the menu (starting with the settings heading) on the left of the screen until you see IoT devices under the Explorers heading. Select that option.
  10. On the next window, press the New button in the top left of the screen to create a new device.
  11. Give your device a name and ensure that symmetric key is selected from the authentication type. Tick the auto-generate keys option and click on save.

That’s it! IoT Hub is set up!

VARIABLES AND STREAMING

Step 6: Changing variables: It is very important to add your IoT hub connection to the application to allow the device to communicate with the backend. The steps that follow illustrate this process.

  1. Get the code from the GitHub repo [3] if you have not done so already and open the solution in Visual Studio.
  2. From the solution explorer on the screen, right click the references option and select Add Connected Service from the dropdown.
  3. On the new window, select Device Connectivity with Azure IoT.
  4. You will be prompted to sign into your Microsoft account. Do so and then select the subscription you used, set the connection type to IoT Hub Connection String, select the IoT Hub and then the device.
  5. Now navigate over to the app_manifest.json file in the solution and check that the AllowedConnections and CmdArgs are populated (if not, go through step 4 again).
  6. Copy the value of the CmdArgs field from the manifest.
  7. Locate the connection_strings.h file in the solution and paste the copied value as the value for MY_CONNECTION_STRING.

That’s it!

Step 7: Setting up the streaming job: The next step is to set up the streaming job that extracts the data from the IoT Hub and inputs it into the Power Bi dataset.

  1. Navigate back to the home page in Azure.
  2. Create a new Stream Analytics Job resource.
  3. Give the job a name and select the same subscription, group and location as the IoT Hub. Set the streaming units to 1.
  4. Click create to deploy the resource and wait for it to deploy.
  5. After the deployment completed, click back into the analytics job.
  6. Scroll down to Inputs under Job topology in the menu on the left of the screen and select that option.
  7. Click on Add Stream Input from the window and select IoT Hub.
  8. Name it “InputFromAzureIoT” and select the IoT Hub. Set the endpoint to Messaging and ensure the access policy is iothubowner.
  9. Click on Save to save the input. Azure will test your input automatically, wait for this to succeed.
  10. After the input testing succeeded, click on Outputs from the same menu and click on the Add button.
  11. Select Power Bi from the options. When you do this, you will be asked to authorize. Click the Authorize button and sign into Power Bi.
  12. After you’ve signed in, fill in the next fields as shown in Figure 12 and wait for the output to be tested.
  13. Finally, click on Query from the menu on the left and paste the code below in the query. If you named your inputs and outputs accordingly, you should get no errors.
SELECT
    Oxygen as oxygen,
    HeartRate as heartrate,
    Temperature as temperature,
    Pressure as pressure,
    System.timestamp as timestamp
INTO
    [OutputToPowerBi]
FROM
    [InputFromAzureIoT]

14. Click on Overview on the left menu on and select Start at the top to start your job.

15. That’s it, your job is running! The job will automatically create a Power Bi dataset if one does not exist and then append data to it.

Figure 12 Stream analytics output
Figure 12
Stream analytics output
FLASHING AND ENCLOSURE

Step 8: Flashing the code: We now have to flash the application to the device to send some data to the backend. For this test, the user will need to take a couple of samples using the device with the debug monitor on and see if the device is successfully sending data to the cloud and the data is found in the Stream Analytics job. Plug the device into your computer and run the solution on the device.

Step 9: Setting up Power Bi: The final thing that we have to do is set up Power Bi. The steps below will guide you through this. If all the previous steps went well, a dataset called MyPulse should be in the datasets section of Power Bi.

  1. First, open powerbi.microsoft.com and sign in.
  2. You will be directed to your dashboard, from here select your workspace from the menu on the left of the page and expand it.
  3. Check to see if MyPulse is under the Datasets section.
  4. We will be using the Power Bi desktop application to develop this dashboard. Install the app if you have not already and then sign in and open it.
  5. Use the application to crate a new report. You will be prompted to select a data source, select Power Bi datasets from the options. Or, if you do not get a prompt, navigate to Home and then Get Data and select Power Bi datasets.
  6. Select the dataset MyPulse from the list, after short time, the menu on the right of the screen should populate with the data.
  7. Now that all the data is there, create visuals for the data. Play with different graphs and text boxes through the Visualizations menu and if you need any help Power Bi has a great getting started guide at [8].

My dashboard ended up as in Figure 13.

Figure 13 My Dashboard in Power Bi
Figure 13
My Dashboard in Power Bi

Step 10: Constructing the enclosure: The last thing to do is build the enclosure for the project. The schematics are all in the GitHub repo. You can 3D print the parts and then glue them together. There is enough space for the device and a breadboard to fit in together with all the sensors. Ensure that the LED, button and heart rate sensors are poking out of the three holes on the top of the enclosure.

And that’s it, thanks for reading the article! 

RESOURCES

References:
[1] https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5647635
[2] https://www.ncbi.nlm.nih.gov/pubmed/29936653
[3] https://github.com/Andrei-Florian/MyPulse
[4] https://www.seeedstudio.com/Azure-Sphere-MT3620-Development-Kit-US-Version-p-3052.html
[5] https://www.mikroe.com/heart-rate-4-click
[6] https://azure.microsoft.com/en-us/services/azure-sphere/get-started
[7] https://azure.microsoft.com/en-us/free
[8] https://docs.microsoft.com/en-us/power-bi/fundamentals/service-get-started

Fritzing | www.fritzing.org
Microsoft Azure | www.azure.microsoft.com
MikroElektronika | www.mikroe.com
Seeed | www.seeedstudio.com
STMicroelectronics | www.st.com

PUBLISHED IN CIRCUIT CELLAR MAGAZINE • NOVEMBER 2021 #376 – Get a PDF of the issue

Keep up-to-date with our FREE Weekly Newsletter!

Don't miss out on upcoming issues of Circuit Cellar.


Note: We’ve made the Dec 2022 issue of Circuit Cellar available as a free sample issue. In it, you’ll find a rich variety of the kinds of articles and information that exemplify a typical issue of the current magazine.

Would you like to write for Circuit Cellar? We are always accepting articles/posts from the technical community. Get in touch with us and let's discuss your ideas.

Sponsor this Article
+ posts

Andrei Florian is a student in Dublin, Ireland. He has been working on tightening the connection between humans and technology by designing applications that will help us in our lives. This includes working on projects that combat pollution and climate change as well as monitoring our natural environment and our cities. He has also been working on personal security and big data. Andrei can be contacted at andrei_florian@universumco.com

Supporting Companies

Upcoming Events


Copyright © KCK Media Corp.
All Rights Reserved

Copyright © 2023 KCK Media Corp.

IoT Device Measures Key Health Stats

by Andrei Florian time to read: 20 min