Mirror of espurna firmware for wireless switches and more
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

149 lines
5.0 KiB

// -----------------------------------------------------------------------------
// BH1750 Liminosity sensor over I2C
// Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
// -----------------------------------------------------------------------------
#if SENSOR_SUPPORT && BH1750_SUPPORT
#pragma once
#include "I2CSensor.h"
#define BH1750_CONTINUOUS_HIGH_RES_MODE 0x10 // Start measurement at 1lx resolution. Measurement time is approx 120ms.
#define BH1750_CONTINUOUS_HIGH_RES_MODE_2 0x11 // Start measurement at 0.5lx resolution. Measurement time is approx 120ms.
#define BH1750_CONTINUOUS_LOW_RES_MODE 0x13 // Start measurement at 4lx resolution. Measurement time is approx 16ms.
#define BH1750_ONE_TIME_HIGH_RES_MODE 0x20 // Start measurement at 1lx resolution. Measurement time is approx 120ms.
// Device is automatically set to Power Down after measurement.
#define BH1750_ONE_TIME_HIGH_RES_MODE_2 0x21 // Start measurement at 0.5lx resolution. Measurement time is approx 120ms.
// Device is automatically set to Power Down after measurement.
#define BH1750_ONE_TIME_LOW_RES_MODE 0x23 // Start measurement at 1lx resolution. Measurement time is approx 120ms.
// Device is automatically set to Power Down after measurement.
static constexpr bool bh1750_is_mode2(unsigned char mode) {
return (mode == BH1750_CONTINUOUS_HIGH_RES_MODE_2) || (mode == BH1750_ONE_TIME_HIGH_RES_MODE_2);
}
class BH1750Sensor : public I2CSensor<> {
public:
void setMode(unsigned char mode) {
if (_mode == mode) return;
_mode = mode;
_dirty = true;
}
unsigned char getMode() const {
return _mode;
}
// ---------------------------------------------------------------------
// Sensor API
// ---------------------------------------------------------------------
unsigned char id() const override {
return SENSOR_BH1750_ID;
}
unsigned char count() const override {
return 1;
}
// Initialization method, must be idempotent
void begin() override {
if (!_dirty) {
return;
}
// I2C auto-discover
static constexpr uint8_t addresses[] {0x23, 0x5C};
auto address = findAndLock(addresses);
if (address == 0) {
return;
}
// Run configuration on next update
_run_configure = true;
_ready = true;
_dirty = false;
}
// Descriptive name of the sensor
String description() const override {
char buffer[32];
snprintf_P(buffer, sizeof(buffer),
PSTR("BH1750 @ I2C (0x%02X)"), lockedAddress());
return String(buffer);
}
// Type for slot # index
unsigned char type(unsigned char index) const override {
if (index == 0) return MAGNITUDE_LUX;
return MAGNITUDE_NONE;
}
// Pre-read hook (usually to populate registers with up-to-date data)
void pre() override {
_error = SENSOR_ERROR_OK;
_lux = _read(lockedAddress());
}
// Current value for slot # index
double value(unsigned char index) override {
if (index == 0) return _lux;
return 0;
}
// Number of decimals for a unit (or -1 for default)
signed char decimals(espurna::sensor::Unit unit) const {
if (bh1750_is_mode2(_mode)) {
return 2;
}
return 1;
}
protected:
double _read(uint8_t address) {
// For one-shot modes reconfigure sensor & wait for conversion
if (_run_configure) {
// Configure mode
i2c_write_uint8(address, _mode);
// According to datasheet
// conversion time is ~16ms for low resolution
// and ~120 for high resolution
// but more time is needed
espurna::time::blockingDelay(
espurna::duration::Milliseconds { (_mode & 0x02) ? 24 : 180 });
// Keep on running configure each time if one-shot mode
_run_configure = (_mode & 0x20) > 0;
}
uint16_t level = i2c_read_uint16(address);
if (level == 0xFFFF) {
_error = SENSOR_ERROR_CRC;
_run_configure = true;
return 0;
}
// When using HIGH Mode2, value is halved
const auto multiplier = bh1750_is_mode2(_mode) ? 0.5 : 1.0;
// TODO also * MTreg?
return ((double)level / 1.2) * multiplier;
}
unsigned char _mode;
bool _run_configure = false;
double _lux = 0;
};
#endif // SENSOR_SUPPORT && BH1750_SUPPORT