analogRead + Serial3.write = Freezeup

Hello all!

I'm experiencing and interesting issue with a project that I'm working on. I'm using a Redpark Serial TTL cable to pass analog sensor data from an Arduino Mega 2560 to an iPad via Serial3.write commands. I've determined that the iPad interface is working properly and have removed portions of the sketch that are not related to the issue at hand... i.e. the issue is not related to the Redpark cable and can be replicated with just the arduino and a few wires.

I verified that the channels I'm reading on A12-A14 are coming in properly on their own right by simply sending them to the terminal and then plotting in excel. I'm confident that this portion of the hardware is working properly.

The interface to the iPad is working properly under the following conditions:

  1. Instead of reading A12-A14, I'm passing both static integers and randomized integers to the Serial3.write commands
  2. Reading A12-A14 with wires disconnected from the A12-A14 headers, meaning the pins are floating here. The data stream jumps around as expected, but causes no freezes
  3. Pins A12-A14 connected to an onboard voltage signal, 5V, 3.3V, and Ground. Everything works independent of which source is connected to which pin.

The system freezes under the following conditions:
4) Similar to (2) above, but reading A12-A14 with wires connected to the A12-A14 headers, but the ends of the wires not connected to anything, i.e. they're still floating but are attached to longer 'antennas'
5) Similar to (3) above, but when any one of the wires are disconnected and transitioned to a floating connection
6) Pins A12-A14 connected to their sensors, as intended. This was the same connection that I verified was working without the Serial3.write

When it freezes, it is not consistently at any given point, but will happen between loopIndex 5 and 50. In short, it appears to occur when the analog inputs experience a large(r) step change in voltage. Interestingly, these same conditions don't freeze up the sketch when the Serial3.write portion of the sketch is not involved. I've verified that the condition exists on multiple Megas and operating platforms.

The code in question is attached below. Thanks in advance for your thoughts, comments, or questions!

Tom

//input keys
const int sys_ready = 1;
const int treatment_start = 2;
const int system_pressure = 3;
const int treatment_time = 4;
const int treatment_stop = 5;
const int treatment_resume = 6;

//others 
int inputData;
int loopIndex = 0;
int bytesReceived = 0;
int currentKey = 0;
boolean systemReady = false;
boolean systemRunning = false;
int pressureByteIndex = 0;
int APin12;
int APin13;
int APin14;
int APin15;

//

unsigned long AD_exit_time;
unsigned long Array_entry_time;
unsigned long Array_exit_time;
unsigned long Serial_process;

union {
  byte asBytes[4];
  float asFloat;
}
sysPressure;

void setup()
{
  Serial3.begin(14400);  // At the moment, this is the max rate the Redpark Cable will consistently operate at
  Serial.begin(115200);

  Serial.println("RESET");

  systemReady = true;
  systemRunning = false;

  digitalWrite(A12, LOW);
  digitalWrite(A13, LOW);
  digitalWrite(A14, LOW);
  pinMode(A12,INPUT);
  pinMode(A13,INPUT);
  pinMode(A14,INPUT);
  
}

void loop()
{
  loopIndex += 1;
  Serial.print("loop# ");
  Serial.println(loopIndex);
  // Waveform 
  String outputECG = ""; 
  String outputPULSE = "";
  String outputBPM = "";
  String outputDS = "";
  Array_entry_time = millis();

  for (int i=0; i < 99; i++){
    // Analog Pin 0 = Filtered ECG Waveform Connects to Pin1 of Device
    // Analog Pin 1 = Pleth PulseOx Waveform Connects to Pin6 of Device
    // Analog Pin 2 = Heart Rate 0-300BPM, 16.666mV per BPM Connects to Pin7 of Device
    // GND connected to Pin10 of Device
    APin12 = analogRead(A12);    // Reads in ECG Waveform
    //APin12 = 100;
    delay(2);
    APin13 = analogRead(A13);    // Reads in PulseOx Waveform
    //APin13 = 200;
    delay(7);

    outputECG += APin12;
    outputECG += ",";
    outputPULSE += APin13;
    outputPULSE +=  ",";

  }

  for (int i=0; i < 4; i++){
    APin14 = analogRead(A14);    // Reads in Analog Voltage Corresponding to BPM
    //APin14 = 300;
    delay(2);
    APin14 = ((double)APin14 * 300)/1024.0;   // ADC to BPM Calc 

    delay(7);
    outputBPM += APin14;
    outputBPM += ",";
    outputDS += APin14;     
    outputDS += ",";       

  }

  Array_exit_time = millis();

  outputECG = "[1," + outputECG + "]";
  outputPULSE = "[2," + outputPULSE + "]";
  outputBPM = "[3," + outputBPM + "]";
  outputDS = "[4," + outputDS + "]";

  int stringLengthECG = outputECG.length();
  int stringLengthPULSE = outputPULSE.length();
  int stringLengthBPM = outputBPM.length();
  int stringLengthDS = outputDS.length();

  char StrECG[stringLengthECG + 1];
  char StrPULSE[stringLengthPULSE + 1];
  char StrBPM[stringLengthBPM + 1];
  char StrDS[stringLengthDS + 1];

  outputECG.toCharArray(StrECG, stringLengthECG + 1);
  outputPULSE.toCharArray(StrPULSE, stringLengthPULSE + 1);
  outputBPM.toCharArray(StrBPM, stringLengthBPM + 1);
  outputDS.toCharArray(StrDS, stringLengthDS + 1);

  Serial3.write((uint8_t *)StrECG, stringLengthECG + 1);
  Serial3.write((uint8_t *)StrPULSE, stringLengthPULSE + 1);
  Serial3.write((uint8_t *)StrBPM, stringLengthBPM + 1);
  Serial3.write((uint8_t *)StrDS, stringLengthDS + 1);

  Serial.println(StrECG);
  Serial.println(StrPULSE);
  Serial.println(StrBPM);
  Serial.println(StrDS);

  Serial_process = millis();

  //  Serial_process = Serial_process-Array_exit_time;
  //  Serial.print("Serial3 write (ms) = ");
  //  Serial.println(Serial_process);
  //
  //  Array_exit_time = Array_exit_time-Array_entry_time;
  //  Serial.print("Analog Read (ms) = ");
  //  Serial.println(Array_exit_time);
  //  Serial.println("--- -- ---");

}

Are you using the A12 to 14 pins as digital pins or as analog pins? If you are using them as analog pins, as evidenced by the analogRead() calls, then the pinMode() and digitalWrite() are not doing anything useful.

    APin12 = analogRead(A12);    // Reads in ECG Waveform

Then why not name the variable something meaningful?

    APin13 = analogRead(A13);    // Reads in PulseOx Waveform

Sure that's obvious from the name APin13. I guessed that up top when you defined the variable.

  String outputECG = ""; 
  String outputPULSE = "";
  String outputBPM = "";
  String outputDS = "";

Here's a gun. Shoot yourself in the foot, please. Again, there's plenty of bullets, and I'll reload.

  char StrECG[stringLengthECG + 1];
  char StrPULSE[stringLengthPULSE + 1];
  char StrBPM[stringLengthBPM + 1];
  char StrDS[stringLengthDS + 1];

  outputECG.toCharArray(StrECG, stringLengthECG + 1);
  outputPULSE.toCharArray(StrPULSE, stringLengthPULSE + 1);
  outputBPM.toCharArray(StrBPM, stringLengthBPM + 1);
  outputDS.toCharArray(StrDS, stringLengthDS + 1);

  Serial3.write((uint8_t *)StrECG, stringLengthECG + 1);
  Serial3.write((uint8_t *)StrPULSE, stringLengthPULSE + 1);
  Serial3.write((uint8_t *)StrBPM, stringLengthBPM + 1);
  Serial3.write((uint8_t *)StrDS, stringLengthDS + 1);

What the heck? Why are you converting the String instances to char arrays and then sending the char arrays as binary data, when the Serial.print() method knows how to send a String?

Thanks for the input Paul! Any thoughts as to why the system is hanging? The system exhibits the same behavior with your suggested changes.

//input keys
const int sys_ready = 1;
const int treatment_start = 2;
const int system_pressure = 3;
const int treatment_time = 4;
const int treatment_stop = 5;
const int treatment_resume = 6;

//others 
int inputData;
int loopIndex = 0;
int bytesReceived = 0;
int currentKey = 0;
boolean systemReady = false;
boolean systemRunning = false;
int pressureByteIndex = 0;
int A_ECG;      // Analog input of the ECG waveform
int A_PULSE;    // Analog input of the SP02 waveform
int A_BPM;       // Analog input of the BPM

//

unsigned long AD_exit_time;
unsigned long Array_entry_time;
unsigned long Array_exit_time;
unsigned long Serial_process;

union {
  byte asBytes[4];
  float asFloat;
}
sysPressure;

void setup()
{
  Serial3.begin(14400);  
  Serial.begin(115200);

  Serial.println("RESET");

  systemReady = true;
  systemRunning = false;
}

void loop()
{
  loopIndex += 1;
  Serial.print("loop# ");
  Serial.println(loopIndex);
  // Waveform 
  String outputECG; 
  String outputPULSE;
  String outputBPM;
  String outputDS;
  Array_entry_time = millis();

  for (int i=0; i < 99; i++){
    // Analog Pin 0 = Filtered ECG Waveform Connects to Pin1
    // Analog Pin 1 = Pleth PulseOx Waveform Connects to Pin6
    // Analog Pin 2 = Heart Rate 0-300BPM, 16.666mV per BPM Connects to Pin7
    // GND connected to Pin10
    A_ECG = analogRead(A12);    // Reads in ECG Waveform
    //A_ECG = 100;
    delay(2);
    A_PULSE = analogRead(A13);    // Reads in PulseOx Waveform
    //A_PULSE = 200;
    delay(7);

    outputECG += A_ECG;
    outputECG += ",";
    outputPULSE += A_PULSE;
    outputPULSE +=  ",";

  }

  for (int i=0; i < 4; i++){
    A_BPM = analogRead(A14);    // Reads in Analog Voltage Corresponding to BPM
    //A_BPM = 300;
    delay(2);
    A_BPM = ((double)A_BPM * 300)/1024.0;   // ADC to BPM Calc 

    delay(7);
    outputBPM += A_BPM;
    outputBPM += ",";
    outputDS += A_BPM;     
    outputDS += ",";       

  }

  Array_exit_time = millis();

  outputECG = "[1," + outputECG + "]";
  outputPULSE = "[2," + outputPULSE + "]";
  outputBPM = "[3," + outputBPM + "]";
  outputDS = "[4," + outputDS + "]";

  Serial3.println(outputECG);
  Serial3.println(outputPULSE);
  Serial3.println(outputBPM);
  Serial3.println(outputDS);

  Serial.println(outputECG);
  Serial.println(outputPULSE);
  Serial.println(outputBPM);
  Serial.println(outputDS);

  Serial_process = millis();

//  Serial_process = Serial_process-Array_exit_time;
//  Serial.print("Serial3 write (ms) = ");
//  Serial.println(Serial_process);
//
//  Array_exit_time = Array_exit_time-Array_entry_time;
//  Serial.print("Analog Read (ms) = ");
//  Serial.println(Array_exit_time);
//  Serial.println("--- -- ---");

}

The system exhibits the same behavior with your suggested changes.

I suggested that you quit shooting yourself in the foot at all.

  String outputECG; 
  String outputPULSE;
  String outputBPM;
  String outputDS;

    outputECG += A_ECG;
    outputECG += ",";
    outputPULSE += A_PULSE;
    outputPULSE +=  ",";

    outputBPM += A_BPM;
    outputBPM += ",";
    outputDS += A_BPM;     
    outputDS += ",";       

  outputECG = "[1," + outputECG + "]";
  outputPULSE = "[2," + outputPULSE + "]";
  outputBPM = "[3," + outputBPM + "]";
  outputDS = "[4," + outputDS + "]";

I did not suggest that shooting yourself in the foot less often would be less painful.

Teach a man to fish, Paul. Thank you very much for your assistance, problem solved :slight_smile:

//input keys
const int sys_ready = 1;
const int treatment_start = 2;
const int system_pressure = 3;
const int treatment_time = 4;
const int treatment_stop = 5;
const int treatment_resume = 6;

//others 
int inputData;
int loopIndex = 0;
int bytesReceived = 0;
int currentKey = 0;
boolean systemReady = false;
boolean systemRunning = false;
int pressureByteIndex = 0;
int A_ECG;      // Analog input of the ECG waveform
int A_PULSE;    // Analog input of the SP02 waveform
int A_BPM;       // Analog input of the BPM

//

unsigned long AD_exit_time;
unsigned long Array_entry_time;
unsigned long Array_exit_time;
unsigned long Serial_process;

union {
  byte asBytes[4];
  float asFloat;
}
sysPressure;

void setup()
{
  Serial3.begin(14400);  
  Serial.begin(115200);

  Serial.println("RESET");

  systemReady = true;
  systemRunning = false;
}

void loop()
{
  loopIndex += 1;
  Serial.print("loop# ");
  Serial.println(loopIndex);
  // Waveform 
  int outputECG[100]; 
  int outputPULSE[100];
  int outputBPM[5];
  int outputDS[5];

  Array_entry_time = millis();

  for (int i=0; i < 100; i++){
    // Analog Pin 0 = Filtered ECG Waveform Connects to Pin1
    // Analog Pin 1 = Pleth PulseOx Waveform Connects to Pin6
    // Analog Pin 2 = Heart Rate 0-300BPM, 16.666mV per BPM Connects to Pin7
    // GND connected to Pin10
    A_ECG = analogRead(A12);    // Reads in ECG Waveform
    A_PULSE = analogRead(A13);    // Reads in PulseOx Waveform
    delay(9);
    outputECG[i]=A_ECG;
    outputPULSE[i]=A_PULSE;
  }

  for (int k=0; k < 5; k++){
    A_BPM = analogRead(A14);    // Reads in Analog Voltage Corresponding to BPM
    A_BPM = ((double)A_BPM * 300)/1024.0;   // ADC to BPM Calc 
    delay(9);
    outputBPM[k]=A_BPM;
    outputDS[k]=A_BPM;
  }

  Array_exit_time = millis();

  Serial3.print("[1,");
  for (int i=0; i < 100; i++){
    Serial3.print(outputECG[i]);
    Serial3.print(",");
  }
  Serial3.println("]");

  Serial3.print("[2,");
  for (int i=0; i < 100; i++){
    Serial3.print(outputPULSE[i]);
    Serial3.print(",");
  }
  Serial3.println("]");

  Serial3.print("[3,");
  for (int k=0; k<5; k++){
    Serial3.print(outputBPM[k]);
    Serial3.print(",");
  }
  Serial3.println("]");

  Serial3.print("[4,");
  for (int k=0; k<5; k++){
    Serial3.print(outputDS[k]);
    Serial3.print(",");
  }
  Serial3.println("]");

  Serial_process = millis();
  Serial_process = Serial_process-Array_exit_time;
  Serial.print("Serial3 write (ms) = ");
  Serial.println(Serial_process);

  Array_exit_time = Array_exit_time-Array_entry_time;
  Serial.print("Analog Read (ms) = ");
  Serial.println(Array_exit_time);
  Serial.println("--- -- ---");


  // Uncomment for debug only  
  Serial.print("[1,");
  for (int i=0; i < 100; i++){

    Serial.print(outputECG[i]);
    Serial.print(",");
  }
  Serial.println("]");

  Serial.print("[2,");
  for (int i=0; i < 100; i++){
    Serial.print(outputPULSE[i]);
    Serial.print(",");
  }
  Serial.println("]");

  Serial.print("[3,");
  for (int k=0; k<5; k++){

    Serial.print(outputBPM[k]);
    Serial.print(",");
  }
  Serial.println("]");

  Serial.print("[4,");
  for (int k=0; k<5; k++){
    Serial.print(outputDS[k]);
    Serial.print(",");
  }
  Serial.println("]");

}