Become a subscriber (Free)

Join 29,000 other subscribers to receive subscriber sale discounts and other free resources.
:
:
Don't worry -- youre-mail address is totally secure. I promise to use it only to send you MicroZine.

Using the ADS1115


The ADS1115 is a precise 16bit ADC with four multiplexed inputs - You can use each input on its own, or in pairs for differential measurements. It has an internal calibrated reference for high accuracy.

Important things to know about the chip:

  • Has 16 bit resolution (It is actually ±15 bit - See here).
  • Can detect from 0.187mV to 7.8uV depending on the PGA Setting.
  • Can sample from 8 to 860 SPS.
  • Has an internal voltage reference.
  • Has an internal PGA (Programmable Gain Amplifier).
ADS1115 Breakout Board
ADS1115 breakout board

This ads1115 tutorial shows you how to setup the libraries to drive the chip, and take readings using different PGA gain settings. It also covers how the device is able to measure negative voltage even though it only operates using a single supply. This makes it useful as a current sink or source measuring device.

ADS1115 Specification

  Parameter
Value
  Voltage Supply (Vdd)
2V0 ~ 5V5
  Measurement range
-300mV to Vdd+300mV
  Interface
I2C
  Resolution 16 bits
  Data rate
8 ~ 860 SPS
  Number of multiplexed inputs 4
  Active current
~150uA (200uA max)
  Power down current
0.5uA (2uA max)
  I2C Addresses (selectable)
0x48, 0x49, 0x4a, 0x4b
  Operating temperature
-40°C ~ 125°C

ADS1115 Datasheet

Here's a copy of the ADS1115 datasheet (revised 2018 - ads1115 pdf)

ADS1115 Block diagram

ads1115 blockdiagram

Image from data sheet [http://www.ti.com/lit/ds/symlink/ads1115.pdf]

ADS115 Accuracy

The interesting diagram that shows the real capability of the device is Figure 19 from the datasheet:

Total Error vs Input signal
ads115 total error Vs input signal

Notice how the accuracy of the system includes all error sources:

  • gain error,
  • differential input error,
  • offset error,
  • and noise.


ADS1115 I2C addressing

You can setup the ADS115 with one of four addresses, so you can place 4 ADS1115 chips on a single I2C bus:

    0x48, 0x49, 0x4a, 0x4b.

The addressing control is unusual in that you only need to use one input pin as the address control pin .

Normally you would need two inputs to switch between 4 addresses but the ADS1115 16-bit ADC uses a clever scheme. The single address input is sampled continuously and if you connect it to GND, VDD, SDA or SCL you can set the address from 0x48, 0x49, 0x4a, 0x4b respectively.

ADS115 Power Saving

Continuous mode

The ADS1115 has an impressive quiescent current of 150uA when in continuous conversion mode. In this mode you can let the ADS1115 sample from between 8Hz and 860Hz.

Single-shot mode

The default mode of the  ADS1115 is single shot mode where the device wakes up, takes a measurement, and then goes back to sleep. While asleep the chip only draws a typical current of 0.5uA. Since the device enters this mode at power up there will not be a surge of startup current.

Note: The command interface remains active in power down mode, so you can still get the data out of the chip!

This chip and mode is ideal for battery operated equipment where precision is needed. It is also useful for space constrained designs since the ultra small package (X2QFN) is only 2 mm × 1.5 mm × 0.4 mm

Performance and noise trade-off

Low Speed averaging

If you run the ADS1115 at low speed the internal sampling rate is not lowered, since this is how delta sigma converter operates, by oversampling. The internal oscillator is set at 1MHz, and reduced to 250kHz for the ADC clock.

While in active mode, samples are gathered continuously. These samples are averaged internally which improves noise performance. It also saves you processing time i.e. you won't have to perform the averaging in the microcontroller.

So if you want the best noise performance, run the sample rate at 8Hz (the lowest sample rate).

TIP: For the best noise performabce run the chip at 8SPS.

The only disadvantage of the low sampling rate is that the device must be on continuously so power is always being used. If you are more concerned with saving power, and are not too worried about noise performance, you can implement burst mode operation.

High speed Speed Burst mode

Under microcontroller control, you can implement burst mode to save power. The data sheet suggests that you will use 1/100th the power used in continuous mode. So you could get a 1.5uA average current use.

This is a similar idea to a joule thief circuit where a burst of energy stored in an inductor pulses an LED for a short time. You get enough usable light but at reduced average power.

To simulate the 8SPS rate as above you would make the ADS1115 take a single shot reading every 125ms (1/125e-3 = 8) 8 Hz (you would set this repeat rate from a timer within the microcontroller code).

You would also set the SPS rate of the ADS1115 to 860Hz to get a high speed capture. Of course you can change the time between captures to every second or every hour for further power savings.

The single shot reading should only take 1.2ms leaving the rest of the period with the ADS1115 in low current mode. This is the ads1115 conversion delay and is stated in the datasheet.

Note: The ADS1115 takes approx 25us to power up - pretty good!

Using the ALERT/READY pin

There are two uses for the ALERT/Ready pin. The first is "comparator threshold" alert (the default mode) and "ADC reading ready" alert. You have to set up some registers to operate the ADC reading ready ALERT mode.

Threshold detection

The ADS1115 has an internal comparator which outputs a signal to the ALERT pin (the default mode). You can use this feature to automatically detect out of range conditions (set by threshold registers). The COMP_QUE register allows you to specify how many conversions exceed upper or lower bounds before the alert is asserted.

The ALERT pin requires a pull-up resistor since it is an open-drain pin.

The comparator has two thresholds (high and low). When the input signal is between thresholds the ALERT signal is set high (window comparator mode). You can invert the Alert output signal using COMP_POL.

ADC Ready Interrupt Signal

The alternative use of this pin is as a ADC ready signal. If you set up the pin as an ADC ready signal you can then feed this into an external interrupt pin on a microcontroller so that it can fetch the ADC reading.

The other way to detect if the ADC has completed is to read a register value (Config register bit 15) but of course this takes a lot more time because an I2C transaction must take place.

Note: The conversion ready signal is an 8us wide (high) pulse and indicates the conversion is available on the falling edge.

To set the chip into conversion ready mode set the following registers:

Set the MSB of the high threshold register to 1
    [e.g. Hi_thresh = 0x8000].
Set the MSB of the low threshold register to 0
    [e.g. Lo_thresh = 0x0000].
Set the Comparator queue control bits to 00 (anything but 0x11)
    [e.g. COMP_QUE[1:0]=0].
    Config Reg  & = Config Reg 0x0003; // Clear b0, b1.

Note: You will still need a pull-up resistor on the Alert/Ready pin.

PGA Gain setting

The gain setting register in the ADS1115 does have standard values e.g. x2 x4 etc. it is easier to think of the resolution and range capability of the Full Scale Reading. This is how the datasheet is arranged - because the device uses an internally fixed voltage reference.

You just have to choose the best range that gets near to your measured signal (or add an amplifier in front to set the range).

You can not change the FSR value by adding an external reference voltage as you do with other ADCs. The ranges and resolutions are shown in the table below.

Full Scale Range FSR
Resoultion (1 LSB)
  ±6411mV
187.5uV
  ±4096mV
125uV
  ±2048mV
62.5uV
  ±1024mV
31.25uV
  ±512mV
15.625uV
  ±256mV
7.8125uV

Full Scale Resolution

Although the ADS1115 has 16 bit resolution capability, it uses twos complement to represent a value (the MSB represents the sign bit). This is really a 15bit resolution ADC capable of negative and positive voltage measurement.

This leaves you with 15 bit resolution for an input signal from GND to positive full-scale-voltage and 15 bit resolution for GND to negative full-scale-voltage.

Note: Note: 15 bit resolution still a very accurate resolution to have as you can see from the table above.

As described above, the measurable input voltage goes down to minus 300mV.

At the lowest PGA gain value you can use the full scale resolution of the device (±256mV) and this also fits into the -300mV measurement capability of the ADS1115.

Therefore you can make a current measuring device that is capable of measuring sink and source currents, even with only this single supply chip. To do this you would use an appropriate measuring resistor and make a differential measurement across it. Negative voltage capability testing results are here.

Choosing a higher PGA gain still allows you to measure the negative value, just at a lower resolution.

A Note on the PGA settings

The programmable gain settings register (PGA) allows 8 values but the last 3 values all provide the same gain, resulting in a FSR of 256mV for PGA values of 5, 6 and 7.

So there are 6 usable settings that allow FSRs of ±6.144V, ±4.096V, ±2.048V, ±1.024V, ±0.512V, ±0.256V.

Input Voltage Range

The absolute maximum voltage inputs are:

     -0.3V ~ 7V

The measurement voltage range is:

    GND - 0.3V  ~  VDD + 0.3V.

Remember that the measurement ranges are fixed so the maximum measurable input voltage is ±6.144V.

Testing negative voltage input

I was not sure that the negative voltage could be measured, especially using the single supply of the ADS1115. The datasheet does indicate that it is capable of measuring from -256mV and not blowing up with a voltage above -300mV.

It turns out that this is true, since I tested an input by carefully attaching a -5V source to a 10k pot and adjusting the wiper (ensuring that it did not go below -300mV) for values -100mV, -260mV 

This was the result for a -260mV input:

A1: -260.437mV	 PGA: 6144 mv acc: 187.5uV
A1: -260.375mV	 PGA: 4096 mv acc: 125uV
A1: -260.375mV	 PGA: 2048 mv acc: 62.5uV
A1: -259.969mV	 PGA: 1024 mv acc: 31.25uV
A1: -259.234mV	 PGA:  512 mv acc: 15.625uV
A1: -256.016mV	 PGA:  256 mv acc: 7.8125uV
Alert/RDY 0

This was the result for a -100mV (approx) input:

A1: -104.625mV	 PGA: 6144 mv acc: 187.5uV
A1: -104.500mV	 PGA: 4096 mv acc: 125uV
A1: -104.500mV	 PGA: 2048 mv acc: 62.5uV
A1: -104.531mV	 PGA: 1024 mv acc: 31.25uV
A1: -104.484mV	 PGA:  512 mv acc: 15.625uV
A1: -104.499mV	 PGA:  256 mv acc: 7.8125uV
Alert/RDY 0

For the -260mV measurement you can see that the full scale is reached for the FSR of 256mV which is what you would expect - this is for PGA gain setting of 256mV (since 260mV is higher than the range capability of 256mV).

You can also see that the -100mV reading is measured correctly for all PGA gains.

So this confirms that the ADS1115 can read negative voltages down to its minimum measurement capability of -256mV without a separate power supply.

Note: The ADS1115 arduino code for this output is available further down the page.

ADS1115 ADC FSR

The full scale value for a positive output will be:

        0x7FFF

The full scale value for a negative output will be:

        0x8000

The plus one ADC value is 0x0001 and the minus one value is 0xFFFF (minus 2 is 0xFFFE).

Warning: For single ended measurements you can still get a negative ADC value because of device offset, when measuring 0V.

What's the deal with differential?

A differential measurement uses two inputs one for the low side and one for the high side voltage so you can measure a voltage difference at any point in a circuit. Normal single ended measurements (Ardiuno ADC) can only measure a voltage referenced to ground.

You typically measure across a small, accurate, resistance to determine current flow. The ADS1115 can measure positive and negative voltages.

One reason for using differential measurement is accuracy, since both high side and low side voltages are measured at the same time noise voltage is eliminated.

The other reason is that you may want to measure a voltage not referenced to ground e.g. a current sense resistor is not connected on one side to ground, but is somewhere else in your circuit.

Software

Arduino IDE : Version 1.8.9+

I2Cdev library

The I2Cdevlib has ADS1115 library code as well as code for many other devices.

https://github.com/jrowberg/i2cdevlib

This library has a lot of features, supported chips, and can operate on multiple processors but it is a little more involved to install and you can not use the automatic Arduino zip file installer.

ADS1115 Arduino Library

Unzip the file (ic2devlib-master) then navigate to the Arduino directory within ic2devlib-master. Copy the directories ADS1115 and I2Cdev to the Arduino libraries directory, usually found here (on windows):

    C:\Users\<User name>\Documents\Arduino\libraries

Hardware

Components

  • Arduino Uno R3.
  • ADS1115 breakout board.
  • Connection wires.
  • 100nF capacitor.
  • 10k pot.

Connections

For testing use an Arduino Uno and connect it as follows:

Arduino ADS1115
  5V
VDD
  GND
GND
  A5
SCL
  A4
SDA
  GND
ADDR
  2
ALRT
  Wiper of 10k pot. A1
Note: Connect the ends of the 10k potentiometer to 5V and GND.
Connect 100nF capacitor across 5V and GND. 

ADS1115 Breadboard layout

ADS1115 connected to Arduino Uno breadboard layout

Arduino Example using the ADS1115

Example Sketch 1

You can test the ADS1115 by polling it using the following program:

To see register status information, edit ads1115.h to allow debug output by un-commenting the following line:

    //#define ADS1115_SERIAL_DEBUG

Type the letter s in the serial monitor to see register status.

Note: I changed the pollAlertReadyPin() code so that if it fails then the ads1115 is re-initialised (see code below). When turning the PC on and off the registers were reset, and the Queue registers set to 11: disabling the alert ready pin. Now, if this error occurs the chip is restarted correctly.

// I2C device class (I2Cdev) demonstration Arduino sketch for ADS1115 class
// Example of reading two differential inputs of the ADS1115 and showing the value in mV
// 2016-03-22 by Eadf (https://github.com/eadf)
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
//
// Changelog:
//     2016-03-22 - initial release
//
//     2019-4-30
// JFM modified for re-initialising and output of multiple PGA resolutions for 
// comparison of readings. Also when debug is active serial receiving 's' 
// outputs register values. 



/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2011 Jeff Rowberg

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================


Wiring the ADS1115 Module to an Arduino UNO

ADS1115 -->  UNO
  VDD        5V
  GND        GND
  SCL        A5 (or SCL)
  SDA        A4 (or SDA)
  ALRT       2


*/

#include "ADS1115.h"

ADS1115 adc0(ADS1115_DEFAULT_ADDRESS);

// Wire ADS1115 ALERT/RDY pin to Arduino pin 2
const int alertReadyPin = 2;

void init_ads1115() {
  Serial.println("Testing device connections...");
    Serial.println(adc0.testConnection() ? "ADS1115 connection successful" : "ADS1115 connection failed");
    
    adc0.initialize(); // initialize ADS1115 16 bit A/D chip

    // We're going to do single shot sampling
    adc0.setMode(ADS1115_MODE_SINGLESHOT);
    
    // Slow things down so that we can see that the "poll for conversion" code works
    adc0.setRate(ADS1115_RATE_8);
      
    // Set the gain (PGA) +/- 6.144v
    // Note that any analog input must be higher than –0.3V and less than VDD +0.3
    adc0.setGain(ADS1115_PGA_6P144);
    // ALERT/RDY pin will indicate when conversion is ready
    
    pinMode(alertReadyPin,INPUT_PULLUP);
    adc0.setConversionReadyPinMode();

    // To get output from this method, you'll need to turn on the 
    //#define ADS1115_SERIAL_DEBUG // in the ADS1115.h file
    #ifdef ADS1115_SERIAL_DEBUG
    adc0.showConfigRegister();
    Serial.print("HighThreshold="); Serial.println(adc0.getHighThreshold(),BIN);
    Serial.print("LowThreshold="); Serial.println(adc0.getLowThreshold(),BIN);
    #endif
}

void setup() {    
    //I2Cdev::begin();  // join I2C bus
    Wire.begin();
    Serial.begin(115200); // initialize serial communication 
    
    init_ads1115();
}

/** Poll the assigned pin for conversion status 
 */
void pollAlertReadyPin() {
  for (uint32_t i = 0; i<100000; i++)
    if (!digitalRead(alertReadyPin)) return;
   Serial.println("Failed to wait for AlertReadyPin, it's stuck high!");
   // If gets stuck do -something = init.
   init_ads1115();
}

void loop() {

    adc0.setMultiplexer(ADS1115_MUX_P1_NG);
       
    adc0.setGain(ADS1115_PGA_6P144);        
    adc0.triggerConversion();
    pollAlertReadyPin();
    Serial.print("A1: "); Serial.print(adc0.getMilliVolts(false),3); Serial.print("mV\t");
    Serial.println(" PGA: 6144 mv acc: 187.5uV");
    
    adc0.setGain(ADS1115_PGA_4P096);
    adc0.triggerConversion();
    pollAlertReadyPin();
    Serial.print("A1: "); Serial.print(adc0.getMilliVolts(false),3); Serial.print("mV\t");
    Serial.println(" PGA: 4096 mv acc: 125uV");

    adc0.setGain(ADS1115_PGA_2P048);
    adc0.triggerConversion();
    pollAlertReadyPin();
    Serial.print("A1: "); Serial.print(adc0.getMilliVolts(false),3); Serial.print("mV\t");
    Serial.println(" PGA: 2048 mv acc: 62.5uV");

    adc0.setGain(ADS1115_PGA_1P024);
    adc0.triggerConversion();
    pollAlertReadyPin();
    Serial.print("A1: "); Serial.print(adc0.getMilliVolts(false),3); Serial.print("mV\t");
    Serial.println(" PGA: 1024 mv acc: 31.25uV");

    adc0.setGain(ADS1115_PGA_0P512);
    adc0.triggerConversion();
    pollAlertReadyPin();
    Serial.print("A1: "); Serial.print(adc0.getMilliVolts(false),3); Serial.print("mV\t");
    Serial.println(" PGA:  512 mv acc: 15.625uV");

    adc0.setGain(ADS1115_PGA_0P256);
    adc0.triggerConversion();
    pollAlertReadyPin();
    Serial.print("A1: "); Serial.print(adc0.getMilliVolts(false),3); Serial.print("mV\t");
    Serial.println(" PGA:  256 mv acc: 7.8125uV");

    Serial.print("Alert/RDY "); Serial.println(digitalRead(alertReadyPin));
    Serial.println();

    if (Serial.available()) {
        char chr = Serial.read();
        //Serial.print("Serial received"); Serial.print(chr);Serial.println("<<");
        switch (chr) {
           case 's' :  adc0.showConfigRegister(); break;
           //default: Serial.println(">>");Serial.print(chr);Serial.println("<<");
        }
    }
    
    delay(500);
}
  

Typical output of program. This is for 100mV (approx) input
A1: -104.625mV	 PGA: 6144 mv acc: 187.5uV
A1: -104.500mV	 PGA: 4096 mv acc: 125uV
A1: -104.500mV	 PGA: 2048 mv acc: 62.5uV
A1: -104.531mV	 PGA: 1024 mv acc: 31.25uV
A1: -104.484mV	 PGA:  512 mv acc: 15.625uV
A1: -104.499mV	 PGA:  256 mv acc: 7.8125uV
Alert/RDY 0

New! Comments

Have your say about what you just read! Leave me a comment in the box below.




Privacy Policy | Contact | About Me

Site Map | Terms of Use



Visit our Facebook Page:
To Visit Click Here


Recent Articles

  1. Arduino EEPROM - how it works and how to use it - with examples.

    Arduino EEPROM: How to use it and How to presrve the life of EEPROM. Two examples sketches to save multiple values to EEPROM.

    Read more

  2. How to use the ADS1115

    A tutorial on using the ADS1115 precision 16 bit ADC for low power use.

    Read more

  3. The TP4056: Lithium Ion/polymer Battery Charger IC

    Learn how to use the TP4056 properly. There's a right, and a wrong way, to use it to safely charge Lithium Ion batteries.

    Read more

  4. DW01A Battery Protector IC

    The DW01A chip is a Lithium Ion battery protector commonly used on TP4056 boards.  Find out Exactly how it works and how to use it the correct way.

    Read more

  5. Arduino String: How to read commands from the serial port.

    For Arduino string operations you can use Object Class Strings or C style strings but which should you use? Also find out how to decode commands and control variables in your programs using strings.

    Read more

  6. A Real Time Clock design (DS1307) with a PIC microcontroller

    Real Time Clock Design (FREE): A Free and Complete RTC design using the DS1307 and a PIC micro (16F88) also re-targetable. This PIC project uses an I2C Clock chip and 7-segment display to create a fou…

    Read more

Readers Comments

"I wanted to thank
you so so so much
for all the information
you have provided in
your site it's

SUPERB and FANTASTIC."

- Ranish Pottath

"This site really is
the best and my favorite.
I find here many useful
projects and tips."

- Milan

bursach<at>gmail.com<

"Awesome site,
very, very easy and nice
to navigate!"


- Matt
matt_tr<at>
wolf359.cjb.net


Learn Microcontrollers

"Interested in
Microcontrollers?"

Sign up for The
Free 7 day guide:

FREE GUIDE : CLICK HERE


"I am a newbie to PIC
and I wanted to say
 how great your
site has been for me."


- Dave

de_scott<at>bellsouth.net

"Your site is a great
and perfect work.
congratulations."


- Suresh

integratredinfosys<at>
yahoo.com

"I couldn't find the correct
words to define
yourweb site.

Very useful, uncovered,
honest and clear.

Thanks so much for
your time and works.
Regards."


- Anon

Back to Top