Energy Meter project Based on ESP8266 Only

Hi, I am Munsif, (Computer engineer).
I am new in this community Very appreciated who make the Arduino eomonlib, I am working on the energy meter project which shows all the Parameters on Small LCD and transmits all the data to the server through the Internet (IOT). My main focus is on cost efficiency I want to make this Project Cheap as possible.
so I decided to make it on ESP8266 using Nodemcu and Arduino IDE, The problem begins with the analog pin. ESP only has 1 analog pin. Emonlib requires minimum 2 analog channels to calculate voltage, current, and PF I extended the analog channel using multiplexer CD4051 with digital switching. I don’t want to use analog Extender IC which communicate with I2C!

1- how I can use 1 analog PIN in to measure voltage and current value?
2- will it work if I use this sort of code.
3- if not what should It be to read from Esp8266 with one analog Pin using a multiplexer ?

void setup() {
  Serial.begin(9600);
  pinMode(1, OUTPUT);    // 
  pinMode(2, OUTPUT);    //
  emon1.voltage(A0, 122, 1.7);  // 
  emon1.current(A0, 3); // Same analog pin

}

void loop() {
  emon1.calcVI(20, 2000);

  digitalWrite(1, LOW);   //
  digitalWrite(2, HIGH);  //  Multiplexer setting to Read voltage

  float Vrms   = emon1.Vrms;
  digitalWrite(1, HIGH);   //
  digitalWrite(2, LOW);  //  Multiplexer setting to Read Current

  Irms = emon1.calcIrms(no_of_samples);
  int power = Irms * Vrms;
}

What you have there won’t work, because emonLib expects the multiplexer to be switched automatically between reading voltage and current. I advise you not to use emonLib directly, but use the methods that emonLib uses to do the same sort of thing.

The core function that you will need to implement is to select an input channel (either current or voltage) and read the value. This is what analogRead(inputPin) does, but of course you don’t have that available.
You then call that repeatedly, and process the numbers. You probably want three things (as emonLib does): (1) square each value separately to ultimately give you the rms, (2) multiply the last voltage and current to give the instantaneous power, which you can average, and (3) keep a tally of the number of readings so that you can calculate the average.
(In other words, you switch the multiplexer between readings, which will allow you to calculate real power; rather than reading the average voltage and then switching to read the average current, which will only give apparent power, and not even an accurate measure of that if conditions change from reading one to the other.)

You might like to look at the Atmel application note “AVR465: Single-Phase Power/Energy Meter
with Tamper Detection”. That is a complete design (not using the ESP8266 of course) but it does include a hardware multiplexer, and it should give you a valuable insight into the design of an energy meter.

1 Like

Thank u very much for your reply you are right I should try to use the method that emonlib uses. and i will let you know if I can’t understand the library or I face any problem. Also this thing very helpful for me thanks for sharing AVR465: Single-Phase Power/Energy Meter with Tamper Detection”.

is that fine I make a bit changing in Emonlib.cpp add two lines for MUX before reading the analog value let me know if that configuration will go wrong in the calculation. if not then why I see garbage value while measuring current with no output load if the load is added then it works fine also it measure the voltage correctly but there is 4 to 5v variation when the board will get power on again why?

14.50, 18.96, 232.54, 0.08,0.76
13.23, 17.44 , 232.49, 0.07,0.76
14.37, 18.83, 232.38, 0.08, 0.76
13.25, 17.44, 232.32, 0.08, 0.76
14.61, 18.72, 232.41, 0.08, 0.78
13.14, 17.67, 232.32, 0.08, 0.74
14.48, 18.84, 232.32, 0.08, 0.77
13.11, 17.48, 232.36, 0.08, 0.75
14.67, 19.06, 232.28, 0.08, 0.77
13.20, 17.65, 232.30, 0.08, 0.75
14.36, 18.74, 232.22, 0.08, 0.77


 while(st==false)                                   //the while loop...
  {
  	  //-------------------------------Configration for slecting Voltage-------Select Y2--------------------
  digitalWrite(D0,LOW);
  digitalWrite(D1,HIGH);
  //delay(1);
  //-------------------------------------------------------------------------------------------
    startV = analogRead(inPinV);                    //using the voltage waveform
    if ((startV < (ADC_COUNTS*0.55)) && (startV > (ADC_COUNTS*0.45))) st=true;  //check its within range
    if ((millis()-start)>timeout) st = true;
  }


  while ((crossCount < crossings) && ((millis()-start)<timeout))
  {
    numberOfSamples++;                       //Count number of times looped.
    lastFilteredV = filteredV;               //Used for delay/phase compensation

    //-----------------------------------------------------------------------------
    // A) Read in raw voltage and current samples
    //-----------------------------------------------------------------------------
     //-------------------------------Configration for slecting Voltage-------Select Y2--------------------
  digitalWrite(D0,LOW);
  digitalWrite(D1,HIGH);
//  delay(1);
  //-------------------------------------------------------------------------------------------
  
    sampleV = analogRead(inPinV);                 //Read in raw voltage signal
    
       //-------------------------------Configration for slecting Current-----Select Y1----------------------
  digitalWrite(D0,HIGH);
  digitalWrite(D1,LOW);
 // delay(1);
  //-------------------------------------------------------------------------------------------
    
    sampleI = analogRead(inPinI);                 //Read in raw current signal

  for (unsigned int n = 0; n < Number_of_Samples; n++)
  {
   //-------------------------------Configration for slecting Current-----Select Y1----------------------
  digitalWrite(D0,HIGH);
  digitalWrite(D1,LOW);
//  delay(1);
  //-------------------------------------------------------------------------------------------
    sampleI = analogRead(inPinI);

    // Digital low pass filter extracts the 2.5 V or 1.65 V dc offset,
    //  then subtract this - signal is now centered on 0 counts.
    offsetI = (offsetI + (sampleI-offsetI)/1024);
    filteredI = sampleI - offsetI;

    // Root-mean-square method current
    // 1) square current values
    sqI = filteredI * filteredI;
    // 2) sum
    sumI += sqI;
  }

I have no idea what you are doing there. You seem to have part of calcVI( ) and part of calcIrms( ).

Surely the easy way is to create a function that is equivalent to analogRead(pin) and switches the multiplexer, like analogRead( ) does inside the Atmel 328P? Then use your function instead of analogRead( )?

It should look something like this:

int mpxRead(byte Pin)
{
    if (Pin == D0)
    {
        digitalWrite(D1, LOW);
        digitalWrite(D0, HIGH);
       return(analogRead(myInputPinFromTheMultiplexerOutput));  // Substitute your Input pin here!
    }

    if (Pin == D1)
    {
        digitalWrite(D0, LOW);
        digitalWrite(D1, HIGH);
       return( analogRead(myInputPinFromTheMultiplexerOutput));  // Substitute your Input pin here!
    }
}

and then you use it like this:

something = mpxRead(D0);
somethingelse = mpxRead(D1);

[I cannot test this, you must make it work yourself!]

That is most likely noise pickup, either from your mains power unit, or it might be from the multiplexer itself. If it is that, you might need to add a delay between switching the multiplexer and reading the output. You must also be very careful with the physical layout of your circuit board to keep the analogue and the digital parts separate.

1 Like

Thank u very Much Rober.Wall it works. It works fine on ESP with multiplexer with this approach instead of that noise i will check my hardware…
i just copped the changed parts from library and past in the post

Why not use the ESP32? It has many more analog inputs than the ESP8266 and costs about the same.

1 Like

One of the answers to that question I’ve heard is the ESP32 has heat issues. i.e. it runs quite hot.

I’ve never noticed heat issues on the '32. Usually the limitation is that the idf isn’t as far along as the one for the '8266. You could underclock it if you want.

yes you are right but i get quotation and the price is high for ESP 32 ($3.0) which effects me much in bulk quantity so i think ESP8266 ($1.5) is suitable for me…

How many are you planning on making/selling?
What accuracy do you need/want?
What types of loads are your devices going to see, very simple linear loads or very complex loads that don’t draw consistent power across a single cycle or several cycles?

While you can use a single ADC to measure multiple channels, you have to be able to sample it fast enough so that the samples you get are a close enough representation of reality for the measurement you are making. You also need take into account the time difference in measuring the voltage and current channels. I would expect that you would need to be able to measure in the kHz to 10s of kHz to get decent accuracy. I don’t believe the accuracy of the ADC in the esp8266 is specified, but I can’t imagine it is great, but it might be good enough for what you need.

If you are building millions of things, then saving $0.10 per item is a big deal. But think how much NRE (non-recurring engineering) cost you will have to keep your BOM (bill of materials) cost down. Only you and your partners can decide what is right. Just remember that almost all of the cheap esp8266 based systems from China use a dedicated power measurement IC. I don’t know what requirements you have that suggest a different solution.

1 Like

What worries me about the ESP series is this: I cannot find a full specification of the ADC. To me, that is a serious warning sign that means its performance is suspect.

In terms of sampling frequency, just looking at Nyquist and assuming there’s no significant power above the 7th harmonic (of 50 Hz), that implies at least 700 sample pairs (current and voltage) per second. I have no idea whether those assumptions are valid, but it does give an indication of the minimum performance required.

EmonLib and the standard sketch loaded into the emonTx does a little more than 2500 sample pairs per second.

1 Like

I’d say your suspicions are correct.


From the Espessif site: (https://bbs.espressif.com/viewtopic.php?t=2430)

Please note that the third party modules such as ESP-01 or ESP-12 may not perform very well with the internal ADC because the I/Os have been led far out on those modules, causing interference.

For obtaining the best results with the ADC:

  • Use moving average of around 5 consecutive samples. The ESP8266 produces significant noise when Wi-Fi is active.
  • Use modem sleep for critical conversions.
  • Make sure the analog and digital power rails are separate and properly decoupled.
  • If your application is powered by USB or other such external power source, use ferrite bead on the power cord.

The ADC pin is not supposed to be used for highly accurate conversions. We recommend using external serial ADC ICs for best performance.


0a-esp8266ex_datasheet_en.pdf (582.7 KB)

1 Like

How many are you planning on making/selling?

Couple of thousand at the start for testing the market then my company sees if the product good enough to produce more.

What accuracy do you need/want?

whatever I get the maximum from ESP.

What types of loads are your devices going to see, very simple linear loads or very complex loads that don’t draw consistent power across a single cycle or several cycles?

Normal House Hold.

While you can use a single ADC to measure multiple channels, you have to be able to sample it fast enough so that the samples you get are a close enough representation of reality for the measurement you are making.

I am using a single ADC channel but switching the Multiplexer same as the speed of the loop with no delay.

You also need take into account the time difference in measuring the voltage and current channels. I would expect that you would need to be able to measure in the kHz to 10s of kHz to get decent accuracy. I don’t believe the accuracy of the ADC in the esp8266 is specified, but I can’t imagine it is great, but it might be good enough for what you need.

i am not getting deep into it yet but I think the frequency is far greater than 10s of kHz.

If you are building millions of things, then saving $0.10 per item is a big deal. But think how much NRE (non-recurring engineering) cost you will have to keep your BOM (bill of materials) cost down. Only you and your partners can decide what is right.

if I use ES32 instead of ESP8266 then the difference of cost is around ($1.5) and if I use ST microcontroller (STM8S003S )for taking analog inputs then the cost is much lesser the controller costs me around $(0.25) but I don’t have much practice in ST microcontrollers so I decided to use Multiplexer with ESP8266 which cost me around ($0.06) CD4051 if I use Arduino with ESP8266 the controller ATMEGA 328 costs me ($1.1) + Additional crystal and some components.

Just remember that almost all of the cheap esp8266 based systems from China use a dedicated power measurement IC. I don’t know what requirements you have that suggest a different solution.

I don’t know about it help me to find that. power measurement IC means to measure mains power or ESP power?

What worries me about the ESP series is this: I cannot find a full specification of the ADC. To me, that is a serious warning sign that means its performance is suspect.

I also see the irregularity in it, a bit noisy and unstable with input voltage range only (1 V) I should consider a separate microcontroller for the analog measurement like AVR or ST.

this is what i made yet…

1 Like

Looks nice, but is +/-10% accuracy in the range of what you consider acceptable? Based on a quick internet search and my personal experience, if you consider +/- 5-10% acceptable, you are fine to continue down the path you are following. For many people that will be good enough. But, some people, mainly those that really care, want 1% or better, but are willing to tolerate 2-5%. Part of it depends on what the actual accuracy looks like, ie what part is absolute, linearity, repeatability, temperature dependence.

I have several esp8266 based sensors. I recently started plotting their self-measured VCC levels. Some are NodeMCU based so they have a voltage divider, which the documentation says NOT to use when measuring VCC. All of them read much lower than the others (some as low as 2V instead of 3V3). But, even the ones that don’t have the extra resistor do not agree with each other. They all have 3V3 regulators. These typically have good regulation and absolute accuracy. The values I am seeing for VCC are more than 10% off the expected value. I have not measured the actual values, because I don’t care that much. For things I care about measuring, I use an external ADC that had specified accuracy and meets it. If all you need is an indication that there is power or not, the internal ADC is great. Beyond that I would not recommend it. The good news is the values seem pretty repeatable, so it might be possible to calibrate it out, somewhat at least. That will increase the manufacturing cost, possibly more than the BOM increase for a different design.

But, do keep us informed on how it works for you. I would love to be proven wrong on this.

1 Like

Yes you are right. the Accuracy is not good enough for me. I was thinking about it would be around 2 to 3% but but while testing it the results are changed there is too much variation in voltages when i restart or reset the ESP. The calibration are out. for example if i calibrate my code according to my multi-meter its fine while the mains voltages remains same. if the mains voltages are changed about 10 Volts there is difference in results around 5 Volts. with multi meter and ESP.

I am thinking to use ADS1115 16bit ADC what you recommend is it the best option for ESP. or should i use another microcontroller for taking analog inputs.

My targeted value for this product is not to exceed $5 (ESP8266 ($1.5) + LCD ($0.4) + PCB(0.3) + Casing ($0.3) + Power Supply ($0.5) + Assembly & Labor cost($0.5) ) = $3.5 + ADC & Passive components…

Guide me if you have a better Idea. !

That’s going to be a tough one. Especially if you want half-way decent accuracy.
Given the premise you get what you pay for, you’re automatically limiting yourself to components that aren’t the best choice for the job.

The 1115 has a max sample rate of ~800 samples per second. i.e. it’s too slow.
Forum user ybizeul tried and found out the hard way…
See this thread: ADS1115 and sampling speed - #2 by Robert.Wall
The picture in post #23 of that thread shows what happens to the waveform when it’s sampled at such a slow rate.

ATM90E26 it even does most of the math for you. Looks like it is available for $1 in quantity 1.