I am using Arduino UNO to Read 8-channel, 24-bits resolution Analog signals using ADS1299 Analog-fornt-end. ADS1299 use SPI interface to talk with Arduino. Currently, I can record the analog signal with arduino based on the SPI protocol and send the data via serial port to the PC.
The ADS1299 has 8 channels with 24-bits resolutions. The sampling rate can be defined from 250s/s to 16Ks/s. As you can see in the below code, when the data is ready I put the device in reading data mode and store 8-bits (1-byte) in each run and concatenate 3 bytes to make a full sample. I repeat these procedures to obtain the whole samples of all channels. At the end I have sent a sample of one channel to the serial port using serial.print command.
Here is my problem: If I want to increase the sampling rate of device to e.g 10 Ks/s the arduino fails to provide this sampling rate due to delay produced by Serial.println command. Is is possible to store the data into a big array and then send the whole array via serial port? Is it possible that other types of microcontroller such as ARM types handle this issue? Generally how it is possible to avoid the delay of serial print?
#include <SPI.h>
#define WAKEUP 0x02
#define STANDBY 0x04
#define RESET 0x06
#define START 0x08
#define STOP 0x0a
#define RDATAC 0x10
#define SDATAC 0x11
#define RDATA 0x12
#define TESTaa 0xaa
#define TEST55 0x55
#define CONFIG1 0x01
#define CONFIG2 0x02
#define CONFIG3 0x03
#define CH1SET 0x05
#define CH2SET 0x06
#define CH3SET 0x07
#define CH4SET 0x08
#define CH5SET 0x09
#define CH6SET 0x0A
#define CH7SET 0x0B
#define CH8SET 0x0C
const int PIN_START = 7;
const int IPIN_DRDY = 9;
const int PIN_CS = 10;
const int DOUT = 12;
const int DIN = 11;
const int PIN_SCLK = 13;
const int PIN_RESET = 8;
byte chSet;
byte chSet2;
boolean flag = false;
long t0, t;
void setup(){
// You can use serial communication for debugging
Serial.begin(2000000);
Serial.flush();
delayMicroseconds(100);
// You have to set SPI communication according to datasheet
SPI.setDataMode(SPI_MODE1);
//SPI.setClockDivider(SPI_CLOCK_DIV16);
SPI.setBitOrder(MSBFIRST);
SPI.begin();
pinMode(DOUT, OUTPUT);
pinMode(PIN_SCLK, OUTPUT);
pinMode(PIN_CS, OUTPUT);
pinMode(PIN_START, OUTPUT);
pinMode(IPIN_DRDY, INPUT);
pinMode(PIN_RESET, OUTPUT);
//reset communication, see datasheet
digitalWrite(PIN_SCLK, LOW);
digitalWrite(DIN, LOW);
digitalWrite(PIN_CS, HIGH);
digitalWrite(PIN_CS, LOW); //Low to communicated
SPI.transfer(RESET);
digitalWrite(PIN_CS, HIGH); //Low to communicated
// Wait longer for TI chip to start
delay(500);
send_command(SDATAC);
delay(10);
chSet = read_byte(0x00);
Serial.println("-- ID CHIP is:" + hex_to_char(chSet) );
// Write Config 1 and 2: see datasheet page 47
// Config 1: Bits 7 6 5 4 3 2 1 0 --- 1 DAISY_EN=1 CLK_EN=0 1 0 DR[2:0] (110-- 250 Sample/S) ---> 0b11010110
// Config 2: Bits 7 6 5 4 3 2 1 0 ---- 1 1 0 INT_CAL=1(Int/Ext test sig) 0 CAL_AMP=(calibration signal amplitude)
// CAL_FREQ[1:0] (calibration signal frequency) -----> 0b11010100
// for normal operation write to config1 0x02, config2 0xA0. For test signal write 0xA3 to config2
write_byte(CONFIG1, 0x96); // Daisy chain Enabled: D6 , Daisy chain Disabled: 96
delay(10);
write_byte(CONFIG2, 0xD1); // Test signal Enabled: D0 Test signal Disabpled: C0
delay(10);
write_byte(CONFIG3, 0xE0); // INT Reference Enabled: E0 else INT Reference Disabled: 60
delay(1000);
//this part is just to check if you send and read correct data
Serial.println("Check Configs");
chSet = read_byte(CONFIG1);
Serial.println("CONFIG1: Received " + hex_to_char(chSet) );
chSet = read_byte(CONFIG2);
Serial.println("CONFIG2: Received " + hex_to_char(chSet) );
chSet = read_byte(CONFIG3);
Serial.println("CONFIG3: Received " + hex_to_char(chSet) );
//remember that ch1 is used for respiration! use channel 2 for ECG measurements
// Ch1 Setting: Bits 7 6 5 4 3 2 1 0 --- PDn(channel power mode) GAINn[2:0] (PGA gain-- 101: 12 110 : 24)
//SRB2 (SRB2 connection) MUXn[2:0] (channel input selection: 000 : Normal electrode input , 101 : Test signal )
/// Input Channel Shorted ---> 0b00000001 0X01; Test signal Activated ---> 0b00000101 0X05;
delay(1000);
write_byte(CH1SET, 0x05); //
write_byte(CH2SET, 0x05); //
write_byte(CH3SET, 0x05); //
write_byte(CH4SET, 0x05); //
write_byte(CH5SET, 0x05); //
write_byte(CH6SET, 0x05); //
write_byte(CH7SET, 0x05); //
write_byte(CH8SET, 0x05); //
Serial.println("Check Channel Settings");
chSet = read_byte(CH1SET);
Serial.println("Ch1: Received " + hex_to_char(chSet) );
chSet = read_byte(CH2SET);
Serial.println("Ch2: Received " + hex_to_char(chSet) );
chSet = read_byte(CH7SET);
Serial.println("Ch7: Received " + hex_to_char(chSet) );
chSet = read_byte(CH8SET);
Serial.println("Ch8: Received " + hex_to_char(chSet) );
// Start communication, you can use RDATAC or RDATA according to datasheet
send_command(RDATAC);
digitalWrite(PIN_START, LOW);
delay(150);
send_command(START);
// digitalWrite(PIN_CS, LOW); //Low to communicated
// SPI.transfer(START);
// digitalWrite(PIN_CS, HIGH); //Low to communicated
}
boolean gActiveChan [2];
int nChannels = 1;
int gMaxChan=1;
void loop(){
// Based on the Page. 36 For the 8-channel ADS1299, the number of data outputs is
//[(24 status bits + 24 bits × 8 channels) = 216 bits].
delayMicroseconds(10);
if(digitalRead(IPIN_DRDY) == LOW){
t0 = micros();
digitalWrite(PIN_CS, LOW);
long output[9];
long dataPacket;
for(int i = 0; i<9; i++){
for(int j = 0; j<3; j++){
byte dataByte = SPI.transfer(0x00);
dataPacket = (dataPacket<<8) | dataByte;
}
output[i] = dataPacket;
dataPacket = 0;
}
digitalWrite(PIN_CS, HIGH);
Serial.println(output[1]);
// t = micros()-t0; // calculate elapsed time
// Serial.print(1000000/float(t));
//Serial.println(" samples per second");
//delay(200);
}
}
String hex_to_char(int hex_in) {
int precision = 2;
char tmp[16];
char format[128];
sprintf(format, "0x%%.%dX", precision);
sprintf(tmp, format, hex_in);
//Serial.print(tmp);
return(String(tmp));
}
// see datasheet 38
int read_byte(int reg_addr){
int out = 0;
digitalWrite(PIN_CS, LOW);
SPI.transfer(0x20 | reg_addr);
delayMicroseconds(5);
SPI.transfer(0x00);
delayMicroseconds(5);
out = SPI.transfer(0x00);
delayMicroseconds(1);
digitalWrite(PIN_CS, HIGH);
return(out);
}
void send_command(uint8_t cmd) {
digitalWrite(PIN_CS, LOW);
delayMicroseconds(5);
SPI.transfer(cmd);
delayMicroseconds(10);
digitalWrite(PIN_CS, HIGH);
}
//see page 38
void write_byte(int reg_addr, int val_hex) {
digitalWrite(PIN_CS, LOW);
delayMicroseconds(5);
SPI.transfer(0x40 | reg_addr);
delayMicroseconds(5);
SPI.transfer(0x00);
delayMicroseconds(5);
SPI.transfer(val_hex);
delayMicroseconds(10);
digitalWrite(PIN_CS, HIGH);
}
output
?