Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Emonlib+Esp32+ADS1115 outputting inconsistant data #61

Open
korishan opened this issue Aug 22, 2020 · 9 comments
Open

Emonlib+Esp32+ADS1115 outputting inconsistant data #61

korishan opened this issue Aug 22, 2020 · 9 comments

Comments

@korishan
Copy link

korishan commented Aug 22, 2020

I did get it to work, by rewriting the emonlib library, but it was crontoversly to say at least. But it works perfectly, it still is measuring the current.
The reason I used the ADS1115 was indeed the ESP. I used the Nodemcu board and could use the extra current sensors.

Originally posted by @SybrenV in #23 (comment)

How were you able to get it working properly??

I have the hardware implemented, and under standard testing (only using an ADS1115 based sketch) the values work fine. However, when using the Emonlib w/ ADS support that Paul provided, I get invalid data.

I have changed the files to EmonLib_I2C considering that's what it's for. This way I don't get conflicts with ArduinoIDE.

#include <Wire.h>
#include <Adafruit_ADS1015.h>
#include "EmonLib_I2C.h"                   // Include Emon Library
EnergyMonitor emon1;                   // Create an instance

Adafruit_ADS1115 ads;                  // Create an instance of the ADS1115 object

// Make a callback method for reading the pin value from the ADS instance
int ads1115PinReader(int _pin){
  return ads.readADC_SingleEnded(_pin);
}

void setup()
{  
  Serial.begin(115200);
  
  emon1.inputPinReader = ads1115PinReader; // Replace the default pin reader with the customized ads pin reader
  emon1.current(3, 111.1);             // Current: input pin, calibration.
}

void loop()
{
  double Irms1 = emon1.calcIrms(250);  // Calculate Irms only

  Serial.print("E1: ");
  emon1.serialprint();
}

Unfortunately, this is the output I get:

E1: 0.00 0.00 0.00 20696.53 0.00 
E1: 0.00 0.00 0.00 16211.26 0.00 
E1: 0.00 0.00 0.00 12698.02 0.00 
E1: 0.00 0.00 0.00 9946.16 0.00 
E1: 0.00 0.00 0.00 7790.67 0.00 
E1: 0.00 0.00 0.00 6102.30 0.00 
E1: 0.00 0.00 0.00 4779.84 0.00 
E1: 0.00 0.00 0.00 3743.97 0.00 
E1: 0.00 0.00 0.00 2932.59 0.00 
E1: 0.00 0.00 0.00 2297.05 0.00 
E1: 0.00 0.00 0.00 1799.24 0.00 
E1: 0.00 0.00 0.00 1409.32 0.00 
.........
E1: 0.00 0.00 0.00 1.18 0.00 
E1: 0.00 0.00 0.00 0.93 0.00 
E1: 0.00 0.00 0.00 0.73 0.00 
E1: 0.00 0.00 0.00 0.57 0.00 
E1: 0.00 0.00 0.00 0.44 0.00 
E1: 0.00 0.00 0.00 0.35 0.00 
E1: 0.00 0.00 0.00 0.27 0.00 
E1: 0.00 0.00 0.00 0.21 0.00 
E1: 0.00 0.00 0.00 0.17 0.00 
E1: 0.00 0.00 0.00 0.13 0.00 
E1: 0.00 0.00 0.00 0.10 0.00 
E1: 0.00 0.00 0.00 0.08 0.00 
E1: 0.00 0.00 0.00 0.06 0.00 
E1: 0.00 0.00 0.00 0.05 0.00 
E1: 0.00 0.00 0.00 0.04 0.00 
E1: 0.00 0.00 0.00 0.03 0.00 
E1: 0.00 0.00 0.00 0.02 0.00 
E1: 0.00 0.00 0.00 0.02 0.00 
E1: 0.00 0.00 0.00 0.01 0.00 
E1: 0.00 0.00 0.00 0.01 0.00 
E1: 0.00 0.00 0.00 0.01 0.00 
E1: 0.00 0.00 0.00 0.01 0.00 
E1: 0.00 0.00 0.00 0.01 0.00 
E1: 0.00 0.00 0.00 0.00 0.00 

It just slowly goes cycles down to "0" and then stays there. It doesn't matter if I have a current load or not.
And no, I don't have an external voltage reading of the mains line. It shouldn't matter for reading "current_only", correct? It would only be used during realpower calculations I would think.

But if I run the ADC only code, I get these values:

ADC Range: +/- 6.144V (1 bit = 3mV/ADS1015, 0.1875mV/ADS1115)
AIN0 	AIN1 	AIN2 	AIN3
770	0	771	0
773	0	771	0
770	0	767	0
773	0	1110	0   ---- Turned on load here
774	0	546	0
774	0	1147	0
775	0	450	0
770	0	818	0
773	0	947	0   ---- Turned off load here
769	0	771	0
773	0	772	0
773	0	772	0

Code:

#include <Wire.h>
#include <Adafruit_ADS1015.h>

// Adafruit_ADS1115 ads;  /* Use this for the 16-bit version */
Adafruit_ADS1015 ads;     /* Use thi for the 12-bit version */

void setup(void) 
{
  Serial.begin(115200);
  Serial.println("Hello!");
  
  Serial.println("Getting single-ended readings from AIN0..3");
  Serial.println("ADC Range: +/- 6.144V (1 bit = 3mV/ADS1015, 0.1875mV/ADS1115)");
  ads.begin();
}

void loop(void) 
{
  int16_t adc0, adc1, adc2, adc3;

  adc0 = ads.readADC_SingleEnded(0);
  adc1 = ads.readADC_SingleEnded(1);
  adc2 = ads.readADC_SingleEnded(2);
  adc3 = ads.readADC_SingleEnded(3);
  Serial.print(adc0);
  Serial.print("\t");
.......
}

Thanks, Kori
@sultanfikri
Copy link

i hope this proble get solved

@persistive
Copy link

Finally i got it to work, thanks to all contributes here and on other forums.
I am using a ESP32 NodeMCU board, ADS1015, SCT013-15 CT and a 0.96"oled display.
I found out that the ADC1015 is much faster than the ADC1115.
Serial communication is disturbing the current reading so i left that out.
I calibrated the unit with an function generator and did some comparison with know loads.
The overall performance is in my opinion very good.

For who is interesting hereby my code:

// In this example we will use an ADS1115 breakout board instead of the Arduino's local analog inputs
// This is especially useful for nodemcu/esp8266 users who only have a single analog input
#include <Wire.h>
#include <Adafruit_ADS1015.h>
#include "SSD1306Wire.h"
SSD1306Wire display(0x3c,21,22);
// EmonLibrary examples openenergymonitor.org, Licence GNU GPL V3

#include "EmonLib.h" // Include Emon Library
EnergyMonitor emon1; // Create an instance
EnergyMonitor emon2; // Create an instance
EnergyMonitor emon3; // Create an instance
EnergyMonitor emon4; // Create an instance

//Adafruit_ADS1115 ads; // Create an instance of the ADS1115 object
Adafruit_ADS1015 ads; /* Use this for the 12-bit version */
// Make a callback method for reading the pin value from the ADS instance
int ads1115PinReader(int _pin){
return ads.readADC_SingleEnded(_pin);
}
void setup()
{
display.init();
display.flipScreenVertically();
display.setFont(ArialMT_Plain_10);
display.drawString(0, 0, "Welcome");
display.drawString(0, 12, "PowerMeter starting up");
display.drawString(0, 24, "Calibrated for");
display.drawString(0, 36, "230VAC and max. 15A");
display.drawString(0, 48, "One moment please...");
display.display();
delay(3000);
//Serial.begin(9600);
// The ADC input range (or gain) can be changed via the following
// functions, but be careful never to exceed VDD +0.3V max, or to
// exceed the upper and lower limits if you adjust the input range!
// Setting these values incorrectly may destroy your ADC!
// ADS1015 ADS1115
// ------- -------
// ads.setGain(GAIN_TWOTHIRDS); // 2/3x gain +/- 6.144V 1 bit = 3mV 0.1875mV (default)
ads.setGain(GAIN_ONE); // 1x gain +/- 4.096V 1 bit = 2mV 0.125mV
// ads.setGain(GAIN_TWO); // 2x gain +/- 2.048V 1 bit = 1mV 0.0625mV
// ads.setGain(GAIN_FOUR); // 4x gain +/- 1.024V 1 bit = 0.5mV 0.03125mV
// ads.setGain(GAIN_EIGHT); // 8x gain +/- 0.512V 1 bit = 0.25mV 0.015625mV
// ads.setGain(GAIN_SIXTEEN); // 16x gain +/- 0.256V 1 bit = 0.125mV 0.0078125mV

ads.begin();

emon1.inputPinReader = ads1115PinReader; // Replace the default pin reader with the customized ads pin reader
emon1.current(0, 9.35); // Current: input pin1, calibration.
emon2.inputPinReader = ads1115PinReader; // Replace the default pin reader with the customized ads pin reader
emon2.current(1, 9.35); // Current: input pin2, calibration.
emon3.inputPinReader = ads1115PinReader; // Replace the default pin reader with the customized ads pin reader
emon3.current(2, 9.35); // Current: input pin3, calibration.
emon4.inputPinReader = ads1115PinReader; // Replace the default pin reader with the customized ads pin reader
emon4.current(3, 9.35); // Current: input pin4, calibration.
}

void loop()
{
double Irms1 = emon1.calcIrms(1480); // Calculate Irms only
int Prms1 = Irms1230;
double Irms2 = emon2.calcIrms(1480); // Calculate Irms only
int Prms2 = Irms2
230;
double Irms3 = emon3.calcIrms(1480); // Calculate Irms only
int Prms3 = Irms3230;
double Irms4 = emon4.calcIrms(1480); // Calculate Irms only
int Prms4 = Irms4
230;
//Serial.print(Prms1); // Apparent power
//Serial.print(" ");
//Serial.println(Irms1); // Irms
display.clear();
display.drawString(0, 0, "Ch1: ");
display.drawString(25, 0, String(Irms1)); // Displays all current data
display.drawString(55, 0, "A");
display.drawString(70, 0, String(Prms1)); // Displays all power data
display.drawString(100, 0, "W");

display.drawString(0, 15, "Ch2: ");
display.drawString(25, 15, String(Irms2)); // Displays all current data
display.drawString(55, 15, "A");
display.drawString(70, 15, String(Prms2)); // Displays all power data
display.drawString(100, 15, "W");

display.drawString(0, 30, "Ch3: ");
display.drawString(25, 30, String(Irms3)); // Displays all current data
display.drawString(55, 30, "A");
display.drawString(70, 30, String(Prms3)); // Displays all power data
display.drawString(100, 30, "W");

display.drawString(0, 45, "Ch4: ");
display.drawString(25, 45, String(Irms4)); // Displays all current data
display.drawString(55, 45, "A");
display.drawString(70, 45, String(Prms4)); // Displays all power data
display.drawString(100, 45, "W");
display.display();
}

@thijstriemstra
Copy link

thijstriemstra commented Mar 9, 2021

thanks for sharing @persistive

How did you connect the SCT013-15 CT to the ADS1015? Any other components needed? Any chance you have a fritzing sketch?

Looks like the SCT-013 has a mini jack plug, I guess a breadboard stereo audio jack would do?

breadboard-audio-jack-18-35mm-stereo

@sultanfikri
Copy link

thanks @persistive
But in my opinion, if we use ESP32, it is better to directly use ESP32 internal ADC instead of External ADC like ADS1115

bytheway, it's worked! NodemCU with ADS1115, but strangely it worked when I used "Adafruit_ADS1015 ads;", i don't know why ...

@persistive
Copy link

persistive commented Mar 9, 2021

I use the ADS1015 because the ADCs on the ESP are not reliable. Not only are the ADCs not lineair, they also are quite sensitive for noise. Using the (cheap) ADS1015 will give a good lineair signal. Do not use the ADS1115, although the higher bandwith (16 bits) looks beter then the 12 bits of the ADC1015, the 1115 is very slow resulting in slow updates of your readings. Furthermore the 16 bits is really 15 bits because you use it in single ended mode.
@Thijstiemstra: indeed i used those connectors, but i used the ones that are connecting the centerpin to ground when the CT plug is not inserted. This will avoid noise on the not used channels. Just connect the CT with the two 10k resistors and a 10uF or so capacitor to create a 1,65 volt base voltage. Take a look at https://www.instructables.com/Simple-Arduino-Home-Energy-Meter for a good example. I also added wifi for communication with my domoticz system. What i saw is that the wifi signal is disturbing the power readings. To overcome that problem i switch wifi off after sending the average value of the four channels to domoticz and turn it on at the moment i send the new values. Still have a misreading of 1 or 2 watts power peaks, but i can live with that.

@thijstriemstra
Copy link

Do not use the ADS1115, although the higher bandwith (16 bits) looks beter then the 12 bits of the ADC1015, the 1115 is very slow resulting in slow updates of your readings.

What arduino package do you use for reading the ADS? Could be the bottleneck as well? I have good results with https://github.com/wollewald/ADS1115_WE

@persistive
Copy link

I use the Adafruit_ADS1X15-master library. Using the ADS1015 is much faster in my setup. According adafruit: These two boards are very similar, differing only in resolution and speed. The ADS1115 has higher resolution and the ADS1015 has a higher sample rate.

@GianRickes
Copy link

Hello.. I'm trying to implement it, but I have an error.. 'class EnergyMonitor' has no member named 'inputPinReader'

I'm not finding the problem.
The code:
#include <EmonLib.h>
#include <Wire.h>
#include <Adafruit_ADS1X15.h>

EnergyMonitor emon1;
Adafruit_ADS1115 ads; // Create an instance of the ADS1115 object

int ads1115PinReader(int _pin){
return ads.readADC_SingleEnded(_pin);
}

void setup(){
Serial.begin(9600);
ads.begin();
emon1.inputPinReader = ads1115PinReader; // Replace the default pin reader with the customized ads pin reader
emon1.current(0, 23.4);
}

void loop(){
double Irms = emon1.calcIrms(1996); // Calculate Irms only

Serial.print("Current: ");
Serial.print(Irms, 3);
Serial.println(" A");
}

@GianRickes
Copy link

I believe I have a problem with EmonLib.. now I used.. https://github.com/PaulWieland/EmonLib ...and I'm still having problems..
image

Can you share Adafruit and EmonLib library?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants