Smartwatch with heart rate monitor for school project

Hi All,

I am looking to make a smart watch with a display to tell the time and a heart rate monitor. I don’t want to use a micro bit to do it as they are a bit clunky.

My online research has pushed me in the direction of an ESP32 based watch but it seems to be very complicated in terms of ordering and securing components.

Does anyone have any ideas on what I could use to make this happen?

Ta
Mark Gregory

2 Likes

Welcome Mark.
Good to have you with us.

I keep seeing this surprisingly affordable weird circular display with the popular RP2040 micro controller built in. Looks like a big digital watch.

It would be able to interface with this gravity heart rate monitor thing no worries.

I’m imagining the screen on the top of the wrist and the sensor on the bottom of the wrist. Both attached the the same band.

I’m sure there are cleaner ways to do it, but I like the simplicity.
It’s the right amount of challenge for a school project in my opinion.
Does that feel doable to you?

3 Likes

Hi. That’s awesome! I haven’t seen anything like that where the pins are accessible. Thanks so much for the suggestion!

They are year 10 kids and pretty bright so they will spend a bit of time programming the watch, assembling it and creating a case and band for it.

Would this sensor work with it?

The board does say it has 2 x I2C channels so I would be surprised if it won’t.

The grove sensor says it only works when the person is stationary so that is unlikely to work well for us.

Thanks again,
Mark

3 Likes

Yeah man looks like it.
The internal chip is the same chip thats inside the raspberry Pi Pico (1) so its gonna work with basically anything.

What ide or software enviroment were you imagining your students using?

2 Likes

Hi,
I spoke to the guys at core electronics and they said that the one you mentioned is a little difficult to use.

They steered me to this one:

The only problem with this one is that it has a weird battery connector so I think I will replace that on the board to a standard one.

We usually use Arduino but these kids haven’t done any programming so it won’t matter. Dan from Core Electronics has written some code for that module as well so we should be able to get it going.

Thanks again,
Mark

3 Likes

Hi Mark,

This should be a great board with your project. A monitor like this one the underside of the board could give you a really sleek compact design. The one you’ve selected is much more cost-effective though, we look forward to seeing ti in action.

2 Likes

Hi Jack,

Thanks for the suggestion. That may be an option.

I’m no expert and it has taken me several days to get the watch to display an image, display a gif, display the time and react to touch at given coordinates. All of that is working correctly and I have learned a lot about how it works.

I am trying to get stable readings off the biometric sensor I purchased and am struggling to get it to work correctly. I am getting readings off it but they are bouncing around a lot. I have tried using 4.7k resistors between SCL and 3.3V and SDA and 3.3V but that didn’t help. I have defined the SDA and SCL pins correctly and the sensor is registering but the values are incorrect. If they’re not, I’ve got a serious case of arrhythmia!

I haven’t tried the logic converter board I purchase as the Internet and Chat GPT seem to think it is not needed. I did have it giving me a fairly accurate reading but now it is giving me all sorts of strange reading despite the wiring being identical.

Would this been normal behaviour if I was using the incorrect logic level?

I will see try the logic level converter but if that doesn’t solve it, I will either need to get a different sensor or do something different with the one I have.

Does anyone have experience using this sensor:

with an ESP32-S3?

Ta
Mark

3 Likes

Hey @Mark57232,

Good to hear you’re making progress!

The issue with the bio-sensor sounds strange. Can you send pictures of your physical setup, as well as code snippets? That should shed some light on the exact setup you’re working with right now.

2 Likes

Hi Zach,

I think I might be totally confused as to how to hook this all up.

I’ve got:

3.3V of the ESP32-S3 hooked up to VIN on the sensor.
GND to GND
GPIO Pin 15 to SDA
GPIO Pin 16 to SCL

The code I am using is an example from the Sparkfun Library.

Optical Heart Rate Detection (PBA Algorithm) using the MAX30105 Breakout
By: Nathan Seidle @ SparkFun Electronics
Date: October 2nd, 2016
https://github.com/sparkfun/MAX30105_Breakout

This is a demo to show the reading of heart rate or beats per minute (BPM) using
a Penpheral Beat Amplitude (PBA) algorithm.

It is best to attach the sensor to your finger using a rubber band or other tightening
device. Humans are generally bad at applying constant pressure to a thing. When you
press your finger against the sensor it varies enough to cause the blood in your
finger to flow differently which causes the sensor readings to go wonky.

Hardware Connections (Breakoutboard to Arduino):
-5V = 5V (3.3V is allowed)
-GND = GND
-SDA = A4 (or SDA)
-SCL = A5 (or SCL)
-INT = Not connected

The MAX30105 Breakout can handle 5V or 3.3V I2C logic. We recommend powering the board with 5V but it will also run at 3.3V.

#include <Wire.h>
#include "MAX30105.h"

#include "heartRate.h"

MAX30105 particleSensor;

const byte RATE_SIZE = 4;  //Increase this for more averaging. 4 is good.
byte rates[RATE_SIZE];     //Array of heart rates
byte rateSpot = 0;
long lastBeat = 0;  //Time at which the last beat occurred

float beatsPerMinute;
int beatAvg;

void setup() {
  Wire.begin(15, 16); // define the SDA / SCL pins
  Serial.begin(115200);
  Serial.println("Initializing...");


  // Initialize sensor
  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.");

  particleSensor.setup();                     //Configure sensor with default settings
  particleSensor.setPulseAmplitudeRed(0x0A);  //Turn Red LED to low to indicate sensor is running
  particleSensor.setPulseAmplitudeGreen(0);   //Turn off Green LED
}

void loop() {
  long irValue = particleSensor.getIR();

  if (checkForBeat(irValue) == true) {
    //We sensed a beat!
    long delta = millis() - lastBeat;
    lastBeat = millis();

    beatsPerMinute = 60 / (delta / 1000.0);

    if (beatsPerMinute < 255 && beatsPerMinute > 20) {
      rates[rateSpot++] = (byte)beatsPerMinute;  //Store this reading in the array
      rateSpot %= RATE_SIZE;                     //Wrap variable

      //Take average of readings
      beatAvg = 0;
      for (byte x = 0; x < RATE_SIZE; x++)
        beatAvg += rates[x];
      beatAvg /= RATE_SIZE;
    }
  }

  Serial.print("IR=");
  Serial.print(irValue);
  Serial.print(", BPM=");
  Serial.print(beatsPerMinute);
  Serial.print(", Avg BPM=");
  Serial.print(beatAvg);

  if (irValue < 50000)
    Serial.print(" No finger?");

  Serial.println();
}


I have also tried this code from a Max 30102 library:

/**
 @file Max30102.ino
 @brief Checks the Heart Rate and SpO2
 @detail Checks the Heart Rate and SpO2 using Max30102 sensor

 * Reference arduino code: https://github.com/bobdavis321/Arduino-MAX30100 , https://www.youtube.com/watch?v=mmXJ33Nx4Mc 
 * Refrence aries board: https://vegaprocessors.in/blog/interfacing-max30102-pulse-oximeter-to-thejas-soc/
 * 
 * MAX30100 sensor
 * Device address -0x57
 * Connections:
 * MAX30102   
 * 3V3      -   3.3V
 * GND      -   GND
 * SDA      -   SDA0
 * SCL      -   SCL0

 * .
 * Note:
 * Use 10K pull-up resistors while connecting SDA and SCL pins to MAX30102 sensor for accurate measurements.
 **/

#include <Wire.h>

#include "MAX30102_PulseOximeter.h"

#define REPORTING_PERIOD_MS     1000

// PulseOximeter is the higher level interface to the sensor
// it offers:
//  * beat detection reporting
//  * heart rate calculation
//  * SpO2 (oxidation level) calculation 
PulseOximeter pox;
uint32_t tsLastReport = 0;
// Callback (registered below) fired when a pulse is detected 
void onBeatDetected()
{
    Serial.println("Beat!");
}
 
void setup()
{
Wire.begin (15, 16);
    Serial.begin(115200);
    Serial.print("Initializing..");
    delay(3000);
    // Initialize the PulseOximeter instance
    if (!pox.begin()) {
        Serial.println("FAILED");
        for(;;);
    } else {
        Serial.println("SUCCESS");
    }
    // The default current for the IR LED is 50mA and is changed below
    pox.setIRLedCurrent(MAX30102_LED_CURR_7_6MA);
    // Register a callback for the beat detection
    pox.setOnBeatDetectedCallback(onBeatDetected);
}
 
void loop()
{
    // Make sure to call update as fast as possible
    pox.update();
   // long irValue = pox.getHeartRate();
    // Asynchronously dump heart rate and oxidation levels to the serial
    // For both, a value of 0 means "invalid"
    if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
        Serial.print("Heart rate:");
        Serial.print(pox.getHeartRate());
        Serial.print("bpm / SpO2:");
        Serial.print(pox.getSpO2());
        Serial.print("%");

        
 // if (irValue < 70)
   // Serial.print(",  No finger?");
    Serial.println();
         
        tsLastReport = millis();
    }
}

Neither are working reliably. I have no idea what the issue is. If I do need the logic converter, how do I hook it up?

Ta
Mark

2 Likes

Hey @Mark57232,

I would think you don’t need the logic level converter, the quote from Nathan at Sparkfun should be a fairly confident source.

Your connections seem fine in theory, though I believe the default i2c pins are GPIO21 for SDA and GPIO22 for SCL. Could be worth changing to test, though given that you are getting any readings at all, the device is likely transmitting something.

Can you provide an example of the output you’re receiving?

3 Likes

Hi Zach,

Thanks for your reply.

I can’t get the output or test the default pin definitions at the moment because I’ve left work and my computer is there (speech night tonight). I should be able to get accurate data tomorrow.

It was giving me a BPM that was rarely in normal human range i.e 17 BPM and it would return the same value over and over again. Then it would jump to 50, maintain that reading for a while then change again to something else. If I took my finger off altogether, it correctly read that my finger was off.

I tried it on my fingers and wrists, all with similar results. I also tried flipping the SCL and SDA pins. I even tried testing it on other people.

It’s strange because it is hooked up the same way on lots of different tutorials.

Ta
Mark

1 Like

Hi Zach,

The waveshare wiki says that the board does not have a pin 22 so I don’t think I will be able to test that.

I am confident the I2C connection is working in some capacity but I don’t know if it working correctly.

I don’t know much about it but apparently it is measuring the difference in light. It is as though the logic level is not high enough i.e. the signal is too weak. I am most likely totally wrong about that too.

I am keen to try the logic converter but I have no idea how to hook it up. It appears to want a 5V line but I don’t have one. The board is powered by a 3.7V battery although I have it hooked up to the computer at the moment.

Ta
Mark

2 Likes

Hi Mark,

I’ve used this sensor to some success, the main variable to get it working was the pressure that I was applying to the sensor.
Sparkfun use a rubber band to maintain constant pressure, and I would highly recommend this approach.
https://learn.sparkfun.com/tutorials/max30105-particle-and-pulse-ox-sensor-hookup-guide/all#example-4---heart-beat-plotting

Since the sensor is getting data out, I would say it is definitely working, no need for the logic level converter. The ESP32 is quite a fancy board, allowing you to use any pins for I2C, no need to move pins.

Behind the scenes the library is doing a lot of math, so that would explain some of the readings not coming through as expected, the second screenshot in that list of 3 look promising, there might have been a good window in there where it got a good set of readings.

Liam

1 Like

Thanks Liam. I think you are most likely correct. I put it on with a rubber band and it gave me a much more stable reading. I think I will just move ahead with it as a project and if it gives the kids the wrong heart rate then so be it :slight_smile:

Thanks again. My next phase is to get the bpm to update on the screen and to wake up the sensor when it is required. I am going to assume that the sensor should be off when not in use to save battery. Is that correct? I don’t even know if it is possible to control when it is awake and when it is asleep. Could I attach the power to one of the GPIO pins and make the pin go high when I want to use the sensor? I know it has an interrupt pin but I don’t know if turning it on is what it is used for. Does anyone know how to turn it on and off?

In an ideal world, I also want to use the accelerometer to turn the watch face on when you raise your hand. Hopefully I can get that working. That will save a lot of battery I would think. If anyone has advice on that, let me know.

Ta
Mark

2 Likes

Hi Mark,

Glad to hear you are making some ground!! To correct it a bit, you could always run a few tests - if you get a smart watch or phone capable of getting heart rate, compare to the output, and try a linear scaling, I would go as far as the offset and gain.

Depending on the library you are using updating the number/graphic on the screen will be a breeze compared to any sensor integration.

Battery life is a fuuuun one!!
First of all, putting your microcontroller to sleep will save the most power, this can be done easily in code (and especially the Arduino language).
Like you mentioned, along side this - putting any sensors and devices to sleep is great, thankfully this device lets you do that in software as well

(A great microcontroller I like it use includes 2 power supplies, and it lets you turn the second one on and off to save power - ProS3 ESP32-S3 Dev board | Buy in Australia | CE08579 | Core Electronics)

The interupt pin is controlled by the sensor, when configured, this pin will turn on when something happens in the sensor - but not strictly necessary for your project.

A couple bits of advice on saving power, without having all of the right tools (Otii, Nordic) optimisation will be hard, and its worth taking one from the books of Fitbit etc, I belive they regularly check heart rate, sleeping in between, but they would keep the sensor on if the user is entering a high rate of change (logging), then only sending to the screen/smartphone when required. (For your project a button would be a great start, and will let you translate into the IMU later)

Liam

The Sparkfun library includes shutDown() and wakeUp() for the MAX30105, so you should be able to use that to control the power.
sparkfun/SparkFun_MAX3010x_Sensor_Library

2 Likes