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: Unexpected result when writing and reading registers

Part Number: ADS1299

I'm getting both an inconsistent and unexpected result when writing and reading to registers on my ADS1299.

I start up the ADS by resetting by sending the command RESET (0x06). I then use the command SDATAC (0x11).
Using RREG (0x20) and reading from register CONFIG1 (0x01) to CONFIG4 (0x17), I get the expected result as stated in the datasheet.

TX comment RESET SDATAC RREG + 0x01 16(+1) registers
TX 06 11 21 16 00 00 00 00 00 00 00 00 00 00 00 00 00 00 etc.
RX 00 3C E0 00 00 96 C0 60 00 61 61 61 61 61 61 61 61 00 etc.
RTX comment CONFIG1 CONFIG2 CONFIG3 CH1SET CH2SET CH3SET CH4SET CH5SET CH6SET CH7SET CH8SET BIAS_SENSP

When writing to register (WREG) CH1SET and setting it to e.g 0xF6 (which should be valid) and then reading (RREG) the registers again, I get 

TX comment RESET SDATAC WREG + CH1SET_addr 0 (+1) registers to write Write value SDATAC RREG + CONFIG1_addr 16 (+1) registers to read
TX 06 11 45 00 B6 11 21 16 00 00 00 00 00 00 00 00 00 00 etc.
RX 00 00 E0 00 00 7F FE 47 FF 96 C0 60 00 7F 61 61 61 0061 etc.
RX comment ? ? ? ? CONFIG1 CONFIG2 CONFIG3 LOFF CH1SET CH2SET CH3SET CH4SET CH5SET

Notice that CH1SET gets the wrong value. However if I try to set CH1SET to 0x20 (which shouldn't be valid since a couple of the bits are reserved?), RREG shows correct result.
Also, often the ADS gives even more wrong values that aren't close to correct. Below is the same commands as above, but with an entirely different outcome.

TX comment RESET SDATAC WREG + CH1SET_addr 0 (+1) registers to write Write value SDATAC RREG + CONFIG1_addr 16 (+1) registers to read
TX 06 11 45 00 B6 11 21 16 00 00 00 00 00 00 00 00 00 00 etc.
RX 00 00 E0 00 00 7F FE 3F FF 00 00 00 0F 00 00 00 00 00 etc.
RX comment ? ? ? ? CONFIG1 CONFIG2 CONFIG3 LOFF CH1SET CH2SET CH3SET CH4SET CH5SET

My best guess is that it would be some error related to timing. I read somewhere that timing issues could cause errors when reading registers.


Trying to write to both CH1SET and CH2SET gives even more odd values. For example if I set CH1SET = 0x20 and CH2SET = 0x30, I get this result.

TX
RX 20 61 30 61
RX comment CH1SET CH2SET CH3SET CH4SET

CH2SET and CH3SET seem to have been switched. I've double and tripled checked the values that I send.

How important are the timings that are explained in the datasheet? In a multibyte-command, instead of waiting exactly <1.46µs between tx, coud I wait 1 ms or could this cause issues?


If you have any idea  what I could be doing wrong, or what I could do to narrow my search for the source of the issue, I'd appreciate the help.

Thank you in advance!

Some relevant code

ADS_Transmit(&(uint8_t) {ADS_CMD_RESET}, 1);

	HAL_Delay(500);	// Wait for power up (min 180 ms)

	//	ADS is waken up in RDATAC mode
	ADS_Transmit(&(uint8_t){ADS_CMD_SDATAC},1);

    // ADS_CH1SET_ADDR = 0x05
	ADS_WriteReg(ADS_CH1SET_ADDR, 0x20);

    // ADS_CH2SET_ADDR = 0x06
	ADS_WriteReg(ADS_CH2SET_ADDR, 0x15);

	ADS_ReadReg(ADS_CONFIG1_ADDR, 17);

	uint8_t tmp;

	 while (1)
	  {
	      ADS_DRDY_Wait();
		  HAL_Delay(1);
		  HAL_SPI_Receive(&hspi3, &tmp, 1, 100);
		  HAL_Delay(500);
		  
	  }

 

/*
 *	\brief Transmits data over SPI to ADS1299. 
 *	@param data Array of data to be transmitted. If only one byte,
 *	please dereference (&data) parameter when calling function.
 *	@param size Number of bytes in the data
 */
void ADS_Transmit(uint8_t* data, uint16_t size)
{
	ADS_DRDY_Wait();		//TODO: Visst ska´re va så?
//	HAL_GPIO_WritePin(ADS_CS_BUS, ADS_CS_PIN, RESET);
	HAL_SPI_Transmit(&hspi3, (uint8_t *) data, size, 100);
//	HAL_GPIO_WritePin(ADS_CS_BUS, ADS_CS_PIN, SET);
	HAL_Delay(1);
}


/*
 * 	\brief Is used to wait for DRDY to go low before sending data
 */
void ADS_DRDY_Wait(){
	while(HAL_GPIO_ReadPin(ADS_DRDY_BUS, ADS_DRDY_PIN) == GPIO_PIN_SET);
}
/*
 * 	\brief Read values of ADS1299 register(s).
 * 	@param baseAddr Address of first register to be read.
 * 	@param numOfReg Number of registers to be read following baseAddr, to only read one register, set numOfReg=1
 *
 */
void ADS_ReadReg(uint8_t baseAddr, uint8_t numOfReg)
{
	uint8_t opcode = ADS_CMD_RREG | baseAddr;

	//	Stop Read Data Continuously
	ADS_Transmit(&(uint8_t){ADS_CMD_SDATAC}, 1);

	ADS_Transmit(&opcode, 1);

	ADS_Transmit(&(uint8_t){numOfReg-1}, 1);

    for(int i = 0; i < numOfReg; i++){
        ADS_DRDY_Wait();
        ADS_Transmit(0, numOfReg);
        HAL_Delay(5);
    }
	
}

/*
 * 	\brief Writes to ADS1299 register. CS need to be active (LOW/RESET) during
 * 	the entire transmission!
 * 	@param address Address to register, use @ADS_REGISTERS
 * 	@param val Set value to register
 *
 */
void ADS_WriteReg(uint8_t address, uint8_t val)
{
	uint8_t opcode = ADS_CMD_WREG | address; 
	//	Stop Read Data Continuously
	ADS_Transmit(&(uint8_t){ADS_CMD_SDATAC}, 1);

	ADS_Transmit(&opcode, 1);

	//	Write to 1 register 
	ADS_Transmit(&(uint8_t){0x00}, 1);

	//	Set register to value
	ADS_Transmit(&val, 1);
}

  • Hi Kristoffer,

    Welcome to the E2E forum, and thanks for the post !!!

    For sending multi-byte commands, the tSDECODE timing is critical to ensure the device has enough time to decode the command. There is no issue if you exceed the minimum required time for tSDECODE. I recommend probing all the SPI signals and ensuring all the TX and RX signals are correct to debug your issue. Start by sending single byte command to the device and read back the value to see if the operation is proper (please see the debug steps in the link below). Once you can read and write to all the registers, you can proceed to the multi-byte command's operation.

    I'm having trouble communicating with my ADS129x device via SPI. What debug steps I should try?

    Thanks

    -TC

  • Thank you for your reply!
    The tables containing the bytes in the post above is as seen using a logic analyzer. Since I wait 1 ms between each byte in multi commands, which is greater than  tSDECODE, that should not be an issue.
    I'm having some odd errors. Ive tried SCLK in a bunch of different settings, all the way from 164 kHz to 4 MHz. Some SCLK seem to work better than others. 
    In my most basic test, I read 14 registers and compare the result to the default value. My best result was at 328 kHz, which gave me 39/40 correct responses - which still seems way to low.

    However, trying to write a value to register CONFIG1 is odd. Writing 0x96 to CONFIG1, as in the example in the datasheet, ALWAYS gives me the wrong result when reading the registers. In about half of the results, the chip spits out 0xE0 as a response, and in the rest of the tries DRDY never goes low hence no data is sent.

    When trying to write another number to CONFIG1, like 0x60. This seems to work fairly good. I get the correct response in 39 out of the 40 tries.

    I've been stuck for a while and I'm trying to find any small issues that could cause this problem. I've checked the digital input voltage, it's OK. 
    DVDD-DGND = 2.89 V, which is OK
    AVDD-DVDD = 1.82, which is OK
    AVDD-AVSS = 4.72 V, which is slightly below MIN value of 4.75 V. Does it seem feasible that something like this is off? I feel that it's a bit weird that my results differ from time to time and that it's possible to write some values to e.g CONFIG1 but it's NEVER possible to write its' default value. I've exceeded tPOR  after sending RESET and still have the same issues.

    Due to the experimental card being designed for a Arduino Nano, and I'm using a STM32F407, there are plenty of long and flimsy cables. Maybe this could be the cause of some of the weird results.

  • Hi Kristoffer,

    There seems to be some timing issue with your SPI communication if you are not able to get consistent results from the register read and write operation. Please make sure you are operating the ADS1299 within the datasheet specification. As suggested, I would start by checking the FAQs listed below for your debug. My recommendation is to observe what is being sent and return on the SPI bus with an oscilloscope.

    [FAQ] ADS129x: How do I verify that my ADS129x device is still functional?

    [FAQ] ADS129x: I'm having trouble communicating with my ADS129x device via SPI. What debug steps I should try?

    Thanks

    -TC

  • Hello again,

    I believe that the inconsistency issue has been resolved. I'm now powering it with a more stable voltage source. I'm getting consistent results when reading values from the registers.

    However, I'm still having issues with writing to registers. Writing to registers no longer messes anything up, however they receive the wrong values (however they receive the the same wrong numbers consistently for each value I try to write).
    For example, writing 0xE0 to CONFIG3, results in no change, that is CONFIG3 reads as 0x60.
    Writing 0x96 to CONFIG1, results in read on CONFIG1 = 0x16.

    For the latter, the data sent (using an oscilloscope to check values) is 0x41 (WREG+CONFIG1), <Wait 1ms> 0x00 (Write to 1 register), <Wait 1ms> 0x96. 

    I'm currently using SCLK 328 kHz (also tried 1.3 MHz). I have tried to further delaying the wait time between each byte, and also removing it entirely. I keep CS tied low. CPOL=0, CPHA=1. I've measured the internal voltage pins according to the link that you sent.

    Thank you for your help!

  • Hi Kristoffer,

    It seems like there is some issue with the MSB bit for your SPI interface. Can you verify the timing of the MSB bit from the oscilloscope capture? Please note that some reserved bits in the register need to be adhered to when writing to these registers. For example, the CONFIG1[4:3] is a reserved bit that needs to be 0b00.

    Thanks

    -TC

  • Thank you for your reply. You're correct. The MSB is missing in each byte that I send. Looking through my settings, I noticed that the IDE that I use have a different opinion on what CPHA 0 and 1 is, compared to me. I should have noticed it earlier, that was an annoying mistake from my side.
    Compare the difference between the two settings. In both examples, 0x96 is being transmitted. To the left, CPOL=0, CPHA=0. To the right, CPOL=0, CPHA=1

    CPOL0 CPHA0, 0x96CPOL0, CPHA1, 0x96

    This should probably be why the most significant bit were tossed away. Changing it to the correct SPI mode (as seen on the picture to the right) causes new issues. Sending the same data as earlier, watching the values on a scope, results in no data coming back.

    0x00​

    TX 0x06 0x11 0x21 0x0D 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 etc.
    RX 0x00 0xC0 0x00 0xE0 0xE0 0xE0 0xE0 0xE0 0xE0 0xE0 0xE0 0xE0 0xE0 0xE0 etc.
    Comment RESET SDATAC RREG CONFIG1 14 registers

    Example from table above, a seen using a scope

    I'm assuming the 0xE0 is from 1100 + LOFF_STATP[7:4]. It's like it doesnt recognize the SDATAC command, nor any other commands. Thank you a lot for you help so far!

  • Hi Kris,

    It is good to know you found some of the SPI issues you have.

    The 24 status bits for data retrieval will always start with 0b1100 and not 0xE0. Please see if you are able to read the correct registers from the device based on the Steps in the FAQ below.

    [FAQ] ADS129x: I'm having trouble communicating with my ADS129x device via SPI. What debug steps I should try?

    Thanks

    -TC

  • Hi,

    Aha, okay.
    I've sent the same thing as the picture you linked. Nothing. It keeps spitting out 0xE0, 0xC0 and 0x00 seemingly randomly. However, changing to CPOL=1 and CPHA=0, seems to do the trick.. With CPOL=1, CPHA=0 I'm able to read and write to all registers without any weird things happening when reading/writing to the registers.

    I've done some testing on channel 1, getting reasonable results when hooking it up for a voltage supply and changing the input. However, when I'm shortening IN1P and IN1N, I would expect to get an output on channel 1 to be 0, or close to 0. But it's around 0xFFFF00. Maybe it doesn't work like I'm assuming. 

    For now, I'll keep it in the wrong CPOL and CPHA, since it seem to work so far. Thank you a lot for your help!

  • Hi Kris,

    Thanks for the update. I will close this thread. Please open another thread if you have further question. 

    Thanks

    -TC