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.

ADS1259 - Changing sampling rate

Other Parts Discussed in Thread: ADS1259

I have the ADS1259 working in my system pretty much in it's default mode (10SPS).  I'm able to turn the A/D sampling on/off (apparently), but I'm not setting the configuration registers correctly to increase the data rate.  I've included my code (for an Atmel ARM SAM3X8C processor.  I'd appreciate any pointers.  I know this has to be something obvious.

I have one more issue, but I need to get over this as I may be able to resolve it in the configuration (data value appears to be rolling over well below max rate).

I've included my initialization source code below:

SPI Bus initialization:

// Clock polarity.
#define SPI_CLK_POLARITY 0 // Clock idles low
// Clock phase.
#define SPI_CLK_PHASE 0
// Delay before SPCK.
#define SPI_DLYBS 0x40
// Delay between consecutive transfers.
#define SPI_DLYBCT 0x10

spi_set_peripheral_chip_select_value(SPI0, SPI_CHIP_PCS);
spi_set_clock_polarity(SPI0, SPI_CHIP_SEL, SPI_CLK_POLARITY);
spi_set_clock_phase(SPI0, SPI_CHIP_SEL, SPI_CLK_PHASE);
spi_configure_cs_behavior(SPI0, SPI_CHIP_PCS, SPI_CSR_CSNAAT);
spi_set_bits_per_transfer(SPI0, SPI_CHIP_SEL, SPI_CSR_BITS_8_BIT);
spi_set_baudrate_div(SPI0, SPI_CHIP_SEL,(sysclk_get_cpu_hz() / gs_ul_spi_clock));
spi_set_transfer_delay(SPI0, SPI_CHIP_SEL, SPI_DLYBS, SPI_DLYBCT);
struct spi_device spi_device_conf = {.id = SPI_CHIP_PCS};
spi_master_setup_device(SPI0, &spi_device_conf, SPI_MODE_0, 9500000, 0); // <SC> bit rate to be determined

// ADS1259 Initialization

uint32_t ADS1259_Init(uint32_t config0, uint32_t config1, uint32_t config2)
{
	printf("\r\nADS1259_Init");

	Scale_Value = 0x00;
	Scale_Temperature = 0x00;

	// Configure ADS1259 /DRDY interrupt
	pio_set_input(PIOB, PIO_PB6, PIO_PULLUP);
	pio_handler_set(PIOB, ID_PIOB, PIO_PB6, PIO_IT_FALL_EDGE, ADS1259_Drdy_Handler);
	NVIC_SetPriority(PIOB_IRQn, 0);
	
	// Configure the AD7714 Chip Select and Reset Pins
	ioport_set_pin_dir(ADS1259_RST, IOPORT_DIR_OUTPUT);		// Configure the reset pin
	
	// Reset the ADS1259
	ioport_set_pin_level(ADS1259_RST, false);				// reset the chip
	tdelay_ms(50);
	ioport_set_pin_level(ADS1259_RST, true);					// clear reset
	tdelay_ms(400);

	spi_set_peripheral_chip_select_value(SPI0, SPI_CHIP_PCS);

	spi_write_single(SPI0, 0x11);									// turn continuous mode off
	tdelay_ms(20);
	spi_write_single(SPI0, (ADS1259_COM_WREG | ADS1259_CONFIG0));	// Write Config0 address  (0x40 | 0x00)
	spi_write_single(SPI0, 0x02);									// write 3 bytes
	spi_write_single(SPI0, config0);								// Bit Mask 1, 0, x, x, 0, bias enabled(1), 0, SPI timeout enabled  
																	// (config0 = 0x04)
	spi_write_single(SPI0, config1);								// Bit Mask 0, 0, 0, filter mode(0), Ref external(1), START conversion delay
																	// (config1 = 0x08)
	spi_write_single(SPI0, config2);								// Bit Mask DRDY (read only), int/ext clock (read only), syncout(0), Gate/Pulse control mode (0-gate), 0, Sample rate(000 - 10SPS)
																	// (config2 = 0x04)
	spi_write_single(SPI0, ADS1259_COM_RDATAC);						// Start conversions (continuous mode)

	pio_enable_interrupt(PIOB, PIO_PB6);							// Enable DReady interrupt
	NVIC_EnableIRQ(PIOB_IRQn);

	return 0;
}

  • Hi Scott,

    Welcome to the TI E2E Forums!

    The ADS1259 SPI uses mode 1, so try setting "SPI_CLK_PHASE" to 1 and see if that helps.

    Additionally, make sure to include a delay after toggling RESET and before communicating with the part. During this time the device will not respond to SPI commands (refer to figure 48 in the datasheet).

     

    Best Regards,
    Chris

  • Hi Chris,

    Thanks for the fast reply.  I made the change to spi mode 1.  I have a 500ms delay between reset clear and my first command.  As an experiment, I even increased it to 2 seconds.  I'm still not writing correctly to the registers (or so it appears).  I'm trying to change the data rate from 10SPS to 400SPS and it's not changing at all.  I'm sure I'm just not sending the proper command string (or formatting it correctly).

    I can tell the SPI bus is talking however, as I am seeing valid (or at least reasonable) data from my interrupt routine.

    Am I sending the commands correctly?

    0x11 - turn continuous off.

    (Delay 20ms)

    0x40 - WREG register write to Config0

    0x02 - write 3 bytes (is it zero based?)

    0x04 - Config 0 data

    0x04 - Config 1 data

    0x04 - Config 2 data

    0x10 - Start automatic conversions

  • One more question. When I send the write command, can the chip select toggle between bytes or does that reset the command? As my code is now, spi_write_single asserts chip select, writes the byte, then clears the chip select for each byte....it appears from what I have read, that I shouldn't be clearing the chip select between bytes. Could this be my issue?
  • Hi Scott,

    Your command sequence looks okay...

    • You're correct in that sending "0x02" after WREG will write to a total of 3 registers.
    • Regarding /CS...Yes, you will need to keep /CS high low until you've completed the entire WREG sequence (0x40, 0x02, 0x04, 0x04, 0x04)
      • Toggling /CS between these byte could cancel the WREG operation.
      • Toggling /CS between the SDATAC and START bytes is not a problem, as these are complete commands.

    Also, what is your SCLK frequency?

    The ADC accepts a master clock (fclk) of upto 8 MHz and the SPI clock must be no faster than fclk/1.8 (or 4.096 MHz with the 7.3728 MHz internal oscillator).

    ...I'd don't know if I'm reading your code correctly, but it looks like you might be running SCLK at 9.5 MHz?

    Scott Copeland said:
    spi_master_setup_device(SPI0, &spi_device_conf, SPI_MODE_0, 9500000, 0); // <SC> bit rate to be determined

     

    Best Regards,
    Chris

  • I changed the clock and have slowed it down below the maximum speed. I noticed that you said the CS should be HIGH? I thought it was low asserted per the datasheet.
  • Hi Scott,

    Sorry, that was a brain-lapse on my part. You're correct, /CS is active low.

    Best Regards,
    Chris

  • I'm still having problems changing register settings.  I can still read data from the A/D if I don't mess with the configuration, but if I try to reconfigure, it goes into the weeds.  Here is what I have to this point.  I hard coded everything to make it easier to read.

    When I send SDATAC, the DREADY should stop toggling, right?  That would make sense, but its not happening.

    	setupdata[0] = 0x40;		// WREG command / start at Config0
    	setupdata[1] = 0x08;		// Length (9 bytes)
    
    	setupdata[2] = 0x04;		// CFG0
    	setupdata[3] = 0x08;		// CFG1
    	setupdata[4] = 0x04;		// CFG2
    
    	setupdata[5] = 0x00;		// OFC0
    	setupdata[6] = 0x00;		// OFC1
    	setupdata[7] = 0x00;		// OFC2
    
    	setupdata[8] = 0x00;		// FSC0
    	setupdata[9] = 0x00;		// FSC1
    	setupdata[10] = 0x00;		// FSC2
    
    	ADS1259_WaitDReady();		// Wait for Ready to go low
    	spiwrite(0x0a);                 // Turn continuous mode off
    
    	uint32_t spisetup = SPI0->SPI_CSR[0];	        // Lock the SPI Chip Select low
    	spisetup = spisetup | 0x00000008;
    	SPI0->SPI_CSR[0] = spisetup;
    
    	spi_write_packet(SPI0, &setupdata[0], 11);	// Write configuration data
    
    	spisetup = spisetup & ~0x00000008;		// Reset the chip select to auto
    	SPI0->SPI_CSR[0] = spisetup;
    
    	ADS1259_ReadReg();				// Display register settings
    
            spiwrite(ADS1259_COM_RDATAC);			// Start conversions (continuous mode)
    	
    

    My current SPI settings are:

    // Clock polarity.
    #define ADS1259_SPI_CLK_POLARITY 0 // Clock idles low
    // Clock phase.
    #define ADS1259_SPI_CLK_PHASE 1
    // Delay before SPCK.
    #define ADS1259_SPI_DLYBS 0x02 // ~60ns delay (50ns minimum required)
    // Delay between consecutive transfers.
    #define ADS1259_SPI_DLYBCT 0x02 // <SC> was 0x10
    	spi_disable(SPI0);
    	spi_reset(SPI0);
    	spi_set_lastxfer(SPI0);
    	spi_set_master_mode(SPI0);
    	spi_disable_mode_fault_detect(SPI0);
    
    	spi_set_peripheral_chip_select_value(SPI0, SPI_CHIP_PCS);
    	spi_set_clock_polarity(SPI0, SPI_CHIP_SEL, ADS1259_SPI_CLK_POLARITY);
    	spi_set_clock_phase(SPI0, SPI_CHIP_SEL, ADS1259_SPI_CLK_PHASE);
    	spi_configure_cs_behavior(SPI0, SPI_CHIP_PCS, SPI_CSR_CSNAAT);
    //	spi_configure_cs_behavior(SPI0, SPI_CHIP_PCS, SPI_CSR_CSAAT);
    	spi_set_bits_per_transfer(SPI0, SPI_CHIP_SEL, SPI_CSR_BITS_8_BIT);
    	spi_set_baudrate_div(SPI0, SPI_CHIP_SEL,(sysclk_get_cpu_hz() / gs_ul_spi_clock));
    	spi_set_transfer_delay(SPI0, SPI_CHIP_SEL, ADS1259_SPI_DLYBS, ADS1259_SPI_DLYBCT);
    
    	struct spi_device spi_device_conf = {.id = SPI_CHIP_PCS};
    	spi_master_setup_device(SPI0, &spi_device_conf, SPI_MODE_1, 2000000, 0);
    	spi_configure_cs_behavior(SPI0, SPI_CHIP_PCS, SPI_CS_KEEP_LOW);
    	spi_enable(SPI0);
    

  • Hi Scott,

    After sending the "SDATAC" command, you should still see /DRDY toggle - so no problem there...

    The only thing that looks off in your configuration is that your writing "0x00" to the FSC2 register. In this case, you'd be telling the device to multiply every conversion result by: FSC[2:0]/400000h = 0h / 400000h = 0. The FSC2 register should default to "0x40" to make the gain correction factor = 1.

    After writing to the ADS1259 device registers, do you read back the correct register settings? Also, do you see /DRDY toggle at the faster 400 SPS data rate after programming the device?

    Best Regards,
    Chris

  • I have it at 400000 right now. I'm using the internal clock for the moment. I think I see the problem and I'm working on it now. The processor I'm using can handle chip selects automatically. It doesn't have a way to be low for x number of writes (it's not that flexible), then go high. I'm going to turn that feature off and use the chip select as an IO pin so I can control when it's on/off.
  • I made the changes you recommended and a few more.  I've added an IO pin to control the START signal.  START is taken low initially, the device configured and then taken high right after the interrupt is enabled.

    I've changed FSC[2] to 0x40.  I'm not seeing the DRDY signal rate change after I configure the registers, which is my first red flag that I don't have the SPI port setup correctly.  I am seeing the chip select go low, all data written, then back high.

    void ADS1259_spi_master_initialize(void)
    {
    	printf("\r\nADS1259_spi_master_initialize");
    
    	// SPI
    	pmc_enable_periph_clk(ID_SPI0);
    	pio_set_peripheral(PIOA, PIO_PERIPH_A, PIO_PA27A_SPI0_SPCK);
    	pio_set_peripheral(PIOA, PIO_PERIPH_A, PIO_PA26A_SPI0_MOSI);
    	pio_set_peripheral(PIOA, PIO_PERIPH_A, PIO_PA25A_SPI0_MISO);
    	pio_set_peripheral(PIOA, PIO_PERIPH_A, PIO_PA28A_SPI0_NPCS0);
    	pio_set_peripheral(PIOA, PIO_PERIPH_A, PIO_PA29A_SPI0_NPCS1);
    
    	pmc_enable_periph_clk(ID_SPI0);
    
    	/* Configure an SPI peripheral. */
    	spi_enable_clock(SPI0);
    
    	// AD7714 Chip Select Configuration
    	spi_disable(SPI0);
    	spi_reset(SPI0);
    	spi_set_lastxfer(SPI0);
    	spi_set_master_mode(SPI0);
    	spi_disable_mode_fault_detect(SPI0);
    
    	spi_set_peripheral_chip_select_value(SPI0, SPI_CHIP_PCS);
    	spi_configure_cs_behavior(SPI0, SPI_CHIP_PCS, SPI_CS_KEEP_LOW);
    	spi_set_clock_polarity(SPI0, SPI_CHIP_SEL, ADS1259_SPI_CLK_POLARITY);
    	spi_set_clock_phase(SPI0, SPI_CHIP_SEL, ADS1259_SPI_CLK_PHASE);
    	spi_set_bits_per_transfer(SPI0, SPI_CHIP_SEL, SPI_CSR_BITS_8_BIT);
    	spi_set_transfer_delay(SPI0, SPI_CHIP_SEL, ADS1259_SPI_DLYBS, ADS1259_SPI_DLYBCT);
    	spi_set_baudrate_div(SPI0, SPI_CHIP_SEL, (sysclk_get_cpu_hz() / gs_ul_spi_clock));
    
    	struct spi_device spi_device_conf = {.id = SPI_CHIP_PCS};
    	spi_master_setup_device(SPI0, &spi_device_conf, SPI_MODE_1, 4000000, 0);
    	spi_configure_cs_behavior(SPI0, SPI_CHIP_PCS, SPI_CS_KEEP_LOW);
    	
    	spi_enable(SPI0);
    }
    uint32_t ADS1259_Init(uint32_t config0, uint32_t config1, uint32_t config2)
    {
    	Scale_Value = 0x00;
    	Scale_Temperature = 0x00;
    
    	uint8_t setupdata[12];
    	setupdata[0] = 0x40;								// WREG command / start at Config0
    	setupdata[1] = 0x08;								// Length (9 bytes)
    
    	setupdata[2] = 0x04;								// CFG0 0x04
    	setupdata[3] = 0x08;								// CFG1 0x08
    	setupdata[4] = 0x04;								// CFG2 0x04
    
    	setupdata[5] = 0x00;								// OFC0
    	setupdata[6] = 0x00;								// OFC1
    	setupdata[7] = 0x00;								// OFC2
    
    	setupdata[8] = 0x00;								// FSC0
    	setupdata[9] = 0x00;								// FSC1
    	setupdata[10] = 0x40;								// FSC2
    
    	// Initialize IO pins (START, RESET, DREADY)
    	// Configure the ADS1259 Start Pin
    	ioport_set_pin_dir(ADS1259_START, IOPORT_DIR_OUTPUT);		// Configure the reset pin
    	ioport_set_pin_level(ADS1259_START, 0);						// stop conversions
    	// Configure the ADS1259 Reset Pin
    	ioport_set_pin_dir(ADS1259_RST, IOPORT_DIR_OUTPUT);			// Configure the reset pin
    	ioport_set_pin_level(ADS1259_RST, 1);						// clear reset
    
    	delay_ms(300);												// 250ms delay <SC>
    
    	// Configure ADS1259 /DRDY interrupt
    	pio_set_input(PIOB, PIO_PB6, PIO_PULLUP);
    	pio_handler_set(PIOB, ID_PIOB, PIO_PB6, PIO_IT_FALL_EDGE, ADS1259_Drdy_Handler);
    	NVIC_SetPriority(PIOB_IRQn, 0);	
    	pio_enable_interrupt(PIOB, PIO_PB6);						// Enable DReady interrupt
    
    	// Setup ADS1259 Registers
    	ADS1259_WaitNotDReady();									// Wait for Ready to go low
    	// Write the configuration data to the chip
    	setupdata[0] = 0x40;										// WREG command / start at Config0
    	spi_write_packet(SPI0, &setupdata[0], 11);
    
    	delay_ms(10);
    
    	pio_enable_interrupt(PIOB, PIO_PB6);						// Enable DReady interrupt
    	NVIC_EnableIRQ(PIOB_IRQn);
    
    	ioport_set_pin_level(ADS1259_START, 1);						// start conversions
    
    	printf("\r\nInterrupt enabled");
    
    	return 0;
    }
    void ADS1259_Drdy_Handler(uint32_t sourceid, uint32_t mask)
    {
    	uint8_t data[3];
    
    	Disable_global_interrupt();				// <SC> 7/6/16 testing disable all interrupts during service routine
    	Scale_Value = 0x00000000;
    
    	spi_read_packet(SPI0, &data[0], 3);				// Reads 24 bit data into byte field
    	// shift each 8 bit into result
    	Scale_Value = Scale_Value | data[0];			// first 8 bits
    	Scale_Value = Scale_Value << 8;					// make room for next byte
    	Scale_Value = Scale_Value | data[1];			// second 8 bits
    	Scale_Value = Scale_Value << 8;					// make room for next 8 bytes
    	Scale_Value = Scale_Value | data[2];			// last 8 bits
    
    	Enable_global_interrupt();
    }

  • Hi Scott,

    Nothing else in your code stands out to me as an issue...

    What about reading back the ADS1259 registers to see what settings it returns?

    The return data from the readback can be a useful clue to see if the SPI communication is partially working.

     

    Have you tried looking at the SPI communication on a scope or logic analyzer to verify your code?

    Sometimes the code doesn't always work as you'd expect it, so troubleshooting communication issues without also probing the signals becomes a guessing game. If you're able to share some screenshots of the SPI communication, I can help you look at them to see if anything looks off in the SPI timing.

    Best Regards,
    Chris