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.
Hi Ti!
I am having an ADS1256 module and I need to configure it as a precision ADC for a photodiode in photovoltaic mode for an environment monitoring system, can you share a base level setup guideline for me to use it in the arduino platform please?
many thanks in advance!
Alvin.
Hi Alvin,
The good news is that the ADS1256 is already configured as precision ADC for you, so you're well on your way there ;)
Unfortunately, we do not work with Arduino Microcontrollers or provide Arduino examples with our devices. However, I have seen many online Arduino projects that either provide generic SPI examples or even specific examples of how to interface to the ADS1256. One recent E2E Thread had some Arduino Uno code, found here: https://e2e.ti.com/support/data-converters/f/73/p/782256/2894069#2894069
There is also a third-party Github project here: https://github.com/baettigp/ADS12xx-Library, though I have not tested this code myself.
Please refer to those examples for specifics on how to interface with an Arduino; however, if you have any general questions about the ADS1256 or how to configure the registers settings for your application, I'll be glad to help provide some guidance there!
Hi Chris,
Thank you for sharing!
I will try the code and revert for specific guidance on how to optimize registers to suit my application.
Many thanks in advance!
Alvin.
Hi Chris,
The code runs on well on the Arduino Uno, however have you come across similar code that can be run on esp32?
Appreciate your help!
Alvin.
Hi Chris,
I am implementing below on ESP32 there seems to be some spiking happening especially close to the lower level of signals, any suggestion to improve? I am also noticing that I cannot get the registers to configure properly, and cannot control PGA etc.
#include <Arduino.h> #include <Wire.h> #include <SPI.h> #define mosi 23 #define miso 19 #define sclk 18 #define cs 5 #define rst 17 #define rdy 16 #define SPISPEED 1000000 // 1.92MHz std.@ 7.68/4 MHz const float Vref = 2.485; void sendAds () { unsigned long adc_val[8] = {0,0,0,0,0,0,0,0}; byte mux[8] = {0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78}; int i = 0; SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE1)); digitalWrite(cs, LOW); delayMicroseconds(1); for (i=0; i <= 7; i++) { byte channel = mux[i]; while (digitalRead(rdy)) {} ; SPI.transfer(0x50 | 0x01); SPI.transfer(0x00); SPI.transfer(channel); delayMicroseconds(2); SPI.transfer(0xFC); delayMicroseconds(2); SPI.transfer(0x00); delayMicroseconds(250); SPI.transfer(0x01); delayMicroseconds(7); adc_val[i] = SPI.transfer(0); adc_val[i] <<= 8; adc_val[i] |= SPI.transfer(0); adc_val[i] <<= 8; adc_val[i] |= SPI.transfer(0); delayMicroseconds(1); } digitalWrite(cs, HIGH); SPI.endTransaction(); for (i=0; i <= 7; i++) { if(adc_val[i] > 0x7fffff) { adc_val[i] = 16777216ul-adc_val[i]; } } double FV0 = adc_val[0] * 2 * Vref / 8388607 ; double FV1 = adc_val[1] * 2 * Vref / 8388607 ; double FV2 = adc_val[2] * 2 * Vref / 8388607 ; double FV3 = adc_val[3] * 2 * Vref / 8388607 ; double FV4 = adc_val[4] * 2 * Vref / 8388607 ; double FV5 = adc_val[5] * 2 * Vref / 8388607 ; double FV6 = adc_val[6] * 2 * Vref / 8388607 ; double FV7 = adc_val[7] * 2 * Vref / 8388607 ; delay(1); } void setup() { Serial.begin(115200); delay(100); pinMode(cs, OUTPUT); digitalWrite(cs, LOW); pinMode(rdy, INPUT); pinMode(rst, OUTPUT); digitalWrite(rst, LOW); delay(1); digitalWrite(rst, HIGH); delay(500); SPI.begin(); delay(500); digitalWrite(cs, LOW); while (digitalRead(rdy)) {} SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE1)); digitalWrite(cs, LOW); delayMicroseconds(10); SPI.transfer(0xFE); delay(10); byte status_reg = 0x00 ; byte status_data = 0x07; SPI.transfer(0x50 | status_reg); SPI.transfer(0x00); SPI.transfer(status_data); delayMicroseconds(10); byte adcon_reg = 0x02; byte adcon_data = 0x00; SPI.transfer(0x50 | adcon_reg); SPI.transfer(0x00); SPI.transfer(adcon_data); delayMicroseconds(10); byte drate_reg = 0x03; byte drate_data = 0xF0; SPI.transfer(0x50 | drate_reg); SPI.transfer(0x00); SPI.transfer(drate_data); delayMicroseconds(10); SPI.transfer(0xF0); delay(400); digitalWrite(cs, HIGH); SPI.endTransaction(); while (!Serial && (millis () <= 5000)); Serial.println("configured, starting"); Serial.println(""); Serial.println("A0,A1,A2,A3,A4,A5,A6,A7"); terminal.flush(); terminal.clear(); timer.setInterval(1000L, sendAds); } void loop() { timer.run(); }
Hi Chris,
I tried including the additional code lines and there was an improvement on the single ended mode- thanks!
However I am still seeing some spikes in the differential mode. Attached is the code, can you suggest an improvement please?
Thanks in advance!
Also, in either case, with open ended imputs, I seldom see the voltage settling to close to zero. any thoughts to why this is the case?
Alvin.
#include <Arduino.h> #include <Wire.h> #include <SPI.h> #define mosi 23 #define miso 19 #define sclk 18 #define cs 5 #define rst 17 #define rdy 16 #define SPISPEED 1920000 // 1.92MHz std.@ 7.68/4 MHz const float Vref = 2.485; void sendAds () { unsigned long adc_val[4] = {0,0,0,0}; byte mux[4] = {0x01,0x23,0x45,0x67}; int i = 0; digitalWrite(cs, LOW); delayMicroseconds(10); //while (digitalRead(rdy)) {} //SPI.transfer(0xFE); for (i=0; i <= 3; i++) { byte channel = mux[i]; while (digitalRead(rdy)) {}; SPI.transfer(0x50 | 0x01); SPI.transfer(0x00); SPI.transfer(channel); delayMicroseconds(2); SPI.transfer(0xFC); delayMicroseconds(2); SPI.transfer(0x00); delayMicroseconds(2); while (digitalRead(rdy)) {} ; SPI.transfer(0x01); delayMicroseconds(7); adc_val[i] = SPI.transfer(0); adc_val[i] <<= 8; adc_val[i] |= SPI.transfer(0); adc_val[i] <<= 8; adc_val[i] |= SPI.transfer(0); } digitalWrite(cs, HIGH); SPI.endTransaction(); for (i=0; i <= 3; i++) { if(adc_val[i] > 0x7fffff) { adc_val[i] = 16777216-adc_val[i]; } } double FV0 = adc_val[0] * 2 * Vref / 8388607 ; double FV1 = adc_val[1] * 2 * Vref / 8388607 ; double FV2 = adc_val[2] * 2 * Vref / 8388607 ; double FV3 = adc_val[3] * 2 * Vref / 8388607 ; Blynk.virtualWrite(V60, FV0); Blynk.virtualWrite(V61, FV1); Blynk.virtualWrite(V62, FV2); Blynk.virtualWrite(V63, FV3); } void setup() { Serial.begin(115200); pinMode(cs, OUTPUT); pinMode(rdy, INPUT); pinMode(rst, OUTPUT); digitalWrite(cs, LOW); digitalWrite(rst, LOW); delay(1); digitalWrite(rst, HIGH); delay(500); SPI.begin(); delay(500); digitalWrite(cs, LOW); while (digitalRead(rdy)) {} SPI.beginTransaction(SPISettings(SPISPEED, MSBFIRST, SPI_MODE1)); digitalWrite(cs, LOW); delayMicroseconds(10); while (digitalRead(rdy)) {} SPI.transfer(0xFE); delay(1); while (digitalRead(rdy)) {} byte status_reg = 0x00 ; byte status_data = 0x05; SPI.transfer(0x50 | status_reg); SPI.transfer(0x00); SPI.transfer(status_data); delayMicroseconds(100); while (digitalRead(rdy)) {} byte adcon_reg = 0x02; byte adcon_data = 0x02; SPI.transfer(0x50 | adcon_reg); SPI.transfer(0x00); SPI.transfer(adcon_data); delayMicroseconds(100); while (digitalRead(rdy)) {} byte drate_reg = 0x03; byte drate_data = 0xF0; SPI.transfer(0x50 | drate_reg); SPI.transfer(0x00); SPI.transfer(drate_data); delayMicroseconds(100); while (digitalRead(rdy)) {} SPI.transfer(0xF0); delay(400); digitalWrite(cs, HIGH); SPI.endTransaction(); while (!Serial && (millis () <= 5000)); Serial.println("configured, starting"); Serial.println(""); Serial.println("A0,A1,A2,A3"); terminal.flush(); terminal.clear(); timer.setInterval(1000L, sendAds); timer.setInterval(1000L, sendWifi); } void loop() { timer.run(); }
Hi Alvin,
Have you tried shorting the inputs to some common voltage and seeing if the spikes are still present in the data?
NOTE: In the case of the ADS1256, you can short both inputs to ground, but on many other ADCs with built-in PGAs this would violate the PGA input common-mode range.
I'd also recommend looking at the raw data bytes contained within the "adc_val" array to see if perhaps the spikes are being introduced into the data during post-processing.
...With the inputs shorted together, you will see some noise, but it should be fairly Gaussian and not contain too many outliers.
ADS diff. code.rtfHi Chris,
I believe I have optimized the code (attached). and let me know if further optimization is possible. I have used a drate of 50 to minimize supply noise.
I am understanding from your site there are newer chips with nano volt level noise, can you recommend some chips that may be superior to the ADS1256? and that are optimized to work with photodiodes in photovoltaic mode? - or does the ADS1256 does it well?
My goal is to design a precision lowest noise possible ADC which can directly draw signals from a Li-Cor 190R PAR sensor. equipped with a millivolt adapter that has a 745 Ohm shunt. (Without the need of pre-amplifying the signal)
Many thanks again I have learnt a lot from you!
Alvin.
Hi Alvin,
If you need a breakout board, then perhaps look for an ADS1262. This is a very similar device to the ADS1261, but I know there are breakout boards available for this device. Otherwise, the ADS1261EVM has an unpopulated header that you could use to jumper wire to your Arduino.
I looked at your code and the only thing that stood out to me was line 66 where you perform the subtraction:
adc_val[i] = adc_val[i] - 16777216ul;
Since "adc_val" is unsigned and this subtraction could result in a negative number, you'll end up with a wrap around positive result (see https://stackoverflow.com/questions/7221409/is-unsigned-integer-subtraction-defined-behavior)