Closed twhiting87 closed 3 years ago
Maybe the serial.begin isn't synchronized: look at devices an printers->drivers->arduino->properties->serial.
Facing the Same problem. was your issue resolved?
i am not able to compile processing code. Can you please send your processing code. @twhiting87
Hi, Did you follow all procedure what we given in our official website(https://github.com/Protocentral/ADS1292rShield_Breakout),if you done those procedure please share the screenshot where you are getting error even though please share your order number.
Thankyou for replying! https://photos.app.goo.gl/3jHZedEEafnVNs7H9 this is my output wave form. i get the heart rate value, but not respiration rate value. even though in arduino ide,i only get heart rate. there also a issue , the code i am using doesnt show values. here i am attaching my arduino ide output. https://photos.google.com/photo/AF1QipNO8xMagkwqkP0eVKDIAztxl8fGNsTPNn8_oofC my arduino program-> ////////////////////////////////////////////////////////////////////////////////////////// // // Arduino Library for ADS1292R Shield/Breakout // // Copyright (c) 2017 ProtoCentral // Heartrate and respiration computation based on original code from Texas Instruments // // This software is licensed under the MIT License(http://opensource.org/licenses/MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT // NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // Requires g4p_control graphing library for processing. Built on V4.1 // Downloaded from Processing IDE Sketch->Import Library->Add Library->G4P Install
// If you have bought the breakout the connection with the Arduino board is as follows: // //|ads1292r pin label| Arduino Connection |Pin Function | //|----------------- |:--------------------:|-----------------:| //| VDD | +5V | Supply voltage | //| PWDN/RESET | D4 | Reset | //| START | D5 | Start Input | //| DRDY | D6 | Data Ready Outpt| //| CS | D7 | Chip Select | //| MOSI | D11 | Slave In | //| MISO | D12 | Slave Out | //| SCK | D13 | Serial Clock | //| GND | Gnd | Gnd | // /////////////////////////////////////////////////////////////////////////////////////////
ads1292r ADS1292; // define class
//Packet format
/ DC Removal Numerator Coeff/
//* ecg filter ***
volatile uint8_t SPI_Dummy_Buff[30]; uint8_t DataPacketHeader[16]; volatile signed long s32DaqVals[8]; uint8_t data_len = 7; volatile byte SPI_RX_Buff[15] ; volatile static int SPI_RX_Buff_Count = 0; volatile char *SPI_RX_Buff_Ptr; volatile bool ads1292dataReceived = false; unsigned long uecgtemp = 0; signed long secgtemp = 0; int i, j;
//** ecg *** int16_t CoeffBuf_40Hz_LowPass[FILTERORDER] = { -72, 122, -31, -99, 117, 0, -121, 105, 34, -137, 84, 70, -146, 55, 104, -147, 20, 135, -137, -21, 160, -117, -64, 177, -87, -108, 185, -48, -151, 181, 0, -188, 164, 54, -218, 134, 112, -238, 90, 171, -244, 33, 229, -235, -36, 280, -208, -115, 322, -161, -203, 350, -92, -296, 361, 0, -391, 348, 117, -486, 305, 264, -577, 225, 445, -660, 93, 676, -733, -119, 991, -793, -480, 1486, -837, -1226, 2561, -865, -4018, 9438, 20972, 9438, -4018, -865, 2561, -1226, -837, 1486, -480, -793, 991, -119, -733, 676, 93, -660, 445, 225, -577, 264, 305, -486, 117, 348, -391, 0, 361, -296, -92, 350, -203, -161, 322, -115, -208, 280, -36, -235, 229, 33, -244, 171, 90, -238, 112, 134, -218, 54, 164, -188, 0, 181, -151, -48, 185, -108, -87, 177, -64, -117, 160, -21, -137, 135, 20, -147, 104, 55, -146, 70, 84, -137, 34, 105, -121, 0, 117, -99, -31, 122, -72 }; int16_t ECG_WorkingBuff[2 * FILTERORDER]; unsigned char Start_Sample_Count_Flag = 0; unsigned char first_peak_detect = FALSE ; unsigned int sample_index[MAX_PEAK_TO_SEARCH + 2] ; uint16_t scaled_result_display[150]; uint8_t indx = 0;
int cnt = 0; volatile uint8_t flag = 0;
int QRS_Second_Prev_Sample = 0 ; int QRS_Prev_Sample = 0 ; int QRS_Current_Sample = 0 ; int QRS_Next_Sample = 0 ; int QRS_Second_Next_Sample = 0 ;
static uint16_t QRS_B4_Buffer_ptr = 0 ; / Variable which holds the threshold value to calculate the maxima / int16_t QRS_Threshold_Old = 0; int16_t QRS_Threshold_New = 0; unsigned int sample_count = 0 ;
/ Variable which will hold the calculated heart rate / volatile uint16_t QRS_Heart_Rate = 0 ; int16_t ecg_wave_buff[1], ecg_filterout[1];
volatile uint8_t global_HeartRate = 0; volatile uint8_t global_RespirationRate = 0; long status_byte=0; uint8_t LeadStatus=0; boolean leadoff_deteted = true;
void setup() { delay(5000); // initalize the data ready and chip select pins: pinMode(ADS1292_DRDY_PIN, INPUT); //6 pinMode(ADS1292_CS_PIN, OUTPUT); //7 pinMode(ADS1292_START_PIN, OUTPUT); //5 pinMode(ADS1292_PWDN_PIN, OUTPUT); //4
Serial.begin(115200); // Baudrate for serial communica
ADS1292.ads1292_Init(); //initalize ADS1292 slave }
void loop() { if ((digitalRead(ADS1292_DRDY_PIN)) == LOW) // Sampling rate is set to 125SPS ,DRDY ticks for every 8ms { SPI_RX_Buff_Ptr = ADS1292.ads1292_Read_Data(); // Read the data,point the data to a pointer
for (i = 0; i < 9; i++)
{
SPI_RX_Buff[SPI_RX_Buff_Count++] = *(SPI_RX_Buff_Ptr + i); // store the result data in array
}
ads1292dataReceived = true;
}
if (ads1292dataReceived == true) // process the data { j = 0; for (i = 3; i < 9; i += 3) // data outputs is (24 status bits + 24 bits Respiration data + 24 bits ECG data) {
uecgtemp = (unsigned long) ( ((unsigned long)SPI_RX_Buff[i + 0] << 16) | ( (unsigned long) SPI_RX_Buff[i + 1] << 8) | (unsigned long) SPI_RX_Buff[i + 2]);
uecgtemp = (unsigned long) (uecgtemp << 8);
secgtemp = (signed long) (uecgtemp);
secgtemp = (signed long) (secgtemp >> 8);
s32DaqVals[j++] = secgtemp; //s32DaqVals[0] is Resp data and s32DaqVals[1] is ECG data
}
status_byte = (long)((long)SPI_RX_Buff[2] | ((long) SPI_RX_Buff[1]) <<8 | ((long) SPI_RX_Buff[0])<<16); // First 3 bytes represents the status
status_byte = (status_byte & 0x0f8000) >> 15; // bit15 gives the lead status
LeadStatus = (unsigned char ) status_byte ;
if(!((LeadStatus & 0x1f) == 0 ))
leadoff_deteted = true;
else
leadoff_deteted = false;
ecg_wave_buff[0] = (int16_t)(s32DaqVals[1] >> 8) ; // ignore the lower 8 bits out of 24bits
if(leadoff_deteted == false)
{
ECG_ProcessCurrSample(&ecg_wave_buff[0], &ecg_filterout[0]); // filter out the line noise @40Hz cutoff 161 order
QRS_Algorithm_Interface(ecg_filterout[0]); // calculate
}
else
ecg_filterout[0] = 0;
DataPacketHeader[0] = CES_CMDIF_PKT_START_1 ; // Packet header1 :0x0A
DataPacketHeader[1] = CES_CMDIF_PKT_START_2; // Packet header2 :0xFA
DataPacketHeader[2] = (uint8_t) (data_len); // data length
DataPacketHeader[3] = (uint8_t) (data_len >> 8);
DataPacketHeader[4] = CES_CMDIF_TYPE_DATA; // packet type: 0x02 -data 0x01 -commmand
DataPacketHeader[5] = ecg_filterout[0];
DataPacketHeader[6] = ecg_filterout[0] >> 8;
DataPacketHeader[7] = s32DaqVals[0]; // 4 bytes ECG data
DataPacketHeader[8] = s32DaqVals[0] >> 8;
DataPacketHeader[9] = s32DaqVals[0] >> 16;
DataPacketHeader[10] = s32DaqVals[0] >> 24;
if(leadoff_deteted == true) // lead in not connected
DataPacketHeader[11] = 0 ;
else
DataPacketHeader[11] = global_HeartRate ;
DataPacketHeader[12] = CES_CMDIF_PKT_STOP_1; // Packet footer1:0x00
DataPacketHeader[13] = CES_CMDIF_PKT_STOP_2 ; // Packet footer2:0x0B
for (i = 0; i < 14; i++)
{
Serial.write(DataPacketHeader[i]); // transmit the data over USB
}
}
ads1292dataReceived = false; SPI_RX_Buff_Count = 0; delay(1000); }
void ECG_FilterProcess(int16_t WorkingBuff, int16_t CoeffBuf, int16_t* FilterOut) {
int32_t acc = 0; // accumulator for MACs int k;
// perform the multiply-accumulate for ( k = 0; k < 161; k++ ) { acc += (int32_t)(CoeffBuf++) (int32_t)(WorkingBuff--); } // saturate the result if ( acc > 0x3fffffff ) { acc = 0x3fffffff; } else if ( acc < -0x40000000 ) { acc = -0x40000000; } // convert from Q30 to Q15 FilterOut = (int16_t)(acc >> 15); //FilterOut = WorkingBuff; }
void ECG_ProcessCurrSample(int16_t CurrAqsSample, int16_t FilteredOut) { static uint16_t ECG_bufStart = 0, ECG_bufCur = FILTERORDER - 1, ECGFirstFlag = 1; static int16_t ECG_Pvev_DC_Sample, ECG_Pvev_Sample;/ Working Buffer Used for Filtering/ // static short ECG_WorkingBuff[2 FILTERORDER]; int16_t CoeffBuf; int16_t temp1, temp2, ECGData;
/ Count variable/ uint16_t Cur_Chan; int16_t FiltOut = 0; // short FilterOut[2]; CoeffBuf = CoeffBuf_40Hz_LowPass; // Default filter option is 40Hz LowPass
if ( ECGFirstFlag ) // First Time initialize static variables. { for ( Cur_Chan = 0 ; Cur_Chan < FILTERORDER; Cur_Chan++) { ECG_WorkingBuff[Cur_Chan] = 0; } ECG_Pvev_DC_Sample = 0; ECG_Pvev_Sample = 0; ECGFirstFlag = 0; }
temp1 = NRCOEFF * ECG_Pvev_DC_Sample; //First order IIR ECG_Pvev_DC_Sample = (CurrAqsSample[0] - ECG_Pvev_Sample) + temp1; ECG_Pvev_Sample = CurrAqsSample[0]; temp2 = ECG_Pvev_DC_Sample >> 2; ECGData = (int16_t) temp2;
/ Store the DC removed value in Working buffer in millivolts range/ ECG_WorkingBuff[ECG_bufCur] = ECGData; ECG_FilterProcess(&ECG_WorkingBuff[ECG_bufCur], CoeffBuf, (int16_t)&FiltOut); / Store the DC removed value in ECG_WorkingBuff buffer in millivolts range*/ ECG_WorkingBuff[ECG_bufStart] = ECGData;
/ Store the filtered out sample to the LeadInfo buffer/ FilteredOut[0] = FiltOut ;//(CurrOut);
ECG_bufCur++; ECG_bufStart++;
if ( ECG_bufStart == (FILTERORDER - 1)) { ECG_bufStart = 0; ECG_bufCur = FILTERORDER - 1; } return ; }
void QRS_Algorithm_Interface(int16_t CurrSample) { // static FILE *fp = fopen("ecgData.txt", "w"); static int16_t prev_data[32] = {0}; int16_t i; long Mac = 0; prev_data[0] = CurrSample;
for ( i = 31; i > 0; i--) { Mac += prev_data[i]; prev_data[i] = prev_data[i - 1];
} Mac += CurrSample; Mac = Mac >> 2; CurrSample = (int16_t) Mac; QRS_Second_Prev_Sample = QRS_Prev_Sample ; QRS_Prev_Sample = QRS_Current_Sample ; QRS_Current_Sample = QRS_Next_Sample ; QRS_Next_Sample = QRS_Second_Next_Sample ; QRS_Second_Next_Sample = CurrSample ;
QRS_process_buffer(); }
static void QRS_process_buffer( void ) {
int16_t first_derivative = 0 ; int16_t scaled_result = 0 ;
static int16_t Max = 0 ;
/ calculating first derivative/ first_derivative = QRS_Next_Sample - QRS_Prev_Sample ;
/taking the absolute value/
if (first_derivative < 0) { first_derivative = -(first_derivative); }
scaled_result = first_derivative;
if ( scaled_result > Max ) { Max = scaled_result ; }
QRS_B4_Buffer_ptr++; if (QRS_B4_Buffer_ptr == TWO_SEC_SAMPLES) { QRS_Threshold_Old = ((Max * 7) / 10 ) ; QRS_Threshold_New = QRS_Threshold_Old ; // if (Max > 70) first_peak_detect = TRUE ; Max = 0;
// ecg_wave_buff[0] = first_derivative;
QRS_B4_Buffer_ptr = 0;
}
if ( TRUE == first_peak_detect ) { QRS_check_sample_crossing_threshold( scaled_result ) ; }
}
static void QRS_check_sample_crossing_threshold( uint16_t scaled_result ) { / array to hold the sample indexes S1,S2,S3 etc /
static uint16_t s_array_index = 0 ; static uint16_t m_array_index = 0 ;
static unsigned char threshold_crossed = FALSE ; static uint16_t maxima_search = 0 ; static unsigned char peak_detected = FALSE ; static uint16_t skip_window = 0 ; static long maxima_sum = 0 ; static unsigned int peak = 0; static unsigned int sample_sum = 0; static unsigned int nopeak = 0; uint16_t Max = 0 ; uint16_t HRAvg; uint16_t RRinterval = 0;
if ( TRUE == threshold_crossed ) { / Once the sample value crosses the threshold check for the maxima value till MAXIMA_SEARCH_WINDOW samples are received / sample_count ++ ; maxima_search ++ ;
if ( scaled_result > peak )
{
peak = scaled_result ;
}
if ( maxima_search >= MAXIMA_SEARCH_WINDOW )
{
// Store the maxima values for each peak
maxima_sum += peak ;
maxima_search = 0 ;
threshold_crossed = FALSE ;
peak_detected = TRUE ;
}
} else if ( TRUE == peak_detected ) { / Once the sample value goes below the threshold skip the samples untill the SKIP WINDOW criteria is meet / sample_count ++ ; skip_window ++ ;
if ( skip_window >= MINIMUM_SKIP_WINDOW )
{
skip_window = 0 ;
peak_detected = FALSE ;
}
if ( m_array_index == MAX_PEAK_TO_SEARCH )
{
sample_sum = sample_sum / (MAX_PEAK_TO_SEARCH - 1);
HRAvg = (uint16_t) sample_sum ;
// Compute HR without checking LeadOffStatus
QRS_Heart_Rate = (uint16_t) 60 * SAMPLING_RATE;
QRS_Heart_Rate = QRS_Heart_Rate / HRAvg ;
if (QRS_Heart_Rate > 250)
QRS_Heart_Rate = 250 ;
// Serial.println(QRS_Heart_Rate);
/* Setting the Current HR value in the ECG_Info structure*/
maxima_sum = maxima_sum / MAX_PEAK_TO_SEARCH;
Max = (int16_t) maxima_sum ;
/* calculating the new QRS_Threshold based on the maxima obtained in 4 peaks */
maxima_sum = Max * 7;
maxima_sum = maxima_sum / 10;
QRS_Threshold_New = (int16_t)maxima_sum;
/* Limiting the QRS Threshold to be in the permissible range*/
if (QRS_Threshold_New > (4 * QRS_Threshold_Old))
{
QRS_Threshold_New = QRS_Threshold_Old;
}
sample_count = 0 ;
s_array_index = 0 ;
m_array_index = 0 ;
maxima_sum = 0 ;
sample_index[0] = 0 ;
sample_index[1] = 0 ;
sample_index[2] = 0 ;
sample_index[3] = 0 ;
Start_Sample_Count_Flag = 0;
sample_sum = 0;
}
} else if ( scaled_result > QRS_Threshold_New ) { / If the sample value crosses the threshold then store the sample index / Start_Sample_Count_Flag = 1; sample_count ++ ; m_array_index++; threshold_crossed = TRUE ; peak = scaled_result ; nopeak = 0;
/* storing sample index*/
sample_index[ s_array_index ] = sample_count ;
if ( s_array_index >= 1 )
{
sample_sum += sample_index[ s_array_index ] - sample_index[ s_array_index - 1 ] ;
}
s_array_index ++ ;
}
else if (( scaled_result < QRS_Threshold_New ) && (Start_Sample_Count_Flag == 1)) { sample_count ++ ; nopeak++; if (nopeak > (3 * SAMPLING_RATE)) { sample_count = 0 ; s_array_index = 0 ; m_array_index = 0 ; maxima_sum = 0 ; sample_index[0] = 0 ; sample_index[1] = 0 ; sample_index[2] = 0 ; sample_index[3] = 0 ; Start_Sample_Count_Flag = 0; peak_detected = FALSE ; sample_sum = 0;
first_peak_detect = FALSE;
nopeak = 0;
QRS_Heart_Rate = 0;
}
} else { nopeak++; if (nopeak > (3 SAMPLING_RATE)) { / Reset heart rate computation sate variable in case of no peak found in 3 seconds */ sample_count = 0 ; s_array_index = 0 ; m_array_index = 0 ; maxima_sum = 0 ; sample_index[0] = 0 ; sample_index[1] = 0 ; sample_index[2] = 0 ; sample_index[3] = 0 ; Start_Sample_Count_Flag = 0; peak_detected = FALSE ; sample_sum = 0; first_peak_detect = FALSE; nopeak = 0; QRS_Heart_Rate = 0; } }
global_HeartRate = (uint8_t)QRS_Heart_Rate; //Serial.println(global_HeartRate);
}
kindly help!
please share your order number so that we can contact you directly to solve your issue
i am not getting it. what is order number? @joicetm
joicetm.. I have a problem with getting output from this circuit, after i following all of the mentioned steps, can you help me please... as fast as possible please
Email: Mo7amed99935@gmail.com Whatsapp: +249100100409
please share your order number so that we can contact you directly to solve your issue
help me please...
Hello Aazeem,
Our ADS1292R Arduino library calculates heart rate, ECG waveform and Respiration waveform. We did not add respiration algorithm to calculate respiration value due to memory sufficiency while compiling in Arduino UNO. You can get the respiration algorithm from our HealthyPi Arduino library and you can add this algorithm and try with some boards with more memory like Arduino mega.
Hello Aazeem,
Please share the screenshots of your GUI and the error your facing to get output. Surely we can help you in figuring it out.
Thank you for replying… I'm trying to implement a system to measure ECG signal + respiration + heartrate..so I chose to work with your ads1292r, I follow all of the steps that mentioned in the site, but I have no output at all, some times the output come-out as a very noisy signal (I will send you a screenshot for it) and sometimes there is no output but the noisy signal appears with body movement and disappear again. But usually there is no response…Actually I was read about the module and the project before getting it, so I decide to use the arduino due, in stead of uno because of the better specifications of it(memory, speed and so on) Sent from my Huawei Mobile-------- Original Message --------Subject: Re: [Protocentral/ADS1292rShield_Breakout] Latest Version not showing any data on Windows 10 (#7)From: Mohammed Ibrahim To: Protocentral/ADS1292rShield_Breakout CC: Mo7amed-Aazeem ,Comment Hello Aazeem, Our ADS1292R Arduino library calculates heart rate, ECG waveform and Respiration waveform. We did not add respiration algorithm to calculate respiration value due to memory sufficiency while compiling in Arduino UNO. You can get the respiration algorithm from our HealthyPi Arduino library and you can add this algorithm and try with some boards with more memory like Arduino mega.
—You are receiving this because you commented.Reply to this email directly, view it on GitHub, or mute the thread.
Sent from my Huawei Mobile-------- Original Message --------Subject: Re: [Protocentral/ADS1292rShield_Breakout] Latest Version not showing any data on Windows 10 (#7)From: Mohammed Ibrahim To: Protocentral/ADS1292rShield_Breakout CC: Mo7amed-Aazeem ,Comment Hello Aazeem, Our ADS1292R Arduino library calculates heart rate, ECG waveform and Respiration waveform. We did not add respiration algorithm to calculate respiration value due to memory sufficiency while compiling in Arduino UNO. You can get the respiration algorithm from our HealthyPi Arduino library and you can add this algorithm and try with some boards with more memory like Arduino mega.
—You are receiving this because you commented.Reply to this email directly, view it on GitHub, or mute the thread.
Hi, Using the latest versions of Arduino and Processing code from Github (both compile and run correctly), the GUI screen is loading but, after choosing the correct COM port (4), there is no data being passed through - see screen shot. I've checked the serial port using RealTerm and good data is coming through so the issue is somewhere in the Processing code. Any ideas?