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);
}