Chapter 8

ADS1115 ADC Digital-Analog Converter for Arduino and ESP8266
The ADS1115 is a 16-bit ADC digital-analog converter that can be very useful for certain projects with Arduino and ESP8266. Although the Arduino boards usually have some built-in ADC digital-analog converter, the ADS1115 has more features and more resolution.
For example, the Arduino UNO incorporates six 10-bit ADCs; however, the ADS1115 has a 16-bit resolution. On the other hand, by using an external ADC digital-analog converter, you will be able to free the processor.
In the case of ESP8266, it only incorporates a 10-bit digital-analog converter that measures in the range of 0V and 1V. This makes the conversion depends on the resistances that are used to make the voltage divider.
Using the ADS1115, you will gain a lot in accuracy and conversion quality. Communication between the external digital-analog converter ADS1115 and Arduino or ESP8266 is through I2C.
All this is what you will see in this lesson, but first, let me show you what analog, digital, and the digital-analog converter is.
What will you learn in this chapter?
What is a Digital-Analog Converter?
The digital-analog converter allows you to convert from the analog world to the digital world. All the signals detected and processed by the human being are analog signals. The objective of converting an analog signal into a digital signal is that it can be treated and processed by a microcontroller for various purposes.
Machines only understand 1s and 0s. Televisions, computers, tablets, or mobiles, all have at least one digital-analog converter. There are different types of the digital-analog converter (ADC) that are used for different purposes. The three most common types are:
The most common and most economical digital-analog converter (ADC) is that of successive approximations. The two most important characteristics of a digital-analog converter (ADC) are the resolution and the sampling rate or frequency.
Resolution of a Digital-Analog Converter
The resolution of a digital-analog converter (ADC) is expressed in the number of bits. Sets the number of levels into which an analog input range can be divided. To calculate the resolution of an n-bit digital-analog converter (ADC), divide 1 by 2 raised to n.
For example, a 16-bit digital-analog converter (ADC) has a resolution of
If the input range is 5V,
What comes to say that we can measure variations of 0.0763mV in the analog input signal?
Variations below this voltage will not be detected.
In general, when a digital-analog converter has a higher resolution, it provides more details of the analog signal than a digital-analog converter with a lower resolution.
Is it better to have an ADC with a higher resolution?
It depends. If you are only interested in temperature variations from grade to grade at best with the Arduino digital-analog converter itself is more than enough.
Whenever possible, avoid adding layers that make the project more complex and expensive without any compelling reason.
Speed of a digital-analog converter
The other characters in which we must look at a digital-analog converter (ADC) is the speed or frequency of sampling. It is the number of times the digital-analog converter (ADC) samples the analog signal in 1 second. Its unit is expressed in hertz (Hz).
For example, sampling frequencies of 44 kHz, 22 kHz, and 11 kHz are mainly used for audio signals. If the first one is used, 44 kHz means that the digital-analog converter samples the signal 44000 times per second. The higher the sampling frequency, the better the conversion from analog to digital.
What is an ADS1115?
Now that we are clear about what a digital-analog converter is let's move on to see the ADS1115. The ADS1115 is an ideal external digital-analog converter when more resolution or more analog pins are required.
A typical case is when you want to measure different analog signals with an ESP8266. This SoC only incorporates an ADC. In these cases, it is essential to use an external digital-analog converter (ADC) such as the ADS1115.
As with many components of this type, the ADS1115 is the chip that names the electronic component. You will find it in different shapes and formats, according to the manufacturer.
One of the most famous is that of Adafruit, although you can find other similar ones from other brands. I am going to work with the GY-ADS1115 / ADS1015, whose price is about $ 5.
Everything you see in this lesson will also be useful for any other ADS1115, no matter the manufacturer. The most normal thing is to come with the solderless pins. So prepare the soldering iron and tin because you have to weld.
Next, we will see the main features of the ADS1115.
Main Features of the ADS1115
The first thing is to always go to the technical data sheet, where you will get the best and most reliable information on an electronic component.
On the website of the chip manufacturer, Texas Instruments, you will find it here.
Characteristic
Value
Operating voltage
from 2V to 5.5V
Current consumption
150 µA (continuous mode)
Programmable Sampling Rate
8 Hz to 860 Hz
Resolution
16-bit
Channels
4 input channels or 2 differentials
Communication interface
I2C (4 addresses)
We will be explaining all these features of the ADS1115 throughout this lesson.
Before we go to see the pins.
ADS1115 Pins
The number of pins depends a lot on the component, but, normally, we have access to 10 pins.
ADDR Pin
The ADS1115 digital-analog converter can be configured with 4 I2C addresses. This means that you can connect up to 4 ADS1115 on the same I2C bus.
The ADDR pin is used to select an address from the four possible ones. Depending on where you connect, you will use one address or another.
The possible I2C addresses are 0x48, 0x49, 0x4A and 0x4B.
In the following table, I show the possible connections with their corresponding addresses.
ADDR connection
Direction
GND
0x48
5V
0x49
SDA
0x4A
SCL
0x4B
What this table means is that the ADDR pin has to be connected to the GND, 5V, SDA or SCL pin to get the corresponding address.
This type of addressing allows up to 4 ADS1115 modules to be connected to the same board.
ALERT Pin
The ADS1115 digital-analog converter is equipped with a customizable comparator that issues an alert on the ALERT / RDY pin. This feature is very useful since it can significantly reduce external circuits in many projects.
Imagine you have a sensor to detect floods. Thanks to a comparator like the ADS1115 you could do that when it exceeds the threshold, on the ALERT pin it emits a signal and wakes the microcontroller. This allows device consumption to be very low.
It can work in two ways.
In traditional comparator mode, the ALERT pin is activated when the signal exceeds a set high threshold (TH_H) and is deactivated when the threshold drops below the low threshold (TH_L).
In the window comparator mode, lets you know if the signal is between the limits of a window set by the high threshold (TH_H) and the low threshold (TH_L).
This means that it is activated when the high threshold is exceeded or when they fall below the low threshold.
These two modes can be configured at the software level.
ADS1115 Conversion Modes
The ADS1115 digital-analog converter can operate in two conversion modes: single-shot mode and continuous conversion mode.
In single-shot mode, the digital-analog converter (ADC) converts the input signal to demand and stores the result in an internal register.
By sending a signal to ADS1115, we can indicate when to convert.
Then the ADS1115 enters the energy-saving mode. This mode is used to save energy on systems that only require periodic conversions, or there are long periods of inactivity between conversions.
In continuous conversion mode, the digital-analog converter (ADC) automatically begins converting the input signal as soon as the previous conversion is complete. That is, convert a value from analog to digital and when it finishes, take another sample. At what velocity?
The conversion rate, as we have seen before, is programmable.
The data can be read at any time and always reflect the most recent conversion.
Resolution of the ADS1115 Digital-Analog Converter
Although I have already commented that the resolution of the ADS1115 is 16-bit, the reality is that not all 16-bit bits are used to express the voltage value. The output you get from the ADS1115 is known as a signed integer, that is, one of the bits of the 16-bit word is used to set the sign, positive or negative.
Therefore, only 15-bit of the 16-bit is used, which means that there are 32,768 possible values (2 15 ).
The first value would be 0, and the last would be 32,767.
Programmable Gain Amplifier or PGA
Another of the peculiarities that give the ADS1115 even greater precision and reliability is the programmable gain amplifier or PGA that is incorporated.
Ok, but what is a programmable gain amplifier?
Basically, it is an operational amplifier to which we can modify the gain through the code, programming. The programmable gain amplifier sets the full scale, that is, indicates the reference value.
In Arduino, this value is determined by the reference voltage, which in the case of Arduino UNO is 5V and in the Arduino MKR range, and the ESP8266 is 3V3.
In ADS1115, it is established by the PGA. By default, this reference value is ± 6,144 V. This means that the value of 32,677 (maximum value with 15-bit) corresponds to 6,144 V.
In Arduino UNO, with a 10-bit ADC (1024 possible values), the value 1023 corresponds to 5 V.
If you do the conversion, you have to for the ADS1115
And for an Arduino UNO
This means that with the ADS1115, a significant improvement is achieved with respect to the ADC of the Arduino UNO, around 26 times better.
But the best thing is that the gain amplifier is programmable, and we can change the reference value to smaller values. The value of 6.144 V is the worst case.
In the following table, you have a summary of all possible PGA values.
PGA
Reference (V)
Scale factor
2/3
6.144 V
0.1875 mV
1
4,096 V
0.1250 mV
two
2,048 V
0.0625 mV
4
1,024 V
0.0312 mV
8
0.512 V
0.0156 mV
16
0.256 V
0.0078 mV
Note that by setting the PGA with the value 16, a scale factor of 0.0078 mV is achieved, that is, very small voltage variations can be detected.
But be careful, the reference in volts of the previous table does not mean that we can measure signals in that range of values.
The Maximum Range of Analog Inputs of ADS1115
The above table can be very misleading as it can lead to error, although the largest reference is 6.1444 V. The ADS1115 can only measure the power value (VDD) plus 0.3 V for its analog pins.
What does this mean? VDD is the supply voltage, and as we have seen, it can be between 2V and 5.5V.
Therefore, if we supply the ADS1115 with 5V, we can only measure voltages on the analog pins up to 5V + 0.3V, that is, 5.3V.
The same will happen if we feed with 3.3V. In this case, the maximum would be 3.6V.
Applying a voltage greater than VDD + 0.3V to an ADS1115 may damage the chip. Never exceed this voltage on an analog pin.
I repeat that the PGA reference is not the same (it is the scale factor) and the maximum value that the analog inputs support.
The last thing we are going to see before seeing the examples are the operating modes: single-ended mode, differential mode, and comparator mode.
ADS1115 Operating Modes
The single-ended mode makes the four analog inputs of the ADS1115 work like those of an Arduino. The digital-analog converter (ADC) reads the difference between each input and ground.
The differential mode, however, measures the difference between two of the analog inputs of the ADS1115. That is, a measurement is made in which neither side is in GND.
In this mode, the pins are paired two by two, A0 with A1 and A2 with A3. This means that you will only have two channels.
In channel 1, returns the difference between pins A0 and A1, and channel 2 returns the difference between pins A2 and A3.
In the comparator mode, the ALERT pin that we have seen before is used to launch a signal every time a threshold set within the ADS1115 is exceeded.
To test each mode, we will make some examples. The first thing we will do is install the library to be able to program the ADS1115.
Install Library for ADS1115
The first thing is to install the library to control the ADS1115. The most famous and popular is the Adafruit.
In the lesson on how to install a library with Arduino, I show you not only to install it but also how to select the most suitable for your project.
Just look for the Adafruit ADS1X15 library in the library manager.
You need to install it and go. Now you can access both the library and the code of the examples.
This library allows you to control both the ADS1115-based board and the ADS1015-based board. In this lesson, I will only talk about ADS1115.
Single-End Mode
The first mode we are going to see is the single-ended mode. This mode causes the ADS1115 to behave like a normal ADC.
It has 4 numbered analog inputs such as A0, A1, A2, and A3.
The idea is to connect an analog sensor to one of those inputs and measure its value.
In this example, you will use a photoresistor or LDR connected to the ADS1115.
Then I leave the electrical scheme to connect the ADS1115 to an Arduino UNO and a NodeMCU board based on the ESP8266.
ADS1115 Connection with Arduino UNO
The connection of the ADS1115 with the Arduino UNO is very simple. Follow the following scheme.
The SDA pin of the ADS1115 goes to the A4 pin of the Arduino UNO and the SCL pin to the A5 pin.
The I2C address is configured by connecting the ADDR pin of the ADS1115 to the GND pin.
In addition, I added a photoresistor or LDR to test the ADS1115 digital-analog converter (ADC).
The resistance is connected through a voltage divider with another 10kΩ resistor.
The analog pin of the ADS1115 that I am going to use is the A0.
ADS1115 Connection with ESP8266
The connection with the ESP8266 is very similar to that of Arduino UNO. In this case, I will use a NodeMCU board.
The SDA pin of the ADS1115 is connected to pin D2 of the NodeMCU ESP8266 board and pin SCL to pin D1.
The I2C address is configured by connecting the ADDR pin of the ADS1115 to the GND pin.
As in the Arduino UNO scheme, I have connected a photoresistor or LDR through a voltage divider with a 10kΩ resistor.
The LDR is connected to pin A0 of ADS1115.
Single-End Mode Programming
Once we have everything connected between the board and the ADS1115, we will see the programming.
We start with libraries and variables.
Libraries and Variables
#include <Wire.h>
#include <Adafruit_ADS1015.h>
// Create class object
Adafruit_ADS1115 ads;
The first thing is to import the Wire.h and Adafruit_ADS1015.h libraries. Although this last library is called ADS1015, it also contains the code to control the ADS1115.
Then create an object of the Adafruit_ADS1115 class that we call ads.
Setup () Function
void setup (void)
{
Serial.begin (9600);
delay (200);
// Start ADS1115
ads.begin ();
}
The setup () function begins by initiating serial communication to display messages through the serial monitor.
Then start the ADS1115 by calling the ads.begin () function that does not support any parameters.
Loop () Function
void loop (void)
{
// Get data from A0 of ADS1115
short adc0 = ads.readADC_SingleEnded (0);
Serial.print ("A0:");
Serial.println (adc0);
delay (1000);
}
The loop () function is where you really have to read the analog pin.
The first thing is to declare a variable of type short called adc0. This variable will store the value of the digital pin A0.
It is of the short type because this type of stores signed 16-bit integers. Enough to store the value returned by an analog pin, a 15-bit number as we have seen before (from 0 to 32767).
The ads.readADC_SingleEnded (0) function is used to obtain the ADS1115 analog pin value. The parameter that is passed to this function is the analog pin number.
0 will return the value of analog pin A0, 1 that of pin A1, and so on.
Finally, the information obtained by the serial monitor is shown in the loop () function.
Now there is only one thing left, upload the code to the board and open the serial monitor.
Full Code
#include <Wire.h>
#include <Adafruit_ADS1015.h>
// Create class object
Adafruit_ADS1115 ads;
void setup (void)
{
Serial.begin (9600);
delay (200);
// Start ADS1115
ads.begin ();
}
void loop (void)
{
// Get data from A0 of ADS1115
short adc0 = ads.readADC_SingleEnded (0);
Serial.print ("A0:");
Serial.println (adc0);
delay (1000);
}
You will get something similar to this.
If you put your hand on top of the photo resistance, the value will decrease, and if you put your hand on it, the value will increase.
But what would happen if I want more precision? As we have seen, the ADS1115 includes a programmable gain amplifier or PGA that allows us to have more precision with the same number of bits.
As it does? Changing the reference value.
By default, the ADS1115 uses the reference voltage of 6.1444V, which implies a scale factor of 0.1875mV.
If we change the reference voltage, for example, to 4,096V, a scale factor of 0.125mV is obtained.
To change the scale factor, you just have to add the call to the ads.setGain (GAIN_ONE) function just before starting the ADS1115 with the ads.begin () function on line 13.
The code would be as follows.
#include <Wire.h>
#include <Adafruit_ADS1015.h>
// Create class object
Adafruit_ADS1115 ads;
void setup (void)
{
Serial.begin (9600);
delay (200);
// Change scale factor
ads.setGain (GAIN_ONE);
// Start ADS1115
ads.begin ();
}
void loop (void)
{
// Get data from A0 of ADS1115
short adc0 = ads.readADC_SingleEnded (0);
Serial.print ("A0:");
Serial.println (adc0);
delay (1000);
}
What happens when you change the voltage reference? Since the range is reduced, and therefore the scale factor decreases.
Thanks to this, smaller variations in brightness can now be measured.
In the following table, I show the different values that this function can take, the reference voltage, and the corresponding scale factor.
Parameter
Reference
Scale factor
GAIN_TWOTHIRDS
6.144V
0.1875mV
GAIN_ONE
4.096V
0.125mV
GAIN_TWO
2,048V
0.0625mV
GAIN_FOUR
1,024V
0.03125mV
GAIN_EIGHT
0.512V
0.015625mV
GAIN_SIXTEEN
0.256V
0.0078125mV
And that's how the ADS1115 works normally, like any other digital-analog converter (ADC).
Now let's see another mode of operation, the differential mode.
Differential Mode
As I said, the differential mode of the ADS1115 allows us to measure the difference between two analog pins of this module.
You can measure the voltage difference between A0 and A1 or between A2 and A3. That is why it is called differential.
But why can this type of measure be useful?
If you usually do projects with Arduino at some point, you will need to power your project with batteries.
The differential mode will allow you to make a measurement in which none of the sides of the measurement is connected to GND, as is the case when measuring a battery or battery with Arduino.
In addition, another benefit of this mode is that you can perform negative voltage measurements.
In the following example, I will show you how you can do it.
ADS1115 Connection with Arduino UNO
Assemble the circuit starting from the following scheme.
I have used a battery holder with two AA batteries, but you can use another class of batteries, such as AAA or even a single 1.5V battery.
The positive end of the battery holder is connected to the A1, and the negative end is connected to the A0 of the ADS1115.
When the two batteries are connected in series, the voltages are added. Therefore 1.5 + 1.5 = 3V. This will be at best.
The programming will be the same: what will change will be the value obtained from the difference.
ADS1115 Connection with ESP8266
In the following scheme, I show you how to connect the ADS1115 with a NodeMCU ESP8266 board to make a differential measurement.
As in the scheme with the Arduino UNO, I used an AA battery holder.
The positive end of the battery holder to A1 and the negative end to A0.
Be very careful if you are going to measure a voltage higher than 3.3V with which the ADS1115 is powered. Remember that you cannot beat VDD + 0.3V, that is 3.3 + 0.3 = 3.6V
Differential Mode Programming
The ADS1115 differential mode programming is very simple and very similar to what we have seen in the single-ended mode.
Then I leave the code
#include <Wire.h>
#include <Adafruit_ADS1015.h>
// Create class object
Adafruit_ADS1115 ads;
// Scale factor. By default the reference value is 6.144V
// The scale factor of this reference is 0.1875mV
float scale factor = 0.1875F;
void setup (void)
{
Serial.begin (9600);
// Scale factor
ads.setGain (GAIN_TWOTHIRDS);
// Start ADS1115
ads.begin ();
}
void loop (void)
{
// Get the differential
short difference_0_1 = ads.readADC_Differential_0_1 ();
// Convert to volts
float volts = (difference_0_1 * scale factor) /1000.0;
Serial.print ("Difference 0-1 =");
Serial.println (difference_0_1);
Serial.print ("Voltage =");
Serial.println (volts, 4);
Serial.println ();
delay (2000);
}
The first thing the code does is import the libraries and create an instance of the Adafruit_ADS1115 class called ads.
Then I declare a float type variable to store the scale factor called the Scale factor.
The scale factor depends on the voltage reference that has been selected. By default, it is 6.144V, which corresponds to a scale factor of 0.1875mV.
If the voltage reference is modified, you will have to modify the scale factor and put the corresponding one according to the table we have seen in the previous section.
In the setup () function, serial communication is initiated, the scale factor is set with the ads.setGain function (GAIN_TWOTHIRDS), and the ADS1115 sensor is started with the ads.begin () function .
As I said, if you modify the scale factor with the function ads.setGain (...) will have to change the initial value of the variable scalefactor to the match.
In the loop () function, the first thing is to obtain the difference between pin A0 and A1 using the ads.readADC_Differential_0_1 () function.
This function returns the difference between A0 and A1; that is, the value in A0 subtracts the value from A1.
If you need to use the other two pins you can use the ads.readADC_Differential_2_3 () a function that will return the difference between A2 and A3.
This difference is expressed as a signed 16-bit number that is between 32,768 and 32,767. This value must be converted to volts.
To do this, multiply by a Scalefactor and get millivolts. To get volts, you have to divide by 1,000. The same is what is done on line 27 of the code.
Finally, the information is shown by the serial monitor.
Now you just have to load the code to the board and open the serial monitor. You will get something similar to this.
As you can see, negative numbers come out. This is because we are subtracting the voltage we have on pin A0 minus pin A1.
As we have connected the positive of the battery holder to A1, the result is negative.
You can try changing the cables (positive at A0 and negative at A1) and see how the positive voltage appears.
Finally, we will see how to make the ADS1115 launch an alert when it is running in comparator mode.
Comparator Mode
The comparator mode allows a comparison of the value obtained by one of the analog pins with a preset threshold.
As we have seen before, two types of comparisons can be configured: the traditional one or by a window.
If the traditional one is used, as long as the value exceeds the maximum threshold, the ALERT pin will be set to LOW. By default, it is always in the HIGH state.
If you use the type per window, it will change state whenever the high threshold is exceeded and whenever it falls below the low threshold.
With the Adafruit library, you can only work with a threshold, high threshold, and traditional mode. It has not implemented the other mode.
This is precisely what we will see next.
ADS1115 and Arduino UNO Connection
The circuit we are going to use is the same as the one we have seen in a previous section.
Follow the following scheme to connect the components.
The photoresistor or LDR is connected to pin A0, and we also connect an LED to the ALERT pin.
The idea is to set a threshold in the ADS1115, and every time you lower the brightness of that threshold, turn on the LED.
ADS1115 and NodeMCU ESP8266 Connection
The connection with the NodeMCU ESP8266 board is practically the same. Follow the following scheme.
As with the Arduino board, the photoresistor or LDR is connected to pin A0, and the LED to pin ALERT.
Now only programming remains.
Programming in Comparator Mode
Below is the complete code with the comparator example.
#include <Wire.h>
#include <Adafruit_ADS1015.h>
// Create class object
Adafruit_ADS1115 ads;
void setup (void)
{
Serial.begin (9600);
delay (200);
// Scale facto r
ads.setGain (GAIN_TWOTHIRDS);
// Start ADS1115
ads.begin ();
// Scale factor. By default the reference value is 6.144V
// The scale factor of this reference is 0.1875mV
float scale factor = 0.1875F;
// Comparator threshold at 2.5V
// To calculate, divide the (voltage / scale factor) * 1,000
float threshold = (2.5 / Scale factor) * 1000.0F;
Serial.print ("Threshold =");
Serial.println (threshold);
// Assign the threshold to analog pin A0
ads.startComparator_SingleEnded (0, threshold);
}
void loop (void)
{
// Only the comparison will be made after reading
short readADC0 = ads.getLastConversionResults ();
Serial.print ("ADC0:");
Serial.println (read ADC0);
delay (100);
}
The first part of the code is the same as the codes we have seen so far in this lesson, importing libraries and instance to the Adafruit_ADS1115 class.
In the setup () function, the serial communication starts, the scale factor is set, and the ADS1115 starts.
In the next part of the code, the high threshold of the comparator mode is set from line 20 to line 29.
The first thing is to declare a variable with the scale factor. Remember that by default, the scale factor is 0.1875mV, corresponding to 6.144V voltage reference.
The variable that stores this value is a scale factor of the float type.
The threshold must be set to a number that ranges from 0 to 32,767 (they are 15-bit resolution). The logical thing is to set a threshold voltage and then pass it to the number.
To do that conversion you have to apply the following formula:
The threshold voltage must be divided by the scale factor. It must be multiplied by 1,000 since the scaling factor is in millivolts, in case it is in Volts it would not be necessary
To assign the threshold in the ADS1115, you must use the ads.startComparator_SingleEnded (ADC, threshold) function.
The first parameter of the function indicates the analog pin to be used, and the second parameter indicates the threshold to be set.
It's that simple.
If, for example, you want to set a threshold of 2.5V, the number to use is the following.
In the loop () function, you must constantly check the value on the analog pin with the ads.getLastConversionResults () function so that the ADS1115 internally makes the comparison.
If the voltage on the A0 is greater than 2.5V, the ALERT pin of the ADS1115 will be in the LOW state, that is, the pin will be activated.
If the voltage at A0 is less than 2.5V, the ALERT pin will be in the HIGH state, that is, the pin will be deactivated.
By default, the ALERT pin works inverted.
Now there is only one thing left, upload the code to the board and try zooming in and out of light to the photoresistor or LDR.
You will see how, when the light hits the LED, the LED goes out, and when the light doesn't hit, the LED goes off.
With this, I conclude this lesson on the digital-analog converter.
The ADS1115 digital-analog converter can be a great ally when we need more analog pins or more precision in our projects.
It is very simple to use with an Arduino or an ESP8266 thanks to its I2C interface.
It allows working in different operating modes: single-ended mode, differential mode, or comparator mode.
Using one or the other will depend on the requirements of our project.
Thanks to the Adafruit library, its use with any of these two plates is very simple, and also the code is 100% compatible between them.