Read PM. - continue here with code and results
Hi,
The library ADS12xx.h doesn't work for me; my board haven't the pin START;
I sent this to "nchazarra".
Compare with datasheet and other libs.
The speed_setting 14MHz may be incorrect for the UNO.
/* 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 0x01 // default contents after reset (no need to write this)
#define mux_reg 1
// mux_data to be changed while running, to select input ports
#define adcon_reg 2
#define adcon_data 0x24 // 0 01 00 100 => clk_out(default), sensor detect OFF, gain 16 (p.31)
#define drate_reg 3
#define drate_data 0x82 // => 100 SPS (samples/secons)
#include <SPI.h>
byte i; // general use
void setup()
{
SPI.begin(); //start the spi-bus
pinMode(cs, OUTPUT);
digitalWrite(cs, LOW); // tied low is also OK.
pinMode(rdy, INPUT);
pinMode(rst, OUTPUT);
Serial.begin(115200);
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(1); // unsure if needed
// 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
{
// digitalWrite(cs, LOW);
while (rdy) {} // wait for ready_line to go low
SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE1)); // start SPI
delayMicroseconds(10);
SPI.transfer(0x50 | reg_num); // dataseheet p.34
SPI.transfer(0x00); // 2nd command byte
SPI.transfer(data); // write tge databyte to the register
delayMicroseconds(10);
SPI.endTransaction();
// digitalWrite(cs, HIGH);
}
byte readreg(byte reg_num) // read from a single register
{
// digitalWrite(cs, LOW); // cs is tied low for now? Theese two lines may be added if other components uses SPI-bus
while (rdy) {} // wait for ready_line to go low
SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE1)); // start SPI
byte bufr;
while (rdy) {} // wait for ready_line to go low
delayMicroseconds(10);
SPI.transfer(0x10 | reg_num); // send 1st command byte, address of the register
SPI.transfer(0); // one byte only
delayMicroseconds(10);
bufr = SPI.transfer(0xff); // read data from register (dummy parameter)
delayMicroseconds(10);
SPI.endTransaction();
// digitalWrite(cs, HIGH);
return bufr;
}
void loop()
{
long adc_val; // store reading
//Read 4 channels from ads1256
for (i = 0; i < 5; i += 2)
{
// digitalWrite(cs, LOW);
adc_val = 0;
while (rdy) {} ;
// send command - select ADC-channel 0000 0001 / 0010 0011 / 0100 0101
SPI.beginTransaction(SPISettings(14000000, 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
while (rdy) {} ;
SPI.transfer(1); // command for: READ DATA (p.34)
delayMicroseconds(10);// read three bytes (adc-value)
adc_val = SPI.transfer(0)<<8;
//delayMicroseconds(10); // needed ?
adc_val |= SPI.transfer(0);
//delayMicroseconds(10); // ??
adc_val <<= 8;
adc_val |= SPI.transfer(0);
delayMicroseconds(10);
// digitalWrite(_CS, HIGH);
SPI.endTransaction();
Serial.print(adc_val);
Serial.print(" / ");
// digitalWrite(cs, HIGH);
}
Serial.println();
}
Hi,
I have the same board in the picture of the first post and I am trying to make this last code work.
I am puzzled a bit by it.
First, I thing that the while(rdy) should really be while (digitalRead(rdy)).
Second, I don't understand the for loop.
It says it wants to read 4 channels, but it iterates only 3 times and I don't know why exactly that choice of values..
Can you make it a bit more explicit?
Thanks!
Thanks..
First, I thing that the while(rdy) should really be while (digitalRead(rdy)).
Of course it shall be..
If you read the compete post, u'll se that OP has only 3 channels used.
I have never seen that sensor, but belive that the code may be a good start..
Knut
Thanks Knut.
I am reading the data sheet and the code is starting to make sense now.
In my case I need to convert a single-ended input, not a differential input.
As far as I understand it, I need to set the multiplex register to 8, which means selecting:
0000 (AIN0) 1000 (AINCOM)
I am not sure if I have got this right.
BTW, there is no AINCOM pin on the board, which makes me think that it is tied to some reference.
With the code as it is now, I get very unstable readings.
Here's an example of readings with AIN0 put to VCC (5V in my case):
16777198
16776701
16777200
0
0
16777200
16777200
16777199
16777202
16776701
16776701
16777200
16777200
0
8388608
16776701
16777198
0
8388608
any suggestion is more than welcome!
AINCOM = Analog Common => reference voltage for ALL inputs
If you've got max 4 analog values to read, you can use the differental setting. This allows for separate ref. voltage for all 4 inputs
A close look at your reading:
chech the binary pattern. compare with 2s compl. zero is 2^23
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);
}
Nice ! I'm sure others will be very happy when u upload your final library .. to github ?
Hi dariosalvi,
I tried your example and it is not clear what is the sampling rate you use?
Thanks,
So I got the code from pafe 1 to spit out some numbers too, but its messed up a lot.
dariosalvis code seems to be right so far.
But how to set the options like PGA, sample rate, buffer etc.?
And how to read the register map?
Hello,
I have created a nicer code, a sort of library, but does not include all the functionalities of the chip.
I have uploaded it on this gist.
Feel free to fork it and improve it!
Do you have a circuit diagram for this?
I am using your code, but I keep on reading 0's, so it could be a hardware wiring problem.
Thanks
Hello Everyone,
I am trying to interface High Precision DA/AD board ADS1256 with Arduino. The code I have taken from library. Actually I am able to read the data but the thing is I am not able to understand the settling time thing and How much settling time I should provide for each command. and also How do I figure what frequency and PGA to be set to read the data?
Thanks
Hi!
Using an ADS1255 (basically the same IC as ADS1256) and dariosalvi code got my ADS1255 working (btw the sample code was missing "SPI.endTransaction();" at the end of the setup).
I've adapted the code a bit to match my setup and configured one more register (DRATE) in order to make sure the ADC is working at it's full 30kSPS potential and the results I'm getting are quite chaotic, making no sense at all:
72655
2966232813
3436158698
255799543
3473817828
534761477
3506425644
1627348985
4257216639
28320544
548220649
3772690109
3792572396
282054638
1610440670
268468467
64021071
1374023375
3174706
4043223809
95399897
871358517
1325613092
1325416659
4267691519
Does anyone know what's the problem?
Here is my code
#include <SPI.h>
#define SPISPEED 1250000
#define SCK 14
#define MOSI 12
#define MISO 27
#define DRDY 26
#define CS 5
#define WREG 0x50
#define RDATA 0x01
void setup()
{
Serial.begin(2000000);
pinMode(MISO, INPUT);
pinMode(MOSI, OUTPUT);
pinMode(SCK, OUTPUT);
pinMode(CS, OUTPUT);
SPI.begin(SCK, MISO, MOSI, CS); //start the spi-bus
delay(1); // LOW at least 4 clock cycles of onboard clock. 100 microsecons is enough
pinMode(DRDY, INPUT);
while (digitalRead(DRDY)) {} // wait for ready_line to go low
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE1)); // start SPI
// Reset to Power-Up Values (FEh)
SPI.transfer(0xFE);
delayMicroseconds(100);
//PGA SETTING
//1 ±5V
//2 ±2.5V
//4 ±1.25V
//8 ±0.625V
//16 ±312.5mV
//32 ±156.25mV
//64 ±78.125mV
byte status_reg = 0x00; // address (datasheet p. 30)
byte status_data = 0B0000001;
//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);
byte adcon_reg = 0x02; //A/D Control Register (Address 02h)
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: 0x3h
byte drate_data = 0B00000011;
// 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);
//SYNC command 1111 1100
SPI.transfer(0xFC);
delayMicroseconds(10);
//WAKEUP 0000 0000
SPI.transfer(0x00);
delayMicroseconds(10);
SPI.endTransaction();
Serial.println("configured, starting");
}
void loop()
{
unsigned long adc_val = 0; // store reading
while (digitalRead(DRDY)) {} ;
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE1)); // start SPI
SPI.transfer(RDATA); // Read Data 0000 0001 (01h)
// delayMicroseconds(10);
adc_val = SPI.transfer(0xff); //0xff is a dummy
adc_val |= (uint32_t)SPI.transfer(0xff) << 8;
adc_val |= (uint32_t)SPI.transfer(0xff) << 16;
adc_val |= (uint32_t)SPI.transfer(0xff) << 24;
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);
}
And the schematic that I use for ADS1255
ADS1255-schematic
Taking a closer look at the datasheet (pg.34) it appears that reading data (in normal reading mode, NOT continuous) requires a settling time t6, hence the " delayMicroseconds(10);" in the original code.
Since I'm after the full 30kSPS data rate, I had to switch to continuous data read mode. using the RDATAC data.(pg.35)
Doing so results in a much higher sample rate that using the first method (posted by dariosalvi). However, once every few samples I get something like a glitch. The output jumps a lot from the normal value.
3313369
3314035
3312667
3313295
3312179
3312508
3312664
3312524
3311696
3311673
3312522
3313006
3313290
3289740
3310820
3311046
7762803
3313255
3312941
7829987
3311065
3311739
3311361
3312014
3312525
3312074
3312182
3313031
3310790
3313129
3313799
3310754
3311421
3289738
3311678
3312615
7697909
3312487
3312331
7632141
3313081
As you can see there are some samples of around ~7600000 that shouldn't be there.
Any idea why?
The code I use is the following (ignore the op-amp setup in the first part of setup() )
#include <AD8555.h>
#include <SPI.h>
#define SCK 14
#define MOSI 12
#define MISO 27
#define DRDY 26
#define CS 5
#define SPISPEED 1900000
// 1700000
unsigned long adc_val = 0; // store reading
int outpin = 19;
AD8555 opamp(outpin);
void setup()
{
Serial.begin(2000000);
//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);
delay(1); // LOW at least 4 clock cycles of onboard clock. 100 microsecons is enough
pinMode(DRDY, INPUT);
delay(500);
SPI.begin(SCK, MISO, MOSI, CS); //start the spi-bus
delay(500);
//init
// digitalWrite(cs, LOW);
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 = 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);
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.endTransaction();
while (digitalRead(DRDY)) {} // wait for ready_line to go low
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE1)); // start SPI
SPI.transfer(0x03); // Read Data Continuous command 0000 0011 (03h)
delayMicroseconds(10);
SPI.endTransaction();
Serial.println("configured, starting");
}
void loop()
{
//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(DRDY)) {} ;
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE1)); // start SPI
//while (millis() - start_time < 1000) {
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);
}
Could someone please explain to me what am I missing when setting up the registers of an ADS1255 ADC?
The setup fails every time. When I read back from the registers (after setting the up) I get back a totally different value from the one that I set up.
STATUS register values:
Received: 11111111
ADCON register values:
Expected: 0
Received: 11111111
DRATE register values:
Expected: 11110000
Received: 11111111
MUX register values:
Expected: 1111
Received: 11111111
Code belllow:
#include <SPI.h>
//ADC hook-up lines
#define SCK 14
#define MOSI 12
#define MISO 27
#define DRDY 26
#define CS 5
//SPI bus settings
#define SPISPEED 1800000
#define CLKIN 7680000 //7.68MHz (external crystal frequency)
//ADC commands
#define WREG 0x50
#define RDATA 0x01
#define RDATAC 0x03
#define RREG 0x10
#define SDATAC 0x0F
//enable stuff
#define ENABLE_VERBOSE_OUTPUT 1
/*
According to datasheet pg.26
---------------------------------
The data input pin (DIN) is used along with SCLK to send
data to the ADS1255/6. The data output pin (DOUT) along
with SCLK is used to read data from the ADS1255/6.
Data on DIN is shifted into the part on the falling edge of SCLK
while data is shifted out on DOUT on the rising edge of SCLK.
DOUT is high impedance when not in use to allow
DIN and DOUT to be connected together and be driven by
a bi-directional bus. Note: the RDATAC command must
not be issued while DIN and DOUT are connected
together.
*/
#define SPI_DATAIN_MODE SPI_MODE0 //DIN shifted out on the falling edge of SCLK
#define SPI_DATAOUT_MODE SPI_MODE1 //DOUT shifted out on the rising edge of SCLK
//ADC related
signed long raw;
byte adcData[3];
bool ok = false;
byte register_values;
//according to datasheet of ADC pg.6 t6 should be at leas 50 time CLKIN (master clock) period
int t6 = round((float)1 / CLKIN * 50 * 1000000) + 1; //*1000000 to convert from seconds to us
void setup() {
Serial.begin(2000000);
//SPI pins
pinMode(MISO, INPUT);
pinMode(MOSI, OUTPUT);
pinMode(SCK, OUTPUT);
pinMode(CS, OUTPUT);
pinMode(DRDY, INPUT);
//init SPI bus
delay(500);
SPI.begin(SCK, MISO, MOSI, CS); //start the spi-bus
delay(500);
/*
ADC setup
*/
while (digitalRead(DRDY)) {} // wait for ready_line to go low
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
//Reset to Power-Up Values (FEh)
SPI.transfer(0xFE);
SPI.endTransaction();
delayMicroseconds(100);
while (digitalRead(DRDY)) {} // wait for ready_line to go low
statusRegister_setup();
adconRegister_setup();
drateRegister_setup();
muxRegister_setup();
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
//SYNC command 1111 1100
SPI.transfer(0xFC);
delayMicroseconds(10);
//WAKEUP 0000 0000
SPI.transfer(0x00);
delayMicroseconds(10);
SPI.endTransaction();
}
void loop() {
// put your main code here, to run repeatedly:
}
void muxRegister_setup() {
/*
MUX REGISTER SETUP
*/
byte mux_reg = 0x01; //Mux Register (Address 01h)
byte mux_data = 0B00001111;
//chose the 2 inputs for your differential signal
// 0000 1111
// 0000 - AIN0 (default)
// 1111 - AINCOM
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
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
SPI.endTransaction();
delayMicroseconds(10); //allow a delay between DIN and DOUT section
if (ENABLE_VERBOSE_OUTPUT) {
Serial.println("\nMUX register values: ");
register_values = 0;
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
SPI.transfer(RREG | mux_reg);
SPI.transfer(0x00); // 2nd command byte, read one register only
SPI.endTransaction();
delayMicroseconds(t6); // a delay of t6 must occur between RREG and data shifted out
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAOUT_MODE));
register_values = SPI.transfer(0);
SPI.endTransaction();
Serial.print("Expected: ");
Serial.println(mux_data, BIN);
Serial.print("Received: ");
Serial.println(register_values, BIN);
}
}
void drateRegister_setup() {
/*
DRATE REGISTER SETUP
*/
byte drate_reg = 0x03; //data rate register address: 0x03
byte maxSampleRate = 0B11110000;
//set data rate to max. (30000 SPS)
byte minSampleRate = 0B00000011;
//set data rate to min. (2.5SPS SPS)
byte chosenRate = maxSampleRate;
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
SPI.transfer(WREG | drate_reg);
SPI.transfer(0x00); // 2nd command byte, write one register only
SPI.transfer(chosenRate); // write the databyte to the register
SPI.endTransaction();
delayMicroseconds(10); //allow a delay between DIN and DOUT section
if (ENABLE_VERBOSE_OUTPUT) {
Serial.println("\nDRATE register values: ");
register_values = 0;
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
SPI.transfer(RREG | drate_reg);
SPI.transfer(0x00); // 2nd command byte, read one register only
SPI.endTransaction();
delayMicroseconds(t6); // a delay of t6 must occur between RREG and data shifted out
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAOUT_MODE));
register_values = SPI.transfer(0);
SPI.endTransaction();
Serial.print("Expected: ");
Serial.println(chosenRate, BIN);
Serial.print("Received: ");
Serial.println(register_values, BIN);
}
}
void adconRegister_setup() {
/*
ADCON REGISTER SETUP
*/
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
//PGA SETTING
//1 ±5V
//2 ±2.5V
//4 ±1.25V
//8 ±0.625V
//16 ±312.5mV
//32 ±156.25mV
//64 ±78.125mV
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
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
SPI.endTransaction();
delayMicroseconds(10); //allow a delay between DIN and DOUT section
if (ENABLE_VERBOSE_OUTPUT) {
Serial.println("\nADCON register values: ");
register_values = 0;
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
SPI.transfer(RREG | adcon_reg);
SPI.transfer(0x00); // 2nd command byte, read one register only
SPI.endTransaction();
delayMicroseconds(t6); // a delay of t6 must occur between RREG and data shifted out
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAOUT_MODE));
register_values = SPI.transfer(0);
SPI.endTransaction();
Serial.print("Expected: ");
Serial.println(adcon_data, BIN);
Serial.print("Received: ");
Serial.println(register_values, BIN);
}
}
void statusRegister_setup() {
/*
STATUS REGISTER SETUP
*/
byte status_reg = 0x00; // address of status reg (datasheet p. 30)
byte status_data = 0B0000001;
//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.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
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
SPI.endTransaction();
delayMicroseconds(10); //allow a delay between DIN and DOUT section
if (ENABLE_VERBOSE_OUTPUT) {
Serial.println("\nSTATUS register values: ");
register_values = 0;
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAIN_MODE)); //force proper SPI settings
SPI.transfer(RREG | status_reg);
SPI.transfer(0x00); // 2nd command byte, read one register only
SPI.endTransaction();
delayMicroseconds(t6); // a delay of t6 must occur between RREG and data shifted out
SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_DATAOUT_MODE));
register_values = SPI.transfer(0);
SPI.endTransaction();
Serial.print("Received: ");
Serial.println(register_values, BIN);
}
}
Hello,
i got out only zero and i check all input on ADS1256
and i have error if i have on this line SPI.begin(SCK, MISO, MOSI, CS); //start the spi-bus
and where to connect Reset and PDWN pin?
Greatings Matej
Moder10:
Hello,i got out only zero and i check all input on ADS1256
and i have error if i have on this line SPI.begin(SCK, MISO, MOSI, CS); //start the spi-busand where to connect Reset and PDWN pin?
Greatings Matej
Reset can be connected to pin 8 or HIGH(3.3 V) and PDWN to HIGH(3.3 V)