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.

ADS1258: ADC Arduino UNO communication and output interpretation

Part Number: ADS1258
Other Parts Discussed in Thread: ADS127L11

Hi,

 we are trying to make it work the ADC ADS1258 to assess its suitability for future projects. To facilitate this, we have developed a custom board to accommodate the geometric constraints of our testing environment, and we have connected it according to the configuration depicted in the attached image.

Our objective is to directly acquire data from the ADCINN and ADCINP pins, bypassing the internal multiplexer.

We have proceeded to establish communication with the ADC using an Arduino UNO, following both the instructions outlined in the datasheet and the example code provided. With the help of scope, we have confirmed that MISO, MOSI, and SCLK are all functioning as expected, with DRDY toggling as foreseen.

The code employed for this purpose is as follows:


 

#include <SPI.h>

#define CS_PIN 10  // Chip select pin for ADS1258
const int DRDY=2;
byte stat,data1,data2,data3;
float dataF;

void setup() {
  Serial.begin(9600);  // Initialize serial communication
  pinMode(CS_PIN, OUTPUT);  // Set CS pin as output

  // Initialize SPI communication
  SPI.begin();
  SPI.setClockDivider(SPI_CLOCK_DIV16); // Set SPI clock frequency (16 MHz / 16 = 1 MHz)
  
  // Initialize ADS1258
  digitalWrite(CS_PIN, HIGH); // Deselect ADS1258
  delay(100); // Delay for stable operation
  digitalWrite(CS_PIN, LOW);  // Select ADS1258
  
  // Send configuration commands to ADS1258
  SPI.transfer(0xC0); // Send command: reset
  delay(100); // Delay for reset to complete
  
    digitalWrite(CS_PIN, HIGH); // Deselect ADS1258


  digitalWrite(CS_PIN, LOW);  // Select ADS1258

  // Configure ADS1258 settings for single-ended operation (example settings, adjust as needed)
  SPI.transfer(0x60); // Send command: write register
  SPI.transfer(0x3A); // Send value to write: CTRL0 register value (example: PGA = 1, SPS = 30)

  digitalWrite(CS_PIN, HIGH); // Deselect ADS1258


  digitalWrite(CS_PIN, LOW);  // Select ADS1258
  // Configure MUX register to select ADCINN and ADCINP as input channels directly

  SPI.transfer(0x62); // Send command: write register

  SPI.transfer(0x17); // Send value to write: CTRL0 register value (example: PGA = 1, SPS = 30)

  digitalWrite(CS_PIN, HIGH); // Deselect ADS1258

  digitalWrite(CS_PIN, LOW);  // Select ADS1258
  // Configure MUX register to select ADCINN and ADCINP as input channels directly

  uint8_t read= SPI.transfer(0x50);
  read= SPI.transfer(0x00);
    Serial.print("register control0:");
  Serial.println(read,HEX);

  Serial.println(read,HEX);
  read= SPI.transfer(0x00);
    Serial.print("register control1:");
  Serial.println(read,HEX);

  Serial.println(read,HEX);
  read= SPI.transfer(0x00);
    Serial.print("register control2:");

  Serial.println(read,HEX);

  // Deselect ADS1258
  digitalWrite(CS_PIN, HIGH);

  digitalWrite(CS_PIN, LOW);
  uint8_t stat=SPI.transfer(0x00);


}

void loop() {
  // Select ADS1258
  digitalWrite(CS_PIN, LOW);
  
  // Send command to read data
  SPI.transfer(0x01); // Send command: read register
  SPI.transfer(0x12); // Send register address: DATA register
  delay(1); // Delay for conversion
 SPI.transfer(0x00) << 16; // Read MSB

  // Read data from ADS1258
  if (digitalRead(DRDY)==LOW)
  {
   delayMicroseconds(30);

  int32_t rawValue = 0;
  //uint8_t stat=SPI.transfer(0x00);

  rawValue |= SPI.transfer(0x00) << 16; // Read MSB
  rawValue |= SPI.transfer(0x00) << 8;  // Read middle byte
  rawValue |= SPI.transfer(0x00);       // Read LSB
  // Deselect ADS1258
  
  digitalWrite(CS_PIN, HIGH);
  
  // Convert raw value to voltage (example: assuming Vref = 5V, 24-bit resolution)
  float voltage = (5.0 / 7864320.0) * rawValue; // Vref / (2^24) * rawValue786432
  
  // Print voltage value to serial monitor
 // Serial.print("Voltage: ");
  Serial.println(rawValue,HEX);
 // Serial.println(" V");
 //Serial.println(stat,HEX);

  // Delay before next reading
  delay(100);
  }
}



However, the communication seems completely wrong. reading the control registers we do not obtain the default values and if we try to write new values in the control registers for bypassing the internal mux and fixing one channel of the mux to not scan over the internal signals, at the next reading of the control register the value is different from the one sent over SPI (sent burst verified with a scope). Also, the converted data seems wrong and does not respond to changes in the applied input voltage.


Do you notice any issues with our approach?

We have also experimented with the libraries in the example code but encountered the same outcome. Even a simple reading of control0 at startup fails to display 0x0A as expected.

Thank you very much for any insights you may be able to provide.

Best regards,

Vincenzo

  • Hi Vincenzo Di Capua,

    Question for you: why are you using this ADC in this way i.e. bypassing the mux? We have better devices to suggest if you just want a 1-channel ADC e.g. ADS127L11

    What is the signal source you are applying to the ADC? Since you are driving the unbuffered modulator inputs, you need to make sure the sampling cap is able to settle within every time the modulator samples the input

    Can you provide logic analyzer images of your communication to and from the ADC? Please include CS, DOUT, DIN, SCLK, and DRDY, and please label your images so it is clear what your intent is in each communication frame

    Finally, I would strongly encourage you to use a 16 MHz discrete clock oscillator instead of a crystal as the ADC clock. Many customers have problems getting these crystals to startup, and without the clock (or with an intermittent clock) the ADC will behave erratically. You can search through e2e to find dozens of posts about this issue, and the only guaranteed way to fix it is to use a discrete clock.

    -Bryan

  • Hello Bryan,  Thanks a lot for your hints,

    To answer your questions we are applying from the outside 1 V DC in the input (only for these first tests).

    sending 3 times 0x00 to read back the ADC data converted

    sending 3 times 0x00 to read back the ADC data converted

    ADC clock on channel 15 measured on the CLOCKIO pin.

    Thanks again for any hint you may have.

  • Hi Vincenzo Di Capua,

    How are you determining when to read data? Typically you monitor the DRDY pin, wait for it to transition high to low, then read data.

    In the screenshot you provided, DRDY is dropping low multiple times, none of which seem to coincide with you actually reading data

    Before you do anything, you should be able to power up the ADC, provide the clock signal, and then see DRDY pulsing at approximately 1/default data rate, which is 23.7kSPS. Do you see this occurring?

    You might also try using the discrete clock oscillator as I suggested previously, to rule out any issues with the ADC clock / crystal

    -Bryan