diff --git a/code/espurna/config/arduino.h b/code/espurna/config/arduino.h index 437148c3..4610f5cc 100644 --- a/code/espurna/config/arduino.h +++ b/code/espurna/config/arduino.h @@ -36,7 +36,7 @@ //#define ENABLE_DHT 1 //#define ENABLE_DS18B20 1 -//#define ENABLE_EMON 1 +#define ENABLE_EMON 1 //#define ENABLE_HLW8018 1 //#define ENABLE_RF 1 //#define ENABLE_FAUXMO 0 diff --git a/code/espurna/config/general.h b/code/espurna/config/general.h index 5e0acb74..efd10af3 100644 --- a/code/espurna/config/general.h +++ b/code/espurna/config/general.h @@ -102,6 +102,15 @@ #define MQTT_USE_GETTER "" #define MQTT_USE_SETTER "" +// ----------------------------------------------------------------------------- +// I2C +// ----------------------------------------------------------------------------- + +#define ENABLE_I2C 1 +#define I2C_SDA_PIN 4 +#define I2C_SCL_PIN 14 +#define I2C_CLOCK_STRETCH_TIME 200 +#define I2C_SCL_FREQUENCY 1000 // ----------------------------------------------------------------------------- // DOMOTICZ diff --git a/code/espurna/config/sensors.h b/code/espurna/config/sensors.h index a39793e5..013b4f1f 100644 --- a/code/espurna/config/sensors.h +++ b/code/espurna/config/sensors.h @@ -37,19 +37,36 @@ //-------------------------------------------------------------------------------- // Custom current sensor // Check http://tinkerman.cat/your-laundry-is-done/ +// Check http://tinkerman.cat/power-monitoring-sonoff-th-adc121/ // Enable support by passing ENABLE_EMON=1 build flag //-------------------------------------------------------------------------------- -#define EMON_CURRENT_PIN 0 +#define EMON_ANALOG_PROVIDER 0 +#define EMON_ADC121_PROVIDER 1 + +#define EMON_PROVIDER EMON_ADC121_PROVIDER + +#if EMON_PROVIDER == EMON_ANALOG_PROVIDER + #define EMON_CURRENT_PIN 0 + #define EMON_ADC_BITS 10 + #define EMON_REFERENCE_VOLTAGE 1.0 + #define EMON_CURRENT_PRECISION 1 + #define EMON_CURRENT_OFFSET 0.25 +#endif + +#if EMON_PROVIDER == EMON_ADC121_PROVIDER + #define EMON_ADC121_ADDRESS 0x50 + #define EMON_ADC_BITS 12 + #define EMON_REFERENCE_VOLTAGE 3.3 + #define EMON_CURRENT_PRECISION 2 + #define EMON_CURRENT_OFFSET 0.10 +#endif + +#define EMON_CURRENT_RATIO 30 #define EMON_SAMPLES 1000 #define EMON_INTERVAL 10000 #define EMON_MEASUREMENTS 6 -#define EMON_ADC_BITS 10 -#define EMON_REFERENCE_VOLTAGE 1.0 -#define EMON_CURRENT_PRECISION 1 -#define EMON_CURRENT_OFFSET 0.25 #define EMON_MAINS_VOLTAGE 230 -#define EMON_CURRENT_RATIO 180 #define EMON_POWER_TOPIC "/power" #define EMON_ENERGY_TOPIC "/energy" diff --git a/code/espurna/emon.ino b/code/espurna/emon.ino index 892fc2bf..f9bd2609 100644 --- a/code/espurna/emon.ino +++ b/code/espurna/emon.ino @@ -9,13 +9,49 @@ Copyright (C) 2016-2017 by Xose Pérez #if ENABLE_EMON #include +#include "brzo_i2c.h" #include +// ADC121 Registers +#define ADC121_REG_RESULT 0x00 +#define ADC121_REG_ALERT 0x01 +#define ADC121_REG_CONFIG 0x02 +#define ADC121_REG_LIMITL 0x03 +#define ADC121_REG_LIMITH 0x04 +#define ADC121_REG_HYST 0x05 +#define ADC121_REG_CONVL 0x06 +#define ADC121_REG_CONVH 0x07 + EmonLiteESP emon; double _current = 0; unsigned int _power = 0; double _energy = 0; +// ----------------------------------------------------------------------------- +// Provider +// ----------------------------------------------------------------------------- + +unsigned int currentCallback() { + + #if EMON_PROVIDER == EMON_ANALOG_PROVIDER + return analogRead(EMON_CURRENT_PIN); + #endif + + #if EMON_PROVIDER == EMON_ADC121_PROVIDER + uint8_t buffer[2]; + brzo_i2c_start_transaction(EMON_ADC121_ADDRESS, I2C_SCL_FREQUENCY); + buffer[0] = ADC121_REG_RESULT; + brzo_i2c_write(buffer, 1, false); + brzo_i2c_read(buffer, 2, false); + brzo_i2c_end_transaction(); + unsigned int value; + value = (buffer[0] & 0x0F) << 8; + value |= buffer[1]; + return value; + #endif + +} + // ----------------------------------------------------------------------------- // EMON // ----------------------------------------------------------------------------- @@ -36,10 +72,6 @@ double getCurrent() { return _current; } -unsigned int currentCallback() { - return analogRead(EMON_CURRENT_PIN); -} - void retrieveEnergy() { unsigned long energy = EEPROM.read(EEPROM_POWER_COUNT + 1); energy = (energy << 8) + EEPROM.read(EEPROM_POWER_COUNT); @@ -73,6 +105,15 @@ void powerMonitorSetup() { ); emon.setPrecision(EMON_CURRENT_PRECISION); + #if EMON_PROVIDER == EMON_ADC121_PROVIDER + uint8_t buffer[2]; + buffer[0] = ADC121_REG_CONFIG; + buffer[1] = 0x00; + brzo_i2c_start_transaction(EMON_ADC121_ADDRESS, I2C_SCL_FREQUENCY); + brzo_i2c_write(buffer, 2, false); + brzo_i2c_end_transaction(); + #endif + apiRegister("/api/power", "power", [](char * buffer, size_t len) { snprintf(buffer, len, "%d", _power); }); @@ -103,13 +144,14 @@ void powerMonitorLoop() { if (millis() > next_measurement) { // Safety check: do not read current if relay is OFF - if (!relayStatus(0)) { - _current = 0; - } else { + // You could be monitoring another line with the current clamp... + //if (!relayStatus(0)) { + // _current = 0; + //} else { _current = emon.getCurrent(EMON_SAMPLES); _current -= EMON_CURRENT_OFFSET; if (_current < 0) _current = 0; - } + //} if (measurements == 0) { max = min = _current; @@ -122,11 +164,14 @@ void powerMonitorLoop() { float mainsVoltage = getSetting("emonMains", EMON_MAINS_VOLTAGE).toFloat(); - //DEBUG_MSG("[ENERGY] Power now: %dW\n", int(_current * mainsVoltage)); + char current[6]; + dtostrf(_current, 5, 2, current); + DEBUG_MSG("[ENERGY] Current: %sA\n", current); + DEBUG_MSG("[ENERGY] Power: %dW\n", int(_current * mainsVoltage)); // Update websocket clients - char text[20]; - sprintf_P(text, PSTR("{\"emonPower\": %d}"), int(_current * mainsVoltage)); + char text[64]; + sprintf_P(text, PSTR("{\"emonVisible\": 1, \"powApparentPower\": %d}"), int(_current * mainsVoltage)); wsSend(text); // Send MQTT messages averaged every EMON_MEASUREMENTS @@ -142,7 +187,7 @@ void powerMonitorLoop() { char power[6]; snprintf(power, 6, "%d", _power); char energy[8]; - snprintf(energy, 6, "%ld", (unsigned long) _energy); + snprintf(energy, 8, "%ld", (unsigned long) _energy); mqttSend(getSetting("emonPowerTopic", EMON_POWER_TOPIC).c_str(), power); mqttSend(getSetting("emonEnergyTopic", EMON_ENERGY_TOPIC).c_str(), energy); #if ENABLE_DOMOTICZ diff --git a/code/espurna/espurna.ino b/code/espurna/espurna.ino index cafc7f22..3461e6b4 100644 --- a/code/espurna/espurna.ino +++ b/code/espurna/espurna.ino @@ -107,6 +107,9 @@ void setup() { webSetup(); ntpSetup(); + #if ENABLE_I2C + i2cSetup(); + #endif #if ENABLE_FAUXMO fauxmoSetup(); #endif diff --git a/code/espurna/i2c.ino b/code/espurna/i2c.ino new file mode 100644 index 00000000..1063d143 --- /dev/null +++ b/code/espurna/i2c.ino @@ -0,0 +1,43 @@ +/* + +I2C MODULE + +Copyright (C) 2017 by Xose Pérez + +*/ + +#if ENABLE_I2C + +#include "brzo_i2c.h" + +void i2cScan() { + + uint8_t address; + uint8_t response; + uint8_t buffer[1]; + int nDevices = 0; + + for (address = 1; address < 128; address++) { + + brzo_i2c_start_transaction(address, I2C_SCL_FREQUENCY); + brzo_i2c_ACK_polling(1000); + response = brzo_i2c_end_transaction(); + + if (response == 0) { + Serial.printf("[I2C] Device found at address 0x%02X\n", address); + nDevices++; + } else if (response != 32) { + Serial.printf("[I2C] Unknown error at address 0x%02X\n", address); + } + } + + if (nDevices == 0) Serial.println("[I2C] No devices found"); + +} + +void i2cSetup() { + brzo_i2c_setup(I2C_SDA_PIN, I2C_SCL_PIN, I2C_CLOCK_STRETCH_TIME); + i2cScan(); +} + +#endif diff --git a/code/html/index.html b/code/html/index.html index 3764f358..71c96e5f 100644 --- a/code/html/index.html +++ b/code/html/index.html @@ -140,7 +140,7 @@ -
+
diff --git a/code/platformio.ini b/code/platformio.ini index 843b95d4..26c803ae 100644 --- a/code/platformio.ini +++ b/code/platformio.ini @@ -16,6 +16,7 @@ lib_deps = NtpClientLib OneWire DallasTemperature + Brzo I2C https://bitbucket.org/xoseperez/justwifi.git https://bitbucket.org/xoseperez/hlw8012.git https://bitbucket.org/xoseperez/fauxmoesp.git @@ -88,7 +89,7 @@ extra_script = pio_hooks.py build_flags = -g -Wl,-Tesp8266.flash.1m128.ld -DDEBUG_PORT=Serial -DSONOFF upload_speed = 115200 upload_port = "192.168.4.1" -upload_flags = --auth=fibonacci --port 8266 +upload_flags = --auth=Algernon1 --port 8266 [env:sonoff-dht22-debug] platform = espressif8266