diff --git a/code/espurna/config/arduino.h b/code/espurna/config/arduino.h index b9d1e652..7339c8cf 100644 --- a/code/espurna/config/arduino.h +++ b/code/espurna/config/arduino.h @@ -67,6 +67,8 @@ //#define HEYGO_HY02 //#define MAXCIO_WUS002S //#define YIDIAN_XSSSA05 +//#define TONBUX_XSSSA06 +//#define GREEN_ESP8266RELAY //-------------------------------------------------------------------------------- // Features (values below are non-default values) @@ -103,6 +105,7 @@ // Sensors (values below are non-default values) //-------------------------------------------------------------------------------- +//#define AM2320_SUPPORT 1 //#define ANALOG_SUPPORT 1 //#define BH1750_SUPPORT 1 //#define BMX280_SUPPORT 1 @@ -114,6 +117,7 @@ //#define EMON_ADS1X15_SUPPORT 1 //#define EMON_ANALOG_SUPPORT 1 //#define EVENTS_SUPPORT 1 +//#define GUVAS12SD_SUPPORT 1 //#define HLW8012_SUPPORT 1 //#define MHZ19_SUPPORT 1 //#define PMSX003_SUPPORT 1 diff --git a/code/espurna/config/hardware.h b/code/espurna/config/hardware.h index ba2e2104..49e42b70 100644 --- a/code/espurna/config/hardware.h +++ b/code/espurna/config/hardware.h @@ -1579,7 +1579,7 @@ // Buttons #define BUTTON1_PIN 13 - #define BUTTON1_MODE BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH + #define BUTTON1_MODE BUTTON_PUSHBUTTON | BUTTON_SET_PULLUP | BUTTON_DEFAULT_HIGH #define BUTTON1_RELAY 1 // Relays @@ -1610,20 +1610,8 @@ #define RELAY1_TYPE RELAY_TYPE_NORMAL // LEDs - #define LED1_PIN 0 + #define LED1_PIN 4 #define LED1_PIN_INVERSE 0 - #define LED2_PIN 15 - #define LED2_PIN_INVERSE 0 - - // HLW8012 - #ifndef HLW8012_SUPPORT - #define HLW8012_SUPPORT 1 - #endif - #define HLW8012_SEL_PIN 3 - #define HLW8012_CF1_PIN 14 - #define HLW8012_CF_PIN 5 - - #define HLW8012_VOLTAGE_R_UP ( 2 * 1200000 ) // Upstream voltage resistor // ----------------------------------------------------------------------------- // Maxcio W-US002S @@ -1682,6 +1670,69 @@ #define LED1_PIN 4 #define LED1_PIN_INVERSE 0 + // HLW8012 + #ifndef HLW8012_SUPPORT + #define HLW8012_SUPPORT 1 + #endif + #define HLW8012_SEL_PIN 3 + #define HLW8012_CF1_PIN 14 + #define HLW8012_CF_PIN 5 + + #define HLW8012_CURRENT_R 0.001 // Current resistor + #define HLW8012_VOLTAGE_R_UP ( 2 * 1200000 ) // Upstream voltage resistor + +// ----------------------------------------------------------------------------- +// TONBUX XS-SSA06 +// ----------------------------------------------------------------------------- + +#elif defined(TONBUX_XSSSA06) + + // Info + #define MANUFACTURER "TONBUX" + #define DEVICE "XSSSA06" + + // Buttons + #define BUTTON1_PIN 13 + #define BUTTON1_MODE BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH + #define BUTTON1_RELAY 1 + + // Relays + #define RELAY1_PIN 15 + #define RELAY1_TYPE RELAY_TYPE_NORMAL + + // LEDs + #define LED1_PIN 0 // R - 8 rgb led ring + #define LED1_PIN_INVERSE 0 + #define LED2_PIN 5 // G + #define LED2_PIN_INVERSE 0 + #define LED3_PIN 2 // B + #define LED3_PIN_INVERSE 0 + +// ----------------------------------------------------------------------------- +// GREEN ESP8266 RELAY MODULE +// https://www.aliexpress.com/wholesale?catId=0&initiative_id=SB_20180323113846&SearchText=Green+ESP8266 +// ----------------------------------------------------------------------------- + +#elif defined(GREEN_ESP8266RELAY) + + // Info + #define MANUFACTURER "GREEN" + #define DEVICE "ESP8266RELAY" + + // Buttons + // Not a button but input via Optocoupler + #define BUTTON1_PIN 5 + #define BUTTON1_MODE BUTTON_PUSHBUTTON + #define BUTTON1_RELAY 1 + + // Relays + #define RELAY1_PIN 4 + #define RELAY1_TYPE RELAY_TYPE_NORMAL + + // LEDs + #define LED1_PIN 2 + #define LED1_PIN_INVERSE 1 + // ----------------------------------------------------------------------------- // TEST boards (do not use!!) // ----------------------------------------------------------------------------- diff --git a/code/espurna/config/prototypes.h b/code/espurna/config/prototypes.h index bda92e08..d9ac791f 100644 --- a/code/espurna/config/prototypes.h +++ b/code/espurna/config/prototypes.h @@ -75,8 +75,10 @@ bool i2cReleaseLock(unsigned char address); unsigned char i2cFindAndLock(size_t size, unsigned char * addresses); void i2c_write_buffer(uint8_t address, uint8_t * buffer, size_t len); +uint8_t i2c_write_buffer_ret(uint8_t address, uint8_t * buffer, size_t len); void i2c_write_uint8(uint8_t address, uint8_t value); void i2c_write_uint8(uint8_t address, uint8_t reg, uint8_t value); +uint8_t i2c_write_uint8(uint8_t address, uint8_t reg, uint8_t value, uint8_t value2); void i2c_write_uint16(uint8_t address, uint16_t value); void i2c_write_uint16(uint8_t address, uint8_t reg, uint16_t value); uint8_t i2c_read_uint8(uint8_t address); diff --git a/code/espurna/config/sensors.h b/code/espurna/config/sensors.h index 4d100c88..05534f80 100644 --- a/code/espurna/config/sensors.h +++ b/code/espurna/config/sensors.h @@ -32,10 +32,24 @@ #define HUMIDITY_MIN_CHANGE 0 // Minimum humidity change to report #endif -#define HUMIDITY_NORMAL 0 -#define HUMIDITY_COMFORTABLE 1 -#define HUMIDITY_DRY 2 -#define HUMIDITY_WET 3 +// American Society of Heating, Refrigerating and Air-Conditioning Engineers suggests a range of 45% - 55% humidity to manage health effects and illnesses. +// Comfortable: 30% - 60% +// Recommended: 45% - 55% +// High : 55% - 80% +#define HUMIDITY_NORMAL 0 // > %30 +#define HUMIDITY_COMFORTABLE 1 // > %45 +#define HUMIDITY_DRY 2 // < %30 +#define HUMIDITY_WET 3 // > %70 + +// United States Environmental Protection Agency - UV Index Scale +// One UV Index unit is equivalent to 25 milliWatts per square meter. +#define UV_INDEX_LOW 0 // 0 to 2 means low danger from the sun's UV rays for the average person. +#define UV_INDEX_MODERATE 1 // 3 to 5 means moderate risk of harm from unprotected sun exposure. +#define UV_INDEX_HIGH 2 // 6 to 7 means high risk of harm from unprotected sun exposure. Protection against skin and eye damage is needed. +#define UV_INDEX_VERY_HIGH 3 // 8 to 10 means very high risk of harm from unprotected sun exposure. + // Take extra precautions because unprotected skin and eyes will be damaged and can burn quickly. +#define UV_INDEX_EXTREME 4 // 11 or more means extreme risk of harm from unprotected sun exposure. + // Take all precautions because unprotected skin and eyes can burn in minutes. #define SENSOR_PUBLISH_ADDRESSES 0 // Publish sensor addresses #define SENSOR_ADDRESS_TOPIC "address" // Topic to publish sensor addresses @@ -88,6 +102,8 @@ #define SENSOR_SHT3X_I2C_ID 0x16 #define SENSOR_BH1750_ID 0x17 #define SENSOR_PZEM004T_ID 0x18 +#define SENSOR_AM2320_ID 0x19 +#define SENSOR_GUVAS12SD_ID 0x20 //-------------------------------------------------------------------------------- // Magnitudes @@ -113,8 +129,9 @@ #define MAGNITUDE_PM10 17 #define MAGNITUDE_CO2 18 #define MAGNITUDE_LUX 19 +#define MAGNITUDE_UV 20 -#define MAGNITUDE_MAX 20 +#define MAGNITUDE_MAX 21 // ============================================================================= // Specific data for each sensor @@ -494,6 +511,37 @@ #define V9261F_POWER_FACTOR 153699.0 #define V9261F_RPOWER_FACTOR V9261F_CURRENT_FACTOR +//------------------------------------------------------------------------------ +// AM2320 Humidity & Temperature sensor over I2C +// Enable support by passing AM2320_SUPPORT=1 build flag +//------------------------------------------------------------------------------ + +#ifndef AM2320_SUPPORT +#define AM2320_SUPPORT 0 +#endif + +#ifndef AM2320_ADDRESS +#define AM2320_ADDRESS 0x00 // 0x00 means auto +#endif + +#if AM2320_SUPPORT +#undef I2C_SUPPORT +#define I2C_SUPPORT 1 +#endif + +//------------------------------------------------------------------------------ +// GUVAS12SD UV Sensor (analog) +// Enable support by passing GUVAS12SD_SUPPORT=1 build flag +//------------------------------------------------------------------------------ + +#ifndef GUVAS12SD_SUPPORT +#define GUVAS12SD_SUPPORT 0 +#endif + +#ifndef GUVAS12SD_PIN +#define GUVAS12SD_PIN 14 +#endif + // ============================================================================= // Sensor helpers configuration // ============================================================================= @@ -504,7 +552,7 @@ || EMON_ADC121_SUPPORT || EMON_ADS1X15_SUPPORT \ || EMON_ANALOG_SUPPORT || EVENTS_SUPPORT || HLW8012_SUPPORT \ || MHZ19_SUPPORT || PMSX003_SUPPORT || SHT3X_I2C_SUPPORT \ - || SI7021_SUPPORT || V9261F_SUPPORT + || SI7021_SUPPORT || V9261F_SUPPORT || AM2320_SUPPORT || GUVAS12SD_SUPPORT #define SENSOR_SUPPORT 1 #else #define SENSOR_SUPPORT 0 @@ -583,6 +631,7 @@ PROGMEM const char magnitude_pm2dot5_topic[] = "pm2dot5"; PROGMEM const char magnitude_pm10_topic[] = "pm10"; PROGMEM const char magnitude_co2_topic[] = "co2"; PROGMEM const char magnitude_lux_topic[] = "lux"; +PROGMEM const char magnitude_uv_topic[] = "uv"; PROGMEM const char* const magnitude_topics[] = { magnitude_unknown_topic, magnitude_temperature_topic, magnitude_humidity_topic, @@ -591,7 +640,7 @@ PROGMEM const char* const magnitude_topics[] = { magnitude_power_factor_topic, magnitude_energy_topic, magnitude_energy_delta_topic, magnitude_analog_topic, magnitude_digital_topic, magnitude_events_topic, magnitude_pm1dot0_topic, magnitude_pm2dot5_topic, magnitude_pm10_topic, - magnitude_co2_topic, magnitude_lux_topic + magnitude_co2_topic, magnitude_lux_topic, magnitude_uv_topic }; PROGMEM const char magnitude_empty[] = ""; @@ -608,6 +657,7 @@ PROGMEM const char magnitude_kwh[] = "kWh"; PROGMEM const char magnitude_ugm3[] = "µg/m3"; PROGMEM const char magnitude_ppm[] = "ppm"; PROGMEM const char magnitude_lux[] = "lux"; +PROGMEM const char magnitude_uv[] = "uv"; PROGMEM const char* const magnitude_units[] = { magnitude_empty, magnitude_celsius, magnitude_percentage, @@ -616,7 +666,7 @@ PROGMEM const char* const magnitude_units[] = { magnitude_percentage, magnitude_joules, magnitude_joules, magnitude_empty, magnitude_empty, magnitude_empty, magnitude_ugm3, magnitude_ugm3, magnitude_ugm3, - magnitude_ppm, magnitude_lux + magnitude_ppm, magnitude_lux, magnitude_uv }; #include "../sensors/BaseSensor.h" @@ -700,4 +750,12 @@ PROGMEM const char* const magnitude_units[] = { #include "../sensors/V9261FSensor.h" #endif +#if AM2320_SUPPORT + #include "../sensors/AM2320Sensor.h" +#endif + +#if GUVAS12SD_SUPPORT + #include "../sensors/GUVAS12SDSensor.h" +#endif + #endif // SENSOR_SUPPORT diff --git a/code/espurna/i2c.ino b/code/espurna/i2c.ino index 7e5dd0df..9dc0f882 100644 --- a/code/espurna/i2c.ino +++ b/code/espurna/i2c.ino @@ -110,6 +110,18 @@ int _i2cClearbus(int sda, int scl) { #if I2C_USE_BRZO +// simple i2c device wakeup +void i2c_wakeup(uint8_t address) { + brzo_i2c_start_transaction(_address, _i2c_scl_frequency); + brzo_i2c_end_transaction(); +} + +uint8_t i2c_write_buffer_ret(uint8_t address, uint8_t * buffer, size_t len) { + brzo_i2c_start_transaction(_address, _i2c_scl_frequency); + brzo_i2c_write_uint8(buffer, len, false); + return brzo_i2c_end_transaction(); +} + void i2c_write_buffer(uint8_t address, uint8_t * buffer, size_t len) { brzo_i2c_start_transaction(_address, _i2c_scl_frequency); brzo_i2c_write_uint8(buffer, len, false); @@ -165,6 +177,18 @@ void i2c_read_buffer(uint8_t address, uint8_t * buffer, size_t len) { #else // not I2C_USE_BRZO +// simple i2c device wakeup +void i2c_wakeup(uint8_t address) { + Wire.beginTransmission((uint8_t) address); + Wire.endTransmission(); +} + +uint8_t i2c_write_buffer_ret(uint8_t address, uint8_t * buffer, size_t len) { + Wire.beginTransmission((uint8_t) address); + Wire.write(buffer, len); + return Wire.endTransmission(); +} + void i2c_write_buffer(uint8_t address, uint8_t * buffer, size_t len) { Wire.beginTransmission((uint8_t) address); Wire.write(buffer, len); @@ -231,6 +255,14 @@ void i2c_write_uint8(uint8_t address, uint8_t reg, uint8_t value) { i2c_write_buffer(address, buffer, 2); } +uint8_t i2c_write_uint8(uint8_t address, uint8_t reg, uint8_t value, uint8_t value2) { + uint8_t buffer[3]; + buffer[0] = reg; + buffer[1] = value; + buffer[2] = value2; + return i2c_write_buffer_ret(address, buffer, 3); +} + void i2c_write_uint16(uint8_t address, uint8_t reg, uint16_t value) { uint8_t buffer[3]; buffer[0] = reg; diff --git a/code/espurna/migrate.ino b/code/espurna/migrate.ino index b69524ea..6a151770 100644 --- a/code/espurna/migrate.ino +++ b/code/espurna/migrate.ino @@ -751,13 +751,13 @@ void migrate() { setSetting("relayType", 1, RELAY_TYPE_INVERSE); setSetting("relayType", 2, RELAY_TYPE_INVERSE); setSetting("relayType", 3, RELAY_TYPE_INVERSE); - setSetting("relayType", 4, RELAY_TYPE_NORMAL); - setSetting("ledGPIO", 0, 0); - setSetting("ledLogic", 0, 0); - setSetting("ledGPIO", 1, 3); - setSetting("ledLogic", 1, 0); + setSetting("relayType", 4, RELAY_TYPE_NORMAL); // Not a relay. USB ports on/off + setSetting("ledGPIO", 0, 0); // 1 blue led + setSetting("ledLogic", 0, 1); + setSetting("ledGPIO", 1, 3); // 3 red leds + setSetting("ledLogic", 1, 1); setSetting("btnGPIO", 0, 5); - setSetting("btnRelay", 0, 0); + setSetting("btnRelay", 0, 1); #elif defined(LINGAN_SWA1) @@ -773,12 +773,12 @@ void migrate() { setSetting("board", 58); setSetting("ledGPIO", 0, 0); - setSetting("ledLogic", 0, 0); + setSetting("ledLogic", 0, 1); setSetting("ledGPIO", 1, 15); setSetting("ledLogic", 1, 0); setSetting("btnGPIO", 0, 13); setSetting("btnRelay", 0, 0); - setSetting("relayGPIO", 0, 12); + setSetting("relayGPIO", 0, 15); setSetting("relayType", 0, RELAY_TYPE_NORMAL); setSetting("selGPIO", 3); setSetting("cf1GPIO", 14); @@ -800,11 +800,35 @@ void migrate() { #elif defined(YIDIAN_XSSSA05) setSetting("board", 60); - setSetting("ledGPIO", 0, 4); + setSetting("ledGPIO", 0, 0); setSetting("ledLogic", 0, 0); + setSetting("ledGPIO", 1, 5); + setSetting("ledLogic", 1, 0); + setSetting("ledGPIO", 2, 2); + setSetting("ledLogic", 2, 0); setSetting("btnGPIO", 0, 13); setSetting("btnRelay", 0, 0); - setSetting("relayGPIO", 0, 12); + setSetting("relayGPIO", 0, 15); + setSetting("relayType", 0, RELAY_TYPE_NORMAL); + + #elif defined(TONBUX_XSSSA06) + + setSetting("board", 61); + setSetting("ledGPIO", 0, 4); + setSetting("ledLogic", 0, 1); + setSetting("btnGPIO", 0, 13); + setSetting("btnRelay", 0, 0); + setSetting("relayGPIO", 0, 5); + setSetting("relayType", 0, RELAY_TYPE_NORMAL); + + #elif defined(GREEN_ESP8266RELAY) + + setSetting("board", 62); + setSetting("ledGPIO", 0, 2); + setSetting("ledLogic", 0, 1); + setSetting("btnGPIO", 0, 5); + setSetting("btnRelay", 0, 0); + setSetting("relayGPIO", 0, 4); setSetting("relayType", 0, RELAY_TYPE_NORMAL); #else diff --git a/code/espurna/sensor.ino b/code/espurna/sensor.ino index 6c5f340e..c932fb3c 100644 --- a/code/espurna/sensor.ino +++ b/code/espurna/sensor.ino @@ -469,6 +469,22 @@ void _sensorLoad() { } #endif + #if AM2320_SUPPORT + { + AM2320Sensor * sensor = new AM2320Sensor(); + sensor->setAddress(AM2320_ADDRESS); + _sensors.push_back(sensor); + } + #endif + + #if GUVAS12SD_SUPPORT + { + GUVAS12SDSensor * sensor = new GUVAS12SDSensor(); + sensor->setGPIO(GUVAS12SD_PIN); + _sensors.push_back(sensor); + } + #endif + } void _sensorCallback(unsigned char i, unsigned char type, const char * payload) { diff --git a/code/espurna/sensors/AM2320Sensor.h b/code/espurna/sensors/AM2320Sensor.h new file mode 100644 index 00000000..be97de1b --- /dev/null +++ b/code/espurna/sensors/AM2320Sensor.h @@ -0,0 +1,193 @@ +// ----------------------------------------------------------------------------- +// AM2320 Humidity & Temperature sensor over I2C +// Copyright (C) 2018 by Mustafa Tufan +// ----------------------------------------------------------------------------- + +#if SENSOR_SUPPORT && AM2320_SUPPORT + +#pragma once + +#include "Arduino.h" +#include "I2CSensor.h" + +// https://akizukidenshi.com/download/ds/aosong/AM2320.pdf +#define AM2320_I2C_READ_REGISTER_DATA 0x03 // Read one or more data registers +#define AM2320_I2C_WRITE_MULTIPLE_REGISTERS 0x10 // Multiple sets of binary data to write multiple registers +/* +Register | Address | Register | Address | Register | Address | Register | Address +-----------------+---------+--------------------+---------+-------------------------+---------+-----------+-------- +High humidity | 0x00 | Model High | 0x08 | Users register a high | 0x10 | Retention | 0x18 +Low humidity | 0x01 | Model Low | 0x09 | Users register a low | 0x11 | Retention | 0x19 +High temperature | 0x02 | The version number | 0x0A | Users register 2 high | 0x12 | Retention | 0x1A +Low temperature | 0x03 | Device ID(24-31)Bit| 0x0B | Users register 2 low | 0x13 | Retention | 0x1B +Retention | 0x04 | Device ID(24-31)Bit| 0x0C | Retention | 0x14 | Retention | 0x1C +Retention | 0x05 | Device ID(24-31)Bit| 0x0D | Retention | 0x15 | Retention | 0x1D +Retention | 0x06 | Device ID(24-31)Bit| 0x0E | Retention | 0x16 | Retention | 0x1E +Retention | 0x07 | Status Register | 0x0F | Retention | 0x17 | Retention | 0x1F +*/ + +class AM2320Sensor : public I2CSensor { + + public: + + // --------------------------------------------------------------------- + // Public + // --------------------------------------------------------------------- + + AM2320Sensor(): I2CSensor() { + _count = 2; + _sensor_id = SENSOR_AM2320_ID; + } + + // --------------------------------------------------------------------- + // Sensor API + // --------------------------------------------------------------------- + + // Initialization method, must be idempotent + void begin() { + if (!_dirty) return; + + // I2C auto-discover + unsigned char addresses[] = {0x23, 0x5C, 0xB8}; + _address = _begin_i2c(_address, sizeof(addresses), addresses); + if (_address == 0) return; + + _ready = true; + _dirty = false; + } + + // Descriptive name of the sensor + String description() { + char buffer[25]; + snprintf(buffer, sizeof(buffer), "AM2320 @ I2C (0x%02X)", _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_OK; + _read(); + } + + // Current value for slot # index + double value(unsigned char index) { + if (index == 0) return _temperature; + if (index == 1) return _humidity; + return 0; + } + + protected: + + // --------------------------------------------------------------------- + // Protected + // --------------------------------------------------------------------- + +/* + // Get device model, version, device_id + + void _init() { + i2c_wakeup(); + 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) { + _error = SENSOR_ERROR_TIMEOUT; + return false; + } + + uint16_t model = (_buffer[2] << 8) | _buffer[3]; + uint8_t version = _buffer[4]; + uint32_t device_id = _buffer[8] << 24 | _buffer[7] << 16 | _buffer[6] << 8 | _buffer[5]; + } +*/ + + void _read() { + i2c_wakeup(); + // 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) { + _error = SENSOR_ERROR_TIMEOUT; + return false; + } + + unsigned char _buffer[8]; + + // waiting time of at least 800 μs, the maximum 3000 μs + delayMicroseconds(800 + ((3000-800)/2) ); + 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 % + // Temperature: 00FA = (F×16)+A = 250 => temperature = 250÷10 = 25.0 C + // 0115 = (1×256)+(1×16)+5 = 277 => temperature = 277÷10 = 27.7 C + // Temperature resolution is 16Bit, temperature highest bit (Bit 15) is equal to 1 indicates a negative temperature + + // _buffer 0 = function code + // _buffer 1 = number of bytes + // _buffer 2-3 = high/low humidity + // _buffer 4-5 = high/low temperature + // _buffer 6-7 = CRC low/high + + unsigned int responseCRC = 0; + responseCRC = ((responseCRC | _buffer[7]) << 8 | _buffer[6]); + + if (responseCRC == _CRC16(_buffer)) { + int foo = (_buffer[2] << 8) | _buffer[3]; + _humidity = foo / 10.0; + + foo = ((_buffer[4] & 0x7F) << 8) | _buffer[5]; // clean bit 15 and merge + _temperature = foo / 10.0; + + if (_buffer[4] & 0x80) { // is bit 15 == 1 + _temperature = _temperature * -1; // negative temperature + } + + _error = SENSOR_ERROR_OK; + } else { + _error = SENSOR_ERROR_CRC; + return; + } + } + + unsigned int _CRC16(unsigned char buffer[]) { + unsigned int crc16 = 0xFFFF; + + for (unsigned int i = 0; i < 6; i++) { + crc16 ^= buffer[i]; + + for (unsigned int b = 8; b != 0; b--) { + if (crc16 & 0x01) { // is lsb set + crc16 >>= 1; + crc16 ^= 0xA001; + } else { + crc16 >>= 1; + } + } + } + + return crc16; + } + + double _temperature = 0; + double _humidity = 0; +}; + +#endif // SENSOR_SUPPORT && AM2320_SUPPORT diff --git a/code/espurna/sensors/GUVAS12SDSensor.h b/code/espurna/sensors/GUVAS12SDSensor.h new file mode 100644 index 00000000..1fb214ba --- /dev/null +++ b/code/espurna/sensors/GUVAS12SDSensor.h @@ -0,0 +1,170 @@ +// ----------------------------------------------------------------------------- +// GUVA-S12SD UV Sensor +// Copyright (C) 2017-2018 by Xose Pérez +// by Mustafa Tufan +// ----------------------------------------------------------------------------- + +#if SENSOR_SUPPORT && GUVAS12SD_SUPPORT + +#pragma once + +#include "Arduino.h" +#include "BaseSensor.h" + +// http://www.eoc-inc.com/genicom/GUVA-S12SD.pdf +// +// GUVA-S12D has a wide spectral range of 200nm-400nm +// The output voltage and the UV index is linear, illumination intensity = 307 * Vsig where: Vsig is the value of voltage measured from the SIG pin of the interface, unit V. +// illumination intensity unit: mW/m2 for the combination strength of UV light with wavelength range: 200nm-400nm +// UV Index = illumination intensity / 200 +// +// UV Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 10+ +// -----------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+------+-------- +// mV | <50 | 227 | 318 | 408 | 503 | 606 | 696 | 795 | 881 | 976 | 1079 | 1170+ +// analog val | <10 | 46 | 65 | 83 | 103 | 124 | 142 | 162 | 180 | 200 | 221 | 240+ +// + +#define UV_SAMPLE_RATE 1 + +class GUVAS12SDSensor : public BaseSensor { + + public: + + // --------------------------------------------------------------------- + // Public + // --------------------------------------------------------------------- + + GUVAS12SDSensor(): BaseSensor() { + _count = 1; + _sensor_id = SENSOR_GUVAS12SD_ID; + } + + ~GUVAS12SDSensor() { + if (_previous != GPIO_NONE) gpioReleaseLock(_previous); + } + + // --------------------------------------------------------------------- + + void setGPIO(unsigned char gpio) { + _gpio = gpio; + } + + // --------------------------------------------------------------------- + + unsigned char getGPIO() { + return _gpio; + } + + // --------------------------------------------------------------------- + // Sensor API + // --------------------------------------------------------------------- + + // Initialization method, must be idempotent + void begin() { + + // Manage GPIO lock + if (_previous != GPIO_NONE) gpioReleaseLock(_previous); + _previous = GPIO_NONE; + if (!gpioGetLock(_gpio)) { + _error = SENSOR_ERROR_GPIO_USED; + return; + } + _previous = _gpio; + + _ready = true; + + } + + // Pre-read hook (usually to populate registers with up-to-date data) + void pre() { + _error = SENSOR_ERROR_OK; + _read(); + } + + // Descriptive name of the sensor + String description() { + char buffer[18]; + snprintf(buffer, sizeof(buffer), "GUVAS12SD @ GPIO%d", _gpio); + return String(buffer); + } + + // Descriptive name of the slot # index + String slot(unsigned char index) { + return description(); + }; + + // Address of the sensor (it could be the GPIO or I2C address) + String address(unsigned char index) { + return String(_gpio); + } + + // Type for slot # index + unsigned char type(unsigned char index) { + if (index == 0) return MAGNITUDE_UV; + return MAGNITUDE_NONE; + } + + // Current value for slot # index + double value(unsigned char index) { + if (index == 0) return _uvindex; + return 0; + } + + + protected: + + // --------------------------------------------------------------------- + // Protected + // --------------------------------------------------------------------- + + void _read() { + int _average = 0; + + #if UV_SAMPLE_RATE == 1 + _average = analogRead(0); + #else + for (unsigned int i=0; i < UV_SAMPLE_RATE; i++) { + _average += analogRead(0); + delay(2); + } + _average = (_average / UV_SAMPLE_RATE); + #endif + // _sensormV = _average / 1023*3.3; + + if (_average < 10) { + _uvindex = 0; + } else if (_average < 46) { + _uvindex = (_average - 10) / (46-10); + } else if (_average < 65) { + _uvindex = 1 + ((_average - 46) / (65-46)); + } else if (_average < 83) { + _uvindex = 2 + ((_average - 65) / (83-65)); + } else if (_average < 103) { + _uvindex = 3 + ((_average - 83) / (103- 83)); + } else if (_average < 124) { + _uvindex = 4 + ((_average - 103) / (124-103)); + } else if (_average < 142) { + _uvindex = 5 + ((_average - 124) / (142-124)); + } else if (_average < 162) { + _uvindex = 6 + ((_average - 142) / (162-142)); + } else if (_average < 180) { + _uvindex = 7 + ((_average - 162) / (180-162)); + } else if (_average < 200) { + _uvindex = 8 + ((_average - 180) / (200-180)); + } else if (_average < 221) { + _uvindex = 9 + ((_average - 200) / (221-200)); + } else { + _uvindex = 10; + } + + return _uvindex; + } + + unsigned char _gpio = GPIO_NONE; + unsigned char _previous = GPIO_NONE; + + double _uvindex = 0; + +}; + +#endif // SENSOR_SUPPORT && GUVAS12SD_SUPPORT diff --git a/code/espurna/sensors/I2CSensor.h b/code/espurna/sensors/I2CSensor.h index bec7d51a..3b1b8ae6 100644 --- a/code/espurna/sensors/I2CSensor.h +++ b/code/espurna/sensors/I2CSensor.h @@ -5,6 +5,24 @@ #if SENSOR_SUPPORT && ( I2C_SUPPORT || EMON_ANALOG_SUPPORT ) +#if I2C_USE_BRZO + #define I2C_TRANS_SUCCESS 0 // All i2c commands were executed without errors + #define I2C_TRANS_ERROR_BUS_NOT_FREE 1 // Bus not free, i.e. either SDA or SCL is low + #define I2C_TRANS_ERROR_NACK_WRITE 2 // Not ACK ("NACK") by slave during write: + // Either the slave did not respond to the given slave address; or the slave did not ACK a byte transferred by the master. + #define I2C_TRANS_ERROR_NACK_READ 4 // Not ACK ("NACK") by slave during read, + // i.e. slave did not respond to the given slave address + #define I2C_TRANS_ERROR_CLOCK 8 // Clock Stretching by slave exceeded maximum clock stretching time. Most probably, there is a bus stall now! + #define I2C_TRANS_ERROR_READ_NULL 16 // Read was called with 0 bytes to be read by the master. Command not sent to the slave, since this could yield to a bus stall + #define I2C_TRANS_ERROR_TIMEOUT 32 // ACK Polling timeout exceeded +#else // Wire + #define I2C_TRANS_SUCCESS 0 // success + #define I2C_TRANS_ERROR_BUFFER_OVERLOW 1 // data too long to fit in transmit buffer + #define I2C_TRANS_ERROR_NACK_ADDRESS 2 // received NACK on transmit of address + #define I2C_TRANS_ERROR_NACK_DATA 3 // received NACK on transmit of data + #define I2C_TRANS_ERROR_OTHER 4 // other error +#endif + #pragma once #include "BaseSensor.h" diff --git a/code/espurna/sensors/SI7021Sensor.h b/code/espurna/sensors/SI7021Sensor.h index 677d8b2d..8a43a619 100644 --- a/code/espurna/sensors/SI7021Sensor.h +++ b/code/espurna/sensors/SI7021Sensor.h @@ -32,6 +32,7 @@ class SI7021Sensor : public I2CSensor { // --------------------------------------------------------------------- SI7021Sensor(): I2CSensor() { + _count = 2; _sensor_id = SENSOR_SI7021_ID; } diff --git a/code/espurna/utils.ino b/code/espurna/utils.ino index a1baee1d..0b7ec1e0 100644 --- a/code/espurna/utils.ino +++ b/code/espurna/utils.ino @@ -389,6 +389,12 @@ void info() { #if V9261F_SUPPORT DEBUG_MSG_P(PSTR(" V9261F")); #endif + #if AM2320_SUPPORT + DEBUG_MSG_P(PSTR(" AM2320_I2C")); + #endif + #if GUVAS12SD_SUPPORT + DEBUG_MSG_P(PSTR(" GUVAS12SD")); + #endif #endif // SENSOR_SUPPORT diff --git a/code/platformio.ini b/code/platformio.ini index 1f8a8858..c6b8f33b 100644 --- a/code/platformio.ini +++ b/code/platformio.ini @@ -1557,7 +1557,20 @@ build_flags = ${common.build_flags_1m} -DHEYGO_HY02 monitor_baud = 115200 extra_scripts = ${common.extra_scripts} -[env:maxcio-wus0025] +[env:heygo-hy02-ota] +platform = ${common.platform} +framework = arduino +board = esp01_1m +board_flash_mode = dout +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +build_flags = ${common.build_flags_1m} -DHEYGO_HY02 +upload_speed = 115200 +upload_port = "${env.ESPURNA_IP}" +upload_flags = --auth=${env.ESPURNA_AUTH} --port 8266 +extra_scripts = ${common.extra_scripts} + +[env:maxcio-wus002s] platform = ${common.platform} framework = arduino board = esp01_1m @@ -1568,6 +1581,19 @@ build_flags = ${common.build_flags_1m} -DMAXCIO_WUS002S monitor_baud = 115200 extra_scripts = ${common.extra_scripts} +[env:maxcio-wus002s-ota] +platform = ${common.platform} +framework = arduino +board = esp01_1m +board_flash_mode = dout +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +build_flags = ${common.build_flags_1m} -DMAXCIO_WUS002S +upload_speed = 115200 +upload_port = "${env.ESPURNA_IP}" +upload_flags = --auth=${env.ESPURNA_AUTH} --port 8266 +extra_scripts = ${common.extra_scripts} + [env:yidian-xsssa05] platform = ${common.platform} framework = arduino @@ -1579,6 +1605,66 @@ build_flags = ${common.build_flags_1m} -DYIDIAN_XSSSA05 monitor_baud = 115200 extra_scripts = ${common.extra_scripts} +[env:yidian-xsssa05-ota] +platform = ${common.platform} +framework = arduino +board = esp01_1m +board_flash_mode = dout +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +build_flags = ${common.build_flags_1m} -DYIDIAN_XSSSA05 +upload_speed = 115200 +upload_port = "${env.ESPURNA_IP}" +upload_flags = --auth=${env.ESPURNA_AUTH} --port 8266 +extra_scripts = ${common.extra_scripts} + +[env:tonbux-xsssa06] +platform = ${common.platform} +framework = arduino +board = esp01_1m +board_flash_mode = dout +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +build_flags = ${common.build_flags_1m} -DTONBUX_XSSSA06 +monitor_baud = 115200 +extra_scripts = ${common.extra_scripts} + +[env:tonbux-xsssa06-ota] +platform = ${common.platform} +framework = arduino +board = esp01_1m +board_flash_mode = dout +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +build_flags = ${common.build_flags_1m} -DTONBUX_XSSSA06 +upload_speed = 115200 +upload_port = "${env.ESPURNA_IP}" +upload_flags = --auth=${env.ESPURNA_AUTH} --port 8266 +extra_scripts = ${common.extra_scripts} + +[env:green-esp8266relay] +platform = ${common.platform} +framework = arduino +board = esp12e +board_flash_mode = dout +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +build_flags = ${common.build_flags} -DGREEN_ESP8266RELAY +monitor_baud = 115200 +extra_scripts = ${common.extra_scripts} + +[env:green-esp8266relay-ota] +platform = ${common.platform} +framework = arduino +board = esp12e +board_flash_mode = dout +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +build_flags = ${common.build_flags} -DGREEN_ESP8266RELAY +upload_speed = 115200 +upload_port = "${env.ESPURNA_IP}" +upload_flags = --auth=${env.ESPURNA_AUTH} --port 8266 +extra_scripts = ${common.extra_scripts} # ------------------------------------------------------------------------------ # GENERIC OTA ENVIRONMENTS