ADS1115 tutorial: a real ADC over i2c
A Raspberry Pi has no analogue input at all. An Uno has ten bits of a noisy one. The ADS1115 fixes both for a couple of dollars and two wires — and the setting that decides whether it's brilliant or useless isn't the one people touch first.
Why bother
Why use an i2c ADC at all
Your board probably has an ADC already, so the honest question is why add one. Three answers, and any single one is usually enough.
Resolution. An Arduino Uno's ADC is 10-bit: 5 V spread over 1024 steps is ~4.9 mV per count. The ADS1115 is 16-bit — and at its highest gain, a count is 7.8 µV. That's the difference between "the sensor moved" and "the sensor moved by this much".
Noise. Your microcontroller's ADC shares silicon with a CPU switching millions of times a second, and it references a supply rail that sags every time the board does something. The ADS1115 sits off to one side with its own reference. For anything slow and small — a thermocouple, a load cell, a battery under load — that isolation matters more than the bit count.
You might have no choice. The Raspberry Pi has no analogue inputs whatsoever. Not bad ones — none. And the ESP32's built-in ADC is notoriously non-linear near the rails. On both, an i2c ADC isn't an upgrade, it's the entry ticket.
Step 1
ADS1115 wiring and the ADDR pin
Four wires, plus one that decides your address:
- VDD / GND — 2–5.5 V. It runs happily from a Pi's 3.3 V or an Uno's 5 V.
- SDA / SCL — to your host. No level shifter needed on a 3.3 V host; on a 5 V Uno powering it from 5 V, everything is already at 5 V and fine.
- ADDR — tie it somewhere. GND →
0x48, VDD →0x49, SDA →0x4A, SCL →0x4B. - A0–A3 — your analogue inputs. ALRT is an optional interrupt output you can ignore at first.
The ADDR pin catches people. It has no internal pull-up or pull-down, so floating it leaves the address undefined — the chip may answer at a random address, answer intermittently, or not show up in a scan at all. If your brand-new ADS1115 is invisible, check ADDR before you check anything else.
Tying it to SDA or SCL looks alarming and is completely legitimate — the chip samples those lines at power-up before any traffic starts. It's the same trick the INA219 uses to reach sixteen addresses from two pins.
Scan first. You want 0x48 before you write a line of code. Be aware that 0x48–0x4B is a busy block: the PCF8591 ADC lives there too, and so do TI's power monitors — see the collision roundup if something else is already home.
Step 2
The ADS1115 gain setting decides everything
This is the one that matters, and it's the one tutorials skip past.
The ADS1115 has a programmable gain amplifier (PGA). It doesn't amplify your signal in any useful sense — it chooses what voltage range those 16 bits are spread across. Get it wrong and you either waste resolution or read nothing but full scale.
| PGA range | One count is | Use it for |
|---|---|---|
| ±6.144 V | ~188 µV | the default — and almost never the right choice |
| ±4.096 V | ~125 µV | a 0–3.3 V or 0–5 V sensor output |
| ±2.048 V | ~62.5 µV | most 3.3 V-referenced signals |
| ±1.024 V | ~31 µV | small sensor swings |
| ±0.512 V | ~15.6 µV | shunt voltages |
| ±0.256 V | ~7.8 µV | thermocouples, load cells |
Pick the smallest range your signal fits inside. A 0–1 V sensor read at the default ±6.144 V uses about a sixth of the ADC's span — you paid for 16 bits and got roughly 13. Switch to ±1.024 V and every bit lands on your actual signal.
And the trap: the PGA is not input protection. The absolute maximum on any input is VDD + 0.3 V. Setting ±6.144 V on a 3.3 V-powered chip does not let you measure 6 V — it lets you scale for 6 V while the input pin dies at 3.6 V. For anything above your supply, use a resistor divider and multiply in software.
Step 3 · Arduino
ADS1115 Arduino code: read a voltage
Install Adafruit's ADS1X15 library from the Library Manager:
#include <Adafruit_ADS1X15.h>
Adafruit_ADS1115 ads;
void setup() {
Serial.begin(115200);
if (!ads.begin(0x48)) { // 0x48 = ADDR tied to GND
Serial.println("No ADS1115 at 0x48 — check the ADDR pin!");
while (1);
}
// Smallest range your signal fits inside. NOT input protection.
ads.setGain(GAIN_ONE); // +/-4.096 V, 125 uV per count
}
void loop() {
int16_t raw = ads.readADC_SingleEnded(0); // channel A0
float volts = ads.computeVolts(raw);
Serial.print(raw); Serial.print(" -> ");
Serial.print(volts, 4); Serial.println(" V");
delay(500);
} The gain constants map to the table above: GAIN_TWOTHIRDS is ±6.144 V (the default), GAIN_ONE ±4.096 V, GAIN_TWO ±2.048 V, and so on up to GAIN_SIXTEEN at ±0.256 V. computeVolts() does the scaling for whichever you set, which is why you should let it rather than hard-coding a divisor.
Readings are signed: int16_t, not uint16_t. In single-ended mode negative values are just noise around zero, but they're real and your code should expect them.
Step 3 · Raspberry Pi
ADS1115 on the Raspberry Pi
This is the case where the ADS1115 isn't optional. Enable i2c first, then:
pip install adafruit-circuitpython-ads1x15 import time, board, busio
import adafruit_ads1x15.ads1115 as ADS
from adafruit_ads1x15.analog_in import AnalogIn
i2c = busio.I2C(board.SCL, board.SDA)
ads = ADS.ADS1115(i2c, address=0x48)
ads.gain = 1 # +/-4.096 V — see the gain table
chan = AnalogIn(ads, ADS.P0) # single-ended on A0
while True:
print("%6d %.4f V" % (chan.value, chan.voltage))
time.sleep(0.5) If that throws ValueError: No I2C device at address: 0x48, it's the same three suspects as always: ADDR floating, i2c not enabled, or wiring. Run i2cdetect -y 1 and trust the grid.
Going further
Differential mode, and four ADS1115s on one bus
Differential measures between two inputs rather than input-to-ground. That's how you read a load cell or a current shunt: the signal is a tiny difference sitting on a large common voltage, and reading it against ground would waste your whole range on the part you don't care about. It also cancels noise picked up equally by both wires. The cost is channels — four single-ended, or two differential pairs (A0-A1 and A2-A3).
int16_t raw = ads.readADC_Differential_0_1(); // A0 - A1 Four on one bus: tie each board's ADDR to a different pin — GND, VDD, SDA, SCL — and you get 0x48, 0x49, 0x4A and 0x4B. That's sixteen single-ended channels over the same two wires, with no multiplexer and no extra host pins. Need more than four? A TCA9548A gives each its own channel and the addresses can repeat.
One honest expectation: the ADS1115's top speed is 860 samples per second, and that's the chip, not the bus. It's a precision part, not a fast one — audio and vibration are out of scope. If you need speed over precision, the pin-compatible ADS1015 trades down to 12 bits for 3300 SPS, and it's a one-line change: same address, same wiring, same library.
Get one
Questions
ADS1115 FAQ
What is the ADS1115's i2c address?
0x48 by default, and 0x49, 0x4A or 0x4B depending on where you tie the ADDR pin — GND gives 0x48, VDD 0x49, SDA 0x4A and SCL 0x4B. Four addresses means four ADS1115s on one bus, so sixteen single-ended channels over two wires. Note that ADDR must be tied somewhere: left floating, the address is undefined and the chip may not answer a scan at all.
What's the difference between the ADS1115 and the ADS1015?
Resolution and speed, nothing else that matters. The ADS1115 is 16-bit at up to 860 samples per second; the ADS1015 is 12-bit at up to 3300 SPS. Same pinout, same addresses, same registers, same library — so you can swap one for the other and change one line. Take the 1115 unless you genuinely need the sample rate; sixteen bits of a slow signal beats twelve bits of a fast one for most sensor work.
Why do I need an external ADC when my board already has one?
Three reasons. Resolution: an Arduino Uno's ADC is 10-bit, so 5 V spread across 1024 steps is about 4.9 mV per count — the ADS1115 gives you 16 bits and, at its highest gain, resolution down to microvolts. Isolation: the ADS1115 has its own reference and sits away from the noisy digital rails your microcontroller's ADC shares. And the ESP32's built-in ADC is famously non-linear, while the Raspberry Pi has no analogue input at all — on a Pi, an i2c ADC isn't an upgrade, it's the only option.
What does the gain (PGA) setting actually do?
It sets the input range the 16 bits are spread across, and it's the setting people get wrong first. At the default ±6.144 V, one count is about 188 µV. At ±0.256 V, one count is 7.8 µV — 24x finer, but any voltage above 0.256 V just pins at full scale. Pick the smallest range your signal fits inside. Critically, the PGA does not protect the input: exceeding VDD+0.3 V damages the chip regardless of gain.
What is differential mode for?
Measuring the voltage between two inputs rather than between one input and ground. It's how you read a load cell or a shunt, where the signal is a small difference riding on a large common voltage — and it rejects noise picked up equally by both wires. You trade channel count for it: four single-ended inputs, or two differential pairs.
Can I measure voltages above 5 V with an ADS1115?
Not directly. The absolute maximum on any input is VDD + 0.3 V, so a 5 V-powered ADS1115 tops out near 5.3 V no matter what the PGA is set to — the ±6.144 V range is about how the bits are scaled, not about input protection. For higher voltages put a resistor divider in front and do the maths in software.