103. Свет и газ: фоторезистор, BH1750, MQ
Три датчика с разной судьбой. Фоторезистор — просто сопротивление, которое падает на свету: делитель, вход АЦП и формула. BH1750 — готовый цифровой люксметр на I²C, но без карты регистров: ему шлют команды, а он отвечает двумя байтами. Газовый датчик MQ — чувствительный слой, который работает только горячим: внутри нагреватель на 5 В, и от него зависит всё остальное — питание, прогрев и показания.
Внутренний АЦП — раздел 14, шина I²C — раздел 17, подключение модулей и уровни — раздел 95.
Как это называется в документации
Оригинал Перевод photoresistor, LDR (light-dependent resistor) фоторезистор illuminance, lux (lx) освещённость, люкс gamma (γ) наклон характеристики фоторезистора в логарифмическом масштабе ambient light sensor датчик внешней освещённости measurement time register (MTreg) время интегрирования BH1750 continuous / one-time measurement непрерывное / однократное измерение heater нагреватель sensing resistance, Rs сопротивление чувствительного слоя load resistance, RL нагрузочный резистор preheat, burn-in прогрев cross-sensitivity чувствительность к посторонним газам hysteresis гистерезис
103.1 Фоторезистор в делителе
Сопротивление фоторезистора падает с освещённостью по степенному закону: R = R10 · (E / 10 лк)^(−γ), где R10 — сопротивление при 10 лк, а γ — наклон. Числа для примера — R10 = 15 кОм, γ = 0,7; у каждой серии свои, и разброс между экземплярами большой. Фоторезистор — к +3,3 В, резистор 10 кОм — к земле, середина — на вход АЦП: чем светлее, тем больше код.
| Освещённость | Примерно так | Сопротивление | Код АЦП |
|---|---|---|---|
| 1 лк | глубокие сумерки | 75 кОм | 481 |
| 10 лк | сумерки | 15 кОм | 1638 |
| 100 лк | очень пасмурный день | 3,0 кОм | 3152 |
| 1000 лк | пасмурный день | 597 Ом | 3864 |
| 10 000 лк | дневной свет в тени | 119 Ом | 4047 |
Делитель сжимает яркий конец шкалы. От 1 до 10 лк код проходит 1157 шагов, от 1000 до 10 000 лк — всего 183. Чувствительнее всего делитель там, где фоторезистор равен постоянному резистору: для 10 кОм это около 18 лк — комната с тусклым светом. Для яркого света резистор берут меньше: с 270 Ом на участок от 1000 до 10 000 лк приходится 1566 кодов, зато от 1 до 10 лк остаётся 57.
103.2 Код — в люксы
Перевод обратный: сопротивление из кода, освещённость из сопротивления.
float ldr_lux(uint16_t code)
{
if (code == 0)
return 0.0f;
if (code >= 4095)
return -1.0f;
float r = LDR_RF * (4095 - code) / code;
return 10.0f * powf(r / LDR_R10, -1.0f / LDR_GAMMA);
}
Код для 100 лк переводится обратно в 100,1 лк, для 1000 лк — в 998,4 лк: у 1000 лк один код — это 0,66 % показания. Крайние коды — не освещённость, а неисправность. Код 0 функция отдаёт как 0 лк, но при этом делителе это почти всегда обрыв фоторезистора: даже 0,01 лк даёт код около 21. Код 4095 — замыкание, и функция отвечает −1.
Фоторезистор медленный: на свет он откликается за десятки миллисекунд, на темноту — дольше. Да и R10 с γ известны приблизительно. Поэтому он хорош для решения «темно — светло» с гистерезисом, а люксы честнее мерить BH1750.
103.3 BH1750: команды вместо регистров
У BH1750 нет карты регистров: каждый записанный байт — команда, а чтение двух байтов отдаёт последний результат, старший байт первым. Адрес задаёт вывод ADDR: к земле — 0x23, к питанию — 0x5C. Модуль питают от 3,3 В; подтяжки SDA и SCL на нём обычно уже есть (раздел 95).
| Команда | Код | Что делает |
|---|---|---|
| включить | 0x01 | ждать команды измерения |
| сброс | 0x07 | обнулить результат; только во включённом состоянии |
| непрерывно, высокое разрешение | 0x10 | мерить без остановки, около 120 мс на измерение |
| однократно, высокое разрешение | 0x20 | одно измерение, затем сон |
int bh_start(uint32_t mt)
{
const uint8_t cmd[4] = { BH_POWER_ON, BH_MT_HI(mt), BH_MT_LO(mt), BH_CONT_H };
for (unsigned i = 0; i < 4; i++)
if (!i2c_send(BH_ADDR, &cmd[i], 1))
return 0;
return 1;
}
int bh_read(uint32_t mt, uint32_t *lux_x10)
{
uint8_t b[2];
if (!i2c_recv(BH_ADDR, b, 2))
return 0;
*lux_x10 = bh_lux_x10((uint16_t)(b[0] << 8 | b[1]), mt); /* старший байт первым */
return 1;
}
Каждая команда — отдельная запись в один байт. Модель на шине получила ровно 0x01, 0x42, 0x65, 0x10, а код 1000 драйвер перевёл в 833,3 лк: при времени интегрирования 69 освещённость — это код, делённый на 1,2. Первое измерение готово через 120 мс, в худшем случае через 180 мс; прочитанное раньше — ноль или старое значение. Лампы от сети 50 Гц мерцают с частотой 100 Гц, и за 120 мс проходит ровно 12 периодов — мерцание усредняется.
103.4 Время интегрирования
MTreg — время интегрирования: от 31 до 254, по умолчанию 69. Его задают двумя командами: старшие три бита — в 0x40, младшие пять — в 0x60; для 69 это 0x42 и 0x65. Люксов на один код — 69 / (1,2 · MTreg):
#define BH_MT_HI(mt) ((uint8_t)(0x40u | ((mt) >> 5)))
#define BH_MT_LO(mt) ((uint8_t)(0x60u | ((mt) & 0x1Fu)))
uint32_t bh_lux_x10(uint16_t raw, uint32_t mt)
{
return ((uint32_t)raw * 6900u + 6u * mt) / (12u * mt);
}
| MTreg | Люксов на код | Предел шкалы | Время измерения |
|---|---|---|---|
| 31 | 1,85 | 121 556,9 лк | около 54 мс |
| 69 | 0,83 | 54 612,5 лк | около 120 мс |
| 254 | 0,23 | 14 835,7 лк | около 442 мс |
Прямое солнце бывает ярче 54 612 лк, и при MTreg 69 код упирается в 65535: на улице ставят 31. В темноте наоборот: 254 даёт 0,23 лк на код ценой почти полсекунды на измерение. Считают в десятых долях люкса целыми числами, с округлением: FPU не нужен, а у F103 его и нет.
103.5 MQ: сначала нагреватель
Чувствительный слой датчиков MQ — оксид олова, и газ меняет его сопротивление, только пока слой горячий. Нагреватель у MQ-2 и MQ-135 — 33 Ом при 5 В: это 152 мА и 0,76 Вт, больше, чем всё остальное на плате. Отсюда правила:
- питать от 5 В, которые выдержат лишние 152 мА; от 3,3 В слой не прогреется, и показания бессмысленны;
- новый датчик прогревают сутки и дольше, а после каждого включения — несколько минут: пока слой не прогрелся, показания плывут;
- от батареи MQ не живёт: аккумулятор на 2000 мА·ч один нагреватель разрядит за 13 часов.
MQ-7 и MQ-9 греют ещё и циклами — высоким и низким напряжением попеременно, как велит их документация: там без ключа на нагревателе не обойтись.
103.6 Сопротивление слоя и делитель на 3,3 В
Слой Rs и нагрузочный резистор RL модуля образуют делитель от 5 В: чем больше газа, тем меньше Rs и тем выше напряжение на выходе AO. Отсюда Rs = RL · (Vc − Vout) / Vout. RL у каждого модуля свой, его номинал читают по маркировке на плате; в примере 10 кОм:
| Выход модуля | Rs |
|---|---|
| 0,5 В | 90 кОм |
| 1,0 В | 40 кОм |
| 2,5 В | 10 кОм |
| 4,0 В | 2,5 кОм |
Выход доходит до 5 В, а вход АЦП STM32 — до 3,3 В, и в аналоговом режиме вывод 5 В не терпит. Между ними делитель 10 кОм и 20 кОм: на вход приходят 2/3 напряжения, мерить можно до 4,95 В, и код 3309 — это 4000 мВ на выходе модуля.
Но делитель сам нагружает выход: его 30 кОм встают параллельно RL, и в формулу идёт 7,5 кОм, а не 10. Код 3309 — это Rs = 1875 Ом, а не 2500: с RL = 10 кОм сопротивление вышло бы на 33,3 % больше настоящего.
#define MQ_RL 10000u /* нагрузочный резистор модуля — по маркировке на плате */
#define MQ_DIV 30000u /* делитель к АЦП нагружает выход */
#define MQ_RL_EFF (MQ_RL * MQ_DIV / (MQ_RL + MQ_DIV))
uint32_t mq_rs(uint32_t vout_mv, uint32_t vc_mv, uint32_t rl_ohm)
{
if (vout_mv == 0)
return UINT32_MAX; /* слой оборван или нагреватель холодный */
if (vout_mv >= vc_mv)
return 0; /* выход у питания: замыкание */
return (uint32_t)((uint64_t)rl_ohm * (vc_mv - vout_mv) / vout_mv);
}
Делитель из 10 и 20 кОм — это 6,7 кОм на входе АЦП: время выборки нужно побольше (раздел 14). Цифровой выход DO модуля — компаратор с подстроечным резистором, обычно с подтяжкой к питанию модуля: при 5 В его подключают к выводу, терпимому к 5 В, и не в аналоговом режиме.
103.7 Чистый воздух и тревога
Концентрацию в ppm дешёвый MQ не даст: слой реагирует сразу на несколько газов, на влажность и на температуру, а сопротивление в чистом воздухе у каждого экземпляра своё. Надёжнее отношение: Rs к сопротивлению того же датчика в чистом воздухе после прогрева. В отношении RL сокращается: 2,5 В против 1,0 В — это 25 % и с RL 10 кОм, и с 7,5 кОм. Графики в документации обычно построены от R0 — сопротивления при эталонной концентрации газа, а не в чистом воздухе: прежде чем снимать с них концентрацию, проверьте, от чего они отсчитаны.
Тревогу включают по порогу, а выключают по другому, повыше:
int mq_alarm(int alarm, uint32_t rs, uint32_t r_air, uint32_t on_pct, uint32_t off_pct)
{
uint32_t pct = (uint32_t)((uint64_t)rs * 100u / r_air);
if (!alarm && pct < on_pct)
return 1;
if (alarm && pct > off_pct)
return 0;
return alarm;
}
Модель: в чистом воздухе 40 кОм, газ нарастает и спадает, а отсчёты дрожат у порога — 100, 65, 52, 48, 51, 49, 57, 53, 61 и 75 % от чистого воздуха. Тревога с одним порогом 50 % переключается 4 раза. С гистерезисом — включение ниже 50 %, отбой выше 60 % — 2 раза: включилась на 48 %, погасла на 61 %.
103.8 Грабли
Фоторезистор показывает 0 или 4095. Это не свет, а обрыв или замыкание в делителе: у краёв шкалы люксов нет.
На солнце BH1750 застыл на 54 612 лк. Код упёрся в 65535 при MTreg 69. Уменьшить MTreg до 31.
Первое чтение BH1750 — ноль. Прочитали раньше, чем закончилось первое измерение. После команды ждать 180 мс.
BH1750 не отвечает по адресу 0x23. ADDR подтянут к питанию — адрес 0x5C.
Показания MQ плывут первые минуты. Слой не прогрелся. Отсчётам после включения не доверять, новый датчик — прогреть сутки.
Rs у MQ на треть больше, чем должно быть. Забыли, что делитель к АЦП стоит параллельно RL.
Код MQ упёрся в 4095, а соседние каналы АЦП врут. Выход модуля подан на вход без делителя: больше 3,3 В на аналоговом входе — ток через защитные диоды, и он сбивает соседние каналы.
Аккумулятор сел за полдня. Нагреватель MQ — 152 мА без перерыва.
103.9 Итоги
- Фоторезистор — делитель и степенной закон; при 10 кОм от 1 до 10 лк — 1157 кодов, от 1000 до 10 000 лк — 183; постоянный резистор выбирают под рабочий участок.
- Крайние коды АЦП — неисправность, а не свет.
- BH1750 — команды по одному байту и результат в двух байтах: при MTreg 69 код, делённый на 1,2, — это люксы; на солнце MTreg 31, в темноте — 254.
- MQ — это нагреватель на 152 мА: 5 В, прогрев, не от батареи.
- Rs считают с учётом делителя к АЦП, тревогу — по отношению к чистому воздуху и с гистерезисом.
Дальше: раздел 103а «Пульсоксиметр MAX30102: фотоплетизмограмма по I2C, FIFO, выделение пульса и оценка SpO₂ — и почему это не медицинский прибор» — пульс и отношение R по свету через палец: MAX30102 на I2C, FIFO и обработка на F103; учебный пример, не медицинский прибор.