Reading registers weird problem

Im reading data off a ADC (ADS1256).
This results in the following data, with (hardware) ch0 connected to 3.3V, ch1 is on GND and the rest is floating:

ch0: 90702 / ch1: 5538205 / ch2: 12131 / ch3: 75446 / ch4: 77493 / ch5: 78029 / ch6: 77114 / ch7: 82250

So for some reason ch7 gets displayed as ch0, ch0 displayed as ch1 etc.

  for (i = 0; i < 8; i ++)        //Read 8 channels from ads1256
  {
    adc_val = 0;
    while (digitalRead(rdy)) {} ;
    SPI.beginTransaction(SPISettings(1250000, MSBFIRST, SPI_MODE1)); // start SPI
    delayMicroseconds(10);
    //    writereg(mux_reg, i << 4 | i + 1 );                  // differential input
    writereg(mux_reg, i << 4 | 1 << 3 );                      // not differential (p.31)
    while (digitalRead(rdy)) {} ;
    SPI.transfer(1);                                     // command for: READ DATA  (p.34)
    delayMicroseconds(10);                               // read three bytes (adc-value)
    adc_val = SPI.transfer(0) << 8;
    adc_val |= SPI.transfer(0);
    adc_val <<= 8;
    adc_val |= SPI.transfer(0);
    delayMicroseconds(10);
    SPI.endTransaction();
    Serial.print("ch");
    Serial.print(i);
    Serial.print(": ");
    Serial.print(adc_val);
    Serial.print(" / ");
    delay(10);
  }
  Serial.println();

However, if I simply fix "i" to 0 in the register:

writereg(mux_reg, 0 << 4 | 1 << 3 );

It will be read correctly as ch.0

Or I can set for (i = 0; i < 1; i ++)
And ch0 will be correct... but i want the other channels too...

Or I can set for (i = 0; i < 2; i ++)
And ch0 will be displayed as ch1 and ch1 will be displayed as ch0. So the shift starts as soon as there is more than 1 channel.

Since I print the current "i" to get the channelnumber itself... and that obvisously is zero at the first reading... why am i not getting that data on ch0 but shifted to the right as soon as I set "i < 2" or more then 2

Complete 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

    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 0x05 // = 101 = Auto-Cal, Buffer off, DRDY
#define status_data 0x07 // = 111 = Auto-Cal, Buffer on, DRDY

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

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

#define drate_reg 3
#define drate_data 0x23 // => 10 SPS (samples/secons)

#include <SPI.h>

byte i; // general use

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);
  // 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
{
  while (digitalRead(rdy)) {}  // wait for ready_line to go low

  SPI.beginTransaction(SPISettings(1250000, MSBFIRST, SPI_MODE1)); // start SPI
  // delayMicroseconds(10);
  //  SPI.transfer(0xFE);
  delayMicroseconds(100);

  SPI.transfer(0x50 | reg_num); // dataseheet p.34
  SPI.transfer(0x00);   // 2nd command byte
  SPI.transfer(data);   // write the databyte to the register
  delayMicroseconds(10);
  SPI.endTransaction();
}


void loop()
{
  long adc_val; // store reading

  for (i = 0; i < 8; i ++)        //Read 8? channels from ads1256
  {
    adc_val = 0;
    while (digitalRead(rdy)) {} ;
    SPI.beginTransaction(SPISettings(1250000, 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
    writereg(mux_reg, i << 4 | 1 << 3 );                      // 1 << 3  == 1000 -> not differential
    while (digitalRead(rdy)) {} ;
    SPI.transfer(1);                                     // command for: READ DATA  (p.34)
    delayMicroseconds(10);                               // read three bytes (adc-value)
    adc_val = SPI.transfer(0) << 8;
    adc_val |= SPI.transfer(0);
    adc_val <<= 8;
    adc_val |= SPI.transfer(0);
    delayMicroseconds(10);
    SPI.endTransaction();
    Serial.print("ch");
    Serial.print(i);
    Serial.print(": ");
    Serial.print(adc_val);
    Serial.print(" / ");
    delay(10);
  }
  Serial.println();
}

READ DATA command is 0x12 according to the datasheet.

SPI.transfer(1);            // command for: READ DATA  (p.34)

Page 34:

RDATA - Read Data - 0000 0001 (01h)

0x12 is for reading the registers, I dont see why I would want to do that.
If you have further information: Please go ahead.

MUX : Input Multiplexer Control Register (Address 01h)
Reset Value = 01h

What if your try to reset the register before pushing new bits in?

writereg(mux_reg, 0x01);//reset register
writereg(mux_reg, i << 4 | 1 << 3 );

That fixes the problem but the performance drops.
Instead of 10 SPS I only get 4 SPS. Instead of 50 SPS I get 19 SPS.

But interesting to isolate the problem some more. Further ideas?

EDIT:
If i put the reset at the end of the loop to get better performace...
ch0 and ch1 get read as the same and ch7 is not read at all.Rest with the usual shift.

Try patching the reset into the writereg function so the entire function isn't called twice

void writereg(byte reg_num, byte data) // write to a single register
{
  while (digitalRead(rdy)) {}  // wait for ready_line to go low

  SPI.beginTransaction(SPISettings(1250000, MSBFIRST, SPI_MODE1)); // start SPI
  // delayMicroseconds(10);
  //  SPI.transfer(0xFE);
  delayMicroseconds(100);

  if (reg_num == mux_reg)
  {
    SPI.transfer(0x50 | reg_num); // dataseheet p.34
    SPI.transfer(0x00);   // 2nd command byte
    SPI.transfer(0x01);   // reset command 
  }

  SPI.transfer(0x50 | reg_num); // dataseheet p.34
  SPI.transfer(0x00);   // 2nd command byte
  SPI.transfer(data);   // write the databyte to the register
  delayMicroseconds(10);
  SPI.endTransaction();
}

Still about as low performance.

EDITED:

In this library for the ADS1256, they use #define SPI_SPEED 1700000 for the SPI clock rate. From the datasheet, min SCLK period is CLKIN/4, so they assume you're using external crystal or external oscillator from 6.8 to 10MHz.

With your SPI clock rate at 1.25MHZ, I would make sure that CLKIN is in the range of 4 to 10MHz.

I'd give the library a try and use #define SPI_SPEED 1250000 in ads1256.h

Jeah, that lib... I tryed to use it, but I simply get nothing out of it. Maybe if I try around some more.

However: No change with the higher speed.

Instead of 10 SPS I only get 4 SPS. Instead of 50 SPS I get 19 SPS.

Still about as low performance.

Can you please explain more about SPS?
I see in the data sheet http://www.ti.com/lit/ds/sbas288j/sbas288j.pdf that SPS is an input--that is, is a d_rate register setting input related to the ADC conversion rate. It can only be set to fixed values. 4 and 19 are not shown on p32 of the data sheet. What are you referring to here, and how do you measure the 4 or 19? SPS would seem to be an input. "performance" would seem to be some sort of measured output.

It's indeed strange that adding three additional SPI.transfer() statements would cut performance like this.

Do you have a logic analyser you can use to see what is going on? I'd be interested to see what is gated by waiting for ready from the chip as opposed to the actual SPI data exchange.

I measured the SPS (amount of samples divided by the time it took to get them).
So when I set it to 10 SPS and have the original code I will also measure 10 SPS. When I add the reset code for the mux-register it will drop to 4 SPS or thereabout.

I have a scope and can check that way. Please specify what u want to see, 4 channels max.

re

Please specify what u want to see, 4 channels max.

That's great. It will get you CLK, MISO,MOSI, and rdy (ready on D9). You should be able to see what is slowing things down. CS is always held low so its not relevant.

Before you spend too much time with the scope, I think you want to take a look at Page 21 of the data sheet which details the most efficient way to cycle through the inputs using a SYNC and a WAKEUP command. It's also shown in the figure 19 on that page, that the data out is one command cycle displaced. The mux data offset that is confusing you may be what is correct.

The extra 3 bytes of the reset command should not be required for you to see the correct channel data. Try and implement the methods of page 21.

I tryed to measure some things now, since the wrong label was not that much of a problem.
But gues what.... the data is mixed.
So if I just read different signals on ch0 and ch1 the data is somehow mixed up to some degree.

Said reset fixes this issue.
Ill try to measure the SPI lines tomorrow if I dont get anywhere with the SYNC / WAKEUP method soon. Thank you.

After greeting
Have you found a solution