Medical IoT device

This page contains the description of the IoT device built to collect medical information about Heart, blood oxigenation 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 opens the way to your fantasy. opening your mind to all different sensor devices available on the market can allow you to build very usefull products able to help you, your family and your friend to simplify life but in certain occasion also to save it. In this case we will see how I built a medical device able to be connected to the Miniservice platform 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, 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 activities so we are not responsible
for any accident caused by it. Please, use it just for educational pourpose

If you explore web site, your curiosity will surelly be captured by the Multidimensional sensor box.
This box has been a first test box used to start working with sensors and devices and to create a stable library to be used at a later stage with Miniservices Miniservices by This device 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 complexity of this project has been 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 Voltage.
In few word, 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 a base 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 in the base code used 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 really 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 able to be linked statically. 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 fixed in a static way to the sensor.
In order to achieve such result I draw an interestin component to print using my Printerina. 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 usefull 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 Buonevacanze 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