101. Ток и напряжение: INA219 и ACS712
Ток меряют двумя способами. Можно поставить в цепь шунт — резистор малого сопротивления — и мерить падение на нём: INA219 делает это сам, со своим усилителем и АЦП, и отдаёт по I²C ток, напряжение и мощность. А можно пропустить ток через датчик Холла: ACS712 выдаёт напряжение, пропорциональное току, и его читает АЦП микроконтроллера. Первому нужно одно калибровочное число, второму — измеренный ноль, и у каждого есть место, где показания тихо врут.
АЦП — раздел 14, I²C — раздел 17, делители — раздел 62, подключение модулей — раздел 95.
Как это называется в документации
Оригинал Перевод shunt resistor шунт — резистор малого сопротивления в цепи тока high-side, low-side sensing шунт в плюсовом проводе и в минусовом current sense amplifier усилитель сигнала шунта calibration register калибровочный регистр LSB, current LSB вес младшего разряда; шаг измерения тока bus voltage напряжение шины — на нагрузке относительно земли Hall effect sensor датчик Холла sensitivity, mV/A чувствительность: милливольт на ампер zero-current output выход при нулевом токе ratiometric output выход, пропорциональный питанию
101.1 Шунт или датчик Холла
| INA219 | ACS712 | |
|---|---|---|
| принцип | шунт, усилитель и АЦП внутри микросхемы | датчик Холла с аналоговым выходом |
| выход | числа по I²C: ток, напряжение, мощность | напряжение: 185 мВ/А у версии на 5 А |
| цепь тока | через шунт, общая с измерением | через саму микросхему, отделена от выхода |
| что настраивать | калибровочный регистр | ноль — измерить без нагрузки |
| слабое место | предел ±320 мВ на шунте | ноль и чувствительность зависят от питания 5 В |
101.2 INA219: шунт и калибровка
INA219 меряет напряжение на шунте (10 мкВ на единицу, до ±320 мВ при усилении по умолчанию) и напряжение шины (4 мВ на единицу), а ток и мощность считает сам — если знает калибровку. Её задают одним числом: CAL = 0,04096 / (I_LSB · R_шунта), где I_LSB — шаг измерения тока.
Шаг выбирают из наибольшего тока: 3,2 А / 32768 = 97,656 мкА — и округляют вверх до удобных 100 мкА. С шунтом 0,1 Ом получается CAL = 4096, а шаг мощности — всегда 20 шагов тока — 2 мВт. Слово настройки после сброса — 0x399F: шкала шины 32 В, шунт ±320 мВ, 12 бит, измерения непрерывно. Шкала шире, чем терпит сам чип: на входах INA219 выдерживает не больше 26 В, и шину выше 26 В к нему не подключают.
#define INA_CONFIG(brng, pg, badc, sadc, mode) \
((uint16_t)((brng) << 13 | (pg) << 11 | (badc) << 7 | (sadc) << 3 | (mode)))
uint16_t ina_cal(uint32_t ilsb_ua, uint32_t rshunt_mohm)
{
return (uint16_t)(40960000u / (ilsb_ua * rshunt_mohm));
}
После включения калибровочный регистр пуст, и пока в него ничего не записано, регистры тока и мощности показывают нули.
101.3 Чтение и перевод
Регистры INA219 — 16-битные, старшим байтом вперёд; шунт и ток — числа со знаком, у шины значение — в битах 15:3, а младший бит — переполнение расчёта тока или мощности (OVF):
int32_t ina_bus_mv(uint16_t reg)
{
return (int32_t)(reg >> 3) * 4;
}
int32_t ina_current_ua(uint16_t reg, uint32_t ilsb_ua)
{
return (int16_t)reg * (int32_t)ilsb_ua;
}
uint32_t ina_power_uw(uint16_t reg, uint32_t ilsb_ua)
{
return reg * 20u * ilsb_ua; /* шаг мощности — 20 шагов тока */
}
int ina_read(uint32_t ilsb_ua, int32_t *bus_mv, int32_t *cur_ua, uint32_t *pow_uw)
{
uint16_t s, b, c, p;
if (!i2c_read_reg16(INA_ADDR, INA_REG_SHUNT, &s) || !i2c_read_reg16(INA_ADDR, INA_REG_BUS, &b)
|| !i2c_read_reg16(INA_ADDR, INA_REG_CURRENT, &c) || !i2c_read_reg16(INA_ADDR, INA_REG_POWER, &p))
return 0;
if ((b & 1u) || (int16_t)s >= 32000 || (int16_t)s <= -32000)
return 0; /* OVF или шунт на пределе ±320 мВ */
*bus_mv = ina_bus_mv(b);
*cur_ua = ina_current_ua(c, ilsb_ua);
*pow_uw = ina_power_uw(p, ilsb_ua);
return 1;
}
На компьютере вместо шины — модель регистров, которая считает ток и мощность так же, как сам чип: из напряжения шунта и калибровки. Ток 1 А через 0,1 Ом — это 100 мВ на шунте (10 000 единиц) и регистр тока 10 000, то есть 1,000 А; шина 12 В — регистр 0x5DC2, из него 12 000 мВ; мощность — 12 Вт. Ток в обратную сторону, −0,5 А, даёт в регистре шунта 0xEC78 — отрицательное число в дополнительном коде. А 3,3 А — это 330 мВ на шунте, за пределом ±320 мВ — полной шкалы шунта, 32 000 единиц. Бит OVF чип ставит, только когда не помещаются вычисленные ток или мощность, а при CAL = 4096 ток с полной шкалы — 32 000, в регистр он помещается. В модели так и вышло: шунт 0x7D00, ток 32 000, OVF не встал. Поэтому драйвер смотрит и на сам регистр шунта: ±32 000 и дальше — ошибка вместо неверного числа.
101.4 ACS712: датчик Холла и его ноль
ACS712 на 5 А выдаёт половину своего питания при нулевом токе и прибавляет 185 мВ на каждый ампер. При питании 5 В это 1,575…3,425 В на ±5 А — больше, чем выдержит вход АЦП на 3,3 В, поэтому выход идёт через делитель 2/3 (10 кОм и 20 кОм). Коды АЦП для ±5 А — 1303…2833, по 6,53 мА на код:
int32_t acs_ma(int32_t code, int32_t zero_code)
{
int64_t n = (int64_t)(code - zero_code) * 4950000;
const int64_t d = 757575; /* 4095 · 185 */
return (int32_t)((n + (n < 0 ? -d / 2 : d / 2)) / d);
}
Ток считается от кода нуля, и вот почему его надо мерить, а не брать «половину шкалы». Ноль и чувствительность ACS712 пропорциональны его собственному питанию 5 В, а АЦП меряет относительно своих 3,3 В — эти два напряжения не связаны. При питании ровно 5,0 В код нуля — 2068, при +1 А — 2221, то есть 1000 мА. Просело питание до 4,9 В — ноль ушёл на код 2027, и с нулём, снятым при 5,0 В, датчик показывает −268 мА без всякого тока. Если ноль перемерить, +1 А даёт код 2177 — 980 мА: вместе с питанием на 2 % упала и чувствительность.
Отсюда правила: ноль мерить без нагрузки при каждом запуске, питание датчика держать стабильным, а если нужна точность — мерить само 5 В вторым каналом АЦП через такой же делитель и поправлять чувствительность.
101.5 Где ставить шунт
Шунт в плюсовом проводе оставляет землю нагрузки землёй: у прибора, который делит землю с другими, это обычно единственный правильный вариант, и INA219 сделан именно для него — меряет шину до 26 В при своём питании 3,3 В. Шунт в минусовом проводе проще для усилителя, но «земля» нагрузки тогда плавает на величину падения на шунте, и всё, что подключено к нагрузке, видит этот сдвиг.
101.6 Грабли
INA219 показывает ток и мощность ноль. Не записан калибровочный регистр: после включения он пуст, и чип ничего не считает.
Ток INA219 скачет в сотни раз. Регистр прочитан младшим байтом вперёд; у INA219 старший первым.
При большом токе показание «замерло». На шунте больше ±320 мВ: регистр шунта упёрся в ±32 000, а бит OVF может и не встать — он про переполнение расчёта. Проверять регистр шунта; меньше шунт или другое усиление.
ACS712 показывает ток без нагрузки. Ноль взят половиной шкалы, а питание датчика не ровно 5 В: при 4,9 В — −268 мА из ниоткуда. Мерить ноль без нагрузки.
Показания ACS712 плавают вместе с питанием 5 В. Выход пропорционален его питанию, а опора АЦП — своя.
Выход ACS712 — прямо на вход АЦП. До 3,425 В на пяти амперах — больше 3,3 В. Делитель.
101.7 Итоги
- INA219: CAL = 0,04096 / (I_LSB · R_шунта); для 0,1 Ом и шага 100 мкА — 4096, шаг мощности — 2 мВт; без калибровки ток и мощность — нули.
- Регистры по 16 бит старшим байтом вперёд; шунт и ток — со знаком; младший бит регистра шины — переполнение расчёта тока или мощности; выход шунта за ±320 мВ видно по его регистру (±32 000).
- ACS712 на 5 А: 185 мВ/А от середины питания; через делитель 2/3 — 6,53 мА на код АЦП.
- Ноль ACS712 мерить без нагрузки: при питании 4,9 В ноль от 5,0 В даёт −268 мА, а чувствительность падает на 2 %.
- Шунт — в плюсовом проводе, чтобы земля нагрузки оставалась землёй.
Дальше: раздел 101а «Монитор тока и мощности INA226: 16 бит, калибровочный регистр, усреднение, тревога по порогу и счёт энергии» — тот же шунт, но шаг вчетверо мельче, усреднение и тревога внутри микросхемы и счёт миллиампер-часов.