TFT LCD Doesn't Output Heart Rate Sensor Values in the Right Places?

For my project, the heart rate sensor SEN-11574 ( something like this: https://www.sparkfun.com/products/11574) measures the raw heart values from a user's index finger.

The code makes it so that the raw heart values are converted to pulse rate (BPM), and then the BPM values are displayed in a 1.44" 128X128 SPI Color TFT LCD Module Display (ILI9163) ( something like this: https://www.creatroninc.com/product/144-tft-graphic-lcd-128x128px/)

This original code was written for the sensor values to output to a 2.2″ TFT display.

It's supposed to look like this: Imgur: The magic of the Internet.

And this is the code.

#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9340.h" 
#define _sclk 13
#define _mosi 11
#define _cs 10
#define _rst 9
#define _dc 8

Adafruit_ILI9340 tft = Adafruit_ILI9340(_cs, _dc, _rst);
int prevCount=1;
int countdigits[] = {
  0, 0, 0};
int prevdigits[] = {
  0, 0, 0};
int digitpos[] = {
  30, 90, 150};
int x=0; 

//  VARIABLES
int pulsePin = 0;                 // Pulse Sensor purple wire connected to analog pin 0

// these variables are volatile because they are used during the interrupt service routine!
volatile int BPM;                   // used to hold the pulse rate
volatile int Signal;                // holds the incoming raw data
volatile int IBI = 600;             // holds the time between beats, must be seeded! 
volatile boolean Pulse = false;     // true when pulse wave is high, false when it's low
volatile boolean QS = false;        // becomes true when Arduoino finds a beat.

void setup(){
  //Start the TFT screen and paint it black
  tft.begin();
  tft.setRotation(1);
  tft.fillScreen(ILI9340_BLACK); 
  tft.setTextColor(ILI9340_WHITE);
  tft.setTextSize(4);
  tft.setCursor(230, 90);
  tft.print("bpm");  
  tft.setTextColor(ILI9340_WHITE);

  Serial.begin(115200);             // we agree to talk fast!
  interruptSetup();                 // sets up to read Pulse Sensor signal every 2mS  
}

void loop(){
  
  if (QS == true){                       // Quantified Self flag is true when arduino finds a heartbeat
    Serial.print("BPM = ");
    Serial.println(BPM);   

    countdigits[2] = BPM % 10;
    //How to handle the middle digit depends on if the
    //the speed is a two or three digit number
    if(BPM > 99){
      countdigits[1] = (BPM / 10) % 10;
    }
    else{
      countdigits[1] = BPM / 10;
    }
    //Grab the first digit
    countdigits[0] = BPM / 100;

    //Split out the digits of the previous speed
    prevdigits[2] = prevCount % 10;
    if(prevCount > 99){
      prevdigits[1] = (prevCount / 10) % 10;
    }
    else{
      prevdigits[1] = prevCount / 10;
    }
    prevdigits[0] = prevCount / 100;
    //Now print the digits on the TFT screen.
    //Only execute this block if the bpm has changed.
    if(BPM != prevCount){
      tft.setTextSize(10);
      //Compare each digit to the value from the previous loop.
      //The digit will only be redrawn if it has changed.
      for(x=0; x < 3; x++){
        if(countdigits[x] != prevdigits[x]){
          //black out old value first.
          //Draw digit in black over the top of white digit
          tft.setCursor(digitpos[x], 70);
          tft.setTextColor(ILI9340_BLACK);
          tft.print(prevdigits[x]);
          //print new value in white
          if((x == 0) and (BPM > 99) and (countdigits[x] > 0)){
            tft.setCursor(digitpos[x], 70);
            tft.setTextColor(ILI9340_WHITE);
            tft.print(countdigits[x]);
          }
          if((x == 1) and (BPM >= 99)){
            tft.setCursor(digitpos[x], 70);
            tft.setTextColor(ILI9340_WHITE);
            tft.print(countdigits[x]);
          }
          else if((x == 1) and (BPM < 99) and (countdigits[x] > 0)){
            tft.setCursor(digitpos[x], 70);
            tft.setTextColor(ILI9340_WHITE);
            tft.print(countdigits[x]);
          }
          if(x == 2){
            tft.setCursor(digitpos[x], 70);
            tft.setTextColor(ILI9340_WHITE);
            tft.print(countdigits[x]);
          }
        }
      }
      prevCount = BPM; //Store current bpm for comparison on the next loop.
    } 
    QS = false;  // reset the Quantified Self flag for next time    
  }
}

So I modified the code so that the ordinary TFT library is used.

#include "SPI.h"
#include "TFT.h"
#define _sclk 13
#define _mosi 11
#define _cs 10
#define _dc 9
#define _rst 8


TFT tft = TFT(_cs, _dc, _rst);
int prevCount=1;
int countdigits[] = {
  0, 0, 0};
int prevdigits[] = {
  0, 0, 0};
int digitpos[] = {
  30, 90, 150};
int x=0; 

//  VARIABLES
int pulsePin = 0;                 // Pulse Sensor purple wire connected to analog pin 0

// these variables are volatile because they are used during the interrupt service routine!
volatile int BPM;                   // used to hold the pulse rate
volatile int Signal;                // holds the incoming raw data
volatile int IBI = 600;             // holds the time between beats, must be seeded! 
volatile boolean Pulse = false;     // true when pulse wave is high, false when it's low
volatile boolean QS = false;        // becomes true when Arduoino finds a beat.

void setup(){
  //Start the TFT screen and paint it black
  tft.begin();
  tft.setRotation(1);       // basically set the rotation   
  tft.background(0, 0, 0);    // Set background color to black
  tft.stroke(255, 255, 255);      // set word to white
  tft.setTextSize(3);         
  tft.setCursor(8, 26);       
  tft.print("bpm");  
  tft.stroke(255, 255, 255);     // Text color is set to white

  Serial.begin(115200);             // we agree to talk fast!
  interruptSetup();                 // sets up to read Pulse Sensor signal every 2mS  
}

void loop(){
  
  if (QS == true){                       // Quantified Self flag is true when arduino finds a heartbeat
    Serial.print("BPM = ");
    Serial.println(BPM);   

    countdigits[2] = BPM % 10;
    //How to handle the middle digit depends on if the
    //the speed is a two or three digit number
    if(BPM > 99){
      countdigits[1] = (BPM / 10) % 10;
    }
    else{
      countdigits[1] = BPM / 10;
    }
    //Grab the first digit
    countdigits[0] = BPM / 100;

    //Split out the digits of the previous speed
    prevdigits[2] = prevCount % 10;
    if(prevCount > 99){
      prevdigits[1] = (prevCount / 10) % 10;
    }
    else{
      prevdigits[1] = prevCount / 10;
    }
    prevdigits[0] = prevCount / 100;
    //Now print the digits on the TFT screen.
    //Only execute this block if the bpm has changed.
    if(BPM != prevCount){
      tft.setTextSize(2);
      //Compare each digit to the value from the previous loop.
      //The digit will only be redrawn if it has changed.
      for(x=0; x < 3; x++){
        if(countdigits[x] != prevdigits[x]){
          //black out old value first.
          //Draw digit in black over the top of white digit
          tft.setCursor(digitpos[x], 70);
          tft.stroke(0, 0, 0);
          tft.print(prevdigits[x]);
          //print new value in white
          if((x == 0) and (BPM > 99) and (countdigits[x] > 0)){
            tft.setCursor(digitpos[x], 70);
            tft.stroke(255, 255, 255);
            tft.print(countdigits[x]);
          }
          if((x == 1) and (BPM >= 99)){
            tft.setCursor(digitpos[x], 70);
            tft.stroke(255, 255, 255);
            tft.print(countdigits[x]);
          }
          else if((x == 1) and (BPM < 99) and (countdigits[x] > 0)){
            tft.setCursor(digitpos[x], 70);
            tft.stroke(255, 255, 255);
            tft.print(countdigits[x]);
          }
          if(x == 2){
            tft.setCursor(digitpos[x], 70);    
            tft.stroke(255, 255, 255);    // set the color to white
            tft.print(countdigits[x]);
          }
        }
      }
      prevCount = BPM; //Store current bpm for comparison on the next loop.
    } 
    QS = false;  // reset the Quantified Self flag for next time    
  }
}

but instead, it looks like this Imgur: The magic of the Internet

How can I fix it so that the texts are all aligned? I suspect it has something to do with the digipos[x] section, but I'm a beginner coder, so I don't understand what it means, and when I tried to search up what the code meant, nothing informative came up.

Thank you.

john6090:
I suspect it has something to do with the digipos[x] section

int digitpos[] = {
  30, 90, 150
};

what happened when you tried changing these to say {30, 60, 90}?

john6090:
For my project, the heart rate sensor SEN-11574 ( something like this: Pulse Sensor - SEN-11574 - SparkFun Electronics) measures the raw heart values from a user's index finger.

I don't think, that the sensor "measures the raw heart values", actually.

I think, the sensor just measures LED light reflection/ absorption.

The amount of LED light reflected or sbsorbed by the finger is constantly changing with the beat of the heart.

And if you want to get a BPM value from the change in the LEDlight, you have to find an algorithm, which detects the beat within the fluctuations of the LED light measured.

As I can read, the sensor provides analog output, so maybe the sketch should read the sensor by using the "analogread()" function at some place in the sketch.

I cannot think of any method getting BPM from the sensor wihout using analogread().

The algorithm was based off of this, except the GUI wasn't needed, so that part was fleshed out.