Back to the main Heart Monitor page

/***************************************************

 Heart_MonitorB

  To test some ideas for buttons. Using a class Button(),

  implement the actual AD8232 Heart Monitor breakout board. 

  Has debouncing and an array of Button class objects-- WORKS

  Modified May 30, 2017 by C. Hartley

 ****************************************************/


#include <Adafruit_GFX.h>    // Core graphics library

#include  <SPI.h>

#include "Adafruit_HX8357.h"

#include "TouchScreen.h"

#include "Arduino.h"

#include "Button.h"


// These are the four touchscreen analog pins

#define YP A2  // must be an analog pin, use "An" notation!

#define  XM A3  // must be an analog pin, use "An" notation!

#define  YM 7   // can be a digital pin

#define  XP 8   // can be a digital pin

// The display uses hardware SPI, plus #9 & #10

#define  TFT_RST -1  // dont use a reset pin, tie to arduino RST if you like

#define  TFT_DC 9

#define  TFT_CS 10

// for the heart monitor (HM)

#define  HM_LOPlus  11 // not same as program with HM by itself; e.g. HeartMonitor_AD8232_No_TFT

#define  HM_LOMinus  12 // ditto

#define  HM_Input A0 // input from the HeartMonitor_AD8232


// This is calibration data for the raw touch data to the screen coordinates

#define TS_MINX 110

#define TS_MINY 80

#define TS_MAXX 900

#define TS_MAXY 940

#define MINPRESSURE 10

#define MAXPRESSURE 1000

#define numberButtons 5

#define PENRADIUS 1

#define BLACK 0X000

#define GREY 0XB576 // use http://www.barth-dev.de/online/rgb565-color-picker/ to pick colors

#define LTBLUE 0XAE3F


Adafruit_HX8357 tft = Adafruit_HX8357(TFT_CS, TFT_DC, TFT_RST);

// For better pressure precision, we need to know the resistance

// between X+ and X- Use any multimeter to read it

// For the one we're using, its 300 ohms across the X plate

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

// Size of the color selection boxes and the paintbrush size

int oldcolor, currentcolor;

unsigned long currentMillis;

unsigned long traceMillis;

bool traceIt;

int traceX = 80;

int traceY_Old = 160;

int traceY = 0;

bool single;

bool single2;

int deltaTime = 9  ;

int points2[400];

int pointCount;

int buttonPushed = -1;


//Buttons ==ARGH! // creates array of Class Button objects

Button button[numberButtons] = {Button(10, 10, 70,50,LTBLUE, "Trace",  0), 

    Button(10, 70, 70,50,LTBLUE, "Stop", 1),

    Button(10, 130, 70,50,LTBLUE, "Clear", 2), 

    Button(10, 190, 70,50,LTBLUE, "Sngl", 3),

    Button(10, 250, 70,50,LTBLUE, "Test", 4)};


void setup(void) 

{  

  tft.begin(HX8357D);// the touch screen

  tft.fillScreen(HX8357_WHITE); 

  // make the color selection boxes

  tft.setTextColor(HX8357_WHITE);

  tft.setRotation(1);

  tft.setTextSize(2);// for the button drawin'

  //Buttons 

  button[0].drawButton(tft);  

  button[1].drawButton(tft);

  button[2].drawButton(tft);

  button[3].drawButton(tft);

  button[4].drawButton(tft); 

  traceIt = false;

  single2 = false; 

  setPoints2();

  // for heart monitor

  pinMode(HM_LOPlus, INPUT); // Setup for lead off detection LO+

  pinMode(HM_LOMinus, INPUT); // Setup for lead off detection LO-

  Serial.begin(9600);// in case I need it.

}


void loop()

{  

   if(traceIt)

   {

      if(digitalRead(HM_LOPlus) == 1 || digitalRead(HM_LOMinus) == 1)

      {

        Serial.println("!");

      }

      else

      {

        if(millis() - traceMillis >deltaTime)

        {

          traceY = analogRead(HM_Input);

          // map it

          traceY =320 - map(traceY, 0, 1023, 10, 320); //screen height is 320 pixels 

          tft.drawLine(traceX-1, traceY_Old, traceX, traceY , HX8357_BLACK);

          traceX ++;

          traceY_Old = traceY;

          if(traceX==480)

          {

             traceX = 80;

             refreshGraph();// clear the screen

          }// closes if(traceX

          traceMillis = millis();// start a new time sequence

        }// closes if(millis()

        if(millis()- currentMillis > 1000)

        {

          // one second gone by

          currentMillis = currentMillis + 1000;

          if(traceX !=80)

          {

            tft.drawLine(traceX, 0, traceX , 320, GREY);

          }

        }// closes if(millis() the other one       

      }// closes else of if(digitalRead . .       

   }// closes if(traceIt)

   if(single)

   {

        if(millis() - traceMillis >deltaTime)

    {

      if(pointCount>0)

      {

        traceY = analogRead(HM_Input);

         // map it

        traceY =320 - map(traceY, 0, 1023, 10, 320); //screen height is 320 pixels 

        tft.drawLine(traceX-1, traceY_Old, traceX, traceY , HX8357_BLACK);

        traceY_Old = traceY;

      }

      traceMillis = millis();

      traceX ++;

      pointCount ++;

      if(pointCount == 400)

      {

        single = false;

      }

    }   

    if(millis()- currentMillis > 1000)

    {

      // one second gone by

      currentMillis = currentMillis + 1000;

      tft.drawLine(traceX, 0, traceX , 320, GREY);

    }

  } // closes if(single)

  if(single2)

  {

        if(millis() - traceMillis >deltaTime)

    {

      if(pointCount>0)

      {

        tft.drawLine(traceX-1, 160 - points2[pointCount -1], traceX, 160 - points2[pointCount],HX8357_BLACK);

      }

      traceMillis = millis();

      traceX ++;

      pointCount ++;

      if(pointCount == 400)

      {

        single2 = false;

      }

    }   

    if(millis()- currentMillis > 1000)

    {

      // one second gone by

      currentMillis = currentMillis + 1000;

      tft.drawLine(traceX, 0, traceX , 320, GREY);

    }

  }

  // wait until no button pressed for a bit (debounding)

  TSPoint p;

  // NOTE: so far does not look like I need a debound

  p = ts.getPoint() ;

  // Scale from ~0->1000 to tft.width using the calibration #'s

  // if one uses  tft.setRotation(1), it rotates coordinates by 90 degrees for purposes

  // of printing, but also then I had to change x max below to tft.height(); it was previoiusly

  // tft.width()

   if(p.z > MINPRESSURE)

   {

      p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.height());// had to reverse height and width if rotate

      p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.width());

   }

  int checker;

  buttonPushed = -1;

  for ( int i = 0; i < numberButtons; i++)

  { 

      checker = button[i].checkButton(p.x, p.y);

      if(checker != -1)

      {

        buttonPushed = checker;

      }      

  } 

  switch(buttonPushed)

  {

    case 0:

     // start continuous trace

      traceIt = true;

      traceMillis = millis();

      currentMillis = millis();

      traceX = 80;

      refreshGraph();

      pointCount = 0;

    break;

    case 1:

     // stop continuous trace

     traceIt = false;

     break;

    case 2:

     // refresh graph

     refreshGraph();

     break;   

    case 3:

      // single trace of ECG

      single = true;

      traceMillis = millis();

      currentMillis = millis();

      refreshGraph();

      traceX = 80;

      traceY = analogRead(HM_Input); 

      traceY_Old = map(traceY, 0, 1023, 10, 320);     

    break;

    case 4:

      // draw a single test trace -- the other one

      single2 = true;

      traceMillis = millis();

      currentMillis = millis();

      refreshGraph();

      traceX = 80;     

      pointCount = 0;

    break;

    default:

      // nothin here

    break;

  }

}// closes loop


void setPoints2()

{ 

  int whole;

  float rads;

  float sinWave;

  for(int i = 0; i<400; i++)

  {

    rads = (float)i;

    rads = rads/11.0;

    sinWave = 10.0*(cos(rads) +cos(2*rads)+ cos(3*rads)+cos(4*rads)+cos(5*rads)+

      cos(6*rads)+cos(7*rads)+cos(8*rads)+cos(9*rads)+cos(10*rads)+cos(11*rads));

    points2[i] =  (int)sinWave;

  }

}


void refreshGraph()

{  

  tft.fillRect(79,0,tft.width()-79,tft.height(),HX8357_WHITE );

  tft.drawLine(80,160, 480,160,GREY );  

}

The following section of program must be placed in a second tab in your Arduino IDE. You need to make a new tab, give it a title, and put the bottom piece of programming in it. I'll explain how that is done.

Open your Arduino IDE. Copy and paste the portion of this program that is above this point. Give it a title: Heart_MonitorB ; that way it will look like the figure below. Copy the portion of this progam that is below, starting with and including "class Button".

On your Arduino IDE you should find a little triangle near the top right corner; see figure below:

IDE

Click on the triangle and select "New Tab". Then you will find a place near the bottom of the page to type in a name for your new tab. Type in:

Button.h

Just this name, no other version. Click the OK. Paste the text that you copied starting at the "class Button" line into the program section of your new tab.

You can click the other tab to get back to the main program, Heart_MonitorB. This Button.h tab is necessary because the main program calls to include that section; that's the #include.Button.h line you find in the Heart_MonitorB program.

class Button

{ 

  #define TFT_RST -1  // dont use a reset pin

  #define TFT_DC 9

  #define TFT_CS 10

  private:

  int x0, y0, w, h;

  String title;

  int color;

  public: 

  int number;

  Button (int xN, int yN, int wN, int hN, int colorN, String titleN, int numberN)

  {

    x0 = xN;

    y0 = yN;

    w = wN;

    h = hN;

    color = colorN;  

    title= titleN;

    number = numberN;   

  }// closes Button constructor 


  void drawButton(Adafruit_HX8357 tft )

  {        

    tft.fillRoundRect(x0, y0, w, h, 10,color);

    tft.setTextColor(HX8357_BLACK);

    tft.setCursor(x0+10 ,y0+20);

    tft.println( title);

  } //closes drawButton


  int checkButton(int x, int  y)

  {

    // gets p.x and p.y from ts.getPoint()

   int numberReturn = -1;

    //  the touch screen coordinates are not same as tft coordinates so this

    //if looks a little strange. Need to check touch screen coordinates x, y.

    if((x < 320 - y0 )&& (y > x0) && (x > 320 - y0 - h) && ( y < x0 +h))

    {

        // button hit

        numberReturn = number;// return which button in the array was hit

    }

    return numberReturn;

  }

};// closes Button class


Back to the main Heart Monitor page


Text and graphs © 2017 by Charles Hartley