diff --git a/code/espurna/config/arduino.h b/code/espurna/config/arduino.h index 635c8abf..d1a1de6e 100644 --- a/code/espurna/config/arduino.h +++ b/code/espurna/config/arduino.h @@ -254,3 +254,4 @@ //#define V9261F_SUPPORT 1 //#define VEML6075_SUPPORT 1 //#define VL53L1X_SUPPORT 1 +//#define HDC1080_SUPPORT 1 diff --git a/code/espurna/config/sensors.h b/code/espurna/config/sensors.h index 3f583aaa..045c1f1d 100644 --- a/code/espurna/config/sensors.h +++ b/code/espurna/config/sensors.h @@ -1057,6 +1057,19 @@ #define SI7021_ADDRESS 0x00 // 0x00 means auto #endif +//------------------------------------------------------------------------------ +// HDC1080 / 831R temperature & humidity sensor +// Enable support by passing HDC1080_SUPPORT=1 build flag +//------------------------------------------------------------------------------ + +#ifndef HDC1080_SUPPORT +#define HDC1080_SUPPORT 0 +#endif + +#ifndef HDC1080_ADDRESS +#define HDC1080_ADDRESS 0x00 // 0x00 means auto +#endif + //------------------------------------------------------------------------------ // Sonar // Enable support by passing SONAR_SUPPORT=1 build flag @@ -1310,7 +1323,8 @@ SI1145_SUPPORT || \ SI7021_SUPPORT || \ VEML6075_SUPPORT || \ - VL53L1X_SUPPORT \ + VL53L1X_SUPPORT || \ + HDC1080_SUPPORT \ ) #undef I2C_SUPPORT #define I2C_SUPPORT 1 @@ -1372,7 +1386,8 @@ TMP3X_SUPPORT || \ V9261F_SUPPORT || \ VEML6075_SUPPORT || \ - VL53L1X_SUPPORT \ + VL53L1X_SUPPORT || \ + HDC1080_SUPPORT \ ) #endif diff --git a/code/espurna/config/types.h b/code/espurna/config/types.h index 47959d56..f5b2421a 100644 --- a/code/espurna/config/types.h +++ b/code/espurna/config/types.h @@ -331,6 +331,7 @@ #define SENSOR_ADE7953_ID 37 #define SENSOR_T6613_ID 38 #define SENSOR_SI1145_ID 39 +#define SENSOR_HDC1080_ID 40 //-------------------------------------------------------------------------------- // Magnitudes diff --git a/code/espurna/sensor.h b/code/espurna/sensor.h index 846af9e8..a59350cc 100644 --- a/code/espurna/sensor.h +++ b/code/espurna/sensor.h @@ -315,5 +315,8 @@ void sensorLoop(); #include "sensors/SI1145Sensor.h" #endif +#if HDC1080_SUPPORT + #include "sensors/HDC1080Sensor.h" +#endif //-------------------------------------------------------------------------------- diff --git a/code/espurna/sensor.ino b/code/espurna/sensor.ino index 516a40be..52f7b20c 100644 --- a/code/espurna/sensor.ino +++ b/code/espurna/sensor.ino @@ -1548,6 +1548,13 @@ void _sensorLoad() { } #endif + #if HDC1080_SUPPORT + { + HDC1080Sensor * sensor = new HDC1080Sensor(); + sensor->setAddress(HDC1080_ADDRESS); + _sensors.push_back(sensor); + } + #endif } void _sensorCallback(unsigned char i, unsigned char type, double value) { diff --git a/code/espurna/sensors/HDC1080Sensor.h b/code/espurna/sensors/HDC1080Sensor.h new file mode 100644 index 00000000..b7c7d31a --- /dev/null +++ b/code/espurna/sensors/HDC1080Sensor.h @@ -0,0 +1,162 @@ +// ----------------------------------------------------------------------------- +// HDC1080 / 831R Sensor over I2C +// Based on SI7021 / HTU21D Sensor over I2C +// Copyright (C) 2017-2019 by Xose PĂ©rez +// Copyright (C) 2020 by Alexander Kolesnikov +// ----------------------------------------------------------------------------- + +#if SENSOR_SUPPORT && HDC1080_SUPPORT + +#pragma once + +#include + +#include "I2CSensor.h" +#include "../utils.h" + +#define HDC1080_SCL_FREQUENCY 200 + +// Middle byte of Device Serial ID. May be diffirent on your chip (see debug i2c.scan) +#define HDC1080_CHIP_HDC1080 0x2C + +#define HDC1080_CMD_TMP 0x00 +#define HDC1080_CMD_HUM 0x01 + +PROGMEM const char hdc1080_chip_hdc1080_name[] = "HDC1080"; + +class HDC1080Sensor : public I2CSensor<> { + + public: + + // --------------------------------------------------------------------- + // Public + // --------------------------------------------------------------------- + + HDC1080Sensor() { + _sensor_id = SENSOR_HDC1080_ID; + } + + // --------------------------------------------------------------------- + // Sensor API + // --------------------------------------------------------------------- + + // Initialization method, must be idempotent + void begin() { + if (!_dirty) return; + _init(); + _dirty = !_ready; + } + + // Descriptive name of the sensor + String description() { + char name[10]; + strncpy_P(name, hdc1080_chip_hdc1080_name, sizeof(name)); + char buffer[25]; + snprintf(buffer, sizeof(buffer), "%s @ I2C (0x%02X)", name, _address); + return String(buffer); + } + + // Descriptive name of the slot # index + String slot(unsigned char index) { + return description(); + }; + + // Type for slot # index + unsigned char type(unsigned char index) { + 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() { + + _error = SENSOR_ERROR_UNKNOWN_ID; + if (_chip == 0) return; + _error = SENSOR_ERROR_OK; + + double value; + + value = _read(HDC1080_CMD_TMP); + if (_error != SENSOR_ERROR_OK) return; + _temperature = (165 * value / 65536) - 40; + + value = _read(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) { + if (index == 0) return _temperature; + if (index == 1) return _humidity; + return 0; + } + + protected: + + // --------------------------------------------------------------------- + // Protected + // --------------------------------------------------------------------- + + void _init() { + + // I2C auto-discover + unsigned char addresses[] = {0x40}; + _address = _begin_i2c(_address, sizeof(addresses), addresses); + if (_address == 0) return; + + // Check device + i2c_write_uint8(_address, 0xFC, 0xC9); + _chip = i2c_read_uint8(_address); + + if (_chip != HDC1080_CHIP_HDC1080) { + + _count = 0; + i2cReleaseLock(_address); + _previous_address = 0; + _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; + + } else { + _count = 2; + } + + _ready = true; + + } + + unsigned int _read(uint8_t command) { + + // Request measurement + i2c_write_uint8(_address, command); + + // When not using clock stretching (*_NOHOLD commands) delay here + // is needed to wait for the measurement. + // According to datasheet the max. conversion time is ~22ms + nice_delay(50); + + // 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; + + // We should be checking there are no pending bytes in the buffer + // and raise a CRC error if there are + _error = SENSOR_ERROR_OK; + + return value; + + } + + unsigned char _chip; + double _temperature = 0; + double _humidity = 0; + +}; + +#endif // SENSOR_SUPPORT && HDC1080_SUPPORT diff --git a/code/espurna/utils.ino b/code/espurna/utils.ino index ab91423c..b5694e30 100644 --- a/code/espurna/utils.ino +++ b/code/espurna/utils.ino @@ -248,9 +248,9 @@ void heartbeat() { if (serial) { infoUptime(); infoHeapStats(); - #if ADC_MODE_VALUE == ADC_VCC + if (ADC_MODE_VALUE == ADC_VCC) { DEBUG_MSG_P(PSTR("[MAIN] Power: %lu mV\n"), ESP.getVcc()); - #endif + } #if NTP_SUPPORT if (ntpSynced()) DEBUG_MSG_P(PSTR("[MAIN] Time: %s\n"), (char *) ntpDateTime().c_str()); #endif @@ -548,9 +548,9 @@ void info(bool first) { DEBUG_MSG_P(PSTR("[MAIN] Firmware MD5: %s\n"), (char *) ESP.getSketchMD5().c_str()); } - #if ADC_MODE_VALUE == ADC_VCC + if (ADC_MODE_VALUE == ADC_VCC) { DEBUG_MSG_P(PSTR("[MAIN] Power: %u mV\n"), ESP.getVcc()); - #endif + } if (espurnaLoopDelay()) { DEBUG_MSG_P(PSTR("[MAIN] Power saving delay value: %lu ms\n"), espurnaLoopDelay()); } diff --git a/code/espurna/ws.ino b/code/espurna/ws.ino index a3e2d567..d25129a4 100644 --- a/code/espurna/ws.ino +++ b/code/espurna/ws.ino @@ -358,9 +358,11 @@ void _wsUpdate(JsonObject& root) { root["uptime"] = getUptime(); root["rssi"] = WiFi.RSSI(); root["loadaverage"] = systemLoadAverage(); - #if ADC_MODE_VALUE == ADC_VCC + if (ADC_MODE_VALUE == ADC_VCC) { root["vcc"] = ESP.getVcc(); - #endif + } else { + root["vcc"] = "N/A (TOUT) "; + } #if NTP_SUPPORT if (ntpSynced()) root["now"] = now(); #endif diff --git a/code/test/build/sensor.h b/code/test/build/sensor.h index 10bf6e1f..59ca771f 100644 --- a/code/test/build/sensor.h +++ b/code/test/build/sensor.h @@ -28,3 +28,4 @@ #define TMP3X_SUPPORT 1 #define VEML6075_SUPPORT 1 #define VL53L1X_SUPPORT 1 +#define HDC1080_SUPPORT 1