Problem with ADS1256 board

Read PM. - continue here with code and results

Hi,
The library ADS12xx.h doesn't work for me; my board haven't the pin START;

I sent this to "nchazarra".
Compare with datasheet and other libs.
The speed_setting 14MHz may be incorrect for the UNO.

/* ADS1256, datasheet: http://www.ti.com/lit/ds/sbas288j/sbas288j.pdf
compare: https://github.com/Flydroid/ADS12xx-Library/blob/master/ads12xx.cpp
    connections to Atmega328 (UNO)

    CLK  - pin 13
    DIN  - pin 11 (MOSI)
    DOUT - pin 12 (MISO)
    CS   - pin 10
    DRDY - pin 9
    RESET- pin 8 (or tie HIGH?)
    DVDD - 3V3

    Analog ch0 (input 0,1)
    Analog ch1 (input 2,3)
    Analog ch2 (input 4,5)
    (Analog ch3 (input 6,7))
*/

#define cs 10 // chip select
#define rdy 9 // data ready, input
#define rst 8 // may omit

// ** asd1256 Register map and data to write **
#define status_reg 0   // address (datasheet p. 30)
#define status_data 0x01 // default contents after reset (no need to write this)

#define mux_reg 1
//  mux_data to be changed while running, to select input ports

#define adcon_reg 2
#define adcon_data 0x24 // 0 01 00 100 => clk_out(default), sensor detect OFF, gain 16 (p.31)

#define drate_reg 3
#define drate_data 0x82 // => 100 SPS (samples/secons)

#include <SPI.h>

byte i; // general use

void setup()
{
  SPI.begin(); //start the spi-bus
  pinMode(cs, OUTPUT);
  digitalWrite(cs, LOW); // tied low is also OK.
  pinMode(rdy, INPUT);
  pinMode(rst, OUTPUT);
  Serial.begin(115200);
  digitalWrite(rst, LOW);
  delay(1); // LOW at least 4 clock cycles of onboard clock. 100 microsecons is enough
  digitalWrite(rst, HIGH); // now reset to deafult values
  delay(1); // unsure if needed
  // now set working parameters
  writereg(status_reg, status_data); // parameters defined on top
  writereg(adcon_reg, adcon_data);
  writereg(drate_reg, drate_data);
}

void writereg(byte reg_num, byte data) // write to a single register
{
  // digitalWrite(cs, LOW);
  while (rdy) {}  // wait for ready_line to go low
  SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE1)); // start SPI
  delayMicroseconds(10);
  SPI.transfer(0x50 | reg_num); // dataseheet p.34
  SPI.transfer(0x00);   // 2nd command byte
  SPI.transfer(data);   // write tge databyte to the register
  delayMicroseconds(10);
  SPI.endTransaction();
  // digitalWrite(cs, HIGH);
}

byte readreg(byte reg_num)  // read from a single register
{
  // digitalWrite(cs, LOW);  // cs is tied low for now? Theese two lines may be added if other components uses SPI-bus
  while (rdy) {}  // wait for ready_line to go low
  SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE1)); // start SPI
  byte bufr;
  while (rdy) {}  // wait for ready_line to go low
  delayMicroseconds(10);
  SPI.transfer(0x10 | reg_num); // send 1st command byte, address of the register
  SPI.transfer(0);  // one byte only
  delayMicroseconds(10);
  bufr = SPI.transfer(0xff); // read data from register (dummy parameter)
  delayMicroseconds(10);
  SPI.endTransaction();
  // digitalWrite(cs, HIGH);
  return bufr;
}

void loop()
{
  long adc_val; // store reading
  //Read 4 channels from ads1256
  for (i = 0; i < 5; i += 2)
  {
    // digitalWrite(cs, LOW);
    adc_val = 0;
    while (rdy) {} ;
    // send command - select ADC-channel 0000 0001 / 0010 0011 / 0100 0101
    SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE1)); // start SPI
    delayMicroseconds(10);
    writereg(mux_reg, i << 4 | i + 1 ); // positive to analog 0,2,4,6, Neg to 1,3,5,7
    while (rdy) {} ;
    SPI.transfer(1); // command for: READ DATA  (p.34)
    delayMicroseconds(10);// read three bytes (adc-value)
    adc_val = SPI.transfer(0)<<8;
    //delayMicroseconds(10); // needed ?
    adc_val |= SPI.transfer(0);
    //delayMicroseconds(10); // ??
    adc_val <<= 8;
    adc_val |= SPI.transfer(0);
    delayMicroseconds(10);
    // digitalWrite(_CS, HIGH);
    SPI.endTransaction();
    Serial.print(adc_val);
    Serial.print(" / ");
    // digitalWrite(cs, HIGH);
  }
  Serial.println();
}

Hi,

I have the same board in the picture of the first post and I am trying to make this last code work.

I am puzzled a bit by it.
First, I thing that the while(rdy) should really be while (digitalRead(rdy)).
Second, I don't understand the for loop.
It says it wants to read 4 channels, but it iterates only 3 times and I don't know why exactly that choice of values..

Can you make it a bit more explicit?

Thanks!

Thanks..

First, I thing that the while(rdy) should really be while (digitalRead(rdy)).

Of course it shall be..

If you read the compete post, u'll se that OP has only 3 channels used.
I have never seen that sensor, but belive that the code may be a good start..

Knut

Thanks Knut.

I am reading the data sheet and the code is starting to make sense now.

In my case I need to convert a single-ended input, not a differential input.
As far as I understand it, I need to set the multiplex register to 8, which means selecting:
0000 (AIN0) 1000 (AINCOM)

I am not sure if I have got this right.

BTW, there is no AINCOM pin on the board, which makes me think that it is tied to some reference.

With the code as it is now, I get very unstable readings.

Here's an example of readings with AIN0 put to VCC (5V in my case):

16777198
16776701
16777200
0
0
16777200
16777200
16777199
16777202
16776701
16776701
16777200
16777200
0
8388608
16776701
16777198
0
8388608

any suggestion is more than welcome!

AINCOM = Analog Common => reference voltage for ALL inputs

If you've got max 4 analog values to read, you can use the differental setting. This allows for separate ref. voltage for all 4 inputs

A close look at your reading:
chech the binary pattern. compare with 2s compl. zero is 2^23

Guys,

I think I've got it working!!

It's been a hard work of reverse engineering from different sources, schematics, and chinese strange documentations.

I am now finally able to measure the voltage at AIN0 (no differential, just voltage between 0 and 5V). The main problem with Knut's code was the SPI speed, it is way too high, I have brought it down to 1.2 MHz. Also, you need to do the 2's complement of the measured value.

I have done some tests with potentiometers and the values make sense.

Some things I have discovered:

  • I think that the second row of pins, close to the AINx pins is the AINCOM. I don't know how to use it really, so I am leaving it floating.
  • The DVDD and DGND pins should be connected to GND and 3.3V, but if you leave them floating it also seem to work.

Here's the code:

/* ADS1256, datasheet: http://www.ti.com/lit/ds/sbas288j/sbas288j.pdf
  compare: https://github.com/Flydroid/ADS12xx-Library/blob/master/ads12xx.cpp
    connections to Atmega328 (UNO)

    CLK  - pin 13
    DIN  - pin 11 (MOSI)
    DOUT - pin 12 (MISO)
    CS   - pin 10
    DRDY - pin 9
    RESET- pin 8 (or tie HIGH?)
    DVDD - 3V3
    DGND - GND
*/

#define cs 10 // chip select
#define rdy 9 // data ready, input
#define rst 8 // may omit

#define SPISPEED 1250000
              // 1700000

#include <SPI.h>

void setup()
{
  Serial.begin(115200);
  
  pinMode(cs, OUTPUT);
  digitalWrite(cs, LOW); // tied low is also OK.
  pinMode(rdy, INPUT);
  pinMode(rst, OUTPUT);
  digitalWrite(rst, LOW);
  delay(1); // LOW at least 4 clock cycles of onboard clock. 100 microsecons is enough
  digitalWrite(rst, HIGH); // now reset to deafult values
  
  delay(500);
  SPI.begin(); //start the spi-bus
  delay(500);

  //init

  // digitalWrite(cs, LOW);
  while (digitalRead(rdy)) {}  // wait for ready_line to go low
  SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE1)); // start SPI
  delayMicroseconds(10);

  //Reset to Power-Up Values (FEh)
  SPI.transfer(0xFE);
  delayMicroseconds(100);
  
  byte status_reg = 0 ;  // address (datasheet p. 30)
  //PGA SETTING
  //1 ±5V
  //2 ±2.5V
  //4 ±1.25V
  //8 ±0.625V
  //16 ±312.5mV
  //32 ±156.25mV
  //64 ±78.125mV
  byte status_data = 0x01; //status: Most Significant Bit First, Auto-Calibration Disabled, Analog Input Buffer Disabled 
  SPI.transfer(0x50 | status_reg);
  SPI.transfer(0x00);   // 2nd command byte, write one register only
  SPI.transfer(status_data);   // write the databyte to the register
  delayMicroseconds(10);
  

  byte adcon_reg = 2; //A/D Control Register (Address 02h)
  byte adcon_data = 0x20; // 0 01 00 000 => Clock Out Frequency = fCLKIN, Sensor Detect OFF, gain 1
  SPI.transfer(0x50 | adcon_reg);
  SPI.transfer(0x00);   // 2nd command byte, write one register only
  SPI.transfer(adcon_data);   // write the databyte to the register
  delayMicroseconds(10);
  
// digitalWrite(cs, HIGH);
  
  Serial.println("configured, starting");
}


void loop()
{
  unsigned long adc_val =0; // store reading

  // digitalWrite(cs, LOW);
  SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE1)); // start SPI
  delayMicroseconds(10);
  //The most efficient way to cycle through the inputs is to
  //change the multiplexer setting (using a WREG command
  //to the multiplexer register MUX) immediately after DRDY
  //goes low. Then, after changing the multiplexer, restart the
  //conversion process by issuing the SYNC and WAKEUP
  //commands, and retrieve the data with the RDATA
  //command. 
  while (digitalRead(rdy)) {} ;

  byte channel = 0;
  byte data = (channel << 4) | (1 << 3); //AIN-channel and AINCOM
  SPI.transfer(0x50 | 1); // MUX register
  SPI.transfer(0x00);   // 2nd command byte, write one register only
  SPI.transfer(data);   // write the databyte to the register
  delayMicroseconds(10);

  //SYNC command 1111 1100
  SPI.transfer(0xFC);
  delayMicroseconds(10);
  
  //WAKEUP 0000 0000
  SPI.transfer(0x00);
  delayMicroseconds(10);
    
  SPI.transfer(0x01); // Read Data 0000  0001 (01h)
  delayMicroseconds(10);
  
  adc_val = SPI.transfer(0);
  adc_val <<= 8; //shift to left
  adc_val |= SPI.transfer(0);
  adc_val <<= 8;
  adc_val |= SPI.transfer(0);
  
  delayMicroseconds(10);
  
  // digitalWrite(cs, HIGH);
  SPI.endTransaction();

  //The ADS1255/6 output 24 bits of data in Binary Two’s
  //Complement format. The LSB has a weight of
  //2VREF/(PGA(223 − 1)). A positive full-scale input produces
  //an output code of 7FFFFFh and the negative full-scale
  //input produces an output code of 800000h. 
  if(adc_val > 0x7fffff){ //if MSB == 1
    adc_val = (16777215ul - adc_val) + 1; //do 2's complement
  }
  Serial.println(adc_val);

  delay(500);
  // digitalWrite(cs, HIGH);
}

Nice ! I'm sure others will be very happy when u upload your final library .. to github ?

Hi dariosalvi,

I tried your example and it is not clear what is the sampling rate you use?

Thanks,

So I got the code from pafe 1 to spit out some numbers too, but its messed up a lot.
dariosalvis code seems to be right so far.

But how to set the options like PGA, sample rate, buffer etc.?
And how to read the register map?

Hello,

I have created a nicer code, a sort of library, but does not include all the functionalities of the chip.

I have uploaded it on this gist.
Feel free to fork it and improve it!

Do you have a circuit diagram for this?

I am using your code, but I keep on reading 0's, so it could be a hardware wiring problem.

Thanks

Hello Everyone,

I am trying to interface High Precision DA/AD board ADS1256 with Arduino. The code I have taken from library. Actually I am able to read the data but the thing is I am not able to understand the settling time thing and How much settling time I should provide for each command. and also How do I figure what frequency and PGA to be set to read the data?

Thanks

Hi!

Using an ADS1255 (basically the same IC as ADS1256) and dariosalvi code got my ADS1255 working (btw the sample code was missing "SPI.endTransaction();" at the end of the setup).

I've adapted the code a bit to match my setup and configured one more register (DRATE) in order to make sure the ADC is working at it's full 30kSPS potential and the results I'm getting are quite chaotic, making no sense at all:

72655
2966232813
3436158698
255799543
3473817828
534761477
3506425644
1627348985
4257216639
28320544
548220649
3772690109
3792572396
282054638
1610440670
268468467
64021071
1374023375
3174706
4043223809
95399897
871358517
1325613092
1325416659
4267691519

Does anyone know what's the problem?

Here is my code

#include <SPI.h>
#define SPISPEED 1250000

#define SCK   14
#define MOSI  12
#define MISO  27
#define DRDY  26
#define CS 5

#define WREG  0x50
#define RDATA 0x01


void setup()
{
  Serial.begin(2000000);

  pinMode(MISO, INPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(SCK, OUTPUT);
  pinMode(CS, OUTPUT);
  SPI.begin(SCK, MISO, MOSI, CS); //start the spi-bus
  delay(1); // LOW at least 4 clock cycles of onboard clock. 100 microsecons is enough

  pinMode(DRDY, INPUT);

  while (digitalRead(DRDY)) {}  // wait for ready_line to go low

  SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE1)); // start SPI
  //  Reset to Power-Up Values (FEh)
  SPI.transfer(0xFE);
  delayMicroseconds(100);

  //PGA SETTING
  //1 ±5V
  //2 ±2.5V
  //4 ±1.25V
  //8 ±0.625V
  //16 ±312.5mV
  //32 ±156.25mV
  //64 ±78.125mV

  byte status_reg = 0x00;  // address (datasheet p. 30)
  byte status_data = 0B0000001;
  //000 0 0 0 1
  //000 - Factory programmed Identification Bits
  //0 - set MSB transfer
  //0 - Auto-Calibration Disabled
  //0 - Buffer Disabled
  //1 - duplicates state of DRDY pin
  SPI.transfer(WREG | status_reg);
  SPI.transfer(0x00);   // 2nd command byte, write one register only
  SPI.transfer(status_data);   // write the databyte to the register
  delayMicroseconds(10);


  byte adcon_reg = 0x02; //A/D Control Register (Address 02h)
  byte adcon_data = 0B00000000;
  // 0 00 00 000
  // 0 reserved always 0
  // 00 - Clock Out off
  // 00 - Sensor Detec off
  // 000 - PGA gain = 1
  SPI.transfer(WREG | adcon_reg);
  SPI.transfer(0x00);   // 2nd command byte, write one register only
  SPI.transfer(adcon_data);   // write the databyte to the register
  delayMicroseconds(10);



  byte drate_reg = 3; //data rate register address: 0x3h
  byte drate_data = 0B00000011;
  // 11110000
  //set data rate to max. (30000 SPS)
  SPI.transfer(WREG | drate_reg);
  SPI.transfer(0x00);   // 2nd command byte, write one register only
  SPI.transfer(drate_data);   // write the databyte to the register
  delayMicroseconds(10);



  byte mux_reg = 0x01; //Mux Register (Address 01h)
  byte mux_data = 0B00001111;
  // 0000 1111
  // 0000 - AIN0 (default)
  // 1111 - AINCOM
  SPI.transfer(WREG | mux_reg); // MUX register
  SPI.transfer(0x00);   // 2nd command byte, write one register only
  SPI.transfer(mux_data);   // write the databyte to the register
  delayMicroseconds(10);

  //SYNC command 1111 1100
  SPI.transfer(0xFC);
  delayMicroseconds(10);

  //WAKEUP 0000 0000
  SPI.transfer(0x00);
  delayMicroseconds(10);


  SPI.endTransaction();

  Serial.println("configured, starting");
}


void loop()
{
  unsigned long adc_val = 0; // store reading

  while (digitalRead(DRDY)) {} ;

  SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE1)); // start SPI
  SPI.transfer(RDATA); // Read Data 0000  0001 (01h)
  // delayMicroseconds(10);

  adc_val = SPI.transfer(0xff);  //0xff is a dummy
  adc_val |= (uint32_t)SPI.transfer(0xff) << 8;
  adc_val |= (uint32_t)SPI.transfer(0xff) << 16;
  adc_val |= (uint32_t)SPI.transfer(0xff) << 24;
  SPI.endTransaction();

  //The ADS1255/6 output 24 bits of data in Binary Two's
  //Complement format. The LSB has a weight of
  //2VREF/(PGA(223 − 1)). A positive full-scale input produces
  //an output code of 7FFFFFh and the negative full-scale
  //input produces an output code of 800000h.
  if (adc_val > 0x7fffff) { //if MSB == 1
    adc_val = (16777215ul - adc_val) + 1; //do 2's complement
  }
  Serial.println(adc_val);
}

And the schematic that I use for ADS1255
ADS1255-schematic

Taking a closer look at the datasheet (pg.34) it appears that reading data (in normal reading mode, NOT continuous) requires a settling time t6, hence the " delayMicroseconds(10);" in the original code.

Since I'm after the full 30kSPS data rate, I had to switch to continuous data read mode. using the RDATAC data.(pg.35)
Doing so results in a much higher sample rate that using the first method (posted by dariosalvi). However, once every few samples I get something like a glitch. The output jumps a lot from the normal value.

3313369
3314035
3312667
3313295
3312179
3312508
3312664
3312524
3311696
3311673
3312522
3313006
3313290
3289740
3310820
3311046
7762803
3313255
3312941
7829987
3311065
3311739
3311361
3312014
3312525
3312074
3312182
3313031
3310790
3313129
3313799
3310754
3311421
3289738
3311678
3312615
7697909
3312487
3312331
7632141
3313081

As you can see there are some samples of around ~7600000 that shouldn't be there.
Any idea why?

The code I use is the following (ignore the op-amp setup in the first part of setup() )

#include <AD8555.h>
#include <SPI.h>

#define SCK   14
#define MOSI  12
#define MISO  27
#define DRDY  26
#define CS 5

#define SPISPEED 1900000
// 1700000

unsigned long adc_val = 0; // store reading

int outpin = 19;
AD8555 opamp(outpin);

void setup()
{
  Serial.begin(2000000);

  //Start----------------Op-Amp setup--------------------

  // get Second Stage Gain code

  Serial.println("Input Second Stage Gain code (0..7)");
  // wait for user to enter value
  while (!Serial.available());

  // set Second Stage Gain code
  if (!opamp.setSecondStageGain(Serial.parseInt())) {
    // opamp will return false if code is out of range
    Serial.println("Invalid Second Stage Gain code. Valid range is 0..7");
    return;
  }


  // First Stage Gain code
  Serial.println("Input First Stage Gain code (0..127)");
  while (!Serial.available());

  if (!opamp.setFirstStageGain(Serial.parseInt())) {
    Serial.println("Invalid First Stage Gain code. Valid range is 0..127");
    return;
  }


  // Offset code
  Serial.println("Input Offset code (0..255)");
  while (!Serial.available());
  if (!opamp.setOffset(Serial.parseInt())) {
    Serial.println("Invalid Offset code. Valid range is 0..255");
    return;
  }

  // Programming mode
  Serial.println("Choose programming mode: Enter \"0\" for simulation, \"1\" for permanent programming");

  while (!Serial.available());
  int mode = Serial.parseInt();
  if (mode == 0) {
    // simulation mode
    opamp.simulate();
    Serial.println("Done!");
  } else if (mode == 1) {
    // permanent programming mode
    Serial.println("Make sure to meet programming requirements described in AD8555 datasheet:");
    Serial.println("- A 5.5 V supply is required");
    Serial.println("- The power supply must be able to deliver 250 mA of current");
    Serial.println("- At least 0.1 uF of decoupling capacitance is needed across the power pins of the device");

    Serial.println("\nWARNING: This operation can not be undone, all programming values are permanent");
    Serial.println("Continue? [y/N]");

    while (!Serial.available());
    if (Serial.read() == 'y') {
      opamp.program();
      Serial.println("Programming... done");
    } else {
      Serial.println("Operation canceled");
    }
  }

  //Finish----------------Op-Amp setup--------------------


  pinMode(MISO, INPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(SCK, OUTPUT);
  pinMode(CS, OUTPUT);
  delay(1); // LOW at least 4 clock cycles of onboard clock. 100 microsecons is enough

  pinMode(DRDY, INPUT);
  delay(500);
  SPI.begin(SCK, MISO, MOSI, CS); //start the spi-bus
  delay(500);

  //init

  // digitalWrite(cs, LOW);
  while (digitalRead(DRDY)) {}  // wait for ready_line to go low
  SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE1)); // start SPI
  delayMicroseconds(10);

  //Reset to Power-Up Values (FEh)
  SPI.transfer(0xFE);
  delayMicroseconds(100);

  SPI.endTransaction();

  while (digitalRead(DRDY)) {}  // wait for ready_line to go low
  SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE1)); // start SPI

  byte status_reg = 0 ;  // address (datasheet p. 30)
  //PGA SETTING
  //1 ±5V
  //2 ±2.5V
  //4 ±1.25V
  //8 ±0.625V
  //16 ±312.5mV
  //32 ±156.25mV
  //64 ±78.125mV
  byte status_data = 0x01; //status: Most Significant Bit First, Auto-Calibration Disabled, Analog Input Buffer Disabled
  SPI.transfer(0x50 | status_reg);
  SPI.transfer(0x00);   // 2nd command byte, write one register only
  SPI.transfer(status_data);   // write the databyte to the register
  delayMicroseconds(10);


  byte adcon_reg = 2; //A/D Control Register (Address 02h)
  byte adcon_data = 0x20; // 0 01 00 000 => Clock Out Frequency = fCLKIN, Sensor Detect OFF, gain 1
  SPI.transfer(0x50 | adcon_reg);
  SPI.transfer(0x00);   // 2nd command byte, write one register only
  SPI.transfer(adcon_data);   // write the databyte to the register
  delayMicroseconds(10);

  byte channel = 0;
  byte data = (channel << 4) | (1 << 3); //AIN-channel and AINCOM
  SPI.transfer(0x50 | 1); // MUX register
  SPI.transfer(0x00);   // 2nd command byte, write one register only
  SPI.transfer(data);   // write the databyte to the register
  delayMicroseconds(10);


  //SYNC command 1111 1100
  SPI.transfer(0xFC);
  delayMicroseconds(10);

  //WAKEUP 0000 0000
  SPI.transfer(0x00);
  delayMicroseconds(10);

  SPI.endTransaction();

  while (digitalRead(DRDY)) {}  // wait for ready_line to go low
  SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE1)); // start SPI
  
  SPI.transfer(0x03); // Read Data Continuous command 0000  0011 (03h)
  delayMicroseconds(10);
  
  SPI.endTransaction();


  Serial.println("configured, starting");
}


void loop()
{
  //The most efficient way to cycle through the inputs is to
  //change the multiplexer setting (using a WREG command
  //to the multiplexer register MUX) immediately after DRDY
  //goes low. Then, after changing the multiplexer, restart the
  //conversion process by issuing the SYNC and WAKEUP
  //commands, and retrieve the data with the RDATA
  //command.
  
  while (digitalRead(DRDY)) {} ;
  SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE1)); // start SPI
  //while (millis() - start_time < 1000) {
  adc_val = SPI.transfer(0);
  adc_val <<= 8; //shift to left
  adc_val |= SPI.transfer(0);
  adc_val <<= 8;
  adc_val |= SPI.transfer(0);
  SPI.endTransaction();
  
  //The ADS1255/6 output 24 bits of data in Binary Two's
  //Complement format. The LSB has a weight of
  //2VREF/(PGA(223 − 1)). A positive full-scale input produces
  //an output code of 7FFFFFh and the negative full-scale
  //input produces an output code of 800000h.
  if (adc_val > 0x7fffff) { //if MSB == 1
    adc_val = (16777215ul - adc_val) + 1; //do 2's complement
  }
  Serial.println(adc_val);
}

Could someone please explain to me what am I missing when setting up the registers of an ADS1255 ADC?
The setup fails every time. When I read back from the registers (after setting the up) I get back a totally different value from the one that I set up.

STATUS register values: 
Received: 11111111

ADCON register values: 
Expected: 0
Received: 11111111

DRATE register values: 
Expected: 11110000
Received: 11111111

MUX register values: 
Expected: 1111
Received: 11111111

Code belllow:

#include <SPI.h>

//ADC hook-up lines
#define SCK   14
#define MOSI  12
#define MISO  27
#define DRDY  26
#define CS 5

//SPI bus settings
#define SPISPEED 1800000
#define CLKIN 7680000 //7.68MHz (external crystal frequency)

//ADC commands
#define WREG    0x50
#define RDATA   0x01
#define RDATAC  0x03
#define RREG    0x10
#define SDATAC  0x0F

//enable stuff
#define ENABLE_VERBOSE_OUTPUT 1

/*
   According to datasheet pg.26
   ---------------------------------
   The data input pin (DIN) is used along with SCLK to send
   data to the ADS1255/6. The data output pin (DOUT) along
   with SCLK is used to read data from the ADS1255/6.
   Data on DIN is shifted into the part on the falling edge of SCLK
   while data is shifted out on DOUT on the rising edge of SCLK.
   DOUT is high impedance when not in use to allow
   DIN and DOUT to be connected together and be driven by
   a bi-directional bus. Note: the RDATAC command must
   not be issued while DIN and DOUT are connected
   together.
*/
#define SPI_DATAIN_MODE SPI_MODE0 //DIN shifted out on the falling edge of SCLK
#define SPI_DATAOUT_MODE   SPI_MODE1 //DOUT shifted out on the rising edge of SCLK

//ADC related
signed long raw;
byte adcData[3];
bool ok = false;
byte register_values;

//according to datasheet of ADC pg.6 t6 should be at leas 50 time CLKIN (master clock) period
int t6 = round((float)1 / CLKIN * 50 * 1000000) + 1; //*1000000 to convert from seconds to us

void setup() {
  Serial.begin(2000000);

  //SPI pins
  pinMode(MISO, INPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(SCK, OUTPUT);
  pinMode(CS, OUTPUT);
  pinMode(DRDY, INPUT);

  //init SPI bus
  delay(500);
  SPI.begin(SCK, MISO, MOSI, CS); //start the spi-bus
  delay(500);

  /*
     ADC setup
  */
  while (digitalRead(DRDY)) {}  // wait for ready_line to go low

  SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings

  //Reset to Power-Up Values (FEh)
  SPI.transfer(0xFE);
  SPI.endTransaction();
  delayMicroseconds(100);

  while (digitalRead(DRDY)) {}  // wait for ready_line to go low

  statusRegister_setup();
  adconRegister_setup();
  drateRegister_setup();
  muxRegister_setup();
  
  SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
  
  //SYNC command 1111 1100
  SPI.transfer(0xFC);
  delayMicroseconds(10);
  
  //WAKEUP 0000 0000
  SPI.transfer(0x00);
  delayMicroseconds(10);

  SPI.endTransaction();

}

void loop() {
  // put your main code here, to run repeatedly:

}
void muxRegister_setup() {
  /*
     MUX REGISTER SETUP
  */
  byte mux_reg = 0x01; //Mux Register (Address 01h)

  byte mux_data = 0B00001111;
  //chose the 2 inputs for your differential signal
  // 0000 1111
  // 0000 - AIN0 (default)
  // 1111 - AINCOM

  SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
  SPI.transfer(WREG | mux_reg); // MUX register
  SPI.transfer(0x00);   // 2nd command byte, write one register only
  SPI.transfer(mux_data);   // write the databyte to the register
  SPI.endTransaction();

  delayMicroseconds(10); //allow a delay between DIN and DOUT section


  if (ENABLE_VERBOSE_OUTPUT) {
    Serial.println("\nMUX register values: ");

    register_values = 0;
    SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
    SPI.transfer(RREG | mux_reg);
    SPI.transfer(0x00);   // 2nd command byte, read one register only
    SPI.endTransaction();

    delayMicroseconds(t6); // a delay of t6 must occur between RREG and data shifted out

    SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAOUT_MODE));
    register_values = SPI.transfer(0);
    SPI.endTransaction();

    Serial.print("Expected: ");
    Serial.println(mux_data, BIN);
    Serial.print("Received: ");
    Serial.println(register_values, BIN);
  }
}
void drateRegister_setup() {
  /*
     DRATE REGISTER SETUP
  */
  byte drate_reg = 0x03; //data rate register address: 0x03

  byte maxSampleRate = 0B11110000;
  //set data rate to max. (30000 SPS)
  byte minSampleRate = 0B00000011;
  //set data rate to min. (2.5SPS SPS)

  byte chosenRate = maxSampleRate;

  SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
  SPI.transfer(WREG | drate_reg);
  SPI.transfer(0x00);   // 2nd command byte, write one register only
  SPI.transfer(chosenRate);   // write the databyte to the register
  SPI.endTransaction();

  delayMicroseconds(10); //allow a delay between DIN and DOUT section


  if (ENABLE_VERBOSE_OUTPUT) {
    Serial.println("\nDRATE register values: ");

    register_values = 0;
    SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
    SPI.transfer(RREG | drate_reg);
    SPI.transfer(0x00);   // 2nd command byte, read one register only
    SPI.endTransaction();

    delayMicroseconds(t6); // a delay of t6 must occur between RREG and data shifted out

    SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAOUT_MODE));
    register_values = SPI.transfer(0);
    SPI.endTransaction();

    Serial.print("Expected: ");
    Serial.println(chosenRate, BIN);
    Serial.print("Received: ");
    Serial.println(register_values, BIN);
  }
}
void adconRegister_setup() {
  /*
     ADCON REGISTER SETUP
  */
  byte adcon_reg = 0x02; //A/D Control Register address: 0x02

  byte adcon_data = 0B00000000;
  // 0 00 00 000
  // 0 reserved always 0
  // 00 - Clock Out off
  // 00 - Sensor Detec off
  // 000 - PGA gain = 1

  //PGA SETTING
  //1 ±5V
  //2 ±2.5V
  //4 ±1.25V
  //8 ±0.625V
  //16 ±312.5mV
  //32 ±156.25mV
  //64 ±78.125mV

  SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
  SPI.transfer(WREG | adcon_reg);
  SPI.transfer(0x00);   // 2nd command byte, write one register only
  SPI.transfer(adcon_data);   // write the databyte to the register
  SPI.endTransaction();

  delayMicroseconds(10); //allow a delay between DIN and DOUT section


  if (ENABLE_VERBOSE_OUTPUT) {
    Serial.println("\nADCON register values: ");

    register_values = 0;
    SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
    SPI.transfer(RREG | adcon_reg);
    SPI.transfer(0x00);   // 2nd command byte, read one register only
    SPI.endTransaction();

    delayMicroseconds(t6); // a delay of t6 must occur between RREG and data shifted out

    SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAOUT_MODE));
    register_values = SPI.transfer(0);
    SPI.endTransaction();

    Serial.print("Expected: ");
    Serial.println(adcon_data, BIN);
    Serial.print("Received: ");
    Serial.println(register_values, BIN);
  }
}
void statusRegister_setup() {
  /*
     STATUS REGISTER SETUP
  */
  byte status_reg = 0x00;  // address of status reg (datasheet p. 30)

  byte status_data = 0B0000001;
  //000 0 0 0 1
  //000 - Factory programmed Identification Bits
  //0 - set MSB transfer
  //0 - Auto-Calibration Disabled
  //0 - Buffer Disabled
  //1 - duplicates state of DRDY pin

  SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
  SPI.transfer(WREG | status_reg);
  SPI.transfer(0x00);   // 2nd command byte, write one register only
  SPI.transfer(status_data);   // write the databyte to the register
  SPI.endTransaction();

  delayMicroseconds(10); //allow a delay between DIN and DOUT section

  if (ENABLE_VERBOSE_OUTPUT) {
    Serial.println("\nSTATUS register values: ");

    register_values = 0;
    SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
    SPI.transfer(RREG | status_reg);
    SPI.transfer(0x00);   // 2nd command byte, read one register only
    SPI.endTransaction();

    delayMicroseconds(t6); // a delay of t6 must occur between RREG and data shifted out

    SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAOUT_MODE));
    register_values = SPI.transfer(0);
    SPI.endTransaction();

    Serial.print("Received: ");
    Serial.println(register_values, BIN);
  }
}

Hello,

i got out only zero and i check all input on ADS1256
and i have error if i have on this line SPI.begin(SCK, MISO, MOSI, CS); //start the spi-bus

and where to connect Reset and PDWN pin?

Greatings Matej

Moder10:
Hello,

i got out only zero and i check all input on ADS1256
and i have error if i have on this line SPI.begin(SCK, MISO, MOSI, CS); //start the spi-bus

and where to connect Reset and PDWN pin?

Greatings Matej

Reset can be connected to pin 8 or HIGH(3.3 V) and PDWN to HIGH(3.3 V)