INA219: подключение датчика тока и напряжения к Arduino по I2C
INA219 измеряет ток и напряжение в разрыве питания нагрузки и отдаёт результат по шине I2C. Модуль ставится последовательно с нагрузкой, ток считается по падению напряжения на шунте, а на Arduino нужны всего четыре провода.
Главное, что надо знать про модуль заранее: у него два разных шунта, 0,1 Ом с пределом 3,2 А и 0,02 Ом с пределом 14,5 А. Ошибиться с этим можно один раз, и тогда датчик будет молча упираться в предел.
Первый раз я подключил INA219 к 12 вольтовому питанию и увидел ток 0,8 ампера при выключенной нагрузке. Причина была не в датчике: я не соединил землю модуля с землёй нагрузки, и напряжение шины считалось не от того нуля.
Как устроен датчик: шунт, усилитель и АЦП
INA219 устроен просто и понятно. Резистор шунта стоит в разрыве измеряемой линии, напряжение на нём усиливается и попадает в 12-битный преобразователь. Рядом тот же преобразователь меряет напряжение между шиной и землёй, а процессор считает ток и мощность.
| Параметр | Значение |
|---|---|
| Напряжение шины | от 0 до 26 В |
| Разрешение АЦП | 12 бит |
| Цена деления напряжения шины | 1,3 мВ |
| Диапазон усиления | ±40, ±80, ±160, ±320 мВ |
| Цена деления на шунте | 10, 20, 40, 80 мкВ |
| Адрес I2C | 0x40 |
| Питание логики | от 3,0 до 5,5 В |
Усиление выбирают по ожидаемому току. Диапазон 40 милливольт самый чувствительный: цена деления 10 микровольт, и при шунте 0,1 Ом это 100 микроампер на одно показание. Диапазон 320 милливольт выдерживает ток до 3,2 А, но на малом токе шаг становится грубым.
Два шунта: 0,1 Ом и 0,02 Ом
На модуле стоит резистор, и от его номинала зависит всё остальное: и предел тока, и точность, и падение напряжения, которое вы теряете на нагрузке.
| Параметр | Шунт 0,1 Ом | Шунт 0,02 Ом |
|---|---|---|
| Предел тока | 3,2 А | 14,5 А |
| Потери на шунте при 1 А | 0,1 В | 0,02 В |
| Нагрев при 1 А | 0,1 Вт | 0,02 Вт |
| Ток одного показания | 100 мкА | 500 мкА |
| Считать для | лабораторных и бытовых нагрузок | двигателей и зарядок |
Обратите внимание на вторую строку таблицы. Шунт это не бесплатный элемент: на нём всегда теряется напряжение. При 0,1 Ом и токе 2 А вы теряете 0,2 В, и для схемы с питанием 5 В это уже четыре процента напряжения на нагрузке.
Подключение: модуль в разрыв питания
- VIN+ подключается к источнику питания, VIN- к нагрузке, модуль стоит в разрыв плюса.
- VCC питает логику датчика, на модуле это 3,3 или 5 В, и этому выводу нельзя дать 26 В.
- GND модуля соединяется с землёй нагрузки, иначе напряжение шины будет считаться неверно.
- SDA и SCL идут к шине I2C Arduino, на Uno это выводы A4 и A5.
- Направление тока задаётся тем, куда смотрит VIN+, при переполясовке ток уйдёт в минус.
- Модуль измеряет ток только в одну сторону, для обратного тока нужен второй датчик.
Формула и код
Ток считается по одной формуле: напряжение на шунте делится на сопротивление шунта. Удобство в том, что милливольты и омы дают миллиамперы напрямую, без пересчёта коэффициентов.
#include <Wire.h>#include <Adafruit_INA219.h> Adafruit_INA219 ina = Adafruit_INA219(0x40); void setup() { Serial.begin(115200); if (!ina.begin()) { Serial.println("INA219 ne nayden: proverit adres i pitanye"); while (true) delay(100); }} void loop() { float u = ina.getVoltage_V(); // napryazhenie shiny float s = ina.getShuntVoltage_mV(); // padenie na shunt float i = ina.getCurrent_mA(); // tok float p = ina.getPower_mW(); // moshchnost Serial.print("U: "); Serial.print(u, 3); Serial.print(" V "); Serial.print("Shunt: "); Serial.print(s, 2); Serial.print(" mV "); Serial.print("I: "); Serial.print(i, 1); Serial.print(" mA "); Serial.print("P: "); Serial.print(p, 1); Serial.println(" mW"); delay(1000);}#define ADRES 0x40#define R_SHUNT_OHM 0.1 // 0.1 Ohm ili 0.02 Ohm float current_mA() { Wire.beginTransmission(ADRES); Wire.write(0x01); // registr napryazheniya na shunt Wire.endTransmission(false); if (Wire.requestFrom(ADRES, 2) != 2) return -1; uint16_t raw = (uint16_t)Wire.read() << 8; // starshii bait pervym raw |= Wire.read(); int16_t shunt = (int16_t)raw; // dopolnitelnyi kod, tok mozhet byt otricatelnym float shunt_mV = shunt * 0.01f; // 10 mkV na odin schyotok return shunt_mV / R_SHUNT_OHM; // mV / Ohm = mA} void loop() { Serial.print("I: "); Serial.println(current_mA()); delay(500);}Регистры, которые пригодятся
| Адрес | Регистр | Что внутри |
|---|---|---|
| 0x00 | Configuration | диапазон усиления и частота замера |
| 0x01 и 0x02 | Shunt Voltage | напряжение на шунте, 12 бит |
| 0x03 и 0x04 | Bus Voltage | напряжение шины, 12 бит |
| 0x05 и 0x06 | Current | ток, 12 бит |
| 0x07 и 0x08 | Power | мощность, ток умноженный на напряжение |
| 0x09 | Calibration | цена деления тока и мощности |
Регистр калибровки задаёт, сколько миллиампер соответствует одному показанию. По даташиту Current_LSB равно цене деления напряжения на шунте, делённому на сопротивление шунта, а Power_LSB равно Current_LSB умноженному на 25. Библиотека считает это за вас, но если считаете ток сами, помните про эти два числа.
INA219 против ACS712 и мультиметра
Два других способа измерить ток дают другой результат, и разница не в цене, а в самом принципе. Датчик Холла ACS712 меряет магнитное поле и отдаёт аналоговое напряжение, а INA219 меряет падение напряжения на резисторе и отдаёт цифру.
| Критерий | INA219 | ACS712 | Мультиметр |
|---|---|---|---|
| Принцип | шунт и АЦП | эффект Холла | шунт или токовые клещи |
| Выход | I2C, цифра | аналог, 2,5 В на нуле | цифра на экране |
| Переменный ток | да, с оговорками | нет | да |
| Обратный ток | нет, нужен второй датчик | нет | да |
| Точность | около 1-2 процентов | около 2-5 процентов | 0,5 процента и лучше |
| Питание нагрузки | пропускает через себя | не пропускает | не пропускает |
| Цена | 150-400 руб | 100-300 руб | не сравнить |
Мультиметр точнее всего, но он не пишет лог и не следит за током в фоне. INA219 даёт поток чисел, которые можно сохранять и строить по ним график. Про то, как правильно мерить ток мультиметром и почему его нельзя включать параллельно нагрузке, написано в уроке про мультиметр.
Что сначала не получилось
Первый провал выглядел как поломка датчика: ток 0,8 ампера при полностью выключенной нагрузке. Я подключил мультиметр последовательно и увидел честный ноль. Через час я нарисовал схему на бумаге и понял, что земля модуля и земля нагрузки у меня разные: у блока питания была своя земля, и я её не связал с Arduino.
Второй раз датчик работал, но ток скакал: 1,7 ампера, потом 0,9, потом ноль. Я грешил на питание и на сопротивление проводов, пока не посмотрел на сам шунт. На модуле стоял 0,1 Ом, а я гонял через него зарядку для телефона, и шунт нагревался. При 2 амперах на нём рассеивалось 0,4 ватта, и это было видно на пальцах.
Личный опыт: контроль заряда батареи
Первое устройство с INA219 у меня было зарядным устройством для сборки аккумуляторов 18650. Нужно было видеть ток заряда и напряжение на ячейке, чтобы не перезарядить её.
Что выяснилось по ходу. Модуль с шунтом 0,02 Ом я поставил сразу, и он держал пиковые 6 амперов без просадки питания. При этом падение напряжения на шунте было 0,12 В, и его пришлось вычитать из показаний, иначе напряжение на ячейке выглядело на 120 милливольт больше настоящего. А ещё я обнаружил, что библиотека по умолчанию пересчитывает ток по своей калибровке, и при шунте 0,02 Ом цифры занижались примерно в пять раз, пока я не задал калибровку вручную.
Авторская позиция: когда INA219 уместен
Если задача разовая, например замерить ток зарядки и записать его в таблицу, то INA219 избыточен. Мультиметр даст то же самое быстрее и без единого провода к Arduino.
Датчик оправдан там, где ток надо видеть постоянно: ограничение по току, отключение по перегреву, накопление статистики, экономия заряда батареи. Тут цифровой поток с I2C окупается и точностью, и тем, что данные можно писать на карту памяти без участия человека.
И отдельно про шунт. Покупать модуль, не разобравшись, какой в нём резистор, бессмысленно: при неверном выборе либо получите копейку точности, либо упрётесь в предел. Сфотографируйте маркировку резистора на плате, измерьте его мультиметром и только потом подключайте нагрузку.