Wireless ECG Monitoring using Nano, Sparkfun AD8232, HC-05

I'm trying to create a wireless setup for measuring ECG from the human body using a Sparkfun AD8232, Nano, and HC-05. My HC-05 doesn't have ZS-040 written on it, but it has the button and EN pin. So far, I have been able to successfully observe ECG by replacing Serial.begin(9600) with Serial.begin(57600) in the tutorial Arduino code at this link: AD8232 Heart Rate Monitor Hookup Guide - SparkFun Learn

So it seems that the arduino baud rate is 57600. The console confirms this when I upload the script from that tutorial:
Using Port : COM7
Using Programmer : arduino
Overriding Baud Rate : 57600
AVR Part : ATmega328P
Chip Erase delay : 9000 us

So I've been trying to make sure that the HC-05 operates at this baud rate because the arduino nano/AD8232 combination works with this baud rate when connected to the serial port. I've tried using the code from Martyn (Arduino with HC-05 (ZS-040) Bluetooth module – AT MODE | Martyn Currey) as is and following these steps (not using a voltage divider at the moment):

  1. Setup all the connections (apart from voltage divider)
  2. Keep the Rx, Tx pins on the HC-05 disconnected and plug in USB to computer.
  3. Upload the code. Then connect the Rx, Tx pins back to the HC-05.
  4. Disconnect the Vcc on the HC-05, hold the button, connect the Vcc on HC-05, then release button.
  5. Open serial monitor, which is set at 9600 baud rate, both NL&CR chosen, and type 'AT' and press enter.

The serial monitor gives no output in response to the 'AT' command:
Sketch: C:\Users\fahee\Desktop\BTTry4\BTTry4.ino
23:41:36.589 -> Uploaded: Mar 10 2019
23:41:36.623 ->
23:41:36.623 -> BTserial started at 38400
23:41:36.623 ->
23:41:40.701 -> >AT

I have tried holding the button and sending the command, but no difference. I've also tried changing the Serial.begin(9600) in the code with Serial.begin(57600) and changing the serial monitor baud rate to 57600, but still doesn't work. I just want to make sure the baud rate is set correctly on the HC-05. Any ideas on what could be wrong? I'm thinking that maybe the voltage divider will fix the issue, based on the comments posted on his website.

Below is the code I'm trying to use for bluetooth:

//  Sketc: basicSerialWithNL_001
// 
//  Uses hardware serial to talk to the host computer and software serial 
//  for communication with the Bluetooth module
//  Intended for Bluetooth devices that require line end characters "\r\n"
//
//  Pins
//  Arduino 5V out TO BT VCC
//  Arduino GND to BT GND
//  Arduino D9 to BT RX through a voltage divider
//  Arduino D8 BT TX (no need voltage divider)
//
//  When a command is entered in the serial monitor on the computer 
//  the Arduino will relay it to the bluetooth module and display the result.
//
 
 
#include <SoftwareSerial.h>
SoftwareSerial BTserial(8, 9); // RX | TX
 
const long baudRate = 38400; 
char c=' ';
boolean NL = true;
 
void setup() 
{
    Serial.begin(9600);
    Serial.print("Sketch:   ");   Serial.println(__FILE__);
    Serial.print("Uploaded: ");   Serial.println(__DATE__);
    Serial.println(" ");
 
    BTserial.begin(baudRate);  
    Serial.print("BTserial started at "); Serial.println(baudRate);
    Serial.println(" ");
}
 
void loop()
{
 
    // Read from the Bluetooth module and send to the Arduino Serial Monitor
    if (BTserial.available())
    {
        c = BTserial.read();
        Serial.write(c);
    }
 
 
    // Read from the Serial Monitor and send to the Bluetooth module
    if (Serial.available())
    {
        c = Serial.read();
        BTserial.write(c);   
 
        // Echo the user input to the main window. The ">" character indicates the user entered text.
        if (NL) { Serial.print(">");  NL = false; }
        Serial.write(c);
        if (c==10) { NL = true; }
    }
 
}

And here is the code I'm using for the AD8232 to function with the Arduino, based on the tutorial provided from Sparkfun:

/******************************************************************************
Heart_Rate_Display.ino
Demo Program for AD8232 Heart Rate sensor.
Casey Kuhns @ SparkFun Electronics
6/27/2014
https://github.com/sparkfun/AD8232_Heart_Rate_Monitor
The AD8232 Heart Rate sensor is a low cost EKG/ECG sensor.  This example shows
how to create an ECG with real time display.  The display is using Processing.
This sketch is based heavily on the Graphing Tutorial provided in the Arduino
IDE. http://www.arduino.cc/en/Tutorial/Graph
Resources:
This program requires a Processing sketch to view the data in real time.
Development environment specifics:
  IDE: Arduino 1.0.5
  Hardware Platform: Arduino Pro 3.3V/8MHz
  AD8232 Heart Monitor Version: 1.0
This code is beerware. If you see me (or any other SparkFun employee) at the
local pub, and you've found our code helpful, please buy us a round!
Distributed as-is; no warranty is given.
******************************************************************************/

void setup() {
  // initialize the serial communication:
  Serial.begin(57600);
  pinMode(10, INPUT); // Setup for leads off detection LO +
  pinMode(11, INPUT); // Setup for leads off detection LO -

}

void loop() {
  
  if((digitalRead(10) == 1)||(digitalRead(11) == 1)){
    Serial.println('!');
  }
  else{
    // send the value of analog input 0:
      Serial.println(analogRead(A0));
  }
  //Wait for a bit to keep serial data from saturating
  delay(1);
}

Hi. I'd recommend testing each part of your circuit one piece at a time. Moving slowly and sequentially will help you isolate problems. Something like:

  • Print something out to screen
  • Print out data from sensor
  • Communicate with bluetooth
  • Send dummy data out bluetooth to phone (or whatever)
  • Send real data out bluetooth

Being methodical will save you a lot of time and headaches.

Thank you very much for your response. I figured out that the issue was actually a bad HC-05 module. Replacing that allowed me to get this to work wirelessly. However, I'm having issues in plotting the data in real-time. I've create code in MATLAB and I'm not sure how much help I can be given here, but I'd appreciate it if anyone has any idea I could try as I haven't gotten a response from the MATLAB forum in over a month.

clear all;close all;
tic;
delete(instrfindall)
instrreset;
b = Bluetooth('HC-05',1);
fopen(b);
figure
h = animatedline;
ax = gca;
ax.YGrid = 'on';
% stop = false;
startTime = datetime('now');
count=1;
numsamples=2500;
y=zeros(1,numsamples);
while count<length(y)
    a = str2num(fscanf(b));
    z(count)=toc;
    if length(a)<1
        a=0;
    else
        y(:,count)=a;
    end
    count=count+1;
    % Get current time
    t =  datetime('now');
    % Add points to animation
    addpoints(h,datenum(t),a)
    % Update axes
%     ax.XLim = datenum([t-seconds(15) t]);
    ax.XLim = datenum([t-seconds(15) t]);
    datetick('x','keeplimits')
end

The problem with this code is that it takes almost 15 seconds to show the figure window and then the plotted line shows up very slowly, definitely not in real-time. Is this due to the transmission of the data over bluetooth? Or is the code the main issue? In addition, is there an alternative program that can accept bluetooth data in real-time? I don't have to use MATLAB as long as the data can be saved.

Just an update. I figured out how to get data to plot in real-time by modifying the original processing sketch from the tutorial link I posted in the original post:

/******************************************************************************
Heart_Rate_Display.ino
Demo Program for AD8232 Heart Rate sensor.
Casey Kuhns @ SparkFun Electronics
6/27/2014
https://github.com/sparkfun/AD8232_Heart_Rate_Monitor
The AD8232 Heart Rate sensor is a low cost EKG/ECG sensor.  This example shows
how to create an ECG with real time display.  The display is using Processing.
This sketch is based heavily on the Graphing Tutorial provided in the Arduino
IDE. http://www.arduino.cc/en/Tutorial/Graph
Resources:
This program requires a Processing sketch to view the data in real time.
Development environment specifics:
  IDE: Arduino 1.0.5
  Hardware Platform: Arduino Pro 3.3V/8MHz
  AD8232 Heart Monitor Version: 1.0
This code is beerware. If you see me (or any other SparkFun employee) at the
local pub, and you've found our code helpful, please buy us a round!
Distributed as-is; no warranty is given.
******************************************************************************/

import processing.serial.*;
  //import the required libraries


Table table;
String filename;

Serial myPort;        // The serial port
int xPos = 1;         // horizontal position of the graph
float height_old = 0;
float height_new = 0;
float inByte = 0;
int BPM = 0;
int beat_old = 0;
float[] beats = new float[500];  // Used to calculate average BPM
int beatIndex;
float threshold = 620.0;  //Threshold at which BPM calculation occurs
boolean belowThreshold = true;
PFont font;


void setup () {
  // set the window size:
  size(1000, 400);        

  // List all the available serial ports
  println(Serial.list());
  // Open whatever port is the one you're using.
  myPort = new Serial(this, Serial.list()[0], 9600);
  // don't generate a serialEvent() unless you get a newline character:
  myPort.bufferUntil('\n');
  // set inital background:
  background(0xff);
  font = createFont("Ariel", 12, true);
  
   //set myPort to listen on COM port 10 at 9600 baud

  table = new Table();
  //add a column header "Data" for the collected data
  table.addColumn("Data");
    //add a column header "Time" and "Date" for a timestamp to each data entry
  table.addColumn("Time");
  table.addColumn("Date");
}


void draw () {
     //Map and draw the line for new data point
     inByte = map(inByte, 0, 1023, 0, height);
     height_new = height - inByte; 
     line(xPos - 1, height_old, xPos, height_new);
     height_old = height_new;
    
      // at the edge of the screen, go back to the beginning:
      if (xPos >= width) {
        xPos = 0;
        background(0xff);
      } 
      else {
        // increment the horizontal position:
        xPos++;
      }
      
      // draw text for BPM periodically
      if (millis() % 128 == 0){
        fill(0xFF);
        rect(0, 0, 200, 20);
        fill(0x00);
        text("BPM: " + inByte, 15, 10);
      }
      
  //variables called each time a new data entry is received
  int d = day();
  int m = month();
  int y = year();
  int h = hour();
  int min = minute();
  int s = second();
  
        String value = str(height_new);

    //check to make sure there is a value
    if(value != null)
    {
      //add a new row for each value
      TableRow newRow = table.addRow();
      //place the new row and value under the "Data" column
      newRow.setString("Data", value);
     //place the new row and time under the "Time" column
      newRow.setString("Time", str(h) + ":" + str(min) + ":" + str(s));
      //place the new row and date under the "Date" column
      newRow.setString("Date", str(d) + "/" + str(m) + "/" + str(y));
  }
}


void serialEvent (Serial myPort) 
{
  // get the ASCII string:
  String inString = myPort.readStringUntil('\n');

  if (inString != null) 
  {
    // trim off any whitespace:
    inString = trim(inString);

    // If leads off detection is true notify with blue line
    if (inString.equals("!")) 
    { 
      stroke(0, 0, 0xff); //Set stroke to blue ( R, G, B)
      inByte = 512;  // middle of the ADC range (Flat Line)
    }
    // If the data is good let it through
    else 
    {
      stroke(0xff, 0, 0); //Set stroke to red ( R, G, B)
      inByte = float(inString); 
      println(inByte);
      // BPM calculation check
      if (inByte > threshold && belowThreshold == true)
      {
        calculateBPM();
        belowThreshold = false;
      }
      else if(inByte < threshold)
      {
        belowThreshold = true;
      }
    }
  }
}
  
void calculateBPM () 
{  
  int beat_new = millis();    // get the current millisecond
  int diff = beat_new - beat_old;    // find the time between the last two beats
  float currentBPM = 60000 / diff;    // convert to beats per minute
  beats[beatIndex] = currentBPM;  // store to array to convert the average
  float total = 0.0;
  for (int i = 0; i < 500; i++){
    total += beats[i];
  }
  BPM = int(total / 500);
  beat_old = beat_new;
  beatIndex = (beatIndex + 1) % 500;  // cycle through the array instead of using FIFO queue
  }





void keyPressed()
{
    //variables used for the filename timestamp
  int d = day();
  int m = month();
  int h = hour();
  int min = minute();
  int s = second();
  //variable as string under the data folder set as (mm-dd--hh-min-s.csv)
  filename = "data/" + str(m) + "-" + str(d) + "--" + str(h) + "-" + str(min) + "-" + str(s) + ".csv";
  //save as a table in csv format(data/table - data folder name table)
  saveTable(table, filename);
  exit();
}

The main thing is that after HC-05 has been connected to the computer via bluetooth, you need to ensure what COM port the 'outgoing' side is. The way I did that is I went to Control Panel -> search for 'change bluetooth' -> click the first option that shows up called Change Bluetooth Settings -> Go to the COM ports tab -> note the port number for the outgoing direction for the HC-05. Change the port number in the above processing code correctly and then run. The above code will save the data at a rate of 60 samples/second. If you use the recommended placement from the tutorial (particularly the one for electrodes on the right and left sides of the chest and on the right hip), you can get really good ECG.

The problem I have now is that it seems that there are occasional drops in the signal. See the attachment. Without those voltage drops, the signal would be perfect. Any ideas on why this could happen? Is it because of a loose connection in the circuit? Suggestions/ideas would be helpful.

firstaccurateECGdatareal-time bluetooth processing.JPG