diff --git a/code/espurna/config/general.h b/code/espurna/config/general.h index 0a0836d1..8d468394 100644 --- a/code/espurna/config/general.h +++ b/code/espurna/config/general.h @@ -667,7 +667,7 @@ PROGMEM const char* const custom_reset_string[] = { #define I2C_SUPPORT 1 // I2C enabled (1.98Kb) #endif -#define I2C_USE_BRZO 0 // Use brzo_i2c library or standard Wire +#define I2C_USE_BRZO 1 // Use brzo_i2c library or standard Wire #ifndef I2C_SDA_PIN #define I2C_SDA_PIN SDA // SDA GPIO (Sonoff => 4) diff --git a/code/espurna/config/hardware.h b/code/espurna/config/hardware.h index 86a55010..6cf83532 100644 --- a/code/espurna/config/hardware.h +++ b/code/espurna/config/hardware.h @@ -223,8 +223,8 @@ #define LED1_PIN_INVERSE 1 // Jack is connected to GPIO14 (and with a small hack to GPIO4) - //#define I2C_SDA_PIN 4 - //#define I2C_SCL_PIN 14 + #define I2C_SDA_PIN 4 + #define I2C_SCL_PIN 14 #elif defined(ITEAD_SONOFF_SV) diff --git a/code/espurna/config/sensors.h b/code/espurna/config/sensors.h index fa1273d2..5c705b02 100644 --- a/code/espurna/config/sensors.h +++ b/code/espurna/config/sensors.h @@ -148,12 +148,12 @@ #define EMON_MODE_MSECONDS 2 //-------------------------------------------------------------------------------- -// Analog Energy Monitor +// Energy Monitor based on interval analog GPIO // Enable support by passing EMON_ANALOG_SUPPORT=1 build flag //-------------------------------------------------------------------------------- #ifndef EMON_ANALOG_SUPPORT -#define EMON_ANALOG_SUPPORT 1 // Do not build support by default +#define EMON_ANALOG_SUPPORT 0 // Do not build support by default #endif #define EMON_ANALOG_MAINS_VOLTAGE 230 // Mains voltage @@ -167,12 +167,33 @@ #define EMON_ANALOG_WARMUP_VALUE 1000 #define EMON_ANALOG_WARMUP_MODE EMON_MODE_MSECONDS - #if EMON_ANALOG_SUPPORT #undef ADC_VCC_ENABLED #define ADC_VCC_ENABLED 0 #endif +//-------------------------------------------------------------------------------- +// Energy Monitor based on ADC121 +// Enable support by passing EMON_ADC121_SUPPORT=1 build flag +//-------------------------------------------------------------------------------- + +#ifndef EMON_ADC121_SUPPORT +#define EMON_ADC121_SUPPORT 1 // Do not build support by default +#endif + +#define EMON_ADC121_I2C_ADDRESS 0x50 // I2C address of the ADC121 + +#define EMON_ADC121_MAINS_VOLTAGE 230 // Mains voltage +#define EMON_ADC121_CURRENT_RATIO 30 // Current ratio in the clamp (30V/1A) +#define EMON_ADC121_ADC_BITS 12 // ADC depth +#define EMON_ADC121_REFERENCE_VOLTAGE 3.3 // Reference voltage of the ADC + +#define EMON_ADC121_READ_VALUE 200 +#define EMON_ADC121_READ_MODE EMON_MODE_MSECONDS + +#define EMON_ADC121_WARMUP_VALUE 1000 +#define EMON_ADC121_WARMUP_MODE EMON_MODE_MSECONDS + //-------------------------------------------------------------------------------- // Internal power montior // Enable support by passing ADC_VCC_ENABLED=1 build flag diff --git a/code/espurna/sensor.ino b/code/espurna/sensor.ino index c5402fc1..e057de19 100644 --- a/code/espurna/sensor.ino +++ b/code/espurna/sensor.ino @@ -240,9 +240,13 @@ void sensorInit() { #if EMON_ANALOG_SUPPORT #include "sensors/EmonAnalogSensor.h" - sensorRegister((BaseSensor *) new EmonAnalogSensor(A0, EMON_ANALOG_MAINS_VOLTAGE, EMON_ANALOG_ADC_BITS, EMON_ANALOG_REFERENCE_VOLTAGE, EMON_ANALOG_CURRENT_RATIO)); + sensorRegister(new EmonAnalogSensor(A0, EMON_ANALOG_MAINS_VOLTAGE, EMON_ANALOG_ADC_BITS, EMON_ANALOG_REFERENCE_VOLTAGE, EMON_ANALOG_CURRENT_RATIO)); #endif + #if EMON_ADC121_SUPPORT + #include "sensors/EmonADC121Sensor.h" + sensorRegister(new EmonADC121Sensor(EMON_ADC121_I2C_ADDRESS, EMON_ANALOG_MAINS_VOLTAGE, EMON_ANALOG_ADC_BITS, EMON_ANALOG_REFERENCE_VOLTAGE, EMON_ANALOG_CURRENT_RATIO)); + #endif #if COUNTER_SUPPORT if (_sensor_isr == 0xFF) { diff --git a/code/espurna/sensors/EmonADC121Sensor.h b/code/espurna/sensors/EmonADC121Sensor.h new file mode 100644 index 00000000..352884ff --- /dev/null +++ b/code/espurna/sensors/EmonADC121Sensor.h @@ -0,0 +1,129 @@ +// ----------------------------------------------------------------------------- +// Energy monitor sensor +// ----------------------------------------------------------------------------- + +#pragma once + +#include "Arduino.h" +#include "BaseSensor.h" +#include "EmonSensor.h" + +#if I2C_USE_BRZO +#include +#else +#include +#endif + +// 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 + +class EmonADC121Sensor : public EmonSensor { + + public: + + EmonADC121Sensor(unsigned char address, double voltage, unsigned char bits, double ref, double ratio): EmonSensor(voltage, bits, ref, ratio) { + + // Cache + _address = address; + + // Init sensor + #if I2C_USE_BRZO + uint8_t buffer[2]; + buffer[0] = ADC121_REG_CONFIG; + buffer[1] = 0x00; + brzo_i2c_start_transaction(_address, I2C_SCL_FREQUENCY); + brzo_i2c_write(buffer, 2, false); + brzo_i2c_end_transaction(); + #else + Wire.beginTransmission(_address); + Wire.write(ADC121_REG_CONFIG); + Wire.write(0x00); + Wire.endTransmission(); + #endif + + // warmup + read(EMON_ADC121_WARMUP_VALUE, EMON_ADC121_WARMUP_MODE, _address); + + } + + // Descriptive name of the sensor + String name() { + char buffer[20]; + snprintf(buffer, sizeof(buffer), "EMON @ ADC121 @ I2C (0x%02X)", _address); + return String(buffer); + } + + // Descriptive name of the slot # index + String slot(unsigned char index) { + return name(); + } + + // Type for slot # index + magnitude_t type(unsigned char index) { + _error = SENSOR_ERROR_OK; + if (index == 0) return MAGNITUDE_CURRENT; + if (index == 1) return MAGNITUDE_POWER_APPARENT; + _error = SENSOR_ERROR_OUT_OF_RANGE; + return MAGNITUDE_NONE; + } + + // Current value for slot # index + double value(unsigned char index) { + + _error = SENSOR_ERROR_OK; + + // Cache the value + static unsigned long last = 0; + static double current = 0; + if ((last == 0) || (millis() - last > 1000)) { + current = read(EMON_ADC121_READ_VALUE, EMON_ADC121_READ_MODE, _address); + last = millis(); + } + + if (index == 0) return current; + if (index == 1) return current * _voltage; + + _error = SENSOR_ERROR_OUT_OF_RANGE; + return 0; + + } + + protected: + + unsigned int readADC(unsigned char port) { + + unsigned int value; + + #if I2C_USE_BRZO + uint8_t buffer[2]; + buffer[0] = ADC121_REG_RESULT; + brzo_i2c_start_transaction(_address, I2C_SCL_FREQUENCY); + brzo_i2c_write(buffer, 1, false); + brzo_i2c_read(buffer, 2, false); + brzo_i2c_end_transaction(); + value = (buffer[0] & 0x0F) << 8; + value |= buffer[1]; + #else + Wire.beginTransmission(port); + Wire.write(ADC121_REG_RESULT); + Wire.endTransmission(); + Wire.requestFrom(port, (unsigned char) 2); + value = (Wire.read() & 0x0F) << 8; + value = value + Wire.read(); + #endif + + return value; + + } + + unsigned char _address; + + +}; diff --git a/code/espurna/sensors/EmonAnalogSensor.h b/code/espurna/sensors/EmonAnalogSensor.h index 2c1b5921..404d8ab6 100644 --- a/code/espurna/sensors/EmonAnalogSensor.h +++ b/code/espurna/sensors/EmonAnalogSensor.h @@ -28,7 +28,7 @@ class EmonAnalogSensor : public EmonSensor { // Descriptive name of the sensor String name() { char buffer[20]; - snprintf(buffer, sizeof(buffer), "ANALOG EMON @ GPIO%d", _gpio); + snprintf(buffer, sizeof(buffer), "EMON @ GPIO%d", _gpio); return String(buffer); } diff --git a/code/espurna/sensors/EmonSensor.h b/code/espurna/sensors/EmonSensor.h index c35926a2..b2bbb130 100644 --- a/code/espurna/sensors/EmonSensor.h +++ b/code/espurna/sensors/EmonSensor.h @@ -7,6 +7,8 @@ #include "Arduino.h" #include "BaseSensor.h" +#define EMON_DEBUG 1 + class EmonSensor : public BaseSensor { public: @@ -25,6 +27,14 @@ class EmonSensor : public BaseSensor { // Calculate multiplier calculateMultiplier(); + #if EMON_DEBUG + Serial.print("[EMON] Current ratio: "); Serial.println(ratio); + Serial.print("[EMON] Ref. Voltage: "); Serial.println(_voltage); + Serial.print("[EMON] ADC Couns: "); Serial.println(_adc_counts); + Serial.print("[EMON] Current factor: "); Serial.println(_current_factor); + Serial.print("[EMON] Multiplier: "); Serial.println(_multiplier); + #endif + } protected: @@ -90,6 +100,17 @@ class EmonSensor : public BaseSensor { current = (double) (round(current * _multiplier) - 1) / _multiplier; if (current < 0) current = 0; + #if EMON_DEBUG + Serial.print("[EMON] Total samples: "); Serial.println(samples); + Serial.print("[EMON] Total time (ms): "); Serial.println(millis() - start); + Serial.print("[EMON] Sample frequency (1/s): "); Serial.println(1000 * samples / (millis() - start)); + Serial.print("[EMON] Max value: "); Serial.println(max); + Serial.print("[EMON] Min value: "); Serial.println(min); + Serial.print("[EMON] Midpoint value: "); Serial.println(_pivot); + Serial.print("[EMON] RMS value: "); Serial.println(rms); + Serial.print("[EMON] Current: "); Serial.println(current); + #endif + return current; }