Serial Monitor Slow?

Hi everyone

I’m working on an ECG-related school project, using the TI ADS1298 with the Arduino. They communicate via SPI and I’ve had success with writing/reading register and getting data out of it. Here’s a sample of the ECG signal I plotted out via Matlab. (I have attached the file)

It has some erroneous spikes and inconsistencies, and after some thinking I am speculating that it is due to the Serial.print taking too much time. Currently, I am saving data by printing it to the Coolterm Serial Terminal which will then save it to a .txt file at the end of it. I’m not sure if the Arduino Serial Monitor is faster.

If data is ready → SPI transfer to read data → Print data to Coolterm Serial Terminal.

In between the time taken to print data to the terminal, the code is unable to check if there is any data is ready, and even if it is, the program will not be able to retrieve it if it is still printing to serial terminal. As such, I am speculating that some data samples might be lost. I am planning to sample at 8000 samples/sec. The above image is sampled at 500 samples/sec and I’m already losing samples.

As such, I have a few questions.

  1. Since it seems like the serial terminal is taking way too long to print (even with baud rate 115200), is there another fast way to save data?

  2. Is the slow Ardunio printing-rate due to hardware or software issues?

  3. I was reading that the Teensy serial can communicate at 12Mbit/sec. Will this alleviate the issue? Cos right now I’m unsure if that itself is a software/hardware issue.

  4. There isn’t much memory on the Arduino to make use of. I’ve read a bit about buffers, as temporary places to store data. Are buffers a physical memory of a microcontroller? Or are they just an extra variable assigned to hold data?

Any advise will be appreciated.
Thanks in advanced.

Post the code, using code tags (button with “<>”).

//THIS CODE IS TO TRY AND GENERATE TEST SIGNAL DATA
//THIS CODE CAN READ IN ECG SIM DATA WITH THE TWO NEW FUNCTIONS

#include <SPI.h>

const int slaveSelectPin = 10;
const int PIN_START = 4;
const int DRDY = 5;
const int testled = 2;

int a = 0;
void setup()
{
  pinMode(testled, OUTPUT);
  // set Pin 10(SS) as output, Pin 4 (Start) as output, pin 5 (DRDY) as input
  pinMode(7, OUTPUT);
  pinMode(slaveSelectPin, OUTPUT);
  pinMode(PIN_START, OUTPUT);
  pinMode(DRDY, INPUT);
  //init SPI bus, SCK, MOSI & SS to outputs. pull SCK and MOSI low, SS high
  SPI.begin();    
  //shifts data with MSB first
  SPI.setBitOrder(MSBFIRST);  
  //sets CPOL = 0, CPHA =1
  SPI.setDataMode(SPI_MODE1);
  delay(500);
  delay(100);  
  adc_send_command(0x11); // OPCODE: stop read data continuously 
  adsSetup();
  adsNormalElectrode_Copy();
  digitalWrite(PIN_START, HIGH);
  adc_send_command(0x10); //RDATAC opcode
}

void adsSetup()
{
  //adc_wreg(0x14,0); //set all GPIOs (0x14) to output. not stated in flow chart
  adc_wreg(0x03, 0xC0); //Write 0xC0 to CONFIG3 (0x03) as required in the flowchart
  adc_wreg(0x01, 0x86); //Write 0x86 to CONFIG1 (0x01) as required in the flowchart
  adc_wreg(0x02, 0x00);  //Write 0x00 to CONFIG2 as required in the flowchart
}


void adsNormalElectrode()
{
  adc_wreg(0x05,0x00); //CH1 as normal electrode input
}

void adsNormalElectrode_Copy()
{
  adc_wreg(0x00, 0x92);
  adc_wreg(0x01, 0x86);
  adc_wreg(0x02, 0x10);
  adc_wreg(0x03, 0xDC);
  adc_wreg(0x04, 0x03);
  adc_wreg(0x05, 0x00);
  adc_wreg(0x06, 0x00);
  adc_wreg(0x07, 0x00);
  adc_wreg(0x08, 0x00);
  adc_wreg(0x09, 0x00);
  adc_wreg(0x0A, 0x00);
  adc_wreg(0x0B, 0x00);
  adc_wreg(0x0C, 0x00);
  adc_wreg(0x0D, 0x00);
  adc_wreg(0x0E, 0x00);
  adc_wreg(0x0F, 0xFF);
  adc_wreg(0x10, 0x02);
  adc_wreg(0x11, 0x00);
  adc_wreg(0x12, 0xFF);
  adc_wreg(0x13, 0x06);
  adc_wreg(0x14, 0x00);
  adc_wreg(0x15, 0x00);
  adc_wreg(0x16, 0xF0);
  adc_wreg(0x17, 0x22);
  adc_wreg(0x18, 0x0A);
  adc_wreg(0x19, 0xE3);
}


int adc_read_data(void) //function to read in 1 channel of data
{
  digitalWrite(testled, HIGH);
  int i = 0;
  digitalWrite(slaveSelectPin, LOW);

  //attempt to read in one channel only. 3 bytes of STATUS + 3 bytes of one channel data
  int numSerialBytes = 6;  
  unsigned char serialBytes[numSerialBytes];  
  for (i = 0; i < numSerialBytes; ++i)
  {
    serialBytes[i] = SPI.transfer(0);
  }
  delayMicroseconds(1);
  digitalWrite(slaveSelectPin, HIGH);

  for (i = 6; i < numSerialBytes; ++i)
  {
    Serial.print(serialBytes[i],BIN);
    Serial.print("\n");
  }  
}

  
void adc_send_command(int cmd)
{
  digitalWrite(slaveSelectPin, LOW);
  SPI.transfer(cmd);
  delayMicroseconds(1);
  digitalWrite(slaveSelectPin, HIGH);      
}

int adc_rreg(int reg)
{  
  int out = 0;
  digitalWrite(slaveSelectPin, LOW);
  SPI.transfer(0x20 | reg);
  delayMicroseconds(5);
  SPI.transfer(0);	// number of registers to be read/written – 1
  delayMicroseconds(5);
  out = SPI.transfer(0);
  	delayMicroseconds(1);
  digitalWrite(slaveSelectPin, HIGH);
  return(out);
}

void adc_wreg(int reg, int val)
{
  //see pages 40,43 of datasheet - 
  digitalWrite(slaveSelectPin, LOW);
  SPI.transfer(0x40 | reg);
  SPI.transfer(0);	// number of registers to be read/written – 1
  SPI.transfer(val);
  delayMicroseconds(1);
  digitalWrite(slaveSelectPin, HIGH);
 }

void loop ()
{
  Serial.begin(115200);
  delay(100);
  if(digitalRead(DRDY) == 0)
  {
    Serial.print("\n");
    adc_read_data();
  }
  else
  {
    Serial.print("\nHIGH");
  }
}

A few thoughts ...

You should just do Serial.begin() once - in setup()

The Serial Monitor only works up to 115200 but other PC software can work at higher Baud rates - up to 1,000,000 baud. I don't know what Matlab's limit is.

Why are you converting your bytes to BIN in Serial.print(serialBytes*,BIN);[/b] That greatly increases the amount of data to be transferred. Serial.write() which just sends the raw byte in binary would be quickest. Let the PC disentangle things with its greater capabilities.*
...R