4-CH 16-Bit ADS1115 ADC Module SKU: CQRADC001
Contents
- 1 Description
- 2 Features
- 3 Certification Documents
- 4 Pin Description and Size
- 5 Specification
- 6 Working Principle
- 7 Power Supply and Sensor Compatibility
- 8 Connections and Examples
- 9 Arduino Example and Test Code
- 10 Raspberry Pi Example and Test Code
- 11 Used in Conjunction with the TDS Meter Sensor (SKU: CQRSENTDS01 / ASIN: B08KXRHK7H)
Description
The 4-channel 16-bit ADS1115 ADC Module is a high-precision analog-to-digital conversion solution based on the TI ADS1115IDGSR chip. This module provides four 16-bit precision analog input channels, supports both 3.3V and 5V operation, and features a hardware-configurable I2C address. The module also integrates an NTC temperature measurement interface, enabling multi-channel signal acquisition and temperature monitoring.
Features
- High-Precision 16-bit ADC Chip: Based on the TI ADS1115IDGSR chip, it provides four 16-bit resolution analog input channels, enabling high-precision signal acquisition.
- Flexible Input Modes: Supports 4 single-ended inputs or 2 differential inputs, suitable for various sensor signal measurement scenarios.
- Configurable I2C Address: Configurable via the ADDR pin, supporting 4 I2C addresses to facilitate multi-device networking.
- Wide Sampling Rate Range: Supports programmable sampling rates from 8 SPS to 860 SPS, meeting the requirements of different applications.
- Integrated NTC Temperature Measurement Interface: Onboard MF52AT 10KΩ NTC temperature sensor interface with a B value of 3950K, ideal for temperature monitoring applications.
- Dual-Voltage Compatible Design: Supports 3.3V/5V dual-voltage operation, with a built-in LP5907 LDO providing stable 3.3V power.
- Automatic Level Conversion: I2C signals are automatically converted to 3.3V levels when powered by 5V, allowing direct connection to 3.3V microcontrollers.
- Standard Interface Design: Equipped with HY2.0mm 4P connectors and 2.54mm pin headers for easy connection to various development boards.
Certification Documents
Media:CQRADC001-CE-Certification.rar
Media:CQRADC001-FCC-SDOC-Certification.rar
Pin Description and Size
Specification
Working Principle
Power Supply and Sensor Compatibility
This module supports dual-voltage operation at 3.3V/5V. When powered at 3.3V, all I/Os are at 3.3V level; when powered at 5V, the I2C signals are automatically converted to 3.3V for communication with the host, while also allowing measurement of 5V sensor signals. The module includes built-in protection circuits to prevent damage from overvoltage and provides a 3.3V LDO output to power external sensors.
Important: When measuring 5V sensors, the module must be powered at 5V. In this case, the I2C signals remain at 3.3V level and can be directly connected to 3.3V host GPIO. Note that the SDA and SCL pins on this module are limited to 3.3V.
Connections and Examples
- Configuration Method:
Use a jumper cap to connect the ADDR pin to the corresponding voltage level point. After configuration, restart the power for the changes to take effect.
- Using an I2C Address Conversion Module for Configuration:
When using an I2C address conversion module, all ADS1115 modules can be set to the same hardware address. Address differentiation is achieved by selecting channels on the conversion module, eliminating the need to modify hardware jumper configurations.
Arduino Example and Test Code
#include <Wire.h>
#include <Adafruit_ADS1X15.h>
Adafruit_ADS1115 ads;
void setup() {
Serial.begin(9600);
ads.begin(0x48);
ads.setGain(GAIN_ONE);
}
void loop() {
int16_t adc = ads.readADC_SingleEnded(0);
float voltage = adc * 0.125 / 1000.0;
float ntc_r = (3.3 * 10000.0 / voltage) - 20000.0;
float temp = 1.0 / (log(ntc_r / 10000.0) / 3950.0 + 1.0 / 298.15) - 273.15;
Serial.print("Temp: ");
Serial.print(temp, 1);
Serial.println("C");
delay(1000);
}
Example Results Explanation:
- Temporarily set the I2C address to 0x48. You can modify this line of code as needed: ads.begin(0x48).
- Temporarily set the input channel to AIN0. You can modify this line of code as needed: int16_t adc = ads.readADC_SingleEnded(0).
- To use the 5V measurement device, replace the conversion formula with the following:
float ntc_r = (5.0 * 10000.0 / voltage) - 20000.0; // Modify to 5V float temp = 1.0 / (log(ntc_r / 10000.0) / 3950.0 + 1.0 / 298.15) - 273.15;
Raspberry Pi Example and Test Code
Raspberry Pi 4B Pinout Diagram
- Create a folder and a “.c” file, then write the code.
- You can directly add to the compressed file.
gcc -Wall -g -o ADS1115 ADS1115.c -lm
./ADS1115
Go to the folder created in the terminal, use GCC cross-compilation and run the file.
- Sample Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <math.h>
#define ADS1115_ADDR 0x48
int main() {
int fd = open("/dev/i2c-1", O_RDWR);
if (fd < 0) return 1;
if (ioctl(fd, I2C_SLAVE, ADS1115_ADDR) < 0) return 1;
while(1) {
unsigned char config[3] = {0x01, 0xC2, 0x83};
unsigned char result[2];
write(fd, config, 3);
usleep(8000);
unsigned char reg[1] = {0x00};
write(fd, reg, 1);
read(fd, result, 2);
int16_t adc = (result[0] << 8) | result[1];
float voltage = adc * 0.125 / 1000.0;
float ntc_r = (3.3 * 10000.0 / voltage) - 20000.0;
float temp = 1.0 / (log(ntc_r / 10000.0) / 3950.0 + 1.0 / 298.15) - 273.15;
printf("Temp: %.1fC\n", temp);
sleep(1);
}
return 0;
}
- Test Results:
- Temporarily set the I2C address to 0x48. You can modify this line of code as needed: #define ADS1115_ADDR 0x48.
- Temporarily set the input channel to AIN0. You can replace it with the following code based on actual needs:
AIN0: 0xC2
AIN1: 0xD2
AIN2: 0xE2
AIN3: 0xF2
Used in Conjunction with the TDS Meter Sensor (SKU: CQRSENTDS01 / ASIN: B08KXRHK7H)
- Example Program
- Create a folder and a .c file, write the code into it, and then you can directly add it to the compressed archive: Media: ADSTDS.rar
gcc -o ADSTDS ADSTDS.c -lwiringPi ./ADSTDS
- Example Code
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <math.h>
#include <time.h>
#define VREF 5.0f
#define SCOUNT 30 // number of sampling points
#define TEMPERATURE 25.0f // water temperature (degrees celsius)
int analogBuffer[SCOUNT];
int analogBufferTemp[SCOUNT];
int analogBufferIndex = 0;
float averageVoltage = 0, tdsValue = 0;
int ads1115_fd;
// function declaration
int getMedianNum(int bArray[], int iFilterLen);
int readADS1115();
unsigned long my_millis();
unsigned long my_millis() {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
}
int getMedianNum(int bArray[], int iFilterLen) {
int bTab[iFilterLen];
for (int i = 0; i < iFilterLen; i++) {
bTab[i] = bArray[i];
}
int i, j, bTemp;
for (j = 0; j < iFilterLen - 1; j++) {
for (i = 0; i < iFilterLen - j - 1; i++) {
if (bTab[i] > bTab[i + 1]) {
bTemp = bTab[i];
bTab[i] = bTab[i + 1];
bTab[i + 1] = bTemp;
}
}
}
if ((iFilterLen & 1) > 0) {
bTemp = bTab[(iFilterLen - 1) / 2];
} else {
bTemp = (bTab[iFilterLen / 2] + bTab[iFilterLen / 2 - 1]) / 2;
}
return bTemp;
}
int readADS1115() {
// configuration ADS1115: aisle 0
uint16_t config = 0xC283;
wiringPiI2CWriteReg16(ads1115_fd, 0x01, (config >> 8) | (config << 8));
usleep(8000);
uint16_t result = wiringPiI2CReadReg16(ads1115_fd, 0x00);
int16_t adc = ((result >> 8) & 0xFF) | ((result & 0xFF) << 8);
static int debug_count = 0;
if (debug_count++ % 20 == 0) {
printf("[original ADC: %d] ", adc);
}
int adc_abs = abs(adc);
// convert to estimated value (0-1023)
int arduino_value = (adc_abs * 1024) / 30000;
// limited to 0-1023 scope
if (arduino_value > 1023) arduino_value = 1023;
if (arduino_value < 0) arduino_value = 0;
return arduino_value;
}
int main() {
printf("=== Raspberry Pi TDS measurement ===\n");
printf("TDS = 133.42*V^3 - 255.86*V^2 + 857.39*V * 0.5\n\n");
// initialization wiringPi
if (wiringPiSetup() < 0) {
printf("wiringPi initialization failed\n");
return 1;
}
// initialization ADS1115
ads1115_fd = wiringPiI2CSetup(0x48);
if (ads1115_fd < 0) {
printf("ADS1115 initialization failed (address 0x48)\n");
printf("check, please: sudo i2cdetect -y 1\n");
return 1;
}
printf("✓ hardware initialization complete\n");
printf("start measuring...\n");
printf("----------------------------------------\n");
// time point variable (using custom my_millis)
unsigned long analogSampleTimepoint = my_millis();
unsigned long printTimepoint = my_millis();
while (1) {
unsigned long currentMillis = my_millis();
if (currentMillis - analogSampleTimepoint > 40U) {
analogSampleTimepoint = currentMillis;
int arduinoValue = readADS1115();
analogBuffer[analogBufferIndex] = arduinoValue;
analogBufferIndex++;
if (analogBufferIndex == SCOUNT) {
analogBufferIndex = 0;
}
}
if (currentMillis - printTimepoint > 800U) {
printTimepoint = currentMillis;
for (int copyIndex = 0; copyIndex < SCOUNT; copyIndex++) {
analogBufferTemp[copyIndex] = analogBuffer[copyIndex];
}
int medianValue = getMedianNum(analogBufferTemp, SCOUNT);
averageVoltage = medianValue * VREF / 1024.0;
float compensationCoefficient = 1.0 + 0.02 * (TEMPERATURE - 25.0);
float compensationVoltage = averageVoltage / compensationCoefficient;
tdsValue = (133.42 * compensationVoltage * compensationVoltage * compensationVoltage
- 255.86 * compensationVoltage * compensationVoltage
+ 857.39 * compensationVoltage) * 0.5;
printf("TDS Value: %.0fppm", tdsValue);
printf(" (ADC:%d, Volt:%.3fV)\n", medianValue, averageVoltage);
fflush(stdout);
}
usleep(1000);
}
return 0;
}
- Test Results Explanation:
The raw ADC value is the raw 16-bit analog-to-digital conversion data from the ADS1115; the ADC value is the stable value after median filtering; the voltage value is the calculated corresponding voltage value; and the TDS value represents the total dissolved solids content of the water. The I2C address is 0x48; the analog port is AIN0.


