#pragma once
#include <Arduino.h>
#include <Wire.h>
/*
Конфигурация датчика освещённости BH1750.
*/
struct Bh1750Config {
uint8_t sda_pin = 16;
uint8_t scl_pin = 17;
uint8_t i2c_address = 0x5C;
/*
Режим измерения:
0x10 = Continuous High Resolution Mode
Это самый удобный стартовый режим.
*/
uint8_t measurement_mode = 0x10;
/*
Через сколько миллисекунд без успешного чтения считать данные устаревшими.
*/
uint32_t stale_after_ms = 2000;
/*
Интервал между попытками чтения.
Для continuous mode слишком часто дёргать датчик не нужно.
*/
uint32_t read_interval_ms = 200;
/*
EMA-фильтр для сглаживания.
0.0 -> почти без обновления
1.0 -> без сглаживания
*/
float lux_ema_alpha = 0.25f;
/*
Максимальное значение lux, соответствующее level=10 и percent=100.
BH1750 в High Resolution Mode выдаёт до ~65535 lux (прямой солнечный свет).
Для офиса / квартиры разумный потолок — 1000 lux.
Откалибруйте под условия эксплуатации.
*/
float lux_max = 1000.0f;
};
/*
Драйвер / обёртка для BH1750 без внешних библиотек.
*/
class Bh1750Sensor {
public:
Bh1750Sensor();
/*
Инициализация I2C и перевод датчика в рабочий режим.
*/
bool begin(const Bh1750Config &config);
/*
Периодическое обновление состояния датчика.
Нужно вызывать часто из loop().
*/
void update();
/*
Последнее сырое значение lux без фильтра.
*/
float get_raw_lux() const;
/*
Последнее сглаженное значение lux.
*/
float get_filtered_lux() const;
/*
Уровень освещения 0..10 (относительно lux_max).
*/
uint8_t get_level() const;
/*
Уровень освещения в процентах 0..100 (относительно lux_max).
*/
uint8_t get_percent() const;
/*
Есть ли валидные данные.
*/
bool has_valid_data() const;
/*
Не устарели ли данные.
*/
bool is_stale() const;
/*
Доступен ли датчик.
*/
bool is_online() const;
/*
JSON состояния датчика.
Формат:
{
"online": true,
"level": 4,
"lux": 160.15,
"percent": 11
}
*/
String get_state_json() const;
private:
Bh1750Config _config;
bool _initialized = false;
bool _online = false;
bool _has_valid_data = false;
uint32_t _last_read_attempt_ms = 0;
uint32_t _last_success_read_ms = 0;
uint16_t _last_raw_value = 0;
float _raw_lux = 0.0f;
float _filtered_lux = 0.0f;
private:
bool send_command(uint8_t command);
bool read_measurement(uint16_t &raw_out);
void update_filtered_lux(float new_lux);
};