Giter Club home page Giter Club logo

ads1x15's People

Contributors

chandrawi avatar chipce avatar devmirek avatar intubun avatar robtillaart avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ads1x15's Issues

ESP32 work on Espressif 1.04 but No on Espressif 2,07

On IDE 2.04 and Espressif 1.04 I can read 6 Channels with PlotChannels.ino
when I install latest Espressif 2,07 and compile the same PlotC hannels.ino script I have no error but the SW return 0 (zero) on al channel

Not working with Nano Every

Hi, this looks like a really good library :) but I can't get anything to compile for the Nano Every. AVR dude seems to have problems with the get clock (what you have listed as a prototype) and set clock functions and a few other things I think related to setting clocks for the I2C bus. I tried to copy the error messages but I not able to. Is there maybe something I can change in the header file to get it working? Thanks! :) Rainer S.

COMP_POL reversed

so did a short test

measured the RDY-pin on an oscilloscope

in single shot mode RDY remains high/low until the next request is made (not just a pulse)

but COMP_POL seems to be switched
COMP_POL (0) goes LOW while convertig (around 1.2 ms) and HIGH when ready for as long as one wishes
COMP_POL(1) goes HIGH while convertig (around 1.2 ms) and LOW when ready

Read 4 channel asynchronous

Hi ,

How can I read 4 channels asynchronus ?
The problem is the readout for each value see line below ;

 int16_t value = ADS.getValue(i); 

and gives the following error ; "invalid types 'int16_t {aka int}[int]' "

I have the followiing sketch to test ;

//

#include "ADS1X15.h"

ADS1115 ADS(0x48);
float f = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("ADS1X15_LIB_VERSION: ");
  Serial.println(ADS1X15_LIB_VERSION);

  ADS.begin();
  ADS.setGain(0);
  f = ADS.toVoltage();      // voltage factor
  ADS.requestADC(0);
}

void loop()
{
  if (ADS.isBusy() == false)
  {
    for (int i = 0; i < 4; i++) {
      int16_t value = ADS.getValue(i);
      ADS.requestADC(i);  // request a new one
      Serial.print("\tAnalog0: ");
      Serial.print(value[i]);
      Serial.print('\t');
      Serial.println(value[i] * f, 3);
    }
  }
  // simulate other tasks...
  delay(2000);
}

// -- END OF FILE --

Klass

Cannot change address

Hi, I am developing a customized PCB that uses ESP32S3 SoC and communicate with an ADS1115 via I2C on PlatformIO. I happened to have the address of my ADS1115 set to 0x49 by connecting the ADDR pin to VDD. Therefore, I used the following code to define my ADS1115 object:

ADS1115 ads(0x49);

I then have the following code to check if the connection is success in setup():

if (!ads.isConnected())
{
	ESP_LOGE(TAG, "Failed to initialize ADS1115.");
	while (1);
}
ESP_LOGV(TAG, "ADS1115 initialized.");

However, this doesn't seem to work since I am receiving the following message from my serial port:

[ 1206][E][main.cpp:109] sensorInit(): [MY_APP] Failed to initialize ADS1115.

In contrast, if I use a normal ESP32S3 devkit and a commercial-available ADS1115 module that pulls down ADDR, I can modify the code to either one of the following and make it work:

ADS1115 ads(0x48); // First approach
ADS1115 ads; // Second approach

The example of the successful output:

[ 1215][V][main.cpp:112] sensorInit(): [MY_APP] ADS1115 initialized.

I also noticed the following comment in ADS1X15.h

//  allow compile time default address
//  address in { 0x48, 0x49, 0x4A, 0x4B }, no test...
#ifndef ADS1015_ADDRESS
#define ADS1015_ADDRESS                   0x48
#endif

Does that mean that it is expected to see this behavior with a non-default address?

Thank you very much!

Documentation clarification. In latch mode, alert pin goes high only after readADC?

I think this might just be and issue about clarifying the documentation.

Here's the setup:

  • I'm using the traditional + latch mode,
  • Switch connected to A0. When the switch is pressed A0 goes HIGH,
  • ALERT pin is connected to D2,
  • When A0 goes HIGH I want the ALERT pin to trigger an interrupt attached to D2,
  • When the interrupt is called I set a flag so that something happens in loop(), in this case print "foo".

Issue?

  • In the code below, when ADS.readADC(0) is called before if (read_ADC){...} everything goes as intended,
  • If it is called within, i.e. if (read_ADC) { ADS.readADC(0); ...} then what's inside the if then the ALERT pin doesn't go HIGH, the interrupt on D2 is not executed so do_thing remains false, and nothing happens.
  • So it appears that you have to readADC() to both make ALERT go HIGH and immediately low again? Why call it LATCH mode? It seems like it simultaneously goes high and then low after readADC().
  • In other words, I thought the whole point of the traditional mode with latch was that like an interrupt ALERT goes high without the need to constantly readADC() in the loopis called and instead serves to reset ALERT.

I thought that the order of event was

  • A0 goes HIGH, triggering an interrupt and ALERT goes HIGH, regardless of if you're in LATCH mode or not.
  • After ALERT goes HIGH, you need to readADC() so that it goes low again.

Here's the code in question.

#include <avr/interrupt.h>
#include <Wire.h>
#include <ADS1X15.h>

ADS1115 ADS(0x48);

volatile bool do_thing = false;

void setup()
{
  pinMode(2, INPUT);
  attachInterrupt(digitalPinToInterrupt(2), foo, RISING);

  Serial.begin(115200);

  Wire.begin();
  Wire.setClock(400000);

  ADS.begin();
  ADS.setGain(0);
  ADS.setComparatorMode(0);
  ADS.setComparatorPolarity(0);
  ADS.setComparatorLatch(1);
  ADS.setComparatorQueConvert(0);
  ADS.setComparatorThresholdLow(2000);
  ADS.setComparatorThresholdHigh(30000);

}

void loop()
{
  int16_t val_0 = ADS.readADC(0);   // code works as intended if here

  if (do_thing) {
    // int16_t val_0 = ADS.readADC(0);   // code doesn't work as intended if here

    Serial.println("foo");
    do_thing = false;
  }
}

void foo() {
  do_thing = true;
}

ADS1115 on RP2040 Wire, 0x4B is busy

Hi,
I have just discovered a problem in the use of the ADS1115 connected Wire0 of the RP2040.
The 3 addresses work correctly except 0x4B which is Busy.
Initially the assembly and the program was functional for the 4 addresses with Arduino Mega.
With the Raspberry Pico everything works correctly, except the address 0x4B which is seen Busy at initialization.
For information on the I2C bus there is also an RTC DS3231 which is on Wire1, but was also present on the Arduino version.
With the Raspberry Pico version I tested the presence of the 3 simultaneous addresses without any problem, only when 0x4B is connected to the assembly, it is not recognized.
I turn in circles.
Thank you for you help.

Erick
Laval in France

How to check if the data rate is correct?

Hi, I just bought an ADS 1015, and I set the data rate to option 1 in the code. However, when I read the serial output with my laptop, the data rate looks lower than the target rate. For instance, it will give me about 160Hz while it is set to 250Hz. So, how do you check if you acquire the correct data rate? Thanks.

#include "ADS1X15.h"

// choose you sensor
// ADS1013 ADS(0x48);
// ADS1014 ADS(0x48);
ADS1015 ADS(0x48);
// ADS1113 ADS(0x48);
// ADS1114 ADS(0x48);

// ADS1115 ADS(0x48);

void setup()
{
  Serial.begin(115200);
  // Serial.println(__FILE__);
  // Serial.print("ADS1X15_LIB_VERSION: ");
  // Serial.println(ADS1X15_LIB_VERSION);

  ADS.begin();
  ADS.setGain(1); // 6.144 volt
  ADS.setDataRate(1);
  Serial.println("Voltage");
  ADS.requestADC(0);
}

void loop()
{
  if (ADS.isReady())
  {
    int16_t value = ADS.getValue();
    ADS.requestADC(0);
    Serial.println(value);
  }
}

ADS1115 resolution question

Hi there! I’m working on a project and using this Arduino library. I’m using a differential sensor and saw that I cannot see some of the data between readings. Is there anything I could add using Arduino code to see the full resolution? I saw that there was a mention of potential future work on the differential side of things, and was wondering if this referring to resolution. Thanks!

ADS1115 value from one channel is being copied to the other

Hi, I'm developing a project using the ADS1115. I'm facing an issue with copying values between two channels; it seems that the value from one channel is being copied to the other. I'm using a sample rate of 860 fps. Below is the acquireData function for reference:

void acquireData(data_t* data) {
   read_data = true; 
   while(read_data){ //wait until the data is read and convReady is true which means that the value is ready.
      if(convReady) //convReady is connected to alertReady PIN
      {
        data->adc[0]  = ADS.getValue();
        ADS.requestADC(1);
        convReady = false;
        read_data = false;
      }
  }

  read_data = true;
  while(read_data){
      if(convReady)
      {
         data->adc[1] = ADS.getValue();
         ADS.requestADC(0);
        convReady = false;
        read_data = false;
      }
  }

}

Please note that the first time the program is executed I'm calling ADS.requestADC(0), do you have any suggestions or ideas about this issue.
Thank you in advance.

getMaxVoltage() does not handle ADS1113

Perhaps related to this issue.
ADS1113 has no gain control and the maximum voltage is fixed to ±2.048 V.

Usually, to convert the ADC readings to a voltage you would write:

float voltage = _ads1113.toVoltage(_ads1113.readADC(0));

but toVoltage() calls getMaxVoltage() and this does not handle the ADC1113:

float ADS1X15::getMaxVoltage()
{
  switch (_gain)
  {
    case ADS1X15_PGA_6_144V: return 6.144;
    case ADS1X15_PGA_4_096V: return 4.096;
    case ADS1X15_PGA_2_048V: return 2.048;
    case ADS1X15_PGA_1_024V: return 1.024;
    case ADS1X15_PGA_0_512V: return 0.512;
    case ADS1X15_PGA_0_256V: return 0.256;
  }
  _err = ADS1X15_INVALID_VOLTAGE;
  return _err;
}

because in the inizialization:

ADS1113::ADS1113(uint8_t address, TwoWire *wire)
{
  _address = address;
  _wire = wire;
  _config = ADS_CONF_NOCOMP | ADS_CONF_NOGAIN | ADS_CONF_RES_16 | ADS_CONF_CHAN_1;
  _conversionDelay = ADS1115_CONVERSION_DELAY;
  _bitShift = 0;
  _maxPorts = 1;
}

the ADS_CONF_NOGAIN would prevent any handling of the gain, falling back to a wrong one (ADS1X15_PGA_6_144V):

void ADS1X15::setGain(uint8_t gain)
{
  if (!(_config & ADS_CONF_GAIN)) gain = 0;
  switch (gain)
  {
    default:  //  catch invalid values and go for the safest gain.
    case 0:  _gain = ADS1X15_PGA_6_144V;  break;
    case 1:  _gain = ADS1X15_PGA_4_096V;  break;
    case 2:  _gain = ADS1X15_PGA_2_048V;  break;
    case 4:  _gain = ADS1X15_PGA_1_024V;  break;
    case 8:  _gain = ADS1X15_PGA_0_512V;  break;
    case 16: _gain = ADS1X15_PGA_0_256V;  break;
  }
}

uint8_t ADS1X15::getGain()
{
  if (!(_config & ADS_CONF_GAIN)) return 0;
  switch (_gain)
  {
    case ADS1X15_PGA_6_144V: return 0;
    case ADS1X15_PGA_4_096V: return 1;
    case ADS1X15_PGA_2_048V: return 2;
    case ADS1X15_PGA_1_024V: return 4;
    case ADS1X15_PGA_0_512V: return 8;
    case ADS1X15_PGA_0_256V: return 16;
  }
  _err = ADS1X15_INVALID_GAIN;
  return _err;
}

To ensure compatibility of the library across all the supported devices, I think it should handle the ADS1113 properly and getMaxVoltage() should return 2.048, perhaps forcing the "gain" to ADS1X15_PGA_2_048V.

ADS1X15::getMaxVoltage()

Dear Rob,
Thank you for set of code and thinking through all parts.

RE: float ADS1X15::getMaxVoltage()
In different Gain values, except "0" this switch is not working properly.
Change to :
float ADS1X15::getMaxVoltage()
{
switch (_gain)
{
/* case 0: return 6.144; // original and it is not correct
case 1: return 4.096;
case 2: return 2.048;
case 4: return 1.024;
case 8: return 0.512;
case 16: return 0.256; */
case ADS1X15_PGA_6_144V: return 6.144;
case ADS1X15_PGA_4_096V: return 4.096;
case ADS1X15_PGA_2_048V: return 2.048;
case ADS1X15_PGA_1_024V: return 1.024;
case ADS1X15_PGA_0_512V: return 0.512;
case ADS1X15_PGA_0_256V: return 0.256;
}
return ADS1X15_INVALID_VOLTAGE;
}
And test - all work for 1115 well.

Also, in setComparatorQueConvert
^
was letter "e" instead "a"

Small and perhaps not important things.
Thank you again for work !

can isBusy() also verify connected() ?

In #24 it becomes clear that if isBusy() is used in a loop it might incorrectly return true if the sensor is not connected.

Strategy may be to test connect or set error flag. Needs some investigation.

  • might change signature?
  • performance penalty?
  • affects underlying readRegister

Error during compiling

I'm receiving the following error when compiling a program which uses the ADS1X15.h file:
Compilation error: call to 'bool Adafruit_ADS1X15::begin(uint8_t, TwoWire*)' uses the default argument for parameter 1, which is not yet defined

Specifically it is coming in twice as follows:
In file included from G:\My Drive\My Documents\3D Print Files\Analyzer\files\o2_analyzer\o2_analyzer.ino:25:0:
C:\Users\bridg\OneDrive\Documents\Arduino\libraries\Adafruit_ADS1015/Adafruit_ADS1015.h:157:31: error: expected primary-expression at end of input
bool begin(uint8_t i2c_addr = ADS1X15_ADDRESS, TwoWire wire = &Wire);
^
G:\My Drive\My Documents\3D Print Files\Analyzer\files\o2_analyzer\o2_analyzer.ino: In function 'void setup()':
G:\My Drive\My Documents\3D Print Files\Analyzer\files\o2_analyzer\o2_analyzer.ino:98:13: error: call to 'bool Adafruit_ADS1X15::begin(uint8_t, TwoWire
)' uses the default argument for parameter 1, which is not yet defined
ads.begin(); // ads1115 start
^

exit status 1

Can anyone explain how I can resolve this error (I'm very new, sorry if this is an easy fix I just don't know how to do yet)?

Thank you.

ALRT Pin number?

This really isn't a issue, but I can't find what pin on the MCU the library looks at for reading the data ready state/pin. Am I just missing it? Is there a way to set the pin it watches? Thanks

Suggestion: Add wrapper method to set I2C clock speed

I am working on a time sensitive measurement, which requires a fast sampling time (< 10 ms). During my testing with the ESP32 and the ADS1115 in continuous mode according to the "continuous_4_channels" example, I found that the reads take in average 0.8 to 1 ms longer than expected.

Since this library uses the "Wire" library, I added the following function to the ADS1X15 library:

void ADS1X15::setClock(uint32_t clockSpeed)
{
  _wire->setClock(clockSpeed);
}

This enables to set the clock speed of the I2C communication. When setting the clock speed to 1 MHz, my latency went down to < 0.1 ms. Maybe, this type of function would be handy for others as well.

PS: Thanks for your nice library!

Check documentation carefully

The 0.2.3 version has both comparator mode and async mode added.
Need to check the documentation again if it matches the code.

Library compatible for STM32F407

Hey,
i'm using your Library with PlatormIO on my Black STM32F407VE. It works good, but the Datarate is a bit too low. I only archive 1375 SPS with the ADS1015.

int x;
int16_t result[600];
long start, end;

void setup()
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("ADS1X15_LIB_VERSION: ");
  Serial.println(ADS1X15_LIB_VERSION);

  ADS.begin();
  ADS.setGain(0);  // 6.144 volt
  ADS.setDataRate(7);
  ADS.setWireClock(400000);

}

void loop()
{
    start = micros();
  for (int i = 0; i < 600; i++)
  {
    
    result[i] = ADS.readADC_Differential_0_1();
    
  }

  end = micros();

  for (int i = 0; i<600; i++){
    Serial.print("Differential: "); Serial.print(result[i]); Serial.print("("); Serial.print(ADS.toVoltage(result[i])); Serial.println("mV)");
  }
  Serial.print("Dauer pro Messung in Mikrosekunden:\t");
  Serial.println((end - start)/600.);

  Serial.println("\nDone...");
  delay(2000);
}

Do you know, where my Problem is?

Thank you very much!

ADS1X15 Continuous Mode AND differential (0_1) & (2_3)

Hi Rob, thanks for your libraries, I've been using many of them for years.

Is there a way to get both differential values (0_1 AND 2_3) on continuous mode?

I've been able to get.Value() on either, depending on the trigger read in setup(), but for the life of me I can't find a way to do it on both channels simultaneously...

Is there something obvious I'm missing?

Thank you Rob.

Differential input and gain for maximum precision.

Hi, I have a question about the gain and differential. There is a voltage that varies around a bias. I want to measure this voltage in reference to the bias with as much precision as possible. If I use the differential input will the gain setting amplify the result of the differential and therefore improve precision or will it amplify the inputs and then get the differential voltage?

possible error in the readme

hi

i tried to implement the rdy pin on an ads1115 but it only worked half the time and depended on input voltages on the adc.
this made me suspicious that it might not work as a ready pin but as a comparator

so i read the datasheet, where it says:
"Set the most-significant bit of the Hi_thresh register to 1 ... "
I believe this is a 16 bit value because it is a 16 bid ADC, so i think this would be 0x8000 ?

in the readme it says:
"If the thresholdHigh is set to 0x0100 and the thresholdLow to 0x0000 the ALERT/RDY pin is triggered when a conversion is ready."

0x0100 did not really work but 0x8000 seems to work so far


I might messed up something else because the ready pin goes high after a conversion insted of low
the datasheet says if comp_pol is 0 it goes low, but it goes high and low if set to 1

kind regards

code for setting up the ads1115

  ADS.begin();
  ADS.setGain(1);        
  ADS.setDataRate(7);    //  0 = slow   4 = medium   7 = fast
  ADS.setMode(1);  //triggered mode
  ADS.setComparatorThresholdLow(0x0000);  // all zero for RDY function
  ADS.setComparatorThresholdHigh(0x8000);  // 0x8000 for RDY function
  ADS.setComparatorQueConvert(0);        //  enable RDY pin after one conversion
  ADS.setComparatorLatch(0);  // no latch
  ADS.setComparatorPolarity(0); // make sure it works as RDY pin (maybe not needed, but datasheet says it goes low if this is 0)

  ADS.requestADC_Differential_1_3(); //do stuff to write commands above

(added code tags for readability)

10-12 Channel Continuous with interrupts.

Hi Rob, all your work on this is much appreciated! By far the most comprehensive implementation for these devices!

I am trying to sample 10-12 channels (3x ADS1115) as quickly as possible. Using 860sps, 6.144 FSR, 5v supply, Arduino Mega2560 (I think I should be able to use 3 interrupt pins - 2, 3, and 18 - per #14 ). My current setup is based off of the ADS_continuous_8_channel.ino example, I simply copied/pasted to create ADS_3. Currently, the code causes a hang with 3 ADCs, I believe due to arbitration issues on the I2C bus. With the third ADC commented out, it works as expected, because it is pretty much identical to the example. The attached code has 3 channels on ADS_1 and ADS_2, and 4 channels on ADS_3. For this reason, I set the address of ADS_3 to 0x48, in hopes that it would win arbitration to make up for the slightly slower sampling (3 vs 4 channels). I was using 3 channels on the other 2 ADCs in an attempt to take advantage of some advantages discussed in #49 - the hope was to sample 10 channels with maximum SPS.

In terms of solutions, the following comment from #53 seems like it may have potential: "What might be an option is to combine async requesting a conversion and use interrupts to trigger the reading of the result. Polling a flag is faster than requesting status over I2C."

I have also played around with the ADS_async_8_channel.ino example (and 16channel variant), #24 . These examples (of course) work flawlessly for my application- but my initial goal was to reach faster sampling rates by modifying the 8channel_continuous code instead.

Should I stick with the async implementation? Is this the fastest performance possible with 3x ADS1115? Thank you!
Code:

uint32_t starttime1;
uint32_t endtime1;
uint32_t starttime2;
uint32_t endtime2;
uint32_t starttime3;
uint32_t endtime3;
uint32_t times[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

int SPS1 = 0;
int SPS2 = 0;
int SPS3 = 0;
uint32_t lastTime1 = 0;
uint32_t lastTime2 = 0;
uint32_t lastTime3 = 0;


#include "ADS1X15.h"


//  adjust addresses if needed
ADS1115 ADS_1(0x49); //VDD 1,2,3
ADS1115 ADS_2(0x4B); //SCL 4,5,6
ADS1115 ADS_3(0x48); //GND 7,8,9,10 - lowest because 4 channels, will win arbitration

//  two interrupt flags
volatile bool RDY_1 = false;
volatile bool RDY_2 = false;
volatile bool RDY_3 = false;

uint8_t channel_1 = 0;  //  channel from device 1
uint8_t channel_2 = 0;  //  channel from device 2
uint8_t channel_3 = 0;  //  channel from device 2

//  array to hold the data.
int16_t val[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };


void setup() {


  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("ADS1X15_LIB_VERSION: ");
  Serial.println(ADS1X15_LIB_VERSION);

  Wire.begin();

  //  SETUP FIRST ADS1115
  ADS_1.begin();
  ADS_1.setGain(0);      //  6.144 volt
  ADS_1.setDataRate(7);  //  0 = slow   4 = medium   7 = fast
  ADS_1.setWireClock(400000);

  //  SET ALERT RDY PIN
  ADS_1.setComparatorThresholdHigh(0x8000);
  ADS_1.setComparatorThresholdLow(0x0000);
  ADS_1.setComparatorQueConvert(0);

  //  SET INTERRUPT HANDLER TO CATCH CONVERSION READY
  pinMode(18, INPUT_PULLUP); //ADC1 whjte wire
  attachInterrupt(digitalPinToInterrupt(18), adsReady_1, RISING);

  ADS_1.setMode(0);             //  continuous mode
  ADS_1.requestADC(channel_1);  //  trigger first read


  //  SETUP SECOND ADS1115
  ADS_2.begin();
  ADS_2.setGain(0);  //  6.144 volt
  ADS_2.setDataRate(7);
  ADS_2.setWireClock(400000);

  //  SET ALERT RDY PIN
  ADS_2.setComparatorThresholdHigh(0x8000);
  ADS_2.setComparatorThresholdLow(0x0000);
  ADS_2.setComparatorQueConvert(0);

  //  SET INTERRUPT HANDLER TO CATCH CONVERSION READY
  pinMode(2, INPUT_PULLUP); //ADC2 yellow wire
  attachInterrupt(digitalPinToInterrupt(2), adsReady_2, RISING);

  ADS_2.setMode(0);             //  continuous mode
  ADS_2.requestADC(channel_2);  //  trigger first read


 //  SETUP THIRD ADS1115
 ADS_3.begin();
 ADS_3.setGain(0);      //  6.144 volt
 ADS_3.setDataRate(7);  //  0 = slow   4 = medium   7 = fast
 ADS_3.setWireClock(400000);

 //  SET ALERT RDY PIN
 ADS_3.setComparatorThresholdHigh(0x8000);
 ADS_3.setComparatorThresholdLow(0x0000);
 ADS_3.setComparatorQueConvert(0);

 //  SET INTERRUPT HANDLER TO CATCH CONVERSION READY
 pinMode(3, INPUT_PULLUP); //ADC3 purple wire
 attachInterrupt(digitalPinToInterrupt(3), adsReady_3, RISING);

 ADS_3.setMode(0);             //  continuous mode
 ADS_3.requestADC(channel_3);  //  trigger first read
}


void loop() {
  handleConversion();

  //mine
  String serial_out = "";
  String time_out = "";

  Serial.println("DEBUG: Entering Loop");
  for (int i = 0; i < 10; i++) {
    serial_out = serial_out + '\t' + val[i];
    time_out = 't' + time_out + '\t' + times[i];
    //Serial.print(val[i]);
    //Serial.print('\t');
    handleConversion();
  }
  //Serial.println();

  //Mine
  Serial.println(serial_out);
  Serial.println(time_out);
  
}


//  catch interrupt and set flag device 1
void adsReady_1() {
  RDY_1 = true;
}

//  catch interrupt and set flag device 1
void adsReady_2() {
  RDY_2 = true;
}

void adsReady_3() {
  RDY_3 = true;
}


//  handle conversions that are ready
bool handleConversion() {
  bool rv = false;
  if (RDY_1) {
    //  save the last value
    SPS1++;
    val[channel_1] = ADS_1.getValue();

    endtime1 = micros();
    times[channel_1] = endtime1 - starttime1;

    //  request next channel
    channel_1++;
    if (channel_1 >= 3) channel_1 = 0;

    starttime1 = micros();

    ADS_1.requestADC(channel_1);
    RDY_1 = false;
    rv = true;

    
    if (SPS1 % 200 == 0) {
      for (int i = 0; i < 3; i++) {
        Serial.print('\t');
        Serial.print(val[i]);
      }
      Serial.println();
    }

    if (millis() - lastTime1 >= 1000) {
      lastTime1 = millis();
      Serial.print("SPS1: ");
      Serial.println(SPS1);
      SPS1 = 0;
    }
    

  }
  if (RDY_2) {
    SPS2++;
    //  save the last value
    val[3 + channel_2] = ADS_2.getValue();

    endtime2 = micros();
    times[3 + channel_2] = endtime2 - starttime2;

    //  request next channel
    channel_2++;
    if (channel_2 >= 3) channel_2 = 0;

    starttime2 = micros();

    ADS_2.requestADC(channel_2);
    RDY_2 = false;
    rv = true;

    
    if (SPS2 % 200 == 0) {
      for (int i = 3; i < 6; i++) {
        Serial.print('\t');
        Serial.print(val[i]);
      }
      Serial.println();
    }
    if (millis() - lastTime2 >= 1000) {
      lastTime2 = millis();
      Serial.print("SPS2: ");
      Serial.println(SPS2);
      SPS2 = 0;
    }
    
  }
 if (RDY_3) {
   SPS3++;
   //  save the last value
   val[6 + channel_3] = ADS_3.getValue();

   endtime3 = micros();
   times[6 + channel_3] = endtime3 - starttime3;

   //  request next channel
   channel_3++;
   if (channel_3 >= 4) channel_2 = 0;

   starttime3 = micros();

   ADS_3.requestADC(channel_3);
   RDY_3 = false;
   rv = true;
   
   if (SPS3 % 200 == 0) {
     for (int i = 6; i < 10; i++) {
       Serial.print('\t');
       Serial.print(val[i]);
     }
     Serial.println();
   }
   if (millis() - lastTime3 >= 1000) {
     lastTime3 = millis();
     Serial.print("SPS3: ");
     Serial.println(SPS3);
     SPS3 = 0;
   }
   
   
 }

  return rv;
}

Alternate I2C/TWI library or library abstraction layer

Hello Rob,

Thank you for your ADS1X15 library! Your work helped me test the performance of the ADS1015 and confirm that it will work well for my needs.

My organization has an existing ATmega328P (AVR) codebase with a custom I2C library, and I needed to add ADS1015 support to our application. The MIT licensing of your library could work for us. We couldn't use the underlying Arduino or Wire (TwoWire) libraries, though.

Are you aware of alternate I2C libraries with MIT or BSD or similar licensing that implement the same interface as the Wire library, so that your ADS1X15 library could operate unmodified? My searches weren't fruitful.

Is there a possibility of abstracting the I2C access so that the user of the library could provide their own adapter between the available I2C library and your ADS1X15 library? This idea is inspired by how the U8g2 display library can be ported to new platforms. (This worked very well for me just recently.)

Is the idea of forking your library and replacing the Wire function calls with similar calls into my custom I2C library sensible? The fork would be publicly accessible as is your library. It would have function calls into my private I2C library, though, and therefore wouldn't be useful to others.

Is the best approach for me to write my own ADS1015 library upon my custom I2C library? While this likely would require the most time investment, the questions surrounding licensing would be simpler.

Thank you for your work and your ideas/suggestions!

Gratefully,
Tim Mason

wire speed

hi

first: thank you for this library =)

I tested it today and found that the wire speed has a great influence on microcontroller performance.
One factor is the time needed to transmit the data, but the other is the time it take to handle the pull-requests (aka ADS.isready) to the ADS1X15.

I was able to set the wire speed up to 1.2 MHz (adafruit feather M0 adalogger). The program was able to make pull-requests around 14'000 times per second and change the DAC output as often, while reading 600 samples per second from an ADS1115. At 400 kHz it managed to do that only around 6'000 times per second.

When i changed the code so that it would only do pull-requests every four cycles it did rund almost times faster.

Is it possible to increase the speed further?
The ADS1X15 does have an high speed mode at up to 3.4 MHz, but I am not sure if the wire can run that fast.
(I did test different pullups on SCL and SDA. There was no difference between 10k and 1.5 k Resistors)

4channel continues read

I cannot find a way to get the continues read example to 4 channels (or even dual ads1115)

How to select the channels to readout ? there is only (ADS.getLastValue()); ?

Add code for Comparator mode

Library supports normal ADC and Differential measurements. The ADS 1014/1015/1114/1115 have also a Comparator mode.

  • config field to indicate Comparator supported
  • get/set ComparatorMode(..)
  • get/set Polarity
  • get/set Latch
  • get/set low + high threshold
  • example how Comparator can be used.
  • check optional differences between the 4 devices worth to support (other than #pins)

Allow specifying I2C bus

This library hardcodes the Wire bus, so it's impossible to use this with sensors on any other I2C bus that may be available (Wire1, Wire2, etc.).

I may see if I can handle this and submit a PR...

ADS1115 Data Rate question

Hello Rob, firstly thank you for the library and your effort.
I have an issue regarding the data rate in the library, when I set the data rate to a slowest rate value for example 4 it does not respond with 128 samples/second, it gives around 250~300.
Also when I set the rate to 7 (860 samples/second) it gives around 817 sps, please find the below the snippet of code I'm using, I need to know the source of the problem, is it a hardware issue or software, thank you in advance.

Environment:

  • ESP32
  • ADS1115

Arduino Code:

#include "ADS1X15.h"

ADS1115 ADS(0x48);
float f = 0;
volatile bool convReady = false;

void convReadyAlert(){
   convReady = true;
}
void setup() 
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("ADS1X15_LIB_VERSION: ");
  Serial.println(ADS1X15_LIB_VERSION);
  
  ADS.begin(21,22); // SDA, SCL
  ADS.setGain(1);     
  ADS.setDataRate(4);  // DATA RATE
  ADS.setMode(0); 
  // set the thresholds to Trigger RDY pin
  ADS.setComparatorThresholdLow(0x0000);
  ADS.setComparatorThresholdHigh(0x8000);
  ADS.setComparatorQueConvert(0);             // enable RDY pin !!
  
  pinMode(23, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(23), convReadyAlert, RISING);
  ADS.requestADC(0);
}

void loop() 
{
  if (convReady)
  { 
    int16_t val_0 = ADS.getValue();
    Serial.print("\Value: ");
    Serial.println(val_0 * f, 3);
    convReady = false;
    ADS.requestADC(0);
    
  }
}

The use of Wire1 is not allowed for ESP32 or ESP8266

the first line of the function definition "bool ADS1X15::begin(int sda, int scl)" used for ESP32 and ESP8266 microcontrollers forces the use of the "Wire" object, but the constructors allow the selection of the TwoWire object that you want to use.

1

ADS1013 broken

Nevermind - in case someone runs across an issue of the ADS1013 not apparently working correctly, keep in mind that it is a single channel only with one differential channel. One datasheet I have seems to elude that you can use both for single-ended purposes, and that is not the case.

[question] About using ALERT RDY in ADS_continuous_differential.ino example.

Hi, thanks for the great library!
I want to ask about using ALERT RDY in continuous differential mode.

As the example in ADS_continuous_differential.ino, you called both setComparatorQueConvert(0) and setComparatorThreshold

  // SET ALERT RDY PIN
  ADS.setComparatorThresholdHigh(0x8000);
  ADS.setComparatorThresholdLow(0x0000);
  ADS.setComparatorQueConvert(0);

As I understand, the RDY pin state will rise when the ADC read completed/ready, but what ComparatorThreshold will affect the RDY state here? They will also rise if the signal passed the set thresholds? If I just need the ADC ready signal, just set the ADS.setComparatorQueConvert(0); will be enough?

Sorry for my bad English!
Thanks you!

Support for missing differential readings

Not supported differential reads in the chips are the

  • readADC_Differential_0_2()
  • readADC_Differential_1_2()

These might be implemented in the future.
Similar for the request...() functions.

int16_t readADC_Differential_0_2()
{
  return ADS.readADC(2) - ADS.readADC(0);
}

int16_t readADC_Differential_0_2()
{
  return ADS.readADC(2) - ADS.readADC(0);
}

interrupt driven reads

Moin Rob.

Thanks for the nice lib.

Just a note, not a real issue.

I was looking for an example of interrupt driven conversions. Looking into the example file name list, I found nothing. Looking into the main .MD page: again nothing.

It needed a text search throu the examples.

Not that a big deal, but from a "marketing" standpoint I think interrupt driven conversions (like in ADS_continuous_4_channel) should be displayed very prominently. Isn't it what we all want?

mfg.

ADS1X15::setWireClock() and high-speed mode

Issue #22 added this handy method for setting the I2C clock, however, it might be incomplete.

Section 9.5.1.3 (page 23) of the datasheet says that while the ADS111x supports all three speed modes, high-speed mode (>400kHz) must be activated:

To activate high-speed mode, send a special address byte of 00001xxx following the START condition, where xxx are bits unique to the Hs-capable master. This byte is called the Hs master code, and is different from normal address bytes; the eighth bit does not indicate read/write status. The ADS111x do not acknowledge this byte; the I2C specification prohibits acknowledgment of the Hs master code. Upon receiving a master code, the ADS111x switch on Hs mode filters, and communicate at up to 3.4 MHz. The ADS111x switch out of Hs mode with the next STOP condition.

It'd be pretty slick to see the ADS1X15::setWireClock() method perform this activation.

[Query] Example for continuously reading all four channels at max sps?

If I read all 4 channels at 860 SPS, it should be 215 SPS per channel, 1.2ms between requesting a conversion and the interrupt on ALRT/Ready. In single shot mode, that is not the case for me, it takes a bit more than 6ms for the interrupt to occur after I switch the channel. I'm not sure if this is expected or am I doing something wrong or the chip is faulty. I can get 1.2ms delay If I read from a single channel in Continuous mode. Is there a way to achieve this 215 (At least 200) SPS from each channel while reading all 4? Can you please provide an example if so?

Thanks!!

ADS1115 reading

hello, I'm working on a project where Im using the ads1115 with esp32 .
Im using ESPIDF v4.2 in let me know if you getting feel any update or need to change here.

	// Select configuration register(0x01)
	// AINP = AIN0 reading voltage 
	// Continuous conversion mode, 128 SPS(0xC1, 0x83)

hardware is fine and working I checked in Arduino IDE but here I'm only getting reading 0x5E, 0x5E

static esp_err_t i2c_master_sensor_test(i2c_port_t i2c_num, uint8_t *data_h, uint8_t *data_l)
{
    int ret;
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, 0x90, 0x01);
    i2c_master_write_byte(cmd, 0x01, 0x01);
    i2c_master_write_byte(cmd, 0xC1, 0x01);
    i2c_master_write_byte(cmd, 0x83, 0x00);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
    if (ret != ESP_OK) {
        return ret;
    }

    vTaskDelay(30 / portTICK_RATE_MS);
    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, 0x91, 0x01);
    i2c_master_write_byte(cmd, 0x00, 0x01);
    i2c_master_read_byte(cmd, data_h, 0x00);
    i2c_master_read_byte(cmd, data_l, 0x01);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);

    printf(" >> data_h: %X\n", *data_h);
    printf(" >> data_l: %X\n", *data_l);
    return ret;
}

(added code tags for readability)

Differential continuous mode

Sorry for writing it as an issue ... i did see your example for differential cont mode reading 0-1 & 0-2. And also your discussion about this in issue #29

Im still unsure about the following:

If i read just one pair in continuous mode, do i still need the interrupt?

Cause this doesnt work in my case:

ADS.setMode(CONT);
ADS.requestADC_Differential_0_1();

and in loop

ADS.getValue();

I understand that this could cause reading the same value multiple times without the Int, but does your library work without the int? In my case i need the sample at a given time, so it doesnt matter if it is the last or a new one.

In single channel polling it should be not necessary to do a requestADC_Differential_0_1() after every getValue(), no?

and 2nd ... for the interrupt its necessary to connect the ADS int pin to one of the arduino inputs, right?

(added link to issue reference + code tags)

Synchronous mode very slow

Hi,
Based on reading the docs I set up an ADS1115 with the following:

    _ads=new ADS1115(_addr);
    // initialize the Analog2Digital sampler
    volatile bool status=_ads->begin();
    _ads->setGain(ADS1x15_GAIN_4_096_VOLTS);
    // set the highest datarate, 860 samples/sec
    // see https://github.com/RobTillaart/ADS1X15       
    _ads->setDataRate(7);   
    // single shot mode
    _ads->setMode(1);
    // set the I2C bus frequency
    _ads->setWireClock(400000);

I access the sampler asynchronously using:

unsigned long start=micros();
_ads-> requestADC_Differential_0_1()
while(!_ads->isReady(){
    yield();
}
unsigned long elapsed=micros()-start;
_ads->getValue();

so to be fair, I wasn't expecting to be able to take 860 samples per second this way, but my benchmarking was a bit disappointing... it takes at least 6300 micros (6.3 millis) to get a sample. I could be doing something wrong but it doesn't seem like it...

To satisfy my curiousity, i switched to a synchronous blocking read like so"

unsigned long start=micros();
_ads->readADC_Differential_0_1()
unsigned long elapsed=micros()-start;

synchronous reads take at least 6500 micros (6.5 millis). My I2C clock is anywhere between 300-400kHZ, lots of clock stretching going on so hard to be more precise with that number. Also, if it makes a difference running on an RP2040 pico, this is the only I2C device on the bus...

so by my math, we are looking at 150 samples per sec ... I haven't dug into the data sheet and perhaps differential mode is slower, the performance numbers you list, i.e. 860 s/sec, don't seem to be achievable in my case... suggestions?

QUESTION: What's the typical conversion time?

I've got Covid lockdown brain, so I hope you'll forgive my mistakes assuming that I've erred, which is quite possible.

The datasheet says the ADS101x series run at a max of 3300 samples per second, flat out. If my math is right (and it might not be!) that puts a typical sample at 0.0003 seconds which is 0.3 miliseconds per sample I think.

I'm getting results of 1650 - 1660 mS per reading in single shot and 8980 mS per sample in continuous on an ESP32. I've tried re-coding the example several different ways and the results are broadly similar.

The exact time isn't that crucial to my application so long as it's in under about one millisecond per sample. Perhaps you can help me clear this up?

Arduino Micro and ADS1115 - 860SPS (Only on 1 channel ?)

Hi everyone, I have a question/issue with my ADS1115 and I'd like to know if my conclusion is right or not.

I wrote this small code to test the speed of the ADS1115:

#include "ADS1X15.h"

// ADS1x15 Definitions
ADS1115 ADS(0x48);

// Timing
unsigned long starttime;
unsigned long endtime ;

void setup() {
  Serial.begin(250000);
  ADS.begin();
  ADS.setGain(0);
  ADS.setDataRate(7);
  ADS.setMode(0);
  ADS.setWireClock(400000);
  if (ADS.isConnected()) ADS.readADC(0);
}

void loop() {
  starttime = micros();
  // Serial.print("Sensor 0: "); Serial.print(ADS.readADC(0));
  Serial.print(" - Sensor 1: ");  Serial.print(ADS.readADC(1));
  // Serial.print(" - Sensor 2: "); Serial.print(ADS.readADC(2));
  endtime = micros();
  Serial.print(" => Tiempo de 1 lectura: "); Serial.print(endtime - starttime);  Serial.print(" us");
  Serial.println();
  delay(1000);
}

Now, when I test this with library delay set on 8, I get: ~8726 us
#define ADS1115_CONVERSION_DELAY 8

If I set this to 1, I get: ~1700 us
#define ADS1115_CONVERSION_DELAY 1

My issue is, I need to read 3 analogs, not 1, as you can see I comment the rest of the readings to check response time PER channel. So, when I add the rest of the channels to this project, the max speed I can get is:

Now, when I test this with library delay set on 6, I get: ~ 6500 PER CHANNEL
#define ADS1115_CONVERSION_DELAY 6

Anything below a delay of 6, the reading get's stuck or star mixing results.

Conclusion: If I'm not wrong, switching channels on ADS1115 requieres an additional delay and that's what's causing the problem. Am I right ? Is there any way to improve this results ?

Thanks a lot.

ADS1013 & ADS1113 do not have gain

Must be fixed, It is no showstopper but need at least documentation.

  • in base-class with a _type check in setGain() or
  • move setGain to supporting classes.
  • GetGain() can stay in baseclass (check)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.