This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADS1299-4: Problem obtaining internal test signals

Part Number: ADS1299-4
Other Parts Discussed in Thread: ADS1299

Hi,

This is my first time posting on the forum, so please bear with me if I leave information out.

I have read some of the other posts on how to obtain the internal test signals and I am struggling to get the square signal. I am using the ADS1299-4 with an ESP32 as an MCU. I will post my code below and the output I keep getting at the bottom. I followed the start-up procedure as stated in the datasheet and able to read and write the registers correctly. At first, I am only trying to get the test signals from channel 1 and shorten the other three channels. I am using Arduino IDE and built a custom PCB. As a reference, I followed openBCI schematic and opensource code to build the PCB.

The problem I have is the output of the test signals. As you can see in the figure below, the output is quite weird and not square as it should be. I don't know if I am just not configuring the registers correctly or maybe my SPI clock is just incorrect. The figure below is what I am getting on the Serial Plotter and on the Serial Monitor I get negative answers around -6000.

Can somebody please help me by showing me what I am doing wrong and what I can do to fix it? It would be much appreciated!

Here is the Serial Plotter output I got.

  

Here are some snippets of my code with my full code afterward:

This is how I write to the registers:

Update channel data:

And here is the function of how I want to print the data:

Full-text file containing the code.

testSignals.txt
Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "EEG.h"
#include "EEG_Definitions.h"
#include <SoftwareSerial.h>
#include <SPI.h>
// start of simulation declarations
#define ISR_TRIGGER_GPIO 39
#define PULSE_OUTPUT_GPIO 32
// Scale factor for data
#define GAIN 1
#define scaleFactor 1000000*((4.5/(2^23)-1)/GAIN)
#define testScale 0.001*4.5/2.4
// Clock Signal
#define tCLK 0.0005 // 2 MHz Clock signal, 500 ns
int sampleFreq = 250; // to 500. A value of 128 will give 512 samples
int factor = 1000/sampleFreq/2;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • Hi Elke,

    Welcome to the E2E forum !!!

    I do not think you are setting the CONFIG2 register correctly for the internal test signal. To enable the internal test signal, you need to set CONFIG2.Bit1 to '1' and CONFIG2.Bit0 to '1' for a square wave internal test signal at 1 Hz. Depending on your hardware design, you need to ensure the reference voltage (VREF = VREFP - VREFN) is set up correctly.

    Thanks

    -TC

  • Thanks for the quick reply!

    I changed both CONFIG2.Bit1 and CONFIG2.Bit0 to '1', thus writing CONFIG2 as 0xD3. I also checked my reference voltage now and when measuring with reference to AVSS, I get the following:

    VREFP = 4.51 V

    VREFN = 0 V

    VCAP1 = 1.2 V

    VCAP2 = 2.52 V

    VCAP3 = 6.9 V

    VCAP4 = 2.25 V

    And with reference to ground:

    AVDD = 2.51 V

    AVSS = -2.51 V

    I am still getting the weird output I got earlier. So I don't know what seems to be the problem. I will attach the schematic I am using if you can help me check to see if I am missing something? I just want to add as I forgot to add it in the original post, I am using a bipolar power supply for the ADS.

  • Hi Elke,

    Thanks for the information.

    The schematic and all the device voltages look fine. For debugging, you may want to look at the SPI interface with a logic analyzer or oscilloscope to see if you are getting the proper output data bits. Please also verify you are getting the correct preamble (0xC0) for the 24 status bits in the stat_1 output. Another option is to provide known signals (DC or sinewave) in the "normal electrode" mode and check if the results match your input.

    Thanks

    -TC

  • I played around with my code to print out the status register and I got FFC00000. Can this be seen as correct or not?

  • Hi Elke,

    The last 3 bytes of the status bits seem correct if you are padding it to 4-byte data. I am not familiar with your code that prints out the decimal value for the ADC output. Please verify that the conversion for the ADC binary twos complement data format is correct.

    Thanks

    -TC

  • Thanks, will do!

    I am busy looking at the SPI communication to see if there is something incorrect. Do you have any advice in where I should look? What are the most occurring problems you have come across when dealing with SPI? I could maybe help me narrow down my search. I know the ADS works with SPI mode 1 according to the datasheet and have my SPI frequency at 2 MHz. 

    If it helps the MCU I am using is the ESP32 Wroom module. 

    Really appreciate all the help!

  • Hi Elke,

    I did not go through your code completely, so I do not know exactly where the issue is. One of the easiest debug methodology is to apply a DC voltage to the input and look at the SPI digital output on the scope. Compare the output from your code to the SPI data observed on the oscilloscope. Start by applying a DC voltage VIN ≥ +VREF or VIN  ≤ -VREF and verify you can get the output code of 0x7FFFFFF and 0x800000, respectively. You can switch to the DC internal test signal (CAL_FREQ[1:0] = 0b11) for a fix DC test signal.

    If you are getting the correct output for the DC test, then the next debug step will be looking at how your uC ISR is processing the DRDY signal.

    I hope this helps you to find the issue you are seeing.

    Thanks

    -TC

  • Hi, 

    Sorry for only replying now. I just want to check something with you. When I am checking the status register, My code does nothing for a long time, then plots a lot of zeros, then followed by FFC00000 with zeros in between (as seen in the attached picture.)

    I will also attach the code giving this output. I just want to know if this is normal to the zeros in between the status register or should the status register output constantly be C0?

    newtestSignals.txt
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include "EEG.h"
    #include "EEG_Definitions.h"
    #include <SoftwareSerial.h>
    #include <SPI.h>
    // start of simulation declarations
    #define ISR_TRIGGER_GPIO 39
    #define PULSE_OUTPUT_GPIO 32
    // Scale factor for data
    #define GAIN 1
    #define scaleFactor 1000000*((4.5/(2^23)-1)/GAIN)
    #define testScale 0.001*4.5/2.4
    // Clock Signal
    #define tCLK 0.0005 // 2 MHz Clock signal, 500 ns
    int sampleFreq = 250; // to 500. A value of 128 will give 512 samples
    int factor = 1000/sampleFreq/2;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • Hi Elke,

    The ADC output will always start with the 24 status bits, followed by the 24-bit data for each channel. The 24 status bit will always begin with 0b1100. The output of the ADC should not be all zero even if you let the channel input floating.  

    Thanks

    -TC

  • Hi TCT,

    Sorry I am only replying now. I am able to output the status register value 0xC0 continuously now (with no zeros in-between as in my previous post). However, my registers are not reading and writing correctly. How can I get the correct status register output with my registers being written incorrectly?

    I will post my code below for you to check. The EEG. functions are just a header file where I pull CS high and low to send the command bytes. 

    Thanks.

    testSignal.txt
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include "EEG1.h"
    #include "EEG1_Definitions.h"
    #include <SoftwareSerial.h>
    #include <SPI.h>
    #include <FunctionalInterrupt.h>
    // start of simulation declarations
    #define ISR_TRIGGER_GPIO 39
    #define PULSE_OUTPUT_GPIO 32
    // Scale factor for data
    #define GAIN 1
    #define scaleFactor 1000000*((4.5/(2^23)-1)/GAIN)
    #define testScale 0.001*4.5/2.4
    // Clock Signal
    #define tCLK 0.0005 // 2 MHz Clock signal, 500 ns
    int sampleFreq = 250; // to 500. A value of 128 will give 512 samples
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • Hi Elke,

    Thanks for update. 

    Please refer to the E2E FAQ below for debugging a digital issue.

    Thanks

    -TC

  • Hi,

    Thank you for referring to this post, but I have read that post in the early stages when I was just trying to read and write to my registers. I am just really confused about how I can get the correct output for the status register if all my other registers are not correct? Surely, I am not supposed to get the correct status register output if my registers are not correct? 

    I will look at the debugging steps again in the post you referred me to and see if I can get my registers to write correctly again while giving me the correct status register output.

    Thanks!

  • Hi,

    I got my registers reading and writing correctly again, but now I sit with the same problem again where I only get zero as an output. I used an oscilloscope to see what happens with my DRDY pin. During the startup process my DRDY pin pulses as it should, but once it reaches the updateChannelData() function, my DRDY pin goes HIGH and stays there. 

    Have you come across such a problem in the past? 

    Thanks!

  • Hi Elke,

    It may be useful to use the oscilloscope to check the SPI interface pins (DRDYB, CSB, SCLK, DIN, DOUT) during the updateChannelData() function. By default, the device should be in the RDATAC mode, which the DRDYB will be toggling even though the data is not retrieved. Please refer to Figure 41 for the Data Ready (DRDYB) behavior. The initial flow at power-up (Figure 67) should be a good starting point to verify the device's functionality.

    Please make sure you are sending the correct command (RDATAC) after writing and reading the device registers to enable conversion data output on each DRDYB.

    Thanks

    -TC

  • Hi,

    So if I am understanding Figure 41 correctly, DRDY should be HIGH the whole time while in the RDATAC mode? I did follow the power-up process as described in Figure 67 and I got my registers to plot correctly again, but now I can't get the correct status register output back again.

    In the start-up procedure described in Figure 67, it says "Issue Reset Pulse" will that be possible by just sending the RESET command to the chip, or should the Reset pin be pulsed by using the PinMode function (PinMode( RESET, LOW); PinMode(RESET, HIGH) )?

  • Hi Elke,

    Thanks for the post.

    In RDATAC mode, the DRDYB will be pulled high when the START pin is pulled high (See Figure 40). The next DRDYB falling edge indicates the data are ready for retrieval. Figure 41 shows the DRDYB pin being pulled high at the first falling edge of the SCLK. This operation is regardless of whether the data are retrieved from the device or command is sent through the DIN pin.

    You can either send the RESET command or toggle the RESET pin to reset the device.

    -TC 

  • Hi TC,

    I looked at Figure 41 and understand how DRDYB should operate. When I start my system, DRDYB is already HIGH before sending the START command and after the registers are written START goes low. I followed the power-up sequence in Figure 67, but it seems START doesn't respond to the START command I send it. If I understand it correctly START is supposed to go HIGH if I send it the START command right?

    Thanks!

  • Hi Elke,

    As indicated in the datasheet, you will need to hold the START pin low when using the START command to control the conversion. If you are in RDATAC mode, the DRDYB will indicate whether the conversion is initiated. 

    Thanks

    -TC

  • Hi,

    I am able to get DRDYB to pulse at 250 Hz, START and RESET are high once updating data, but I am still getting 0 for my status register output. I will attach the oscilloscope output of DRDYB and the code. Is there anything that can you wrong otherwise? Should I pull RESET back low after the start-up procedure when I want to obtain the status register output?

    Sorry about the rotation of the photo. I can't seem to upload it in the correct rotation.

    1222.New Text Document.txt
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include "EEG1.h"
    #include "EEG1_Definitions.h"
    #include <SoftwareSerial.h>
    #include <SPI.h>
    #include <FunctionalInterrupt.h>
    // start of simulation declarations
    #define ISR_TRIGGER_GPIO 39
    #define PULSE_OUTPUT_GPIO 32
    // Scale factor for data
    #define GAIN 1
    #define scaleFactor 1000000*((4.5/(2^23)-1)/GAIN)
    #define testScale 0.001*4.5/2.4
    // Clock Signal
    #define tCLK 0.0005 // 2 MHz Clock signal, 500 ns
    int sampleFreq = 250; // to 500. A value of 128 will give 512 samples
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • I checked now and my DOUT voltage is in the mV range. RESET and START are high and DRDYB is pulsing at 250 Hz. What can be keeping DOUT low? I think that is the reason I am getting a zero output for my status register.

  • Hi Elke,

    Have you verified that the uC SPI interface is not interfering with the DOUT pin of the ADS1299? Please follow some of the debugging suggestions I listed in the earlier posts.

    Thanks

    -TC

  • Hi,

    Yes, I followed the debugging suggestions you gave me and I can get an output now. Thanks! I noticed that my channel 1 pin is HIGH and once it should start outputting data, the pin goes low. Have you come across a problem like this before? The values I get are quite large negative values. The code is the same as my previous post and the picture shows the serial output I get. The three zeros represent channels 2-4 which I have written as power down.

  • Hi Elke,

    Thanks for the test data. 

    Can you please clarify which pin you refer to for channel 1 pin?

    Once you are able to capture the data with the correct status bit, you can verify the validity of the data by using the internal test signal as you have done in your initial post. Again, this will help to ensure all the hardware and software are functioning correctly.

    Thanks

    -TC

  • Apologies. For channel 1, I am using IN1P (pin 16).

    I printed out the registers and I got the default register setting as stated on pg 44 of the datasheet, followed the start-up procedure on pg 62 (fig 67), and got the registers to print correctly according to that. However, I write to my registers as stated in fig 67 but the registers return wrong when I output it back out. With these wrong registers, I do get the correct status register and a block wave between the values of 2500 and -4500 and my DRDYB is pulsing as it should. All registers write out as 00h until BIAS_SENSP and then it rest writes random values for the registers.

    When I output the correct test signal register output, I get a 0 output for everything. How can I get the correct status register value (C0h) and a block test signal when my registers are writing incorrectly? I followed the SPI debugging steps you provided early and everything is correct, except for the test signal registers writing incorrectly. The default settings and the start-up procedure registers write correctly and then followed by the incorrect test signal registers.

    Hopes this makes sense what I am trying to explain? Cause I am assuming these incorrectly written registers will also prohibit me from obtaining data when I apply a signal to the channel 1 (IN1P) pin?

  • Hi Elke,

    Thanks for the clarification.

    The IN1P pin is a high impedance input pin and should not be affected by the device's operation. Please check if there is an issue with the IN1N causing the external input to behave incorrectly.

    The device registers read/write operation shares the same SPI interface as the read/write operation. Therefore, it is crucial that you do not corrupt or mix the operation. The RDATAC and the SDATAC commands are in place to avoid any miscommunication when operating in the continuous conversion mode. As long as the critical registers are not corrupted and causing the DRDY signal to misbehave, you will always see the correct preamble for the status bit during data retrieval. However, you may see the incorrect channel data in this case.

    Thanks

    -TC

  • If I want to put my ADS into normal electrode mode, will this function be correct? Is SDATAC and RDATAC in the correct place? I am trying to see if there is any functions or code interfering with the SPI interface, so maybe I am missing something?

    void ADSMode() {
    // ADS1299-4 Datasheet pg 62:

    digitalWrite(CS_ADS,LOW); //Pull CS LOW to start communication

    SPI.transfer(_SDATAC);
    delayMicroseconds(4*tCLK); //delay 4 tCLK cycles

    //Using internal reference i.e BIASREF siganl (AVDD + AVSS)/2
    WREGConf(CONFIG2, 0xD0);
    delayMicroseconds(2);

    // Set Device for f_mod/4096 (250 SPS)
    WREGConf(CONFIG1, 0x96); WREGConf(CONFIG3, 0xE8);

    // Set Channels to Input Short
    WREGConf(CH1SET, 0x60); WREGConf(CH2SET, 0x89);
    WREGConf(CH3SET, 0x89); WREGConf(CH4SET, 0x89);
    delayMicroseconds(2);

    // MISC1
    WREGConf(MISC1, 0x20); // COnnects SRB1 to all 4 channels inverting inputs

    SPI.transfer(_RDATAC);
    delayMicroseconds(2);
    digitalWrite(CS_ADS,HIGH); //Pull CS HIGH to stop communication
    SPI.endTransaction();
    }

  • Hi Elke,

    The function looks fine to me. 

    Thanks

    -TC

  • Hi TC,

    Thanks! I am also just going to ask you to please check my update channel function, I just want to make sure I am doing the ADC code to volt conversion correctly as I understood it from the forum post (https://e2e.ti.com/support/data-converters-group/data-converters/f/data-converters-forum/772488/faq-ads129x-how-do-i-convert-adc-output-codes-to-volts/2856893#2856893).

    Then I want to ask about the output I am getting. I am currently using a DC power supply and giving channel 1 (IN1P) 4.7V and 20 mA. The registers seem to print out correctly, channel 1 is set to 0x60 (Gain = 24 and normal electrode input), and channel 2-4 is set to 0x89 (Channel power down, gain = 1, input shorten). The picture I attached is a piece of the output I am obtaining after the conversion in the order status register followed by channels 1-4 in that order.  As you can see, my channel 1's value does not change and is also 2.38 V, and isn't channel 2 also supposed to be 0? There is an electrode attached to channel 2 but nothing was connected to it. 

    It also bothers me that the numbers are not changing but just staying constant. The output is the same when I apply the DC voltage when there is no power supplied when I tap my finger on it.

    I am going to attach a picture of my electrode input sub-circuit and a close-up of my ADS1299-4 schematic. The entire schematic can be seen in one of my first posts. Do you think that the resistor and capacitor can somehow be blocking the signal to get through from the electrode to the chip? I followed the openBCI's schematic and they had these components on their Cyton board, so surely it is supposed to be able to cross?

    My other registers are configured as followed:

    CONFIG1 0x96

    CONFIG2 0xD3

    CONFIG3 0xe8

    CH1SET 0x60

    CH2-4SET 0x89

    MISC1 0x20

    and the rest 0x00.

    I am only using my positive channel inputs and all the negative channel inputs are connected to AVDD as stated in the datasheet. 

    Might you know the cause of this problem?

    5483.Code.txt
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    void updateChannelData(){
    byte inByte;
    int byteCounter = 0;
    int numChan = 4; //assume 4 channel. If needed, it automatically changes to 16 automatically in a later block.
    long stat_1[1];
    channelData[4] = 0;
    if(digitalRead(ADS_DRDY) == LOW){
    digitalWrite(CS_ADS, LOW); // open SPI
    // READ CHANNEL DATA FROM FIRST ADS
    for(int i=0; i<1; i++){ // read 3 byte status register from ADS 1 (1100+LOFF_STATP+LOFF_STATN+GPIO[7:4])
    inByte = SPI.transfer(0x00);
    stat_1[i] = (stat_1[i]<<8) | inByte;
    }
    for(int i = 0; i < numChan; i++){
    for(int j=0; j < 3; j++){ // read 24 bits of channel data from 1st ADS in 8 3 byte chunks
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • Hi Elke,

    Please see some of my previous suggestions to make sure your signal chain is working properly by utilizing the internal test signal. The digital output code should be zero if the channel is powered down. I am not sure why you are getting non-zero data for this particular channel. Please verify the SPI output with an oscilloscope.

    Please note that if you set the channel gain to 24, the input signal for the channel will be limited. What you are seeing is the ADC output saturates to the full scale with the DC input. Please refer to the Analog Input section of the datasheet for more detailed information.

    Thanks

    -TC