ADS1115: 16-битный АЦП для Arduino и работа с ним

Как устроен модуль внешнего АЦП ADS1115, какие у него режимы измерения и как подключить его к Arduino по шине I2C.
Зачем нужен внешний АЦП
У плат Arduino есть собственный аналого-цифровой преобразователь: он 10-битный и выведен на пины A0–A7. Для простых задач этого достаточно, но когда от измерений требуется высокая точность, скорость или гибкая настройка, встроенного АЦП начинает не хватать. В таких случаях ставят внешний преобразователь, и один из распространённых вариантов — модуль на микросхеме ADS1115 с разрешением 16 бит.
Помимо разрядности, у ADS1115 есть собственный источник опорного напряжения, программируемая частота дискретизации, усилитель с настраиваемым коэффициентом, встроенный компаратор и два режима измерения — одиночный (несимметричный) и дифференциальный.

Выводы и схема модуля
На плате десять контактов. VDD и GND — питание, допустимый диапазон от 2 до 5,5 В. SCL и SDA — линии шины I2C; подтягивающие резисторы уже установлены на модуле, внешние не нужны. Вывод ADDR выбирает один из четырёх адресов, ALRT — выход компаратора, A0–A3 — аналоговые входы.

По схеме: конденсаторы C1 и C2 фильтруют помехи по питанию, R2 и R3 подтягивают линии I2C к напряжению питания, R1 притягивает выход компаратора к низкому уровню, поэтому сигнал оповещения соответствует логической единице. Резистор R4 соединяет ADDR с минусом питания, и по умолчанию модуль отвечает по адресу 0x48. Переключив ADDR на другую линию, можно получить адреса 0x49, 0x4A или 0x4B, то есть на одной шине уживаются четыре таких модуля.

| Напряжение питания | 2–5,5 В |
| Минимальный ток потребления | 150 мкА |
| Разрешение | 16 бит |
| Интерфейс | I2C, адреса 0x48, 0x49, 0x4A, 0x4B |
| Входы | 4 несимметричных или 2 дифференциальных |
| Усилитель PGA | до x16 |
| Напряжение смещения | 100 мкВ |
| Скорость преобразования | 8–860 выборок/с |
| Рабочая температура | −40…+125 °C |
| Корпус микросхемы | X2QFN-10 или VSSOP-10 |
| Размер модуля | 28 x 16 мм |
Режимы измерения и усиление
Четыре входа коммутируются внутренним мультиплексором, причём в каждый момент времени активна только одна конфигурация. В одиночном режиме напряжение на каждом из четырёх каналов измеряется относительно общего провода микросхемы; отрицательные значения в нём получить нельзя. В дифференциальном режиме каналов два: измеряется разность потенциалов между A0–A1 и между A2–A3. Если на положительном входе напряжение выше, чем на отрицательном, результат положительный, иначе — отрицательный.

После мультиплексора сигнал проходит через программируемый усилитель PGA. У него шесть ступеней, и каждая задаёт верхнюю границу измеряемого напряжения и цену одного разряда:
- 2/3x — до ±6,144 В, 1 бит = 0,1875 мВ
- 1x — до ±4,096 В, 1 бит = 0,125 мВ
- 2x — до ±2,048 В, 1 бит = 0,0625 мВ
- 4x — до ±1,024 В, 1 бит = 0,03125 мВ
- 8x — до ±0,512 В, 1 бит = 0,015625 мВ
- 16x — до ±0,256 В, 1 бит = 0,0078125 мВ
Выходить за выбранный предел не рекомендуется, а напряжение питания модуля должно быть не меньше максимума измеряемого диапазона. Настройки усиления действуют сразу на все каналы — задать их для каждого входа отдельно не получится.
Подключение к Arduino и чтение каналов
Модуль подключается по I2C к любой плате Arduino. Для работы удобна библиотека Adafruit (заголовочный файл Adafruit_ADS1015.h, объект Adafruit_ADS1115). Усиление задаётся вызовом вида ads.setGain(GAIN_TWOTHIRDS), после чего выполняется ads.begin().
В примере с одиночным режимом на Arduino Nano задействованы все четыре входа: A0 измеряет линию 5 В платы, A1 — линию 3,3 В, A2 — пальчиковую батарейку, A3 — Li-Ion аккумулятор. Поскольку на вход попадает до 5 В, выбран коэффициент 2/3. Скетч раз в секунду читает каналы функцией readADC_SingleEnded(), умножает отсчёт на 0,1875 и делит на 1000, получая вольты, и выводит результат в монитор порта.
Дифференциальный режим полезен, когда нужна разность напряжений между двумя точками: контроль отдельных элементов в батарее или падение на токоизмерительном шунте. В примере пара A0–A1 измеряет напряжение аккумулятора, а пара A2–A3 — падение на резисторе 1 Ом в цепи электромотора, из которого вычисляется ток. Используются функции readADC_Differential_0_1() и readADC_Differential_2_3(). Соединять минус измеряемой цепи с общим проводом Arduino здесь не требуется. Плюс подаётся на каналы 0 и 2, минус — на 1 и 3; если перепутать провода, значения станут отрицательными, как у неправильно подключённого вольтметра.
Компаратор
Встроенный компаратор позволяет следить за порогом напряжения, например за окончанием заряда аккумулятора: при срабатывании он выдаёт сигнал на вывод ALRT. В демонстрационной схеме потенциометр меняет напряжение на входе AIN0 от 0 до 5 В, а светодиод на ALRT загорается при превышении 1,875 В. Порог задаётся в отсчётах АЦП: при усилении 2/3 один разряд равен 0,1875 мВ, поэтому 1,875 В соответствует числу 10000 — в скетче это вызов ads.startComparator_SingleEnded(0, 10000). Компаратор начинает работать после чтения результата функцией getLastConversionResults().
Измерение напряжений выше 6,144 В
Предел 6,144 В — максимум для входа ADS1115, более высокое напряжение выведет микросхему из строя. Чтобы измерять большие значения, перед входом ставят резистивный делитель, а в программе умножают результат на коэффициент деления. Для диапазона до 25 В в источнике рассчитан делитель из резисторов 120 кОм и 39 кОм: при 25,05 В на входе он даёт 25,05 x 39 / (120 + 39) = 6,144 В на выходе. В скетче измеренное значение домножается на 25,05 / 6,144.
Проект: блок питания с индикацией
В качестве практического примера описан регулируемый блок питания 0–24 В, 2 А, с выводом напряжения и тока на семисегментный индикатор. В нём используются ADS1115, понижающий DC-DC модуль LM2596 (его подстроечный резистор заменён выносным переменным на 10 кОм), восьмиразрядный индикатор с общим катодом на двух микросхемах 74HC595, источник 24 В, стабилизатор L7805, Arduino Pro Mini, делитель 120 кОм / 39 кОм для напряжения и резистор 0,47 Ом 5 Вт для измерения тока. Напряжение читается с канала 0, ток — с канала 1; программа делает по восемь замеров каждого параметра и усредняет их перед выводом.