Table of Contents
Toggle
In this article, we will explore the interfacing of an ADS1115 16-bit ADC module with the XIAO ESP32C3 microcontroller board developed by the Seeed Studio. ADS1115 is a 16-bit analog-to-digital converter (ADC) from Texas Instruments that can convert an analog voltage signal into a digital value with high precision. It can easily be interfaced with a variety of microcontrollers such as Arduino, ESP8266/32, STM32, etc.
The XIAO ESP32C3 is a small-sized development board based on the ESP32-C3 chip, which is a highly integrated Wi-Fi 6 and Bluetooth 5.0 chip. The XIAO ESP32C3 board has a compact design and is compatible with the Arduino development environment, making it an ideal choice for IoT projects.
The XIAO ESP32C3 microcontroller has a built-in 12-bit analog-to-digital converter (ADC) that can be used to measure analog signals. However, the ADC’s accuracy depends on its resolution and nonlinearity.
Limitation in Resolution:
The ESP32’s ADC has a resolution of 12 bits, which means it can detect changes in voltage as small as 0.000244 V (3.3V / 2^12).
Limitation in Nonlinearity:
The built-in 12-bit ADC has a common issue with nonlinearity that can affect the accuracy of measurements. The nonlinearity can cause the ADC to produce non-linear output, which can be problematic when trying to accurately measure analog signals.
ADS1115 Analog-to-Digital Converter Module with XIAO ESP32
This behavior means that your ESP32 is not able to distinguish 3.3 V from 3.2 V. You’ll get the same value for both voltages: 4095. The same happens for very low voltage values: for 0 V and 0.1 V you’ll get the same value: 0
Solution:
By interfacing the ADS1115 module, which has a 16-bit ADC resolution, the ADC capabilities of XIAO ESP32 can be significantly improved. With the ADS1115, the smallest voltage that can be measured is 3.3V / 65536 = 0.000076V (76uV), providing higher precision for your projects.
You may see my DIY Solar Projects.
Bill Of Materials ( BOM ):
SL No.
|
Components
|
Quantity
|
Buying Link
|
1
|
XIAO ESP32C3
|
1
|
|
2
|
ADS1115 Module
|
1
|
|
3
|
Resistor 33K
|
1
|
|
4
|
Resistor 100K
|
1
|
|
5
|
Jumper Wires
|
1
|
|
6
|
18650 Battery
|
1
|
|
7
|
Battery Holder
|
1
|
|
8
|
Bread Board
|
1
|
Overview Of Seeed Studio ESP32C3 Board:
Seeed Studio XIAO ESP32C3 is an IoT mini development board based on the Espressif ESP32-C3 WiFi/Bluetooth dual-mode chip. ESP32-C3 is a 32-bit RISC-V CPU, which includes an FPU (Floating Point Unit) for 32-bit single-precision arithmetic with powerful computing power. It has excellent radio frequency performance, supporting IEEE 802.11 b/g/n WiFi, and Bluetooth 5 (LE) protocols. This board comes included with an external antenna to increase the signal strength for your wireless applications. It also has a small and exquisite form factor combined with a single-sided surface-mountable design.
Features:
- Powerful CPU: ESP32-C3, 32bit RISC-V singlecore processor that operates at up to 160 MHz
- Complete WiFi subsystem: Complies with IEEE 802.11b/g/n protocol and supports Station mode, SoftAP mode, SoftAP + Station mode, and promiscuous mode
- Bluetooth LE subsystem: Supports features of Bluetooth 5 and Bluetooth mesh
- Ultra-Low Power: Deep sleep power consumption is about 43μA
- Better RF performance: External RF antenna included
- Battery charging chip: Supports lithium battery charge and discharge management
- Rich on-chip resources: 400KB of SRAM, and 4MB of on-board flash memory
- Ultra-small size: As small as a thumb(20×17.5mm) XIAO series classic form-factor for wearable devices and small projects
- Reliable security features: Cryptographic hardware accelerators that support AES-128/256, Hash, RSA, HMAC, digital signature and secure boot
- Rich interfaces: 1xI2C, 1xSPI, 1xI2S, 2xUART, 11xGPIO(PWM), 4xADC, 1xJTAG bonding pad interface
- Single-sided components, surface mounting design
Pinout diagram:
Overview Of ADS1115 Module / Breakout Board:
ADS1115 is an analog-to-digital converter module with a 16-bit resolution. It is a low-power device and operates at a voltage range of 2.0-5.5V. It has a programmable gain amplifier that allows for voltage measurements ranging from ±256mV to ±6.144V. The ADS1115 uses the I2C protocol to communicate with other devices, such as the ESP32.
Features and Specifications Of ADS1115 Module:
This section mentions some of the features and specifications of the ADS1115 module:
- Supply voltage range: 2-5.5V
- 16-bit ADC
- Continuous current consumption: 150uA
- I2C interface
- Internal Oscillator
- Programmable data rate: 8SPS to 860SPS
- 860 samples/second over I2C
ADS1115 Module Pinout:
Pin. No. | Pin Name | Pin Description |
1 | VDD | Power supply: 2.0V to 5.5V |
2 | GND | Ground |
3 | SCL | Serial clock input: Clocks data on SDA (used for I2C communication) |
4 | SDA | Serial data: Transmits and receives data (used for I2C communication) |
5 | ADDR | I2C address select (slave) |
6 | ALERT/RDY | Digital comparator output or conversion ready |
7 | AIN0 | Differential channel 1: Single-ended channel 1 input or Negative input |
8 | AIN1 | Differential channel 1: Single-ended channel 2 input or Negative input |
9 | AIN2 | Differential channel 2: Single-ended channel 3 input or Positive input |
10 | AIN3 | Differential channel 2: Single-ended channel 4 input or Negative input |
Battery Voltage Level Monitoring:
In this section, we will use ADS1115 16-Bit ADC Module with XIAO ESP32C3 to measure the voltage of a 18650 Li-Ion battery with higher precision.
ADS1115 is 16 bit which means the minimum step of each voltage level is between 0 and 65536. Analog channel produces a digital value between 0 and 65536 according to the voltage at the input of the analog channel. For example 3.3V / 65536 = 0.000050354V (50.354uV),
- If the voltage is 0 at the input of the analog channel, the digital value will be zero.
- If the voltage is 3.3 volt at the input, the digital value will be 65535. So the maximum voltage limit is 3.3 volt.
- But we can measure higher voltage else by using voltage step-down methods like the voltage divider method
The battery we’re using here outputs a maximum of 4.2V when fully charged, but the ADS work at 3.3V. So, we need to add a voltage divider so that we’re able to read the voltage from the battery.
Wiring the XIAO ESP32 with the ADS1115:
- Connect the ADS1115 16-Bit ADC Module to the ESP32 using the I2C interface. Connect the SDA and SCL pins of the ADS1115 to the corresponding pins on the ESP32, and connect the VCC and GND pins of the ADS1115 to the 3.3V and GND pins on the ESP32, respectively.
- Connect the 18650 battery to the voltage divider circuit using R1 and R2. Connect the positive terminal of the battery to one end of R1, and connect the other end of R1 to one end of R2. Connect the other end of R2 to the negative terminal of the battery.
- Connect the output of the voltage divider circuit to one of the input channels of the ADS1115. The ADS1115 has four input channels, so you can choose any one of them to connect to the voltage divider output. Here I have connected to pin A0.
The voltage divider formula is as follows:
Vout = (Vin*R2)/(R1+R2)
So, if we use R1=33k Ohm, and R2=100k Ohm, we get:
Vout = (4.2*100k)/(33k + 100k) = 3.1578V which is less than 3.3V
So, when the battery is fully charged, the Vout outputs 3.1578V that we can easily read with ADS1115.
ARDUINO CODE/PROGRAM:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
#include <Wire.h> #include <Adafruit_ADS1X15.h> Adafruit_ADS1115 ads; const int batteryPin = 0; // Connect the positive terminal of the battery to AIN0 on the ADS1115 const float r1 = 33.0; // Resistance of R1 in kohms const float r2 = 100.0; // Resistance of R2 in kohms void setup() { Serial.begin(9600); Wire.begin(); ads.begin(); } void loop() { int16_t adcValue; float voltage; float bat_voltage; adcValue = ads.readADC_SingleEnded(batteryPin); voltage = adcValue * 0.0001875; // Convert the ADC value to voltage in volts bat_voltage = voltage*(r1 + r2) / r2; // Calculate the actual battery voltage using the voltage divider formula Serial.print("ADC Value: "); Serial.print(adcValue); Serial.println(" "); Serial.print("Battery voltage: "); Serial.print(bat_voltage); Serial.println(" V"); delay(1000); } |
Let’s go through the code line by line:
1 2 |
#include <Wire.h> #include <Adafruit_ADS1X15.h> |
We include the Wire library for I2C communication and the Adafruit_ADS1X15 library for interfacing with the ADS1115 ADC.
1 2 3 4 5 |
Adafruit_ADS1115 ads; const int batteryPin = 0; // Connect the positive terminal of the battery to AIN0 on the ADS1115 const float r1 = 33.0; // Resistance of R1 in kohms const float r2 = 100.0; // Resistance of R2 in kohms |
We declare an instance of the Adafruit_ADS1115
class as ads
. We also define three variables: batteryPin
represents the ADS1115 input pin connected to the positive terminal of the battery, r1
represents the value of the first resistor in the voltage divider circuit, and r2
represents the value of the second resistor in the voltage divider circuit.
1 2 3 4 5 |
void setup() { Serial.begin(9600); Wire.begin(); ads.begin(); } |
In the setup()
function, we initialize the serial communication, the I2C bus, and the ADS1115.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
void loop() { int16_t adcValue; float voltage; float bat_voltage; adcValue = ads.readADC_SingleEnded(batteryPin); voltage = adcValue * 0.0001875; // Convert the ADC value to voltage in volts bat_voltage = voltage*(r1 + r2) / r1; // Calculate the actual battery voltage using the voltage divider formula Serial.print("ADC Value: "); Serial.print(adcValue); Serial.println(" "); Serial.print("Battery voltage: "); Serial.print(bat_voltage); Serial.println(" V"); delay(1000); } |
In the loop()
function, we declare two variables – adcValue
and voltage
. The adcValue
variable stores the ADC reading for the battery voltage, and voltage
stores the actual battery voltage.
We first use the ads.readADC_SingleEnded()
function to read the ADC value for the battery voltage and store it in adcValue
.
Next, we convert the ADC value to voltage in volts using the formula voltage = adcValue * 0.0001875
, where 0.0001875 is the voltage resolution of the ADS1115 for the selected range.
Finally, we calculate the actual battery voltage using the voltage divider formula bat_voltage = voltage * (r1 + r2) / r1
, where we multiply the ADC voltage reading by the voltage divider ratio (r1 + r2) / r2
to get the actual battery voltage.
We then print the adc value and battery voltage to the serial monitor using Serial.print()
and Serial.println()
functions, with a delay of one second (delay(1000)
) between readings.
Testing the Code:
Now upload the above code, if all connections are correct, the serial monitor will show the ADC Value and the battery voltage value.
From the serial monitor, it is observed that the battery voltage reading is very stable and it is almost equal to the actual measured value.
Thus we can conclude that the ADS1115 16-Bit ADC Module has good accuracy and can be used for multipurpose applications.