Browse Source

Improve ADS1115 speed to 1450 SPS, keep separate pivot for each channel

fastled
Xose Pérez 6 years ago
parent
commit
edf9d465ba
5 changed files with 36 additions and 37 deletions
  1. +1
    -1
      code/espurna/config/sensors.h
  2. +5
    -5
      code/espurna/sensors/EmonADC121Sensor.h
  3. +21
    -21
      code/espurna/sensors/EmonADS1115Sensor.h
  4. +3
    -2
      code/espurna/sensors/EmonAnalogSensor.h
  5. +6
    -8
      code/espurna/sensors/EmonSensor.h

+ 1
- 1
code/espurna/config/sensors.h View File

@ -143,7 +143,7 @@
//--------------------------------------------------------------------------------
#define EMON_MAX_SAMPLES 1000 // Max number of samples to get
#define EMON_MAX_TIME 500 // Max time in ms to sample
#define EMON_MAX_TIME 250 // Max time in ms to sample
#define EMON_FILTER_SPEED 512 // Mobile average filter speed
#define EMON_MAINS_VOLTAGE 230 // Mains voltage


+ 5
- 5
code/espurna/sensors/EmonADC121Sensor.h View File

@ -88,7 +88,7 @@ class EmonADC121Sensor : public EmonSensor {
static unsigned long energy_delta = 0;
if ((last == 0) || (millis() - last > 1000)) {
current = read(_address);
current = read(0, _pivot);
energy_delta = current * _voltage * (millis() - last) / 1000;
_energy += energy_delta;
last = millis();
@ -113,17 +113,17 @@ class EmonADC121Sensor : public EmonSensor {
#if I2C_USE_BRZO
uint8_t buffer[2];
buffer[0] = ADC121_REG_RESULT;
brzo_i2c_start_transaction(channel, I2C_SCL_FREQUENCY);
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(channel);
Wire.beginTransmission(_address);
Wire.write(ADC121_REG_RESULT);
Wire.endTransmission();
Wire.requestFrom(channel, (unsigned char) 2);
Wire.requestFrom(_address, (unsigned char) 2);
value = (Wire.read() & 0x0F) << 8;
value = value + Wire.read();
#endif
@ -134,6 +134,6 @@ class EmonADC121Sensor : public EmonSensor {
unsigned char _address;
unsigned long _energy = 0;
double _pivot = 0;
};

+ 21
- 21
code/espurna/sensors/EmonADS1115Sensor.h View File

@ -84,7 +84,7 @@
#define ADS1015_REG_CONFIG_CQUE_NONE (0x0003) // Disable the comparator and put ALERT/RDY in high state (default)
*/
#define EMON_ADS1115_CHANNELS 4
#define EMON_ADS1115_CHANNELS 4
#define EMON_ADS1115_MAGNITUDES_PER_PORT 2
class EmonADS1115Sensor : public EmonSensor {
@ -106,13 +106,16 @@ class EmonADS1115Sensor : public EmonSensor {
// Initialize
_ads = new ADS1115(_address);
_ads->initialize();
_ads->setMode(ADS1115_MODE_SINGLESHOT);
_ads->setMode(ADS1115_MODE_CONTINUOUS);
_ads->setRate(ADS1115_RATE_860);
_ads->setGain(ADS1115_PGA_4P096);
_ads->setConversionReadyPinMode();
// warmup
read(_address);
for (unsigned char port=0; port<_ports; port++) {
unsigned char channel = getChannel(port);
_ads->setMultiplexer(channel + 4);
read(channel, _pivot[channel]);
}
}
@ -126,8 +129,8 @@ class EmonADS1115Sensor : public EmonSensor {
// Descriptive name of the slot # index
String slot(unsigned char index) {
char buffer[35];
unsigned char port = getChannel(index / EMON_ADS1115_MAGNITUDES_PER_PORT);
snprintf(buffer, sizeof(buffer), "EMON @ ADS1115 (A%d) @ I2C (0x%02X)", port, _address);
unsigned char channel = getChannel(index % _ports);
snprintf(buffer, sizeof(buffer), "EMON @ ADS1115 (A%d) @ I2C (0x%02X)", channel, _address);
return String(buffer);
}
@ -135,8 +138,7 @@ class EmonADS1115Sensor : public EmonSensor {
magnitude_t type(unsigned char index) {
if (index < _count) {
_error = SENSOR_ERROR_OK;
unsigned char port = getChannel(index / EMON_ADS1115_MAGNITUDES_PER_PORT);
unsigned char magnitude = index % EMON_ADS1115_MAGNITUDES_PER_PORT;
unsigned char magnitude = index / _ports;
if (magnitude == 0) return MAGNITUDE_CURRENT;
if (magnitude == 1) return MAGNITUDE_POWER_APPARENT;
//if (magnitude == 2) return MAGNITUDE_ENERGY;
@ -148,9 +150,10 @@ class EmonADS1115Sensor : public EmonSensor {
void pre() {
//static unsigned long last = 0;
for (unsigned char index=0; index<_ports; index++) {
unsigned char port = getChannel(index);
_current[port] = read(port);
for (unsigned char port=0; port<_ports; port++) {
unsigned char channel = getChannel(port);
_ads->setMultiplexer(channel + 4);
_current[port] = read(channel, _pivot[channel]);
//if (last > 0) {
// _delta[port] = _current[port] * _voltage * (millis() - last) / 1000;
//}
@ -164,8 +167,8 @@ class EmonADS1115Sensor : public EmonSensor {
if (index < _count) {
_error = SENSOR_ERROR_OK;
unsigned char port = getChannel(index / EMON_ADS1115_MAGNITUDES_PER_PORT);
unsigned char magnitude = index % EMON_ADS1115_MAGNITUDES_PER_PORT;
unsigned char port = index % _ports;
unsigned char magnitude = index / _ports;
if (magnitude == 0) return _current[port];
if (magnitude == 1) return _current[port] * _voltage;
//if (magnitude == 2) return _energy[port];
@ -193,11 +196,7 @@ class EmonADS1115Sensor : public EmonSensor {
}
unsigned int readADC(unsigned char channel) {
if (channel < EMON_ADS1115_CHANNELS) {
_ads->setMultiplexer(channel + 4);
return _ads->getConversion(true);
}
return 0;
return _ads->getConversion();
}
/*
@ -272,9 +271,10 @@ class EmonADS1115Sensor : public EmonSensor {
unsigned char _address;
unsigned char _mask;
unsigned char _ports;
double _current[EMON_ADS1115_CHANNELS] = {0, 0, 0, 0};
//unsigned long _energy[EMON_ADS1115_CHANNELS] = {0, 0, 0, 0};
//unsigned long _delta[EMON_ADS1115_CHANNELS] = {0, 0, 0, 0};
double _pivot[EMON_ADS1115_CHANNELS] = {0};
double _current[EMON_ADS1115_CHANNELS] = {0};
//unsigned long _energy[EMON_ADS1115_CHANNELS] = {0};
//unsigned long _delta[EMON_ADS1115_CHANNELS] = {0};
};

+ 3
- 2
code/espurna/sensors/EmonAnalogSensor.h View File

@ -60,7 +60,7 @@ class EmonAnalogSensor : public EmonSensor {
static unsigned long energy_delta = 0;
if ((last == 0) || (millis() - last > 1000)) {
current = read(_gpio);
current = read(0, _pivot);
energy_delta = current * _voltage * (millis() - last) / 1000;
_energy += energy_delta;
last = millis();
@ -79,11 +79,12 @@ class EmonAnalogSensor : public EmonSensor {
protected:
unsigned int readADC(unsigned char channel) {
return analogRead(channel);
return analogRead(_gpio);
}
unsigned char _gpio;
unsigned long _energy = 0;
double _pivot = 0;
};

+ 6
- 8
code/espurna/sensors/EmonSensor.h View File

@ -18,7 +18,6 @@ class EmonSensor : public BaseSensor {
// Cache
_voltage = voltage;
_adc_counts = 1 << bits;
_pivot = _adc_counts >> 1;
// Calculate factor
_current_factor = ratio * ref / _adc_counts;
@ -52,7 +51,7 @@ class EmonSensor : public BaseSensor {
}
}
double read(unsigned char channel) {
double read(unsigned char channel, double &pivot) {
int sample;
int max = 0;
@ -69,8 +68,8 @@ class EmonSensor : public BaseSensor {
if (sample < min) min = sample;
// Digital low pass filter extracts the VDC offset
_pivot = (_pivot + (sample - _pivot) / EMON_FILTER_SPEED);
filtered = sample - _pivot;
pivot = (pivot + (sample - pivot) / EMON_FILTER_SPEED);
filtered = sample - pivot;
// Root-mean-square method
sum += (filtered * filtered);
@ -79,8 +78,8 @@ class EmonSensor : public BaseSensor {
time_span = millis() - time_span;
// Quick fix
if (_pivot < min || max < _pivot) {
_pivot = (max + min) / 2.0;
if (pivot < min || max < pivot) {
pivot = (max + min) / 2.0;
}
// Calculate current
@ -95,7 +94,7 @@ class EmonSensor : public BaseSensor {
Serial.print("[EMON] Sample frequency (Hz): "); Serial.println(1000 * _samples / time_span);
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] Midpoint value: "); Serial.println(pivot);
Serial.print("[EMON] RMS value: "); Serial.println(rms);
Serial.print("[EMON] Current: "); Serial.println(current);
#endif
@ -114,7 +113,6 @@ class EmonSensor : public BaseSensor {
unsigned long _adc_counts;
unsigned int _multiplier = 1;
double _current_factor;
double _pivot;
unsigned long _samples = EMON_MAX_SAMPLES;


Loading…
Cancel
Save