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 );
}
On your Arduino IDE you should find a little triangle near the top right corner; see figure below:
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