Medical IoT device

This page contains the description of the IoT device built to collect medical information about Heart, blood oxygenation and temperature.

If you need additional specific information about this topic or if you want to look it personally please write an email

Miniservice technology proposes different options to your fantasy. Opening your mind to all different sensor devices available on the market, can allow you to build very useful products able to help you, your family and your friends to simplify life and, in certain occasions, also to take care of your healt.
In this article, we will see how I built a medical device able to be connected to the Miniservices infrastructure and to monitor healt conditions of a connected person.

Before to start any description, it is important for me to evidence that this is not a game so, please, do not try to use such similar equipments on someone who really needs to be monitored. This test device is not certified to be used for real medical stuff and we will not be responsible for any damage caused by it. Please, use it for educational pourpose only.

If you explore web site, your curiosity will surely be captured by the Multidimensional sensor box.
This box represented a first test, used to start working with sensors and devices and to create a stable library to be used, at a later stage, with Miniservices by The device described here, is exactly the result of all those tests and has been built using the same platform as base architecture.

Heart rate sensor box is composed by:

1) Arduino 101
2) Oled Display 2.5 Inch
3) Max 30102 Sensor to meausre Heart Rate and Blood oxygenation
4) WiFi ESP8266
5) Temperature Sensor (added at a later stage and not present in the current version of this project)

The biggest complexity of this project is represented by the need to use Arduino 101 (device based on Intel Curie) togheter with the ESP8266 and to use the MAX30102 togheter with the OLED display accessing the I2C bus with two different Voltages.

In few words, the ESP 8266 is 3.3V based and uses the serial port so it is not a problem to use it directly connected to the board. However the MAX 30102 sensor is 3.3v based while the Oled Display is 5V and they share the i2C Bus which cannot be used with two different levels of V. For this reason, we need to use a "logic level converter" in order to adapt the level of te MAX to the level of the I2C bus. This is the schema I used to connect the sensor to Arduino 101

Connection schema for the MAX30100 with Arduino 101

This special connection will allow you to work using the same I2C bus with two different logic levels.
Also the use of an ESP8266 serial module has some complexity on a basic arduino 101. In fact, the number of libraries available for this board is limited and you cannot use the same ones available to compile NodeMCU projects (WebServer, WebClient,HTTP etc)
Fortunatelly, I found an interesting project named: "WiFiESP" wich contains all the needed functions to send the right AT command to the ESP board in order to use it in a way similar to the libraries available for other boards.

If you are interested in this library you can download the one I used in the Download page directly following this Link.

Another interesting part of the project has been the "mechanical" one. In few words the MAX 30102 sensor needs to be fixed to the finger and cables need to be soldered and fixed to something statically fixed. This mainly for two reasons. The first one is to not risk to disconnect cables during meausres, the second reason is that the MAX30102 sensor works using infrared refraction and every small movement of your finger can significantly change the results obtained. For this reason the finger must be "connected" in a static way to the sensor.
In order to achieve such result I draw an interesting component to print using my Printerina 3d printer. If needed, you can download STL files directly from the thingiverse page I published on the main web site.

Following some pictures of the Heart Sensor box.

As you can see (if you remember the multi sensor box), I left the red button in the middle of the box. This button is very useful because it is needed every time you need to start reading values. The right way to use the MAX 30102 library is to touch the sensor with your finger and then start reading values from the sensor. For this pourpose you need to have some switch able to activate the reading process.

This means that the algorithm will wait for the button to be pressed then will start read values from the sensor. If the finger is disconnected it will stop reading values and wait for the button to be pushed again before to start reading again values from the device
Obviously after an interval of time the miniservice platform is invoked and parameters are stored into the Buonevacanze database ready to be evaluated and managed by robots or by queries executed on it using standard functions.

In order to run the box you need also a library able to run the Max3010X. This library is different from the library you can find to run the MAX30100 version and can be downloaded in the BVRobotics Download Page

And now let's talk about the source code

You need to declare those two headers if you want both to read the heart rate and the SPO value.

    #include "MAX30105.h"
    #include "spo2_algorithm.h"

Now declare the following global variables:

    uint32_t irBuffer[100]; //infrared LED sensor data
    uint32_t redBuffer[100];  //red LED sensor data

    int32_t bufferLength; //data length
    int32_t spo2; //SPO2 value
    int8_t validSPO2; //indicator to show if the SPO2 calculation is valid
    int32_t heartRate; //heart rate value
    int8_t validHeartRate; //indicator to show if the heart rate calculation is valid

In the setup function you need now to init the sensor with the following easy lines. The values you will see are the optimal values I identified for my device. Honestly I cannot imagine a big variation on similar device

    if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed
        Serial.println("MAX30105 was not found. Please check wiring/power. ");
        while (1);
    Serial.println("Place your index finger on the sensor with steady pressure. and press the button");

    byte ledBrightness = 60; //Options: 0=Off to 255=50mA
    byte sampleAverage = 4; //Options: 1, 2, 4, 8, 16, 32
    byte ledMode = 2; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green
    byte sampleRate = 100; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
    int pulseWidth = 411; //Options: 69, 118, 215, 411
    int adcRange = 4096; //Options: 2048, 4096, 8192, 16384

    particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); //Configure sensor with these settings


Now the most important part. In the loop cycle you will read values and will display results both on the display or sending them to the Miniservice infrastructure. Be carefull to optimise this piece of code more than possible in order to speed up the sensor reading phase

    bufferLength = 100; //buffer length of 100 stores 4 seconds of samples running at 25sps

    //read the first 100 samples, and determine the signal range
    for (byte i = 0; i < bufferLength; i++)
    while (particleSensor.available() == false)     //do we have new data?
    particleSensor.check();                         //Check the sensor for new data

    redBuffer[i] = particleSensor.getRed();
    irBuffer[i] = particleSensor.getIR();
    particleSensor.nextSample();                    //We're finished with this sample so move to next sample

    Serial.print(redBuffer[i], DEC);
    Serial.print(F(", ir="));
    Serial.println(irBuffer[i], DEC);

    //calculate heart rate and SpO2 after first 100 samples (first 4 seconds of samples)
    maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);

    //Continuously taking samples from MAX30102.  Heart rate and SpO2 are calculated every 1 second
    while (1)
        bool FingerFound=false;
        //dumping the first 25 sets of samples in the memory and shift the last 75 sets of samples to the top
        for (byte i = 25; i < 100; i++)
            redBuffer[i - 25] = redBuffer[i];
            irBuffer[i - 25] = irBuffer[i];

        //take 25 sets of samples before calculating the heart rate.
        for (byte i = 75; i < 100; i++)
        while (particleSensor.available() == false) //do we have new data?
        particleSensor.check(); //Check the sensor for new data

        redBuffer[i] = particleSensor.getRed();
        irBuffer[i] = particleSensor.getIR();
        particleSensor.nextSample(); //We're finished with this sample so move to next sample

        if (irBuffer[i] > 50000)
        FingerFound = true;


        //After gathering 25 new samples recalculate HR and SP02
        maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);

        //print on the LCD Display
            //do something here to display results ...
        if (!FingerFound){
        sprintf(ScreenOutput, "finger not found");
        break;    //reset and out from the loop
        sprintf(ScreenOutput, "HR:%l, PO2:%l", heartRate, spo2);
                //put the string on your display ...
        if ((millis() - time) > SEND_INTERVALL) {
            BVReturnString = BVAuthenticate(SVCBiomedical, ObjectCode, (String)WiFi.localIP());
            Token = xmlTakeParam(BVReturnString, "Message");
            if ((Token != "Not Authorized") && (Token != "not found")) {
            SendBioMedicalValues(Token, 0 ,heartRate, spo2);
            time = millis();



As you can see in order to connect to the miniservice infrastructure I've used some basic functions provided by the Miniservices library.

Leave a Comment