From edf9d465ba31016947eb26d25ec5803cb5de52cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xose=20P=C3=A9rez?= Date: Sat, 16 Dec 2017 22:14:24 +0100 Subject: [PATCH] Improve ADS1115 speed to 1450 SPS, keep separate pivot for each channel --- code/espurna/config/sensors.h | 2 +- code/espurna/sensors/EmonADC121Sensor.h | 10 +++--- code/espurna/sensors/EmonADS1115Sensor.h | 42 ++++++++++++------------ code/espurna/sensors/EmonAnalogSensor.h | 5 +-- code/espurna/sensors/EmonSensor.h | 14 ++++---- 5 files changed, 36 insertions(+), 37 deletions(-) diff --git a/code/espurna/config/sensors.h b/code/espurna/config/sensors.h index b9de94a4..e690ed13 100644 --- a/code/espurna/config/sensors.h +++ b/code/espurna/config/sensors.h @@ -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 diff --git a/code/espurna/sensors/EmonADC121Sensor.h b/code/espurna/sensors/EmonADC121Sensor.h index 1395d6cf..2a890474 100644 --- a/code/espurna/sensors/EmonADC121Sensor.h +++ b/code/espurna/sensors/EmonADC121Sensor.h @@ -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; }; diff --git a/code/espurna/sensors/EmonADS1115Sensor.h b/code/espurna/sensors/EmonADS1115Sensor.h index 889b0bac..7446e329 100644 --- a/code/espurna/sensors/EmonADS1115Sensor.h +++ b/code/espurna/sensors/EmonADS1115Sensor.h @@ -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}; }; diff --git a/code/espurna/sensors/EmonAnalogSensor.h b/code/espurna/sensors/EmonAnalogSensor.h index 3e6e977a..0a7db4de 100644 --- a/code/espurna/sensors/EmonAnalogSensor.h +++ b/code/espurna/sensors/EmonAnalogSensor.h @@ -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; }; diff --git a/code/espurna/sensors/EmonSensor.h b/code/espurna/sensors/EmonSensor.h index 29912b0c..acf8afde 100644 --- a/code/espurna/sensors/EmonSensor.h +++ b/code/espurna/sensors/EmonSensor.h @@ -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;