Browse Source

Added analog energy monitor sensor to new sensors module

fastled
Xose Pérez 7 years ago
parent
commit
3ade0ae035
8 changed files with 1972 additions and 1741 deletions
  1. +32
    -0
      code/espurna/config/general.h
  2. +58
    -44
      code/espurna/config/sensors.h
  3. BIN
      code/espurna/data/index.html.gz
  4. +44
    -29
      code/espurna/sensor.ino
  5. +156
    -0
      code/espurna/sensors/AnalogEmonSensor.h
  6. +7
    -6
      code/espurna/sensors/BaseSensor.h
  7. +1664
    -1660
      code/espurna/static/index.html.gz.h
  8. +11
    -2
      code/html/custom.js

+ 32
- 0
code/espurna/config/general.h View File

@ -766,12 +766,27 @@ PROGMEM const char* const custom_reset_string[] = {
#define SENSOR_TEMPERATURE_DECIMALS 1 #define SENSOR_TEMPERATURE_DECIMALS 1
#define SENSOR_HUMIDITY_DECIMALS 0 #define SENSOR_HUMIDITY_DECIMALS 0
#define SENSOR_PRESSURE_DECIMALS 2
#define SENSOR_ANALOG_DECIMALS 0 #define SENSOR_ANALOG_DECIMALS 0
#define SENSOR_EVENTS_DECIMALS 0 #define SENSOR_EVENTS_DECIMALS 0
#define SENSOR_CURRENT_DECIMALS 3
#define SENSOR_VOLTAGE_DECIMALS 0
#define SENSOR_POWER_DECIMALS 0
#define SENSOR_POWER_FACTOR_DECIMALS 0
#define SENSOR_ENERGY_DECIMALS 3
#define SENSOR_UNKNOWN_TOPIC "unknown" #define SENSOR_UNKNOWN_TOPIC "unknown"
#define SENSOR_TEMPERATURE_TOPIC "temperature" #define SENSOR_TEMPERATURE_TOPIC "temperature"
#define SENSOR_HUMIDITY_TOPIC "humidity" #define SENSOR_HUMIDITY_TOPIC "humidity"
#define SENSOR_PRESSURE_TOPIC "pressure"
#define SENSOR_CURRENT_TOPIC "current"
#define SENSOR_VOLTAGE_TOPIC "voltage"
#define SENSOR_ACTIVE_POWER_TOPIC "power"
#define SENSOR_APPARENT_POWER_TOPIC "apparent"
#define SENSOR_REACTIVE_POWER_TOPIC "reactive"
#define SENSOR_POWER_FACTOR_TOPIC "factor"
#define SENSOR_ENERGY_TOPIC "energy"
#define SENSOR_ENERGY_DELTA_TOPIC "energy_delta"
#define SENSOR_ANALOG_TOPIC "analog" #define SENSOR_ANALOG_TOPIC "analog"
#define SENSOR_EVENTS_TOPIC "events" #define SENSOR_EVENTS_TOPIC "events"
@ -892,3 +907,20 @@ PROGMEM const char* const custom_reset_string[] = {
#endif #endif
#endif // IR_SUPPORT #endif // IR_SUPPORT
//--------------------------------------------------------------------------------
// Custom RF module
// Check http://tinkerman.cat/adding-rf-to-a-non-rf-itead-sonoff/
// Enable support by passing RF_SUPPORT=1 build flag
//--------------------------------------------------------------------------------
#ifndef RF_SUPPORT
#define RF_SUPPORT 0
#endif
#ifndef RF_PIN
#define RF_PIN 14
#endif
#define RF_CHANNEL 31
#define RF_DEVICE 1

+ 58
- 44
code/espurna/config/sensors.h View File

@ -1,20 +1,3 @@
//--------------------------------------------------------------------------------
// Custom RF module
// Check http://tinkerman.cat/adding-rf-to-a-non-rf-itead-sonoff/
// Enable support by passing RF_SUPPORT=1 build flag
//--------------------------------------------------------------------------------
#ifndef RF_SUPPORT
#define RF_SUPPORT 0
#endif
#ifndef RF_PIN
#define RF_PIN 14
#endif
#define RF_CHANNEL 31
#define RF_DEVICE 1
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// General // General
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -62,6 +45,46 @@
#define HUMIDITY_DRY 2 #define HUMIDITY_DRY 2
#define HUMIDITY_WET 3 #define HUMIDITY_WET 3
//--------------------------------------------------------------------------------
// SI7021 temperature & humidity sensor
// Enable support by passing SI7021_SUPPORT=1 build flag
//--------------------------------------------------------------------------------
#ifndef SI7021_SUPPORT
#define SI7021_SUPPORT 0
#endif
#ifndef SI7021_ADDRESS
#define SI7021_ADDRESS 0x40
#endif
//--------------------------------------------------------------------------------
// DS18B20 temperature sensor
// Enable support by passing DS18B20_SUPPORT=1 build flag
//--------------------------------------------------------------------------------
#ifndef DS18B20_SUPPORT
#define DS18B20_SUPPORT 0
#endif
#ifndef DS18B20_PIN
#define DS18B20_PIN 13
#endif
#ifndef DS18B20_PULLUP
#define DS18B20_PULLUP 1
#endif
#ifndef DS18B20_UPDATE_INTERVAL
#define DS18B20_UPDATE_INTERVAL 60000
#endif
#ifndef DS18B20_TEMPERATURE_TOPIC
#define DS18B20_TEMPERATURE_TOPIC "temperature"
#endif
#define DS18B20_RESOLUTION 9
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// Analog sensor // Analog sensor
// Enable support by passing ANALOG_SUPPORT=1 build flag // Enable support by passing ANALOG_SUPPORT=1 build flag
@ -116,45 +139,36 @@
#define COUNTER_TOPIC "counter" // Default topic for MQTT, API and InfluxDB #define COUNTER_TOPIC "counter" // Default topic for MQTT, API and InfluxDB
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// SI7021 temperature & humidity sensor
// Enable support by passing SI7021_SUPPORT=1 build flag
// Analog Energy Monitor
// Enable support by passing EMON_ANALOG_SUPPORT=1 build flag
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
#ifndef SI7021_SUPPORT
#define SI7021_SUPPORT 0
#ifndef EMON_ANALOG_SUPPORT
#define EMON_ANALOG_SUPPORT 0 // Do not build support by default
#endif #endif
#ifndef SI7021_ADDRESS
#define SI7021_ADDRESS 0x40
#endif
#define EMON_ANALOG_MAINS_VOLTAGE 230 // Mains voltage
#define EMON_ANALOG_CURRENT_RATIO 30 // Current ratio in the clamp (30V/1A)
#define EMON_ANALOG_ADC_BITS 10 // ADC depth
#define EMON_ANALOG_REFERENCE_VOLTAGE 3.3 // Reference voltage of the ADC
//--------------------------------------------------------------------------------
// DS18B20 temperature sensor
// Enable support by passing DS18B20_SUPPORT=1 build flag
//--------------------------------------------------------------------------------
#define EMON_ANALOG_FILTER_SPEED 512
#ifndef DS18B20_SUPPORT
#define DS18B20_SUPPORT 0
#endif
#define EMON_ANALOG_MODE_SAMPLES 1
#define EMON_ANALOG_MODE_MSECONDS 2
#ifndef DS18B20_PIN
#define DS18B20_PIN 14
#endif
#define EMON_ANALOG_READ_VALUE 1000
#define EMON_ANALOG_READ_MODE EMON_ANALOG_MODE_SAMPLES
#ifndef DS18B20_PULLUP
#define DS18B20_PULLUP 1
#endif
#define EMON_ANALOG_WARMUP_VALUE 1000
#define EMON_ANALOG_WARMUP_MODE EMON_ANALOG_MODE_MSECONDS
#ifndef DS18B20_UPDATE_INTERVAL
#define DS18B20_UPDATE_INTERVAL 60000
#endif
#ifndef DS18B20_TEMPERATURE_TOPIC
#define DS18B20_TEMPERATURE_TOPIC "temperature"
#if EMON_ANALOG_SUPPORT
#undef ADC_VCC_ENABLED
#define ADC_VCC_ENABLED 0
#endif #endif
#define DS18B20_RESOLUTION 9
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
// Internal power montior // Internal power montior
// Enable support by passing ADC_VCC_ENABLED=1 build flag // Enable support by passing ADC_VCC_ENABLED=1 build flag


BIN
code/espurna/data/index.html.gz View File


+ 44
- 29
code/espurna/sensor.ino View File

@ -37,43 +37,52 @@ unsigned char _sensor_isr = 0xFF;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
String _sensorTopic(magnitude_t type) { String _sensorTopic(magnitude_t type) {
if (type == MAGNITUDE_TEMPERATURE) {
return String(SENSOR_TEMPERATURE_TOPIC);
} else if (type == MAGNITUDE_HUMIDITY) {
return String(SENSOR_HUMIDITY_TOPIC);
} else if (type == MAGNITUDE_ANALOG) {
return String(SENSOR_ANALOG_TOPIC);
} else if (type == MAGNITUDE_EVENTS) {
return String(SENSOR_EVENTS_TOPIC);
}
if (type == MAGNITUDE_TEMPERATURE) return String(SENSOR_TEMPERATURE_TOPIC);
if (type == MAGNITUDE_HUMIDITY) return String(SENSOR_HUMIDITY_TOPIC);
if (type == MAGNITUDE_PRESSURE) return String(SENSOR_PRESSURE_TOPIC);
if (type == MAGNITUDE_CURRENT) return String(SENSOR_CURRENT_TOPIC);
if (type == MAGNITUDE_VOLTAGE) return String(SENSOR_VOLTAGE_TOPIC);
if (type == MAGNITUDE_POWER_ACTIVE) return String(SENSOR_ACTIVE_POWER_TOPIC);
if (type == MAGNITUDE_POWER_APPARENT) return String(SENSOR_APPARENT_POWER_TOPIC);
if (type == MAGNITUDE_POWER_REACTIVE) return String(SENSOR_REACTIVE_POWER_TOPIC);
if (type == MAGNITUDE_POWER_FACTOR) return String(SENSOR_POWER_FACTOR_TOPIC);
if (type == MAGNITUDE_ENERGY) return String(SENSOR_ENERGY_TOPIC);
if (type == MAGNITUDE_ENERGY_DELTA) return String(SENSOR_ENERGY_DELTA_TOPIC);
if (type == MAGNITUDE_ANALOG) return String(SENSOR_ANALOG_TOPIC);
if (type == MAGNITUDE_EVENTS) return String(SENSOR_EVENTS_TOPIC);
return String(SENSOR_UNKNOWN_TOPIC); return String(SENSOR_UNKNOWN_TOPIC);
} }
unsigned char _sensorDecimals(magnitude_t type) { unsigned char _sensorDecimals(magnitude_t type) {
if (type == MAGNITUDE_TEMPERATURE) {
return SENSOR_TEMPERATURE_DECIMALS;
} else if (type == MAGNITUDE_HUMIDITY) {
return SENSOR_HUMIDITY_DECIMALS;
} else if (type == MAGNITUDE_ANALOG) {
return SENSOR_ANALOG_DECIMALS;
} else if (type == MAGNITUDE_EVENTS) {
return SENSOR_EVENTS_DECIMALS;
}
if (type == MAGNITUDE_TEMPERATURE) return SENSOR_TEMPERATURE_DECIMALS;
if (type == MAGNITUDE_HUMIDITY) return SENSOR_HUMIDITY_DECIMALS;
if (type == MAGNITUDE_PRESSURE) return SENSOR_PRESSURE_DECIMALS;
if (type == MAGNITUDE_CURRENT) return SENSOR_CURRENT_DECIMALS;
if (type == MAGNITUDE_VOLTAGE) return SENSOR_VOLTAGE_DECIMALS;
if (type == MAGNITUDE_POWER_ACTIVE) return SENSOR_POWER_DECIMALS;
if (type == MAGNITUDE_POWER_APPARENT) return SENSOR_POWER_DECIMALS;
if (type == MAGNITUDE_POWER_REACTIVE) return SENSOR_POWER_DECIMALS;
if (type == MAGNITUDE_POWER_FACTOR) return SENSOR_POWER_FACTOR_DECIMALS;
if (type == MAGNITUDE_ENERGY) return SENSOR_ENERGY_DECIMALS;
if (type == MAGNITUDE_ENERGY_DELTA) return SENSOR_ENERGY_DECIMALS;
if (type == MAGNITUDE_ANALOG) return SENSOR_ANALOG_DECIMALS;
if (type == MAGNITUDE_EVENTS) return SENSOR_EVENTS_DECIMALS;
return 0; return 0;
} }
String _sensorUnits(magnitude_t type) { String _sensorUnits(magnitude_t type) {
if (type == MAGNITUDE_TEMPERATURE) {
if (_sensor_temperature_units == TMP_CELSIUS) {
return String("C");
} else {
return String("F");
}
} else if (type == MAGNITUDE_HUMIDITY) {
return String("%");
} else if (type == MAGNITUDE_EVENTS) {
return String("/m");
}
if (type == MAGNITUDE_TEMPERATURE) return (_sensor_temperature_units == TMP_CELSIUS) ? String("C") : String("F");
if (type == MAGNITUDE_HUMIDITY) return String("%");
if (type == MAGNITUDE_PRESSURE) return String("hPa");
if (type == MAGNITUDE_CURRENT) return String("A");
if (type == MAGNITUDE_VOLTAGE) return String("V");
if (type == MAGNITUDE_POWER_ACTIVE) return String("W");
if (type == MAGNITUDE_POWER_APPARENT) return String("W");
if (type == MAGNITUDE_POWER_REACTIVE) return String("W");
if (type == MAGNITUDE_POWER_FACTOR) return String("%");
if (type == MAGNITUDE_ENERGY) return String("J");
if (type == MAGNITUDE_ENERGY_DELTA) return String("J");
if (type == MAGNITUDE_EVENTS) return String("/m");
return String(); return String();
} }
@ -229,6 +238,12 @@ void sensorInit() {
sensorRegister(new AnalogSensor(ANALOG_PIN)); sensorRegister(new AnalogSensor(ANALOG_PIN));
#endif #endif
#if EMON_ANALOG_SUPPORT
#include "sensors/AnalogEmonSensor.h"
sensorRegister(new AnalogEmonSensor(A0, EMON_ANALOG_MAINS_VOLTAGE, EMON_ANALOG_ADC_BITS, EMON_ANALOG_REFERENCE_VOLTAGE, EMON_ANALOG_CURRENT_RATIO));
#endif
#if COUNTER_SUPPORT #if COUNTER_SUPPORT
if (_sensor_isr == 0xFF) { if (_sensor_isr == 0xFF) {
#include "sensors/EventSensor.h" #include "sensors/EventSensor.h"


+ 156
- 0
code/espurna/sensors/AnalogEmonSensor.h View File

@ -0,0 +1,156 @@
// -----------------------------------------------------------------------------
// Eergy monitor sensor
// -----------------------------------------------------------------------------
#pragma once
#include "Arduino.h"
#include "BaseSensor.h"
class AnalogEmonSensor : public BaseSensor {
public:
AnalogEmonSensor(unsigned char gpio, double voltage, unsigned char bits, double ref, double ratio): BaseSensor() {
// Prepare GPIO
pinMode(gpio, INPUT);
// Cache
_gpio = gpio;
_voltage = voltage;
_adc_counts = 1 << bits;
_pivot = _adc_counts >> 1;
_count = 2;
// Calculate factor
_current_factor = ratio * ref / _adc_counts;
// Calculate multiplier
calculateMultiplier();
// warmup
read(EMON_ANALOG_WARMUP_VALUE, EMON_ANALOG_WARMUP_MODE, _gpio);
}
// Descriptive name of the sensor
String name() {
char buffer[20];
snprintf(buffer, sizeof(buffer), "ANALOG EMON @ GPIO%d", _gpio);
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_ANALOG_READ_VALUE, EMON_ANALOG_READ_MODE, _gpio);
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) {
return analogRead(port);
}
void calculateMultiplier() {
unsigned int s = 1;
unsigned int i = 1;
unsigned int m = s * i;
while (m * _current_factor < 1) {
_multiplier = m;
i = (i == 1) ? 2 : (i == 2) ? 5 : 1;
if (i == 1) s *= 10;
m = s * i;
}
}
double read(unsigned long value, unsigned char mode, unsigned char port) {
int sample;
int max = 0;
int min = _adc_counts;
double filtered;
double sum = 0;
unsigned long start = millis();
unsigned long samples = 0;
while (true) {
// Read analog value
sample = readADC(port);
if (sample > max) max = sample;
if (sample < min) min = sample;
// Digital low pass filter extracts the VDC offset
_pivot = (_pivot + (sample - _pivot) / EMON_ANALOG_FILTER_SPEED);
filtered = sample - _pivot;
// Root-mean-square method
sum += (filtered * filtered);
++samples;
// Exit condition
if (mode == EMON_ANALOG_MODE_SAMPLES) {
if (samples >= value) break;
} else {
if (millis() - start >= value) break;
}
yield();
}
// Quick fix
if (_pivot < min || max < _pivot) {
_pivot = (max + min) / 2.0;
}
double rms = samples > 0 ? sqrt(sum / samples) : 0;
double current = _current_factor * rms;
current = (double) (round(current * _multiplier) - 1) / _multiplier;
if (current < 0) current = 0;
return current;
}
double _voltage;
unsigned char _gpio;
unsigned int _adc_counts;
unsigned int _multiplier = 1;
double _current_factor;
double _pivot;
};

+ 7
- 6
code/espurna/sensors/BaseSensor.h View File

@ -12,12 +12,13 @@ typedef enum magnitude_t {
MAGNITUDE_HUMIDITY, MAGNITUDE_HUMIDITY,
MAGNITUDE_PRESSURE, MAGNITUDE_PRESSURE,
MAGNITUDE_ACTIVE_POWER,
MAGNITUDE_APPARENT_POWER,
MAGNITUDE_REACTIVE_POWER,
MAGNITUDE_VOLTAGE_POWER,
MAGNITUDE_CURRENT_POWER,
MAGNITUDE_ENERGY_POWER,
MAGNITUDE_CURRENT,
MAGNITUDE_VOLTAGE,
MAGNITUDE_POWER_ACTIVE,
MAGNITUDE_POWER_APPARENT,
MAGNITUDE_POWER_REACTIVE,
MAGNITUDE_ENERGY,
MAGNITUDE_ENERGY_DELTA,
MAGNITUDE_POWER_FACTOR, MAGNITUDE_POWER_FACTOR,
MAGNITUDE_ANALOG, MAGNITUDE_ANALOG,


+ 1664
- 1660
code/espurna/static/index.html.gz.h
File diff suppressed because it is too large
View File


+ 11
- 2
code/html/custom.js View File

@ -30,8 +30,17 @@ function initMessages() {
function sensorType(type) { function sensorType(type) {
if (type == 1) return "Temperature"; if (type == 1) return "Temperature";
if (type == 2) return "Humidity"; if (type == 2) return "Humidity";
if (type == 11) return "Analog";
if (type == 12) return "Events";
if (type == 3) return "Pressure";
if (type == 4) return "Current";
if (type == 5) return "Voltage";
if (type == 6) return "Active Power";
if (type == 7) return "Apparent Power";
if (type == 8) return "Reactive Power";
if (type == 9) return "Energy";
if (type == 10) return "Energy (delta)";
if (type == 11) return "Power Factor";
if (type == 12) return "Analog";
if (type == 13) return "Events";
return null; return null;
} }


Loading…
Cancel
Save