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.

ADS1218: Data Reading Problem

Part Number: ADS1218

Hi,

I am trying to configure my ADS1218 with arduino board. I am using following setting:

AVCC = 5 v

Unipolar

Decimation 1920

Digital filter SINC3

I perform calibration with buffer off and turn it on after calibration.

I am applying 1.3 Vdc on channel Ain0 and Ain1 by setting the MUX to 0x01, fMOD = 9600 hz

Problem is that after calibration I read 0.00 all the time regardless of input which I can vary from 0 to 2 volts.

If I use it without calibration I get 2.5 V all the time regardless of input which I can vary from 0 to 2 volts.

Here is my code:

/**************************************************************
  Aalto_ADS1218.ino
  this example gives differential voltage across the AN0 And AN1 in uV
  Hooking-up with the Arduino
  |ADS1218 pin label| Pin Function         |Arduino Connection|
  |-----------------|:--------------------:|-----------------:|
  | DRDY            | Data ready Output pin|  D6              |
  | MISO            | Slave Out            |  D12             |
  | MOSI            | Slave In             |  D11             |
  | SCLK            | Serial Clock         |  D13             |
  | CS              | Chip Select          |  D7              |
  | DVDD            | Digital VDD          |  +5V             |
  | DGND            | Digital Gnd          |  Gnd             |
  | AN0-AN3         | Analog Input         |  Analog Input    |
  | AVDD            | Analog VDD           |  -               |
  | AGND            | Analog Gnd           |  -               |
*************************************************************/

#include <SPI.h>


#define SPI_MASTER_DUMMY 0xff
#define RESET 0x06                                                    //Send the RESET command (06h) to make sure the ADS1220 is properly reset after power-up
#define START 0x08                                         //Send the START/SYNC command (08h) to start converting in continuous conversion mode

// define the ads1218 command
#define RDATA 0x01    // read the latest ad conversion data
#define RDATAC 0x03   // continuously read the converted data
#define STOPC 0x0F    // Stop continuous read mode
#define RREG 0x10     // Two-byte command to read register contents First byte: bit3-bit0 = 0-16;
#define RRAM 0x20     // two-byte command to read the contents of the first byte ram: bit3-bit0 = 0-16;
#define CREG 0x40     // copy the contents of the register to the specified ram bank, the lower three bits specify the ram page address
#define CREGA 0x48    // copy the contents of the register into all ram banks.
#define WREG 0x50     // 2 byte command, write data to register 0-15
#define WRAM 0x60     // 2 bytes instruction, write data to 128 bytes in ram
#define RF2R 0x80     // read the data of the specified FLASH page into 128 bytes of RAM
#define WR2F 0xA0     // Write the data in ram to the specified FLASH page
#define CRAM 0xC0     // Copy the selected ram data into the configuration register, which will overwrite the current working register contents
#define CSRAMX 0xD0   // Calculate the checksum in the specified page ram, do not include ID, DRDY DIO
#define CSARAMX 0xD8  // Calculate the checksum in all rams, do not include ID, DRDY DIO
#define CSREG 0xDF    // Calculate the checksum of the configuration register
#define CSRAM 0xE0    // Calculates the checksum in the specified page ram, containing all bits
#define CSARAM 0xE8   // Calculates the checksum in all rams, containing all bits
#define CSFL 0xEC     // Calculate the checksum in all FLASH, including all bits
#define SELFCAL 0xF0  // Offset and gain self-calibration
#define SELFOCAL 0xF1 // offset self-calibration
#define SELFGCAL 0xF2 // gain self-calibration
#define SYSOCAL 0xF3  // System Offset Calibration
#define SYSGCAL 0xF4  // System Gain Calibration
#define DSYNC 0xFC    // Sync DRDY
#define SLEEP 0xFD    // sleep mode
#define RESET 0xFE    // reset the register to the power of the data, stop the continuous read mode, does not affect the ram data

// define the ads1218 register Addresses
#define SETUP_REG_ADRS 0x00
#define MUX_REG_ADRS 0x01
#define ACR_REG_ADRS 0x02
#define IDAC1_REG_ADRS 0x03
#define IDAC2_REG_ADRS 0x04
#define ODAC_REG_ADRS 0x05
#define DIO_REG_ADRS 0x06
#define DIR_REG_ADRS 0x07
#define DEC0_REG_ADRS 0x08
#define DEC1_REG_ADRS 0x09
#define OCR0_REG_ADRS 0x0A
#define OCR1_REG_ADRS 0x0B
#define OCR2_REG_ADRS 0x0C
#define FSR0_REG_ADRS 0x0D
#define FSR1_REG_ADRS 0x0E
#define FSR2_REG_ADRS 0x0F



#define ADS1218_CS_PIN 7
#define ADS1218_DRDY_PIN 6


void writeRegister(uint8_t address, uint8_t value)
{
  uint8_t numReg = 0x01;
  noInterrupts();
  digitalWrite(ADS1218_CS_PIN, LOW);
//  delayMicroseconds(500);
  SPI.transfer(WREG | address);
  SPI.transfer(numReg);
  SPI.transfer(value);
//  delayMicroseconds(500);
  digitalWrite(ADS1218_CS_PIN, HIGH);
  interrupts();
}

uint8_t readRegister(uint8_t address)
{
  uint8_t data;
  uint8_t numReg = 0x01;
  noInterrupts();
  digitalWrite(ADS1218_CS_PIN, LOW);
//  delayMicroseconds(500);
  SPI.transfer(RREG | address);
  SPI.transfer(numReg);
  delayMicroseconds(20);       // delay of 10 uS needed
  data = SPI.transfer(SPI_MASTER_DUMMY);
//  delayMicroseconds(500);
  digitalWrite(ADS1218_CS_PIN, HIGH);
  interrupts();
  return data;
}


void printAllreg(void)
{
  int read_data0;
  for (int i = 0; i <= 15; i++) {
    read_data0 = readRegister(i);
    Serial.println(read_data0, HEX);
    delay(10);
  }
}

void SendSELFCALCommand(void)
{
  noInterrupts();
  digitalWrite(ADS1218_CS_PIN, LOW);
  delayMicroseconds(500);
  SPI.transfer(SELFCAL);
  delayMicroseconds(500);
  digitalWrite(ADS1218_CS_PIN, HIGH);
  interrupts();
  delay(2000);

}

void syncSerialData(void)
{
  noInterrupts();
  digitalWrite(ADS1218_CS_PIN, LOW);
  delayMicroseconds(500);
  SPI.transfer(DSYNC);
  delayMicroseconds(500);
  digitalWrite(ADS1218_CS_PIN, HIGH);
  interrupts();
  delay(2000);

}

void waitForDataReady(int timeOut)  //wait for data ready
{
  // wait for /DRDY = 1
  while ((digitalRead(ADS1218_DRDY_PIN)) != LOW);

  // wait for /DRDY = 0
  while ((digitalRead(ADS1218_DRDY_PIN)) == LOW);
}


uint32_t Read_Data(int passFlag)
{
  uint32_t dataBits = 0x0000;
 if (passFlag)
  {
   waitForDataReady(0);

    noInterrupts();
    digitalWrite(ADS1218_CS_PIN, LOW);                        //Take CS low
    //    delayMicroseconds(500);

    SPI.transfer(RDATA);
    delayMicroseconds(20);
    byte  msbData = SPI.transfer(SPI_MASTER_DUMMY);
    byte  midData = SPI.transfer(SPI_MASTER_DUMMY);
    byte  lsbData = SPI.transfer(SPI_MASTER_DUMMY);
    //    delayMicroseconds(500);
    digitalWrite(ADS1218_CS_PIN, HIGH);                 //  Clear CS to high
    interrupts();
    dataBits = msbData;
    dataBits = (dataBits << 8) | midData;
    dataBits = (dataBits << 8) | lsbData;
  }
  return dataBits;
}

void setup()
{

  digitalWrite(ADS1218_CS_PIN, HIGH);
  pinMode(ADS1218_CS_PIN, OUTPUT);

  Serial.begin(9600);           //115200 57600
  SPI.begin();                           // wake up the SPI bus.
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE1);
  SPI.setClockDivider(SPI_CLOCK_DIV64);
  writeRegister(0x00, 0xfc);  //0000 1100 ,buffer disabled.
  delay(50);
  writeRegister(0x08, 0x80);  // Decimation register 1, DEC0
  delay(50);
  writeRegister(0x09, 0x77);  // Decimation register 2, DEC1, unipolar, SINC3 filter set
  delay(50);
  printAllreg();
  delay(5000); 
  SendSELFCALCommand();
  delay(5000);  
  writeRegister(0x00, 0xfe);  //0000 01110 ,buffer enabled, fMOD = 9600
  delay(50);
  writeRegister(0x08, 0x80);  // Decimation register 1, DEC0
  delay(50);
  writeRegister(0x09, 0x77);  // Decimation register 2, DEC1, unipolar, SINC3 filter set
  delay(50);
  writeRegister(0x01, 0x01);  // set MUX
  delay(50);
  syncSerialData();    // Sync Data Ready with Serial clock edge
  delay(50); 
  printAllreg();

}

void loop()
{

  uint32_t data32 = 0;


  data32 = Read_Data(1);



  float value = (float(data32) * 2.5 * 1000000) / 16777216;

  Serial.print("  32bit BIN : ");
  Serial.println(data32, BIN);
  Serial.print("  Value : ");
  Serial.println(value, BIN);

  delay(50);

}


Here is my schematic:

Any suggestions???

Thanks in advance,

Tanweer

  • Hi Tanweer,

    Welcome to the forum!  Can you try reposting the schematic?  I think the link got caught in the code section by accident.

    Were you able to successfully read the register settings back, and were the registers set the way you wrote them?  I would suggest looking at the SPI communication with a scope or logic analyzer to make sure the communication is as you are expecting it.  If you can, please post those shots.  I would also monitor the DRDY with a scope to make sure that it is pulsing at the proper rate as specified by the decimation you are using. Also make sure pins such as RESET, PDWN, and DSYNC are logic high and POL pin should be logic low.

    Thanks,

    Bob B

  • Hi Bob B.

    Thanks for quick response.

    Here is my schematic:

    Here is my code:

      
    #define PGA 1  
    #define VREF 2.5          
    #define VFSR VREF/PGA             
    #define FSR (((long int)1<<23)-1)  
    
    #define SPI_MASTER_DUMMY 0xff
    #define RESET 0x06                                                    //Send the RESET command (06h) to make sure the ADS1220 is properly reset after power-up
    #define START 0x08                                         //Send the START/SYNC command (08h) to start converting in continuous conversion mode
    
    
    #define ADS1218_CS_PIN 7
    #define ADS1218_DRDY_PIN 6
    
    
    void writeRegister(uint8_t address, uint8_t value)
    {
      uint8_t numReg = 0x01;
      noInterrupts();
      digitalWrite(ADS1218_CS_PIN, LOW);
      SPI.transfer(WREG | address);
      SPI.transfer(numReg);
      SPI.transfer(value);
      digitalWrite(ADS1218_CS_PIN, HIGH);
      interrupts();
    }
    
    uint8_t readRegister(uint8_t address)
    {
      uint8_t data;
      uint8_t numReg = 0x01;
      noInterrupts();
      digitalWrite(ADS1218_CS_PIN, LOW);
      SPI.transfer(RREG | address);
      SPI.transfer(numReg);
      delayMicroseconds(20);       // delay of 10 uS needed
      data = SPI.transfer(SPI_MASTER_DUMMY);
      digitalWrite(ADS1218_CS_PIN, HIGH);
      interrupts();
      return data;
    }
    
    
    void printAllreg(void)
    {
      int read_data0;
      for (int i = 0; i <= 15; i++) {
        read_data0 = readRegister(i);
        Serial.println(read_data0, HEX);
        delay(10);
      }
    }
    
    void SendSELFCALCommand(void)
    {
      noInterrupts();
      digitalWrite(ADS1218_CS_PIN, LOW);
      delayMicroseconds(500);
      SPI.transfer(SELFCAL);
      delayMicroseconds(500);
      digitalWrite(ADS1218_CS_PIN, HIGH);
      interrupts();
      delay(2000);
    
    }
    
    void syncSerialData(void)
    {
      noInterrupts();
      digitalWrite(ADS1218_CS_PIN, LOW);
      delayMicroseconds(500);
      SPI.transfer(DSYNC);
      delayMicroseconds(500);
      digitalWrite(ADS1218_CS_PIN, HIGH);
      interrupts();
      delay(2000);
    
    }
    
    void waitForDataReady(int timeOut)  //wait for data ready
    {
      // wait for /DRDY = 1
      while ((digitalRead(ADS1218_DRDY_PIN)) != LOW);
    
      // wait for /DRDY = 0
      while ((digitalRead(ADS1218_DRDY_PIN)) == LOW);
    }
    
    
    uint32_t Read_Data(int passFlag)
    {
      uint32_t dataBits = 0x0000;
     if (passFlag)
      {
       waitForDataReady(0);
    
        noInterrupts();
        digitalWrite(ADS1218_CS_PIN, LOW);  
        SPI.transfer(RDATA);
        delayMicroseconds(20);
        byte  msbData = SPI.transfer(SPI_MASTER_DUMMY);
        byte  midData = SPI.transfer(SPI_MASTER_DUMMY);
        byte  lsbData = SPI.transfer(SPI_MASTER_DUMMY);
        digitalWrite(ADS1218_CS_PIN, HIGH);   
        interrupts();
        dataBits = msbData;
        dataBits = (dataBits << 8) | midData;
        dataBits = (dataBits << 8) | lsbData;
      }
      return dataBits;
    }
    
    void setup()
    {
    
      digitalWrite(ADS1218_CS_PIN, HIGH);
      pinMode(ADS1218_CS_PIN, OUTPUT);
      
      pinMode(3, OUTPUT);
      
      Serial.begin(9600);           //115200 57600
      SPI.begin();                           // wake up the SPI bus.
      SPI.setBitOrder(MSBFIRST);
      SPI.setDataMode(SPI_MODE1);
      SPI.setClockDivider(SPI_CLOCK_DIV64);
     writeRegister(0x00, 0x0c);  //0000 1100 ,buffer disabled.
      delay(50);
      writeRegister(0x08, 0x80);  // Decimation register 1, DEC0
      delay(50);
      writeRegister(0x09, 0x37);  // Decimation register 2, DEC1, unipolar, SINC3 filter set
      delay(50);
      printAllreg();
      writeRegister(0x00, 0x0e);  //0000 01110 ,buffer enabled, fMOD = 9600
      delay(50);
      writeRegister(0x08, 0x80);  // Decimation register 1, DEC0
      delay(50);
      writeRegister(0x09, 0x37);  // Decimation register 2, DEC1, unipolar, SINC3 filter set
      delay(50);
      writeRegister(0x01, 0x01);  // set MUX
      delay(50);
    }
    
    void loop()
    {
    
    
      uint32_t data24 = 0;
      uint32_t data32 = 0;
    
      data24 = Read_Data(1);
    
    
     if (data24 & 0x800000)
        data24 = (data24 | 0xFF000000);             // Converting 24 bit two's complement to 32 bit two's complement
      else    
        data32 = data24;
      
      float value = (float)((data32*VFSR*1000)/FSR);     //In  mV
    
      Serial.println(value, DEC);
    
      digitalWrite(3, value);
    
    }
    
    
    
    

  • My SPI is working well as I can write and read the registers as I want. Data received at serial is:

    Register values:

    4C
    1
    0
    0
    0
    0
    0
    FF
    80
    37
    0
    0
    0
    24
    90
    67

    Data:
    0.0000000000
    74.7066802978
    89.9285125732
    69.1011657714
    28.9744186401
    58.7806167602
    102.5310287475
    76.8572158813
    30.8483886718
    74.0453643798
    84.5700607299
    61.3355712890
    37.1384658813
    50.5206069946
    88.0023880004
    61.4208068847
    36.3436393737
    60.6283607482
    85.2540206909
    69.2382507324
    40.2054214477
    77.8013534545
    98.3891067504
    52.3343772888
    28.5217208862
    63.3314323425
    82.9973907470
    49.8226356506
    51.5481910705
    41.0923385620
    83.2027282714
    69.0388717651
    38.5171203613
    61.8293952941
    88.5644607543
    71.5115737915
    26.4665527343
    95.7369918823
    88.0390472412
    78.0397720336
    31.3851280212
    75.3760452270
    88.1099777221
    86.7533798217
    34.0619735717
    71.8164520263
    105.4191741943

    As I start decreasing the input signal amplitude from 2 V(peak to peak)  to 1.2V (peak to peak) or less ADC reads 2.5 (Vref) all the time. here is data:

    2500.0000000000
    2500.0000000000
    2500.0000000000
    2500.0000000000
    2500.0000000000
    2500.0000000000
    2500.0000000000
    2500.0000000000
    2500.0000000000
    2500.0000000000
    2500.0000000000
    2500.0000000000
    2500.0000000000
    2500.0000000000

    Here are my scope images:

    Please suggest if I am doing something wrong.

    Regards,
    Tanweer

  • Hi Tanweer,

    I apologize that I have not responded sooner.  It is often easier to see what might be going on using the raw codes from the ADS1218 as opposed to the converted result as this will eliminate any confusion with respect to data conversion error.  Based on your returned register results, you are using bipolar data format (register address 0x09=37 where bit 6 is low), which means that positive full-scale is 0x7FFFFF.  From your scope shots I see 0xFFFFFF if I'm reading the shots correctly.  As the output is binary 2's complement the value of 0xFFFFFF is actually -1 code, or very close to zero. 

    I think you have a couple of issues.  One, you need to make sure you are interpreting the code returned correctly.  The second is your input of 2Vpp does not match any of your results.  If 2500 corresponds to 2.5V, then 100 corresponds to 100mV and this is about the largest value I see.  The output of your generator must not go below AGND, so your generator must be setup so that the output is referenced properly to AGND and have a DC offset that keeps the output of the signal generator within the proper and correct input range of the ADS1218.

    Best regards,

    Bob B