diff --git a/code/espurna/sensors/ADE7953Sensor.h b/code/espurna/sensors/ADE7953Sensor.h index d220a4fc..a556925c 100644 --- a/code/espurna/sensors/ADE7953Sensor.h +++ b/code/espurna/sensors/ADE7953Sensor.h @@ -352,8 +352,16 @@ public: MAGNITUDE_ENERGY }; + unsigned char id() const override { + return SENSOR_ADE7953_ID; + } + + unsigned char count() const override { + return std::size(Magnitudes); + } + // Initialization method, must be idempotent - void begin() { + void begin() override { if (!_dirty) { return; } @@ -369,20 +377,15 @@ public: } // Descriptive name of the sensor - String description() { + String description() const override { char buffer[25]; - snprintf(buffer, sizeof(buffer), - "ADE7953 @ I2C (0x%02X)", _port.address()); + snprintf_P(buffer, sizeof(buffer), + PSTR("ADE7953 @ I2C (0x%02X)"), _port.address()); return String(buffer); } - // Descriptive name of the slot # index - String description(unsigned char) { - return description(); - } - // Address of the sensor (it could be the GPIO or I2C address) - String address(unsigned char) override { + String address(unsigned char) const override { char buffer[5]; snprintf_P(buffer, sizeof(buffer), PSTR("0x%02X"), _port.address()); @@ -390,22 +393,20 @@ public: } // Pre-read hook (usually to populate registers with up-to-date data) - void pre() { + void pre() override { _last_reading = read(); _energy[0] += sensor::Ws(_last_reading.a.active_energy); _energy[1] += sensor::Ws(_last_reading.b.active_energy); } - // Sensor has a fixed number of channels - ADE7953Sensor() { - _sensor_id = SENSOR_ADE7953_ID; - _count = std::size(Magnitudes); - _dirty = true; - findAndAddEnergy(Magnitudes); - } + // Sensor has a fixed number of channels, so just use the static magnitudes list + + ADE7953Sensor() : + BaseEmonSensor(Magnitudes) + {} // Current value for slot # index - double value(unsigned char index) { + double value(unsigned char index) override { switch (index) { case 0: return _last_reading.voltage; @@ -441,7 +442,7 @@ public: } // Type for slot # index - unsigned char type(unsigned char index) { + unsigned char type(unsigned char index) const override { if (index < std::size(Magnitudes)) { return Magnitudes[index].type; } @@ -521,7 +522,7 @@ private: }; #if __cplusplus < 201703L -constexpr BaseEmonSensor::Magnitude ADE7953Sensor::Magnitudes[]; +constexpr BaseSensor::Magnitude ADE7953Sensor::Magnitudes[]; #endif #endif // SENSOR_SUPPORT && ADE7953_SUPPORT diff --git a/code/espurna/sensors/AM2320Sensor.h b/code/espurna/sensors/AM2320Sensor.h index f50a3dc9..a96d87d8 100644 --- a/code/espurna/sensors/AM2320Sensor.h +++ b/code/espurna/sensors/AM2320Sensor.h @@ -29,59 +29,56 @@ class AM2320Sensor : public I2CSensor<> { public: - // --------------------------------------------------------------------- - // Public - // --------------------------------------------------------------------- - - AM2320Sensor() { - _count = 2; - _sensor_id = SENSOR_AM2320_ID; - } - // --------------------------------------------------------------------- // Sensor API // --------------------------------------------------------------------- + unsigned char id() const override { + return SENSOR_AM2320_ID; + } + + unsigned char count() const override { + return 2; + } + // Initialization method, must be idempotent - void begin() { + void begin() override { if (!_dirty) return; // I2C auto-discover - unsigned char addresses[] = {0x23, 0x5C, 0xB8}; - _address = _begin_i2c(_address, sizeof(addresses), addresses); - if (_address == 0) return; + static constexpr uint8_t addresses[] {0x23, 0x5C, 0xB8}; + auto address = findAndLock(addresses); + if (address == 0) { + return; + } _ready = true; _dirty = false; } // Descriptive name of the sensor - String description() { + String description() const override { char buffer[25]; - snprintf(buffer, sizeof(buffer), "AM2320 @ I2C (0x%02X)", _address); + snprintf_P(buffer, sizeof(buffer), + PSTR("AM2320 @ I2C (0x%02X)"), getAddress()); return String(buffer); } - // Descriptive name of the slot # index - String description(unsigned char index) { - return description(); - }; - // Type for slot # index - unsigned char type(unsigned char index) { + unsigned char type(unsigned char index) const override { if (index == 0) return MAGNITUDE_TEMPERATURE; if (index == 1) return MAGNITUDE_HUMIDITY; return MAGNITUDE_NONE; } // Pre-read hook (usually to populate registers with up-to-date data) - void pre() { + void pre() override { _error = SENSOR_ERROR_OK; - _read(); + _read(getAddress()); } // Current value for slot # index - double value(unsigned char index) { + double value(unsigned char index) override { if (index == 0) return _temperature; if (index == 1) return _humidity; return 0; @@ -96,15 +93,15 @@ class AM2320Sensor : public I2CSensor<> { /* // Get device model, version, device_id - void _init() { - i2c_wakeup(_address); + void _init(uint8_t address) { + i2c_wakeup(address); delayMicroseconds(800); unsigned char _buffer[11]; // 0x08 = read address // 7 = number of bytes to read - if (i2c_write_uint8(_address, AM2320_I2C_READ_REGISTER_DATA, 0x08, 7) != I2C_TRANS_SUCCESS) { + if (i2c_write_uint8(address, AM2320_I2C_READ_REGISTER_DATA, 0x08, 7) != I2C_TRANS_SUCCESS) { _error = SENSOR_ERROR_TIMEOUT; return false; } @@ -115,16 +112,16 @@ class AM2320Sensor : public I2CSensor<> { } */ - void _read() { + void _read(uint8_t address) { - i2c_wakeup(_address); + i2c_wakeup(address); // waiting time of at least 800 μs, the maximum 3000 μs delayMicroseconds(800); // just to be on safe side // 0x00 = read address // 4 = number of bytes to read - if (i2c_write_uint8(_address, AM2320_I2C_READ_REGISTER_DATA, 0x00, 4) != I2C_TRANS_SUCCESS) { + if (i2c_write_uint8(address, AM2320_I2C_READ_REGISTER_DATA, 0x00, 4) != I2C_TRANS_SUCCESS) { _error = SENSOR_ERROR_TIMEOUT; return; } @@ -133,7 +130,7 @@ class AM2320Sensor : public I2CSensor<> { // waiting time of at least 800 μs, the maximum 3000 μs delayMicroseconds(800 + ((3000-800)/2) ); - i2c_read_buffer(_address, _buffer, 8); + i2c_read_buffer(address, _buffer, 8); // Humidity : 01F4 = (1×256)+(F×16)+4 = 500 => humidity = 500÷10 = 50.0 % // 0339 = (3×256)+(3×16)+9 = 825 => humidity = 825÷10 = 82.5 % @@ -168,7 +165,7 @@ class AM2320Sensor : public I2CSensor<> { } } - unsigned int _CRC16(unsigned char buffer[]) { + static unsigned int _CRC16(unsigned char (&buffer)[8]) { unsigned int crc16 = 0xFFFF; for (unsigned int i = 0; i < 6; i++) { diff --git a/code/espurna/sensors/BH1750Sensor.h b/code/espurna/sensors/BH1750Sensor.h index 12de40cd..b8de59a5 100644 --- a/code/espurna/sensors/BH1750Sensor.h +++ b/code/espurna/sensors/BH1750Sensor.h @@ -23,26 +23,13 @@ class BH1750Sensor : public I2CSensor<> { public: - // --------------------------------------------------------------------- - // Public - // --------------------------------------------------------------------- - - BH1750Sensor() { - _sensor_id = SENSOR_BH1750_ID; - _count = 1; - } - - // --------------------------------------------------------------------- - void setMode(unsigned char mode) { if (_mode == mode) return; _mode = mode; _dirty = true; } - // --------------------------------------------------------------------- - - unsigned char getMode() { + unsigned char getMode() const { return _mode; } @@ -50,15 +37,25 @@ class BH1750Sensor : public I2CSensor<> { // 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() { + void begin() override { if (!_dirty) return; // I2C auto-discover - unsigned char addresses[] = {0x23, 0x5C}; - _address = _begin_i2c(_address, sizeof(addresses), addresses); - if (_address == 0) return; + static constexpr uint8_t addresses[] {0x23, 0x5C}; + auto address = findAndLock(addresses); + if (address == 0) { + return; + } // Run configuration on next update _run_configure = true; @@ -68,39 +65,39 @@ class BH1750Sensor : public I2CSensor<> { } // Descriptive name of the sensor - String description() { + String description() const override { char buffer[25]; - snprintf(buffer, sizeof(buffer), "BH1750 @ I2C (0x%02X)", _address); + snprintf(buffer, sizeof(buffer), "BH1750 @ I2C (0x%02X)", getAddress()); return String(buffer); } // Type for slot # index - unsigned char type(unsigned char 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() { + void pre() override { _error = SENSOR_ERROR_OK; - _lux = _read(); + _lux = _read(getAddress()); } // Current value for slot # index - double value(unsigned char index) { + double value(unsigned char index) override { if (index == 0) return _lux; return 0; } protected: - double _read() { + double _read(uint8_t address) { // For one-shot modes reconfigure sensor & wait for conversion if (_run_configure) { // Configure mode - i2c_write_uint8(_address, _mode); + i2c_write_uint8(address, _mode); // According to datasheet // conversion time is ~16ms for low resolution @@ -115,7 +112,7 @@ class BH1750Sensor : public I2CSensor<> { } - double level = (double) i2c_read_uint16(_address); + double level = (double) i2c_read_uint16(address); if (level == 0xFFFF) { _error = SENSOR_ERROR_CRC; _run_configure = true; diff --git a/code/espurna/sensors/BMP180Sensor.h b/code/espurna/sensors/BMP180Sensor.h index 9ad2e457..a2080281 100644 --- a/code/espurna/sensors/BMP180Sensor.h +++ b/code/espurna/sensors/BMP180Sensor.h @@ -38,44 +38,42 @@ class BMP180Sensor : public I2CSensor<> { public: - static unsigned char addresses[1]; - - // --------------------------------------------------------------------- - // Public - // --------------------------------------------------------------------- - - BMP180Sensor() { - _sensor_id = SENSOR_BMP180_ID; - _count = 2; - } - // --------------------------------------------------------------------- // Sensor API // --------------------------------------------------------------------- + unsigned char id() const override { + return SENSOR_BMP180_ID; + } + + unsigned char count() const override { + return 2; + } + // Initialization method, must be idempotent - void begin() { + void begin() override { if (!_dirty) return; _init(); _dirty = !_ready; } // Descriptive name of the sensor - String description() { + String description() const override { char buffer[20]; - snprintf(buffer, sizeof(buffer), "BMP180 @ I2C (0x%02X)", _address); + snprintf_P(buffer, sizeof(buffer), + PSTR("BMP180 @ I2C (0x%02X)"), getAddress()); return String(buffer); } // Type for slot # index - unsigned char type(unsigned char index) { + unsigned char type(unsigned char index) const override { if (index == 0) return MAGNITUDE_TEMPERATURE; if (index == 1) return MAGNITUDE_PRESSURE; return MAGNITUDE_NONE; } // Pre-read hook (usually to populate registers with up-to-date data) - virtual void pre() { + void pre() override { if (_run_init) { i2cClearBus(); @@ -83,12 +81,12 @@ class BMP180Sensor : public I2CSensor<> { } if (_chip == 0) { - _error = SENSOR_ERROR_UNKNOWN_ID; + resetUnknown(); return; } _error = SENSOR_ERROR_OK; - _error = _read(); + _error = _read(getAddress()); if (_error != SENSOR_ERROR_OK) { _run_init = true; } @@ -96,7 +94,7 @@ class BMP180Sensor : public I2CSensor<> { } // Current value for slot # index - double value(unsigned char index) { + double value(unsigned char index) override { if (index == 0) return _temperature; if (index == 1) return _pressure / 100; return 0; @@ -110,65 +108,60 @@ class BMP180Sensor : public I2CSensor<> { espurna::time::blockingDelay(espurna::duration::Milliseconds(10)); // I2C auto-discover - _address = _begin_i2c(_address, sizeof(BMP180Sensor::addresses), BMP180Sensor::addresses); - if (_address == 0) return; + static constexpr uint8_t addresses[] {0x77}; + auto address = findAndLock(addresses); + if (address == 0) { + return; + } // Check sensor correctly initialized - _chip = i2c_read_uint8(_address, BMP180_REGISTER_CHIPID); + _chip = i2c_read_uint8(address, BMP180_REGISTER_CHIPID); if (_chip != BMP180_CHIP_ID) { - _chip = 0; - _sensor_address.unlock(); - _error = SENSOR_ERROR_UNKNOWN_ID; - - // Setting _address to 0 forces auto-discover - // This might be necessary at this stage if there is a - // different sensor in the hardcoded address - _address = 0; - + resetUnknown(); return; } - _readCoefficients(); + _readCoefficients(address); _run_init = false; _ready = true; } - void _readCoefficients() { + void _readCoefficients(uint8_t address) { + _bmp180_calib = bmp180_calib_t{ + .ac1 = i2c_read_int16(address, BMP180_REGISTER_CAL_AC1), + .ac2 = i2c_read_int16(address, BMP180_REGISTER_CAL_AC2), + .ac3 = i2c_read_int16(address, BMP180_REGISTER_CAL_AC3), - _bmp180_calib.ac1 = i2c_read_int16(_address, BMP180_REGISTER_CAL_AC1); - _bmp180_calib.ac2 = i2c_read_int16(_address, BMP180_REGISTER_CAL_AC2); - _bmp180_calib.ac3 = i2c_read_int16(_address, BMP180_REGISTER_CAL_AC3); - - _bmp180_calib.ac4 = i2c_read_uint16(_address, BMP180_REGISTER_CAL_AC4); - _bmp180_calib.ac5 = i2c_read_uint16(_address, BMP180_REGISTER_CAL_AC5); - _bmp180_calib.ac6 = i2c_read_uint16(_address, BMP180_REGISTER_CAL_AC6); - - _bmp180_calib.b1 = i2c_read_int16(_address, BMP180_REGISTER_CAL_B1); - _bmp180_calib.b2 = i2c_read_int16(_address, BMP180_REGISTER_CAL_B2); - _bmp180_calib.mb = i2c_read_int16(_address, BMP180_REGISTER_CAL_MB); - _bmp180_calib.mc = i2c_read_int16(_address, BMP180_REGISTER_CAL_MC); - _bmp180_calib.md = i2c_read_int16(_address, BMP180_REGISTER_CAL_MD); + .ac4 = i2c_read_uint16(address, BMP180_REGISTER_CAL_AC4), + .ac5 = i2c_read_uint16(address, BMP180_REGISTER_CAL_AC5), + .ac6 = i2c_read_uint16(address, BMP180_REGISTER_CAL_AC6), + .b1 = i2c_read_int16(address, BMP180_REGISTER_CAL_B1), + .b2 = i2c_read_int16(address, BMP180_REGISTER_CAL_B2), + .mb = i2c_read_int16(address, BMP180_REGISTER_CAL_MB), + .mc = i2c_read_int16(address, BMP180_REGISTER_CAL_MC), + .md = i2c_read_int16(address, BMP180_REGISTER_CAL_MD), + }; } // Compute B5 coefficient used in temperature & pressure calcs. // Based on Adafruit_BMP085_Unified library long _computeB5(unsigned long t) { - long X1 = (t - (long)_bmp180_calib.ac6) * ((long)_bmp180_calib.ac5) >> 15; - long X2 = ((long)_bmp180_calib.mc << 11) / (X1+(long)_bmp180_calib.md); + const long X1 = (t - (long)_bmp180_calib.ac6) * ((long)_bmp180_calib.ac5) >> 15; + const long X2 = ((long)_bmp180_calib.mc << 11) / (X1+(long)_bmp180_calib.md); return X1 + X2; } - unsigned char _read() { + unsigned char _read(uint8_t address) { // Read raw temperature - i2c_write_uint8(_address, BMP180_REGISTER_CONTROL, BMP180_REGISTER_READTEMPCMD); + i2c_write_uint8(address, BMP180_REGISTER_CONTROL, BMP180_REGISTER_READTEMPCMD); espurna::time::blockingDelay(espurna::duration::Milliseconds(5)); - unsigned long t = i2c_read_uint16(_address, BMP180_REGISTER_TEMPDATA); + unsigned long t = i2c_read_uint16(address, BMP180_REGISTER_TEMPDATA); // Compute B5 coeficient long b5 = _computeB5(t); @@ -177,10 +170,10 @@ class BMP180Sensor : public I2CSensor<> { _temperature = ((double) ((b5 + 8) >> 4)) / 10.0; // Read raw pressure - i2c_write_uint8(_address, BMP180_REGISTER_CONTROL, BMP180_REGISTER_READPRESSURECMD + (_mode << 6)); + i2c_write_uint8(address, BMP180_REGISTER_CONTROL, BMP180_REGISTER_READPRESSURECMD + (_mode << 6)); espurna::time::blockingDelay(espurna::duration::Milliseconds(26)); - unsigned long p1 = i2c_read_uint16(_address, BMP180_REGISTER_PRESSUREDATA); - unsigned long p2 = i2c_read_uint8(_address, BMP180_REGISTER_PRESSUREDATA+2); + unsigned long p1 = i2c_read_uint16(address, BMP180_REGISTER_PRESSUREDATA); + unsigned long p2 = i2c_read_uint8(address, BMP180_REGISTER_PRESSUREDATA+2); long p = ((p1 << 8) + p2) >> (8 - _mode); // Pressure compensation @@ -220,8 +213,7 @@ class BMP180Sensor : public I2CSensor<> { double _pressure = 0; unsigned int _mode = BMP180_MODE; - typedef struct { - + struct bmp180_calib_t { int16_t ac1; int16_t ac2; int16_t ac3; @@ -235,15 +227,10 @@ class BMP180Sensor : public I2CSensor<> { int16_t mb; int16_t mc; int16_t md; - - } bmp180_calib_t; + }; bmp180_calib_t _bmp180_calib; }; -// Static inizializations - -unsigned char BMP180Sensor::addresses[1] = {0x77}; - #endif // SENSOR_SUPPORT && BMP180_SUPPORT diff --git a/code/espurna/sensors/HDC1080Sensor.h b/code/espurna/sensors/HDC1080Sensor.h index ba948b5f..043f9259 100644 --- a/code/espurna/sensors/HDC1080Sensor.h +++ b/code/espurna/sensors/HDC1080Sensor.h @@ -26,62 +26,64 @@ class HDC1080Sensor : public I2CSensor<> { public: - // --------------------------------------------------------------------- - // Public - // --------------------------------------------------------------------- - - HDC1080Sensor() { - _sensor_id = SENSOR_HDC1080_ID; - } - // --------------------------------------------------------------------- // Sensor API // --------------------------------------------------------------------- + unsigned char id() const override { + return SENSOR_HDC1080_ID; + } + + unsigned char count() const override { + return 2; + } + // Initialization method, must be idempotent - void begin() { + void begin() override { if (!_dirty) return; _init(); _dirty = !_ready; } // Descriptive name of the sensor - String description() { + String description() const override { char buffer[25]; - snprintf_P(buffer, sizeof(buffer), PSTR("HDC1080 @ I2C (0x%02X)"), _address); + snprintf_P(buffer, sizeof(buffer), + PSTR("HDC1080 @ I2C (0x%02X)"), getAddress()); return String(buffer); } // Descriptive name of the slot # index - String description(unsigned char index) { + String description(unsigned char) const override { return description(); }; // Type for slot # index - unsigned char type(unsigned char index) { + unsigned char type(unsigned char index) const override { if (index == 0) return MAGNITUDE_TEMPERATURE; if (index == 1) return MAGNITUDE_HUMIDITY; return MAGNITUDE_NONE; } // Pre-read hook (usually to populate registers with up-to-date data) - void pre() { + void pre() override { _error = SENSOR_ERROR_OK; + const auto address = getAddress(); double value; - value = _read(HDC1080_CMD_TMP); + value = _read(address, HDC1080_CMD_TMP); if (_error != SENSOR_ERROR_OK) return; _temperature = (165 * value / 65536) - 40; - value = _read(HDC1080_CMD_HUM); + value = _read(address, HDC1080_CMD_HUM); if (_error != SENSOR_ERROR_OK) return; value = (value / 65536)*100; _humidity = constrain(value, 0, 100); } // Current value for slot # index - double value(unsigned char index) { + double value(unsigned char index) override { if (index == 0) return _temperature; if (index == 1) return _humidity; return 0; @@ -96,41 +98,34 @@ class HDC1080Sensor : public I2CSensor<> { void _init() { // I2C auto-discover - unsigned char addresses[] = {0x40}; - _address = _begin_i2c(_address, sizeof(addresses), addresses); - if (_address == 0) return; + static constexpr uint8_t addresses[] {0x40}; + auto address = findAndLock(addresses); + if (address == 0) { + return; + } // Check device ID before doing anything else // ref. https://github.com/xoseperez/espurna/issues/2270#issuecomment-639239944 // > Also there are clones of HDC1080 and they may have different Device ID // > values. You need to check it by reading and debug output this bytes. - i2c_write_uint8(_address, 0xFF); - _device_id = i2c_read_uint16(_address); + i2c_write_uint8(address, 0xFF); + _device_id = i2c_read_uint16(address); - if (_device_id == HDC1080_DEVICE_ID) { - _ready = true; - _count = 2; + if (_device_id != HDC1080_DEVICE_ID) { + DEBUG_MSG_P(PSTR("[HDC1080] ERROR: Expected Device ID 0x%04X, received 0x%04X\n"), + HDC1080_DEVICE_ID, _device_id); + _ready = false; + resetUnknown(); return; } - DEBUG_MSG_P(PSTR("[HDC1080] ERROR: Expected Device ID %04X, received %04X\n"), HDC1080_DEVICE_ID, _device_id); - - _count = 0; - _sensor_address.unlock(); - _error = SENSOR_ERROR_UNKNOWN_ID; - - // Setting _address to 0 forces auto-discover - // This might be necessary at this stage if there is a - // different sensor in the hardcoded address - _address = 0; - _ready = false; - + _ready = true; } - unsigned int _read(uint8_t command) { + unsigned int _read(uint8_t address, uint8_t command) { // Request measurement - i2c_write_uint8(_address, command); + i2c_write_uint8(address, command); // When not using clock stretching (*_NOHOLD commands) delay here // is needed to wait for the measurement. @@ -140,7 +135,7 @@ class HDC1080Sensor : public I2CSensor<> { // Clear the last to bits of LSB to 00. // According to datasheet LSB of Temp and RH is always xxxxxx00 - unsigned int value = i2c_read_uint16(_address) & 0xFFFC; + unsigned int value = i2c_read_uint16(address) & 0xFFFC; // We should be checking there are no pending bytes in the buffer // and raise a CRC error if there are diff --git a/code/espurna/sensors/SHT3XI2CSensor.h b/code/espurna/sensors/SHT3XI2CSensor.h index 8cb5bea6..b50a5c4b 100644 --- a/code/espurna/sensors/SHT3XI2CSensor.h +++ b/code/espurna/sensors/SHT3XI2CSensor.h @@ -15,60 +15,68 @@ class SHT3XI2CSensor : public I2CSensor<> { public: - // --------------------------------------------------------------------- - // Public - // --------------------------------------------------------------------- - - SHT3XI2CSensor() { - _sensor_id = SENSOR_SHT3X_I2C_ID; - _count = 2; - } - // --------------------------------------------------------------------- // Sensor API // --------------------------------------------------------------------- + unsigned char id() const override { + return SENSOR_SHT3X_I2C_ID; + } + + unsigned char count() const override { + return 2; + } + // Initialization method, must be idempotent - void begin() { + void begin() override { if (!_dirty) return; // I2C auto-discover - unsigned char addresses[] = {0x44,0x45}; - _address = _begin_i2c(_address, sizeof(addresses), addresses); - if (_address == 0) return; - i2c_write_uint8(_address, 0x30, 0xA2); // Soft reset to ensure sensor in default state + static constexpr uint8_t addresses[] {0x44, 0x45}; + const auto address = findAndLock(addresses); + if (address == 0) { + return; + } + + // Soft reset, ensure sensor is in default state + i2c_write_uint8(address, 0x30, 0xA2); espurna::time::blockingDelay( espurna::duration::Milliseconds(500)); + _ready = true; _dirty = false; } // Descriptive name of the sensor - String description() { + String description() const override { char buffer[25]; - snprintf(buffer, sizeof(buffer), "SHT3X @ I2C (0x%02X)", _address); + snprintf(buffer, sizeof(buffer), "SHT3X @ I2C (0x%02X)", getAddress()); return String(buffer); } // Type for slot # index - unsigned char type(unsigned char index) { + unsigned char type(unsigned char index) const override { if (index == 0) return MAGNITUDE_TEMPERATURE; if (index == 1) return MAGNITUDE_HUMIDITY; return MAGNITUDE_NONE; } // Pre-read hook (usually to populate registers with up-to-date data) - void pre() { + void pre() override { _error = SENSOR_ERROR_OK; - unsigned char buffer[6]; - i2c_write_uint8(_address, 0x2C, 0x06); // Measurement High Repeatability with Clock Stretch Enabled + const auto address = getAddress(); + + // Measurement High Repeatability with Clock Stretch Enabled + i2c_write_uint8(address, 0x2C, 0x06); espurna::time::blockingDelay( espurna::duration::Milliseconds(500)); - i2c_read_buffer(_address, buffer, 6); + + unsigned char buffer[6]; + i2c_read_buffer(address, buffer, std::size(buffer)); // cTemp msb, cTemp lsb, cTemp crc, humidity msb, humidity lsb, humidity crc _temperature = ((((buffer[0] * 256.0) + buffer[1]) * 175) / 65535.0) - 45; @@ -77,7 +85,7 @@ class SHT3XI2CSensor : public I2CSensor<> { } // Current value for slot # index - double value(unsigned char index) { + double value(unsigned char index) override { if (index == 0) return _temperature; if (index == 1) return _humidity; return 0; diff --git a/code/espurna/sensors/SI1145Sensor.h b/code/espurna/sensors/SI1145Sensor.h index fa44f9ed..b97222fe 100644 --- a/code/espurna/sensors/SI1145Sensor.h +++ b/code/espurna/sensors/SI1145Sensor.h @@ -16,25 +16,27 @@ class SI1145Sensor : public I2CSensor<> { public: - SI1145Sensor() { - _count = 1; - _sensor_id = SENSOR_SI1145_ID; - _si1145 = new Adafruit_SI1145(); + unsigned char id() const override { + return SENSOR_SI1145_ID; } - void begin() { - static unsigned char addresses[1] = { SI1145_ADDRESS }; - _address = _begin_i2c(_address, sizeof(addresses), addresses); - if (_address == 0) return; + unsigned char count() const override { + return 1; + } - if (!_si1145->begin()) { + void begin() override { + const auto address = findAndLock(); + if (address == 0) { + return; + } + + if (!_si1145.begin()) { _ready = false; return; } // Adafruit library never sets any errors _error = SENSOR_ERROR_OK; - _ready = true; } @@ -43,36 +45,36 @@ class SI1145Sensor : public I2CSensor<> { // --------------------------------------------------------------------- // Descriptive name of the sensor - String description() { + String description() const override { char buffer[25]; - snprintf(buffer, sizeof(buffer), "SI1145 @ I2C (0x%02X)", _address); + snprintf(buffer, sizeof(buffer), "SI1145 @ I2C (0x%02X)", getAddress()); return String(buffer); } // Descriptive name of the slot # index - String description(unsigned char index) { + String description(unsigned char index) const override { return description(); }; // Type for slot # index - unsigned char type(unsigned char index) { + unsigned char type(unsigned char index) const override { if (index == 0) return MAGNITUDE_UVI; return MAGNITUDE_NONE; } // Pre-read hook (usually to populate registers with up-to-date data) - void pre() { - _uvi = _si1145->readUV() / 100.0; + void pre() override { + _uvi = _si1145.readUV() / 100.0; } // Current value for slot # index - double value(unsigned char index) { + double value(unsigned char index) override { if (index == 0) return _uvi; return 0.0; } - protected: - Adafruit_SI1145 * _si1145 = nullptr; + private: + Adafruit_SI1145 _si1145; double _uvi = 0.0; }; diff --git a/code/espurna/sensors/VEML6075Sensor.h b/code/espurna/sensors/VEML6075Sensor.h index abdd5602..219b76c9 100644 --- a/code/espurna/sensors/VEML6075Sensor.h +++ b/code/espurna/sensors/VEML6075Sensor.h @@ -15,46 +15,43 @@ class VEML6075Sensor : public I2CSensor<> { public: - // --------------------------------------------------------------------- - // Public - // --------------------------------------------------------------------- - - VEML6075Sensor() { - _count = 3; - _sensor_id = SENSOR_VEML6075_ID; - _veml6075 = new VEML6075(); - } - - ~VEML6075Sensor() { - delete _veml6075; - } - - void begin() { - if (!_veml6075->begin()) { - return; - }; - - _ready = true; - } - // --------------------------------------------------------------------- // Sensor API // --------------------------------------------------------------------- + unsigned char id() const override { + return SENSOR_VEML6075_ID; + } + + unsigned char count() const override { + return 3; + } + + void begin() override { + if (_veml6075) { + _veml6075.reset(nullptr); + } + + _ready = false; + _veml6075 = std::make_unique(); + if (!_veml6075->begin()) { + return; + } + + _ready = true; + } + + // Descriptive name of the sensor - String description() { + String description() const override { char buffer[25]; - snprintf(buffer, sizeof(buffer), "VEML6075 @ I2C (0x%02X)", _address); + snprintf_P(buffer, sizeof(buffer), + PSTR("VEML6075 @ I2C (0x%02X)"), getAddress()); return String(buffer); } - // Descriptive name of the slot # index - String description(unsigned char index) { - return description(); - }; - // Type for slot # index - unsigned char type(unsigned char index) { + unsigned char type(unsigned char index) const override { if (index == 0) return MAGNITUDE_UVA; if (index == 1) return MAGNITUDE_UVB; if (index == 2) return MAGNITUDE_UVI; @@ -62,12 +59,12 @@ class VEML6075Sensor : public I2CSensor<> { } // Pre-read hook (usually to populate registers with up-to-date data) - void pre() { + void pre() override { _error = SENSOR_ERROR_OK; } // Current value for slot # index - double value(unsigned char index) { + double value(unsigned char index) override { if (index == 0) return _veml6075->a(); if (index == 1) return _veml6075->b(); if (index == 2) return _veml6075->index(); @@ -76,16 +73,16 @@ class VEML6075Sensor : public I2CSensor<> { } void setIntegrationTime(VEML6075::veml6075_uv_it_t integration_time) { - _veml6075->setIntegrationTime(integration_time); + _veml6075->setIntegrationTime(integration_time); } void setDynamicMode(VEML6075::veml6075_hd_t dynamic_mode) { - _veml6075->setHighDynamic(dynamic_mode); + _veml6075->setHighDynamic(dynamic_mode); } - protected: + private: - VEML6075 * _veml6075 = NULL; + std::unique_ptr _veml6075; };