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.

ADS1256 spi read problems

Other Parts Discussed in Thread: ADS1256

Hello,

I'm working with an ADS1256 and arduino. I'm having what seems an odd problem(to me anyway), the First read and every other read of either data or registers results in all 1s, The remainder of reads seem to be correct.

ie if i read in the value of all the registers and print them to serial monitor byte at a time the first read results in

FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF

The second read produces:

C5
30
01
20
F0
E1
A9
FD
FF
51
17

third, same as first

fourth, same as second and the pattern repeats.

Any suggestions?

The ADS1256 is an implementation that was commercially produced on a pcb with crystal and reference circuitry et al. I'm using an arduino due.

Main code:

#include "ads1256.h"
ADS1256 ads;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  ads.begin();
}

void loop() {
  int avail = Serial.available();
  if(avail > 0)//Triggered on any serial input
  {
    Serial.print("\n");
    while(avail--) Serial.print((char)Serial.read()); //echo serial
    Serial.print("\n\n");
    ads.readRegisters();
    for(int i = 0; i < NUM_REGISTERS; i++)
    Serial.println(ads.reg[i],HEX);
  }
}

ADS1256.h:

#ifndef __ADS1256_h
#define __ADS1256_h
#include <arduino.h>

#define DRDY_PIN 25
#define CS_PIN 23

#define MISO_PIN 27
#define MOSI_PIN 26
#define SCK_PIN 24

#define RESET_PIN 22


#define XIN_FREQ 7680000

#define XIN_PER 1 / XIN_FREQ
//these define timing relationships #define WRITEINST_READDATA 75 * XIN_PER #define SCKLAST_CSHIGH 8 * XIN_PER #define WREG_DELAY 4 * XIN_PER #define RREG_DELAY 4 * XIN_PER #define SYNC_DELAY 24 * XIN_PER #define MICROSECONDS(a) a * 1000 *1000 //values are in seconds * 1000 gets millis *1000 gets micros #define ADS_WAKEUP 0b00000000 #define ADS_RDATA 0b00000001 #define ADS_RDATAC 0b00000011 #define ADS_SDATAC 0b00001111 #define ADS_SELFCAL 0b11110000 #define ADS_SELFOCAL 0b11110001 #define ADS_SELFGCAL 0b11110010 #define ADS_SYSOCAL 0b11110011 #define ADS_SYSGCAL 0b11110100 #define ADS_SYNC 0b11111100 #define ADS_STANDBY 0b11111101 #define ADS_RESET 0b11111110 #define ADS_RREG(ADDR) 0b0001 << 4 | ADDR #define ADS_WREG(ADDR) 0b0101 << 4 | ADDR enum REG_ADDR { STATUS = 0, MUX, ADCON, DRATE, IO, OFC0, OFC1, OFC2, FSC0, FSC1, FSC2, NUM_REGISTERS }; class ADS1256 { public: byte reg[NUM_REGISTERS]; void readRegisters() { shiftOut(MOSI_PIN, SCK_PIN, MSBFIRST, ADS_RREG(STATUS)); shiftOut(MOSI_PIN, SCK_PIN, MSBFIRST, NUM_REGISTERS - 1); delayMicroseconds(MICROSECONDS(WRITEINST_READDATA)); for(int i = 0; i < NUM_REGISTERS; i++) reg[i] = shiftIn(MISO_PIN, SCK_PIN, MSBFIRST); } byte readReg(byte addr) { shiftOut(MOSI_PIN, SCK_PIN, MSBFIRST, ADS_RREG(addr)); shiftOut(MOSI_PIN, SCK_PIN, MSBFIRST, 0x00); delayMicroseconds(MICROSECONDS(WRITEINST_READDATA)); byte val = shiftIn(MISO_PIN, SCK_PIN, MSBFIRST); delayMicroseconds(RREG_DELAY); return val; } void writeReg(byte addr, byte value) { shiftOut(MOSI_PIN, SCK_PIN, MSBFIRST, ADS_WREG(addr)); shiftOut(MOSI_PIN, SCK_PIN, MSBFIRST, 0x00); shiftOut(MISO_PIN, SCK_PIN, MSBFIRST, value); delayMicroseconds(WREG_DELAY); } void ADCreset(int pin) { digitalWrite(pin, LOW); delayMicroseconds(MICROSECONDS(5 * XIN_PER));//Make sure we start low for long enough //now we reset digitalWrite(pin, HIGH); delayMicroseconds(MICROSECONDS(300 * XIN_PER)); digitalWrite(pin, LOW); delayMicroseconds(MICROSECONDS(5 * XIN_PER)); digitalWrite(pin, HIGH); delayMicroseconds(MICROSECONDS(550 * XIN_PER)); digitalWrite(pin, LOW); delayMicroseconds(MICROSECONDS(5 * XIN_PER)); digitalWrite(pin, HIGH); delayMicroseconds(MICROSECONDS(1050 * XIN_PER)); digitalWrite(pin, LOW); } void begin() { pinMode(RESET_PIN, OUTPUT); digitalWrite(RESET_PIN, HIGH); pinMode(DRDY_PIN, INPUT); pinMode(CS_PIN, OUTPUT); digitalWrite(CS_PIN, LOW); pinMode(SCK_PIN, OUTPUT); digitalWrite(SCK_PIN, LOW); pinMode(MOSI_PIN, OUTPUT); digitalWrite(MOSI_PIN, HIGH); pinMode(MISO_PIN, INPUT_PULLUP); digitalWrite(RESET_PIN, LOW); delayMicroseconds(4 * XIN_PER); digitalWrite(RESET_PIN, HIGH); shiftOut(MOSI_PIN, SCK_PIN, MSBFIRST, ADS_SDATAC); while (digitalRead(DRDY_PIN == HIGH)); shiftOut(MOSI_PIN, SCK_PIN, MSBFIRST, ADS_SELFCAL); unsigned long last = micros(); while (digitalRead(DRDY_PIN == HIGH)); Serial.println(micros() - last); readRegisters(); } bool channel(int ch) { //Channel 2 is jumpered to AGND and is the defacto AINn if (ch == 2) return false; byte _ch = 0; switch (ch) { case 1: _ch = 0x01; break; case 3: _ch = 0x21; break; case 4: _ch = 0x31; break; case 5: _ch = 0x41; break; case 6: _ch = 0x51; break; case 7: _ch = 0x61; break; case 8: _ch = 0x71; break; } while (digitalRead(DRDY_PIN) == HIGH); shiftOut(MOSI_PIN, SCK_PIN, MSBFIRST, ADS_WREG(MUX)); shiftOut(MOSI_PIN, SCK_PIN, MSBFIRST, 0b00000000); //num bytes 0000 = 1, 0001 = 2, 0010 = 3, etc max 11 bytes per data sheet shiftOut(MOSI_PIN, SCK_PIN, MSBFIRST, _ch); delayMicroseconds(MICROSECONDS(WREG_DELAY)); shiftOut(MOSI_PIN, SCK_PIN, MSBFIRST, ADS_SYNC); delayMicroseconds(MICROSECONDS(SYNC_DELAY)); shiftOut(MOSI_PIN, SCK_PIN, MSBFIRST, ADS_WAKEUP); } int read() { int result = 0; while (digitalRead(DRDY_PIN) == HIGH); shiftOut(MOSI_PIN, SCK_PIN, MSBFIRST, ADS_RDATA); delayMicroseconds(MICROSECONDS(WRITEINST_READDATA)); result |= (shiftIn(MISO_PIN, SCK_PIN, MSBFIRST) << 16); result |= (shiftIn(MISO_PIN, SCK_PIN, MSBFIRST) << 8); result |= shiftIn(MISO_PIN, SCK_PIN, MSBFIRST); // result |= (this->readByte() << 16); // result |= (this->readByte() << 8); // result |= this->readByte(); result &= 0x00FFFFFF; // if(result & 0x00800000){ // result |= 0xFE000000; // } delayMicroseconds(MICROSECONDS(SCKLAST_CSHIGH)); return result; } }; #endif

  • Additional information/problems. I noted the output that looked valid was only partially valid. By starting the read command with the MUX address:

    #define ADS_RREG(ADDR)   0b00010000 | ADDR
    #define ADS_WREG(ADDR)   0b01010000 | ADDR
    
    enum REG_ADDR { STATUS = 0, MUX, ADCON, DRATE, IO, OFC0, OFC1, OFC2, FSC0, FSC1, FSC2, NUM_REGISTERS };
    void readRegisters() {
          while (digitalRead(DRDY_PIN) == LOW);
          shiftOut(MOSI_PIN, SCK_PIN, MSBFIRST, ADS_RREG(MUX));      //Read from MUX
          shiftOut(MOSI_PIN, SCK_PIN, MSBFIRST, NUM_REGISTERS - 1);  //For Num Registers 0 based
         
          delayMicroseconds(MICROSECONDS(WRITEINST_READDATA));       //50 * XIN_PER
         
          for (int i = 0; i < NUM_REGISTERS; i++)                    //Read 11 Bytes
            reg[i] = shiftIn(MISO_PIN, SCK_PIN, MSBFIRST);
    }

    I at least got the registers in the expected order, but this seems odd to me. Furthermore the first byte(STATUS register) is corrupted sometimes on reads where i don't receive all HIGH state. 

  • Hi CP Wilkinson II,

    Nothing is looking wrong to me from from your code. I'll continue to look through it in more detail though...

    Have you looked at the SPI communication with an oscilloscope or logic analyzer? If you are able to provide me with some SPI screenshots I'll be able to spot any possible issues fairly quickly.

    Best Regards,
    Chris