Parsing ECG Data

Hi there,

This is my first time posting to the forum, so please let me know if I misunderstand the purpose of the forum or if my question is too broad.

I am performing a project wiring an ECG to an arduino. I hope to read the raw voltages in real time and write programs based upon this data. For now I am still in the stage of being able to access the data in a usable form.

http://m5.img.dxcdn.com/CDDriver/CD/sku.241178.pdf This is the ECG I have purchased. It explains how the data is structured and provides step by step instructions. I imagine they are designed for someone with just a bit more experience than I, but I am still making much progress. I have the V hole (chip) plugged in to 3.3 V (arduino), the G (chip) in to ground (arduino), the transmitting (chip) into receiving (arduino), and receiving (chip) in to transmitting (arduino).

int IncomingByte=0;
boolean toggle;
int stage;
int ParsingStage;
enum States {SearchingForStartByte,FirstStartByteDetected, SecondStartByteDetected, ReadingPayload, Chksum};
enum Parsing {Excode, Code, SignalQuality, HeartRate, RawData};
int payload[256];
int PayloadCounter;
int pLength;
int chksum;
int sum;
int code;
int signalquality;
int heartrate;
int rawdata1;
int rawdata2;

//int ParsingData(int seed[256]) {
//  for (int i = 0; i < pLength; i = i + 1) {
//              
//  switch(ParsingStage) {
//  
//    case Excode:
//       if (seed[i]!=85) {
//        ParsingStage=Code;
//       }
//
//    case Code:
//      code=seed[i];
////      Serial.println(code);
//      if (code==2) {
//        ParsingStage=SignalQuality;
//      }
//      else if (code==3) {
//        ParsingStage=HeartRate;
//      }
//
//      else if (code==128) {
//        ParsingStage=RawData;
//      }
//
//      else {
//        ParsingStage=Excode;
//      }
//
//    case SignalQuality:
//      signalquality=seed[i];
////      Serial.println(signalquality);
//      ParsingStage=Excode;
//      
//
//    case HeartRate:
//      heartrate=seed[i];
////      Serial.println(heartrate);
//      ParsingStage=Excode;
//
//    case RawData:
//      rawdata1=seed[i+1];
//      rawdata2=seed[i+2];
////      Serial.println(rawdata1);
////      Serial.println(rawdata2);
//      i=i+2;
//      ParsingStage=Excode; 
//    }
//
// }
//
//}

void setup() {
  // put your setup code here, to run once:
Serial.begin(57600);
stage=SearchingForStartByte;
PayloadCounter=0;
sum=0;
}

void loop() {
  // put your main code here, to run repeatedly:
    IncomingByte=Serial.read();
  
  switch(stage) {
    
    case SearchingForStartByte: //Before any 170 byte (Start byte) has been detected
      sum=0;
      Serial.println(sum);
      if (IncomingByte==170) {
//        Serial.println(IncomingByte);
        stage=FirstStartByteDetected;
    }

    case FirstStartByteDetected: //First 170 byte has been detected
//      Serial.println(IncomingByte);
      if (IncomingByte==170) {
//        Serial.println(IncomingByte);
        stage=SecondStartByteDetected;
      }

    case SecondStartByteDetected: //Both 170 bytes have been detected, pLength (length of payload) is being read)
      pLength=IncomingByte;
//      Serial.println(pLength);
      stage=ReadingPayload;

    case ReadingPayload: //Payload will be read for a total of pLength bytes
        if (PayloadCounter<pLength) {
          payload[PayloadCounter]=IncomingByte;
//          Serial.println(PayloadCounter);
          PayloadCounter=PayloadCounter+1;
//          Serial.println("Start");
//          Serial.println(IncomingByte);         
          sum=IncomingByte+sum;
          Serial.println(sum);
          stage=ReadingPayload;
          }
        
        else {
          PayloadCounter=0;
          stage=Chksum;
          Serial.println("End");
        }
     
  
  
    case Chksum: //The cksum byte is compared to the calculated sum to determine if the data is good
      chksum= IncomingByte;
      sum &= 0xFF;
      sum = ~sum & 0xFF;
      sum=(int)sum;
      if (sum==chksum) {
//        Serial.println("The data is gooooood...");

//      ParsingData(payload);

      for (int i=0; i<pLength; i++) {
//        Serial.println("Start");
//        Serial.println(i);
//        Serial.println(payload[i]);
      }

      stage=SearchingForStartByte;
    
      }

      else {
//        Serial.println("The data's poop.");
        stage=SearchingForStartByte;
      }
      
  }
}

This is what I have so far. I don't think I'm having issues with all of it but I figured it'd be difficult to diagnose the problem without seeing everything, and it isn't so long. Right now I am debugging the checksum accumulator, maybe some of you have experience with these? For some reason my sum is just being reset to zero every time it tries to add something new. This is odd, as sum=0; is in an entirely different case, so I am not sure how it is getting mixed up. I am sure it will seem obvious once it is found, but I have been unable to where my cases are "leaking" so to speak.

The data parsing part commented in the beginning is just the final step where I actually pull the packets apart to be able to print relevant data, such as heart rate or raw voltage. I'm sure I need to debug this as well, but I

For anyone who has more experience in these sort of matters, I'd love your feedback and advice. I would really like to be able to have this up and running as soon as possible so I may begin gathering and analyzing data, which is more of my expertise.

Thanks for any help!

The first thing I noticed is that you don't have a 'break;' at the end of each case. Without it, execution will 'fall through' from the valid case statement to each of the others in turn until it reaches the end of the 'switch case'.

You should do it as in this excerpt:-

switch(stage)
{
   
    case SearchingForStartByte: //Before any 170 byte (Start byte) has been detected
      sum=0;
      Serial.println(sum);
      if (IncomingByte==170) {
//        Serial.println(IncomingByte);
        stage=FirstStartByteDetected;
    }
    break;

    case FirstStartByteDetected: //First 170 byte has been detected
//      Serial.println(IncomingByte);
      if (IncomingByte==170) {
//        Serial.println(IncomingByte);
        stage=SecondStartByteDetected;
      }
    break;

// etc
// etc

There are possibly other problems, but that will get the ball rolling. (I have to go out.)

void loop() {
  // put your main code here, to run repeatedly:
    IncomingByte=Serial.read();

Note that if IncomingByte has a value of -1 it means the receive buffer was empty and the value should be ignored. One easy way to do that is:

void loop() {
  // put your main code here, to run repeatedly:
    IncomingByte=Serial.read();
    if (IncomingByte == -1)
        return;

OldSteve:
The first thing I noticed is that you don't have a 'break;' at the end of each case. Without it, execution will 'fall through' from the valid case statement to each of the others in turn until it reaches the end of the 'switch case'.

You should do it as in this excerpt:-

switch(stage)

{
 
    case SearchingForStartByte: //Before any 170 byte (Start byte) has been detected
      sum=0;
      Serial.println(sum);
      if (IncomingByte==170) {
//        Serial.println(IncomingByte);
        stage=FirstStartByteDetected;
    }
    break;

case FirstStartByteDetected: //First 170 byte has been detected
//      Serial.println(IncomingByte);
      if (IncomingByte==170) {
//        Serial.println(IncomingByte);
        stage=SecondStartByteDetected;
      }
    break;

// etc
// etc




There are possibly other problems, but that will get the ball rolling. (I have to go out.)

old steve

int IncomingByte=0;

It is stupid to use a type in the name of the variable when the type is NOT the type of the variable.

That looks as stupid as

int myFloat;

You don't want to look stupid, do you?