Part Number: ADS1255
Other Parts Discussed in Thread: ADS1256
Hi!
Regarding ADS1255: I've been trying to make it work with an ESP32 (the platform is not important though) at it's full potential of 30kSPS.
Unfortunatelly, reading data in continuous mode (RDATAC) yields some strange behaviour: the raw ADC values that I'm getting are not stable at all varying by a lot (more than 5000000 in magnitude), compared to using the normal reading mode (RDATA) where the values vary by no more than a few thousands (which corresponds to the specified noise performance).
I'm using Arduino IDE and an ESP32 connected via SPI to talk with the ADC.
Some other components include an AD8555 op-amp and a +2.5V low noise voltage source, the ADR431BRZ. (see the folowing schematic).
The code that I use for setting up the ADC can be found below and is an adaption of the one posted over here by darioslavi.
Apparently, the registers don't seem to be set up properly. For example after writing a value of 0B00000001 in the Status Register (0x00h), I'm reading back 0 instead of 1. Why so?
Also, in the loop function, am I continuously reading the ADC output in the right way? Am I missing something?
Thanks for your help! Here's the code that I use.
#include <AD8555.h>
#include <SPI.h>
#define SCK 14
#define MOSI 12
#define MISO 27
#define DRDY 26
#define CS 5
#define SPISPEED 1200000
#define WREG 0x50
#define RDATA 0x01
#define RDATAC 0x03
#define RREG 0x10
#define ENABLE_OP_AMP_SETUP 0
unsigned long adc_val = 0; // store reading
int outpin = 19; //op-amp data in pin
AD8555 opamp(outpin);
void setup()
{
Serial.begin(2000000);
if (ENABLE_OP_AMP_SETUP) {
//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);
pinMode(DRDY, INPUT);
delay(1);
delay(500);
SPI.begin(SCK, MISO, MOSI, CS); //start the spi-bus
delay(500);
//init
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 = 0x00; // address of status reg (datasheet p. 30)
byte status_data = 0B0000001;
byte status_read;
//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);
Serial.println("Status register values: ");
SPI.transfer(RREG | status_reg);
SPI.transfer(0x00); // 2nd command byte, read one register only
SPI.transfer(status_read);
delayMicroseconds(10);
Serial.print("Expected: ");
Serial.println(status_data, BIN);
Serial.print("Received: ");
Serial.println(status_read);
//PGA SETTING
//1 ±5V
//2 ±2.5V
//4 ±1.25V
//8 ±0.625V
//16 ±312.5mV
//32 ±156.25mV
//64 ±78.125mV
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
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: 0x03
byte drate_data = 0B11110000;
// 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);
byte channel = 0;
byte data = 0B00001000; //AIN-channel and AINCOM
//configured for single ended input measurement on AIN0
//AINCON = VREFP = +2.5V
SPI.transfer(0x50 | mux_reg); // 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(RDATAC); // Read Data Continuous command 0000 0011 (03h)
delayMicroseconds(10);
SPI.endTransaction();
Serial.println("ADC configured, starting sampling");
}
void loop()
{
while (digitalRead(DRDY)) {} ;
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE1)); // start SPI
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);
}