Using Arduino and Emonlib to view on LCD and log to an SD card

I built an arduino weather station 9 years ago with Adafruit RGBLCD and SD card shields. I am very rusty and forgetful now. I have bought a SCT 013 030 (Voltage) current transformer. I have downloaded your “How to build an Arduino energy monitor… voltage and current.” I want to measure and log the power into an OHME electric-car wall supply. I would like to see and understand the functions available in emonlib and to write code to detect when power flows and measure and log it using the two shields. (With Uno or Mega). So the first need is a line or two to detect the start of flow, before recording the quantity and timing. I would be grateful for any links to coding or examples and instruction. The purpose is to use existing Arduino hardware and to practise the craft. I have already found difficulty trying to use the old Adafruit display because of the updated libraries and Arduino IDE; I shall probably stick with 1.8.18, though that too is much later than the IDE used for the weather station.

Welcome, Norman, to the OEM forum.

There are now two versions of emonLib, the original ‘discrete sample’ (DS) emonLib, and the newer continuous monitoring version EmonLibCM. The difference is the DS version records a sample of voltage and current normally lasting 100 - 200 ms (but definable) essentially when you tell it to, whereas the CM version records continuously and reports regularly at defined intervals - normally every 10 s.

I think either version will suit your purpose, because mains power is available. (We discourage the use of emonLibCM if the power source is batteries, as the power demand is continuous.)

I suggest downloading emonLibCM from the forum here https://community.openenergymonitor.org/t/emonlibcm-version-2-2-2/
There’s comprehensive documentation and some example sketches - these assume the data is going somewhere to be recorded so you’ll need to handle that according to what you have available in your existing kit.

(Your choice of IDE shouldn’t make a difference to emonLib or emonLibCM.)

Thank you Robert Wall. I shall download emonLibCM as you suggest, and see how I get on.

Thank you Robert Wall,
I think the complexity and technical knowledge needed may stretch me beyond breaking point. I shall understand if you do not have time to answer simpleton questions.
The examples seem to be written for the Emon transmitter hardware. I suppose I would be attemopting to replace that with my Arduino. I have no need to transmit RF data, so I suppose I should delete Jeelib and all RF lines?
I should use only power1 & vrms and no temperatures?
To what does “pulse” refer? Spurious mains fluctuations?
When I ordered the CT I was expecting a current version with pulse protection included; the voltage version which was sent has the burden resistor included and no protection - so I suppose my arduino could be in danger of an over-voltage.

No, it’s that I don’t know in detail what you have and how you’re using or want to use it. Remember, all we know is what you tell us here. I’ll do as much as I can to help and guide you.

Correct.

Probably. Everything else is available - you don’t need to include anything if you have no need. Pulses refers to counting pulses from your meter using the optical pick-up - or some other way, I use a reed switch and the magnet inside my gas meter to create the pulses, to get gas consumption.

You really mean surge protection. This will normally only happen while you’re blowing a fuse somewhere due to an instantaneous fault (like a nail through a cable), when the rupture current for the fuse is extremely high - limited only by the resistance of the wiring. On the plus side, I’v never read here of a problem due to this - because the transformer will saturate and limit the voltage to the Arduino anyway. If you’re concerned, two 3.3 V zener diodes in series back to back should help to limit the voltage to about 3.9 V peak (one zener voltage plus one forward drop of ~ 0.6 V), which should be OK as 30 A peak is 1.42 V peak out of the c.t. I think you won’t get the 3.9 V out of the c.t. anyway (but I’ve only tested the 100 A : 50 mA one).

Thank you Robert,
All very helpful and confirmatory; I must now get on and try to add some of my own coding - in stages.
Yes, “surge” was the word which would not come out of my brain.

I have simplified the CMmin example. It compiles and runs on an original Arduino Mega.
I do not understand the EmonLibCM explanations and so I do not know how to change the defaults.
I think the AC voltage from the mains transformer is expected on Analogue 0 - mine is on Analogue 2.
I don’t know what to do about AC calibration. There was an insignificant current running through the SCT device. Perhaps I should have commented out the IF statement - not just the ELSE.
I wanted just to get the measurement working before adding LCD display and logging lines.
I don’t understand “Nodes” Are they relevant for my Arduino code?
Here is the code, followed by the Serial Print.


"Minimal" sketch to demonstrate emonLibCM

This sketch assumes that the default values for the emonTx V3.4 are 
applicable, that no input calibration is required, mains frequency 
is 50 Hz and data logging period interval is 10 s, pulse counting 
and temperature monitoring are not required, and that 4 'standard' 
100 A CTs and the UK a.c. adapter from the OEM Shop are being used.

*/
#include <Arduino.h>
#include "emonLibCM.h"

                                     
// ISR(WDT_vect) { Sleepy::watchdogEvent(); } 

                                                     
const int nodeID = 10;                                     //  node ID for this emonTx. This sketch does NOT interrogate the DIP switch.

const int networkGroup = 210;                              //  wireless network group
                                                           //  - needs to be same as emonBase / emonPi and emonGLCD. OEM default is 210

/*
emonhub.conf nodeid is 10 - switch is ignored)
See: https://github.com/openenergymonitor/emonhub/blob/emon-pi/configuration.md

[[10]]
    nodename = emontx1
    [[[rx]]]
       names = power1, 
       datacode = h
       scales = 1,1,1,1,0.01,0.1,0.1,0.1,0.1,0.1,0.1,1
       units =W,V
*/       
 
void setup() 
{  
  Serial.begin(9600);
  Serial.println("Set baud=115200");
  Serial.end();
  Serial.begin(115200);
  
  Serial.println("\nEmonTx v3.4 EmonLibCM Continuous Monitoring Minimal Demo"); 

  EmonLibCM_Init();                                        // Start continuous monitoring.
}

void loop()             
{
 // if (EmonLibCM_Ready())   
  {
 
    Serial.println(EmonLibCM_acPresent()?"AC present ":"AC missing ");
    delay(5);
  
    delay(50);
 
    Serial.print(" V=");Serial.println(EmonLibCM_getVrms());

  byte ch=1;
    {
        Serial.print("Ch ");Serial.print(ch);
        Serial.print(" I=");Serial.println(EmonLibCM_getIrms(ch),3);
        Serial.print(" W=");Serial.println(EmonLibCM_getRealPower(ch));
        Serial.print(" VA=");Serial.println(EmonLibCM_getApparentPower(ch));
        Serial.print(" Wh=");Serial.println(EmonLibCM_getWattHour(ch));
        Serial.print(" pf=");Serial.print(EmonLibCM_getPF(ch),4);      
        Serial.println();
        delay(10);
    } 

    delay(10);

  }   // else
    delay(20000);
  }

Serial snip

Could you show me how to define the AC voltage pin please? Is there a simple way of setting the calibration?

I meant to add this photo to the previous post.

Have you looked at this, in the PDF file?

EmonLibCM Application Interface

Power & Energy
void EmonLibCM_SetADC_VChannel(byte ADC_Input, double _amplitudeCal)
void EmonLibCM_SetADC_IChannel(byte ADC_Input, double _amplitudeCal,
double _phaseCal)

Everything you need to answer your question is in that section. Which part(s) don’t you understand?

No, forget this - and ‘Group’, they relate to the radio channel and JeeLib/LPLib (when it’s used).

Note: you might not need to change the baud rate to 115200, you could remain at 9600 (the previous default - hence the hint to change) - or you might want to set your monitor to 115200 and always run at that.

If you’re running emonLibCM, DON’T run a timing delay in your sketch - the delay(20000); – you don’t need it and it will stop emonLibCM from running properly. You must use the timing built into emonLibCM, i.e. all your code to print, drive your LCD etc is in the correct place inside the “if”.

(Explanation: EmonLibCM_Ready( ) returns true every (in your case, when you’ve set it up) 20 s, and in the meantime continuously monitors - the clue is in the name - voltage and current, so it mustn’t stop for a delay; then it reports the average over the last 20 seconds.)

Thank you Robert,
Yes I have read the whole of the PDF file but most of it went over my head.
I am beyond rusty with C++.
My trouble is I just don’t understand what to do with these lines -
void EmonLibCM_SetADC_VChannel(byte ADC_Input, double _amplitudeCal)
void EmonLibCM_SetADC_IChannel(byte ADC_Input, double _amplitudeCal,
double _phaseCal)
And my old C++ book doesn’t help. Where do I put “2” for the AC voltage?
What does EmonCM lib need to be “Ready”? A current above zero, an AC voltage - or both?

There’s little C++ you need to know. All you have to do is plug the appropriate numbers in where byte ADC_Input and double _amplitudeCal are. A byte is a number 0 - 255, a double is a decimal value. Looking at the max example sketch (because these aren’t needed in the minimal sketch, you need them as you don’t have our default pins etc):

  EmonLibCM_SetADC_VChannel(0, 268.97);                    // ADC Input channel, voltage calibration - for Ideal UK Adapter = 268.97 
  EmonLibCM_SetADC_IChannel(1, 90.91, 4.2);                // ADC Input channel, current calibration, phase calibration

“0” is the voltage input pin - you want 2
“268.97” is the voltage calibration, you want 292.3. How did I get this? From the section I suggested you read: “Voltage amplitude calibration constant: This is the unitless ratio of mains voltage to the alternating component of the voltage at the ADC input” so divide your mains voltage by your Pin 2 voltage and this is the value.

You do the same with current as far as the pin (1) and amplitude calibration is concerned (Hint: 30 A per 1 volt = 30), but the one I can’t tell you is phaseCal. This depends on the properties of both your c.t and voltage transformer, and I don’t know either. I’d guess a number around 3 - 5, but it’s very much “how long is a piece of string?” You can only set it on test - measure an electric kettle or something like that (no fan or motor) and try numbers until it reports a power factor as close to 1.00 as you can get.

You’re asking it, is it ready to give you a result? It comes back ‘Yes I am’ (true) or ‘No not yet’ (false).

You then extract the numbers, look at the voltage and/or current to decide what to do.

Great. Thank you.
So I just write those 2 (modified) lines before
EmonLibCM_Init();
and with a bit of luck I shall be away.
Coffee from the kettle afterwards!

1 Like

Yes. And if you want your result every 20 s rather than 10, add (and change)

EmonLibCM_datalog_period(10);

If the voltages come badly wrong, you need to change

  EmonLibCM_ADCCal(3.3);                                   // ADC Reference voltage, (3.3 V for emonTx,  5.0 V for Arduino)

and possibly, for your Mega (is it a 10-bit or 12-bit ADC?)

  EmonLibCM_setADC(10, 104);                               // ADC Bits (10 for emonTx & Arduino except Due=12 bits, ADC Duration 104 us for 16 MHz operation)

Thanks. Changed those two lines and loaded the code. It did not work with the kettle running over 10 amps and 2 turns through the SCT.


I does not look as though either voltage or current is registering.
I shall ask about old Mega ADC bits. and do some checking tomorrow. My better-half needs me now.

You’d better take

  Serial.println("Set baud=115200");
  Serial.end();
  Serial.begin(115200);

out if you’re going to leave your monitor set at 9600 baud.

I thought that I had tried that, but I shall make sure.
Thanks,
Norman

This is the cause of the unreadable characters at the bottom of your screenshot:

After the Arduino changes the baud rate - the monitor needs changing too, hence the command to you to “Set baud = 115200”

How do you know? We need to know what it’s printing to your monitor - we can’t see while the Arduino is talking at one baud rate and your monitor is listening at another.

Robert, I appreciate your help, but do pull the plug when you have had enough!
The Arduino Mega 2560 has 10 bit ADC and is happy with Baud 115200, so I reinstated the baud lines and selected 115200 on the monitor.
Partial success, Voltage (?) but no current. The CT is outputting 0.8 Volts RMS for something over 10 amps and 2 turns in the CT.

EmonTx v3.4 EmonLibCM Continuous Monitoring Minimal Demo
AC present
V=243.55
Ch 1 I=0.000
W=0
VA=0
Wh=0
pf=0.0000

Could you confirm that my defining AI 2 for voltage and AI 1 for current is correct - I have ignored AI 0. Ch 1 does mean No.1?
I have checked the connections - but I shall do it again.

#include <Arduino.h>
#include "emonLibCM.h"

                                     
// ISR(WDT_vect) { Sleepy::watchdogEvent(); } 

 
void setup() 
{  
  Serial.begin(9600);
  Serial.println("Set baud=115200");
  Serial.end();
  Serial.begin(115200);
  
  Serial.println("\nEmonTx v3.4 EmonLibCM Continuous Monitoring Minimal Demo"); 

  EmonLibCM_SetADC_VChannel(2, 292.3);                    // ADC Input channel, voltage calibration - for Ideal UK Adapter = 268.97 
  EmonLibCM_SetADC_IChannel(1, 30, 4.2);                // ADC Input channel, current calibration, phase calibration
  EmonLibCM_setADC(10, 104);                               // ADC Bits (10 for emonTx & Arduino except Due=12 bits, ADC Duration 104 us for 16 MHz operation)
  EmonLibCM_datalog_period(20);
  EmonLibCM_ADCCal(5.0);                                   // ADC Reference voltage, (3.3 V for emonTx,  5.0 V for Arduino)
  
  EmonLibCM_Init();                                        // Start continuous monitoring.
}

void loop()             
{
   if (EmonLibCM_Ready())   
  {
 
    Serial.println(EmonLibCM_acPresent()?"AC present ":"AC missing ");
    delay(5);
  
    delay(50);
 
    Serial.print(" V=");Serial.println(EmonLibCM_getVrms());

  byte ch=1;
    {
        Serial.print("Ch ");Serial.print(ch);
        Serial.print(" I=");Serial.println(EmonLibCM_getIrms(ch),3);
        Serial.print(" W=");Serial.println(EmonLibCM_getRealPower(ch));
        Serial.print(" VA=");Serial.println(EmonLibCM_getApparentPower(ch));
        Serial.print(" Wh=");Serial.println(EmonLibCM_getWattHour(ch));
        Serial.print(" pf=");Serial.print(EmonLibCM_getPF(ch),4);      
        Serial.println();
        delay(10);
    } 

    delay(10);

  }  else
    delay(20000);
  }
  

I have left the 20000 delay in for the moment because the program sulks with nothing in “else.” It repeats the output every 20 seconds.

Do I need to do something about the unused current inputs?

The logical channels start at zero. These are not the same as pin numbers. In your case, the 0th channel is the first and only current / current & voltage pair that you’ve defined.

In any set of measurements, the voltage channel is always the first to be read. Thereafter,
the current inputs are read in the sequence in which they are defined in the sketch. This
sequence becomes the logical order used thereafter. For example, if (in the case of the
emonTx V3) the input labelled CT3 [= ADC Input 3] on the pcb legend is the first current
channel to be defined, it will be accessed as channel 0.

You shouldn’t need the else statement at all - the idea is the main program loop does as little as possible in between handling the output, leaving the processor free to handle the interrupts and the code they trigger to process each sample.
If you want to leave it in, have the contents empty, with only a null statement - the semicolon.
i.e.

 ...
  }  
  else
  {
    ;
  }

No, they won’t even be looked at in emonLibCM (in emonLibDB, they’re read and ignored, otherwise the timing gets impossible to handle).

Thanks Robert,
I checked that there was approximately 0.8 V RMS on both pin 1 and 2 with the kettle on. Same result, a figure for voltage and zero for current.
I moved the current I/P to pin 3 and altered byte ch=3 and EmonLibCM_SetADC_IChannel(3, 30, 4.2);
Same result V = 247.42 and Ch 3 I= 0.000
So I am stumped. I wonder if something is amis with the calibration.
Anyway, have a good evening.
Norman