Community
OpenEnergyMonitor

OpenEnergyMonitor Community

EmonlibCM no readings

Good morning everyone,

So I have finally finished my Emon hardware (I have been waiting for 3 years to do it :slight_smile:) and flashed succesfully the EmonlibCM “max” example adapted to my setup in the atmega.
The setup is as follows :

And the code in the atmega is the one below. You will see that I transfer the data through I2C because I fetch it from an ESP32 to send it to my raspberrypi.

/*

"Maximal" sketch to demonstrate emonLibCM

This demonstrates the use of every API function.
This sketch provides an example of every Application Interface function. 
Many in fact set the default value for the emonTx V3.4, and are therefore
not needed in most cases. If you do need to change a value, the 
Application Interface section of the User Documentation gives full details.

*/

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

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

bool recalibrate = false;                                  //  Do not demonstrate the recalibration functions
int waittime = 10;
/*

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, power2, power3, power4, vrms, temp1, temp2, temp3, temp4, temp5, temp6, pulse
       datacode = h
       scales = 1,1,1,1,0.01,0.1,0.1,0.1,0.1,0.1,0.1,1
       units =W,W,W,W,V,C,C,C,C,C,C,p

*/       

typedef struct {int power1, power2, power3, power4, Vrms; } PayloadTX;        // package the data for RF comms

PayloadTX emontx;                                          // create an instance

int Vrms_val;
 
/* Example - how to define temperature sensors, prevents an automatic search

DeviceAddress allAddresses[6] = {       
    {0x28, 0x81, 0x43, 0x31, 0x7, 0x0, 0x0, 0xD9}, 
    {0x28, 0x8D, 0xA5, 0xC7, 0x5, 0x0, 0x0, 0xD5},         // Use the actual addresses, as many as required
    {0x28, 0xC9, 0x58, 0x32, 0x7, 0x0, 0x0, 0x89}          //  up to a maximum of 6
};

*/


void setup() 
{  

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

  EmonLibCM_SetADC_VChannel(3, 268.97);                    // ADC Input channel, voltage calibration - for Ideal UK Adapter = 268.97 
  EmonLibCM_SetADC_IChannel(0, 90.91, 4.2);                // ADC Input channel, current calibration, phase calibration
  EmonLibCM_SetADC_IChannel(1, 90.91, 4.2);                //  The current channels will be read in this order
  EmonLibCM_SetADC_IChannel(2, 90.91, 4.2);                //  90.91 for 100 A : 50 mA c.t. with 22R burden - v.t. leads c.t by ~4.2 degrees
  EmonLibCM_SetADC_IChannel(6, 16.67, 1.0);                //  16.67 for 100 A : 50 mA c.t. with 120R burden - v.t. leads c.t by ~1 degree

  EmonLibCM_setADC(10, 104);                               // ADC Bits (10 for emonTx & Arduino except Due=12 bits, ADC Duration 104 us for 16 MHz operation)
  EmonLibCM_ADCCal(3.3);                                   // ADC Reference voltage, (3.3 V for emonTx,  5.0 V for Arduino)
  
  EmonLibCM_cycles_per_second(50);                         // mains frequency 50Hz, 60Hz
  EmonLibCM_datalog_period(1);                            // period of readings in seconds - normal value for emoncms.org
  
  EmonLibCM_min_startup_cycles(10);                        // number of cycles to let ADC run before starting first actual measurement



  //Initialize I2C
  //rf12_initialize(nodeID, RF_freq, networkGroup);          // initialize radio module

  EmonLibCM_Init();                                        // Start continuous monitoring.

  Wire.begin(8);                // join i2c bus with address #8
  Wire.onRequest(requestEvent); // register event

}



void loop()             
{

  if (recalibrate)                                         // recalibrate should be set when new calibration values become available
  {
      
    EmonLibCM_ReCalibrate_VChannel(268.97);                // ADC Input channel, voltage calibration new value 
    EmonLibCM_ReCalibrate_IChannel(1, 90.91, 4.2);         // ADC Input channel, current calibration, phase calibration new values
    EmonLibCM_ReCalibrate_IChannel(2, 90.91, 4.2);         //  It is only necessary to use one of these functions if that calibration 
    EmonLibCM_ReCalibrate_IChannel(3, 90.91, 4.2);         //  value needs to be changed.
    EmonLibCM_ReCalibrate_IChannel(4, 16.67, 1.0);         //  
    recalibrate = false;                                   // Do it once only.
  }

}


void requestEvent() {
  if (EmonLibCM_Ready())   
  {
    Serial.println(EmonLibCM_acPresent()?"AC present ":"AC missing ");
    Wire.write("Ready");
    //delay(5);
    waittime = millis();
    while (millis()-waittime < 5){    
    }

    emontx.power1 = EmonLibCM_getRealPower(0);   // Copy the desired variables ready for transmission 
    emontx.power2 = EmonLibCM_getRealPower(1); 
    emontx.power3 = EmonLibCM_getRealPower(2);
    emontx.power4 = EmonLibCM_getRealPower(3);
    emontx.Vrms   = EmonLibCM_getVrms() * 100;

   //Send to ESP32 via I2C
    Wire.write(EmonLibCM_getRealPower(0)); // 2 bytes
    Wire.write(EmonLibCM_getRealPower(1)); // 2 bytes
    Wire.write(EmonLibCM_getRealPower(2)); // 2 bytes
    Wire.write(EmonLibCM_getRealPower(3)); // 2 bytes
    Vrms_val = EmonLibCM_getVrms() * 100;
    Wire.write(Vrms_val);                  // 2 bytes
                                           // 10 bytes Total 
    //rf12_sendNow(0, &emontx, sizeof emontx);     //send data
  }
  else {
    //Wire.write("No data"); // respond with message of 6 bytes
    I2C_writeAnything(EmonLibCM_getLineFrequency());
    Wire.write("-");
    I2C_writeAnything(EmonLibCM_getVrms());
//    if (EmonLibCM_polarityConfirmed() == 0){
//      Wire.write("pol NOK ");
//    } else {
//      Wire.write("pol OK");
//    }
    //Wire.write(EmonLibCM_getRealPower(0));
  }
}

My issue is that I have no readings. When doing the check " EcmMonLib_Readu()" it always returns 0. I checked some paramters and can confirm that
AC_present = 1
Polarity = negative (when I check it)

It there any obvious set-up I am missing ? I have the voltage measurment on ADC3 so I adapted it into the code.

Thank you for your help

Adrien

When creating the schematic I had a lot of doubt about the layout for AREF (to GND with capacitor).
But by reading some forum I found out that doing this + the following line of code would inform the Atmega to set Aref = AVcc.
So I guess my schematic is correct on that point no ?

byte ADCRef = VREF_NORMAL << 6; //Taken from EmonLibCM

If you are not intending to change the calibration on-line, you don’t need the “recalibrate” block of code. That, like any of the settings where you do not want to change from the default value, is only there in the example sketch to show you how to use the function.

Also, as you are not using the emontx structure, you do not need those assignments either.

I cannot see anything obviously wrong in the set-up.

Your drawing appears to be correct in that regard. From Page 250 of the Atmel ATMega data sheet:

“The ADC has a separate analog supply voltage pin, AVCC. AVCC must not differ more than ±0.3V from VCC. See the paragraph ”ADC Noise Canceler” on page 256 on how to connect this pin.
Internal reference voltages of nominally 1.1V or AVCC are provided On-chip. The voltage reference may be externally decoupled at the AREF pin by a capacitor for better noise performance.”

I suggest you put EmonLibCM_Ready() directly inside the main loop - as in the example code, and then print the values returned by the EmonLibCM_get... functions. That will demonstrate that the library and the analogue side of your hardware is working (which it seems to be as you say AC is detected). EmonLibCM_Ready()will always return false except for one time immediately after the datalogging period set by EmonLibCM_datalog_period(1) has expired.

I have no knowledge of the I²C library you are using, so I cannot help you with that.

Typo?
Should that be EcmMonLib_Ready() ?

Hello,

Thanks you to both of you. Yes it was a typo. The function is correctly written in the code.

Following Robert’s advice I have modified the code as follows but I am still getting no results. By no results, I mean that it seems I do not enter the if (EmonLibCM_Ready()) statement in the loop.

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


bool recalibrate = false;                                  //  Do not demonstrate the recalibration functions
int waittime = 10;

typedef struct {int power1, power2, power3, power4, Vrms; } PayloadTX;        // package the data for RF comms

PayloadTX emontx;                                          // create an instance

bool SENT = 1;
 
void setup() 
{  

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

  EmonLibCM_SetADC_VChannel(3, 268.97);                    // ADC Input channel, voltage calibration - for Ideal UK Adapter = 268.97 
  EmonLibCM_SetADC_IChannel(0, 90.91, 4.2);                // ADC Input channel, current calibration, phase calibration
  EmonLibCM_SetADC_IChannel(1, 90.91, 4.2);                //  The current channels will be read in this order
  EmonLibCM_SetADC_IChannel(2, 90.91, 4.2);                //  90.91 for 100 A : 50 mA c.t. with 22R burden - v.t. leads c.t by ~4.2 degrees
  EmonLibCM_SetADC_IChannel(6, 16.67, 1.0);                //  16.67 for 100 A : 50 mA c.t. with 120R burden - v.t. leads c.t by ~1 degree

  EmonLibCM_setADC(10, 104);                               // ADC Bits (10 for emonTx & Arduino except Due=12 bits, ADC Duration 104 us for 16 MHz operation)
  EmonLibCM_ADCCal(3.3);                                   // ADC Reference voltage, (3.3 V for emonTx,  5.0 V for Arduino)
  
  EmonLibCM_cycles_per_second(50);                         // mains frequency 50Hz, 60Hz
  EmonLibCM_datalog_period(5);                            // period of readings in seconds - normal value for emoncms.org
  
  EmonLibCM_min_startup_cycles(10);                        // number of cycles to let ADC run before starting first actual measurement

  EmonLibCM_Init();                                        // Start continuous monitoring.

  Wire.begin(8);                // join i2c bus with address #8
  Wire.onRequest(requestEvent); // register event

}

void loop()             
{
  if (EmonLibCM_Ready())   
  {
    Serial.println(EmonLibCM_acPresent()?"AC present ":"AC missing ");
    waittime = millis();
    while (millis()-waittime < 5){    
    }
    emontx.power1 = EmonLibCM_getRealPower(0);   // Copy the desired variables ready for transmission 
    emontx.power2 = EmonLibCM_getRealPower(1); 
    emontx.power3 = EmonLibCM_getRealPower(2);
    emontx.power4 = EmonLibCM_getRealPower(3);
    emontx.Vrms   = EmonLibCM_getVrms() * 100;
    SENT = 0;
  }
}

void requestEvent() {
  bool acpresent = EmonLibCM_acPresent();
  Wire.write((byte *) &acpresent, sizeof(acpresent));
  if (SENT == 0){
   //Send to ESP32 via I2C
    Wire.write((byte *) &emontx.power1,sizeof(emontx.power1));
    Wire.write((byte *) &emontx.power1,sizeof(emontx.power2));
    SENT = 1;
                                           // 10 bytes Total 
  } else {
        // Nothing

  }

}

I left the calibration function for reference but will re,ove the, in my final code if needed (I have a 230-7.5V transfomer that will probably need proper calibration).

So with this code I still get the fact that EmonLibCM_acPresent()= 1. My idea was to let the code run within the main loop and the “SENT” boolean is used for two purposes

  1. Confirm is there is data to be sent
  2. Confirm is the data has been sent (no to send it twice)

As an information, I cannot use serial direclty because I was really limited in space and I can only send data through I2C to the ESP32 and do the serial.print from there.

So I Come with two new questions :

  1. Is there any measure I can check on my board that would be blocking the execution of Emonlib
  2. Can the I2C request mess with the interup of EmonLIbCM

By the way, it is a pleasure to work with this library thanks to its awsome comments and explanation. Thanks for all the work.

Adrien

Your code, with the “wire” etc library and associated code removed (because I don’t have the other library), works for me. “AC missing” is because I have a standard emonTx. Clearly, I cannot test on your hardware.

17:37:41.348 -> 
17:37:41.381 -> EmonTx v3.4 EmonLibCM Continuous Monitoring Maximal Demo
17:37:46.391 -> AC missing 
17:37:51.406 -> AC missing 
17:37:56.388 -> AC missing 
17:38:01.403 -> AC missing 
17:38:06.384 -> AC missing 
17:38:11.398 -> AC missing 
17:38:16.413 -> AC missing 
17:38:21.393 -> AC missing 
17:38:26.406 -> AC missing 
17:38:31.435 -> AC missing 

That is surely proof that it is entering the conditional block controlled by if (EmonLibCM_Ready())

And here’s the code that produced that output:

#include <Arduino.h>
#include "emonLibCM.h"
// #include <Wire.h>
// #include <I2C_Anything.h>


bool recalibrate = false;                                  //  Do not demonstrate the recalibration functions
int waittime = 10;


bool SENT = 1;
 
void setup() 
{  

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

  EmonLibCM_SetADC_VChannel(3, 268.97);                    // ADC Input channel, voltage calibration - for Ideal UK Adapter = 268.97 
  EmonLibCM_SetADC_IChannel(0, 90.91, 4.2);                // ADC Input channel, current calibration, phase calibration
  EmonLibCM_SetADC_IChannel(1, 90.91, 4.2);                //  The current channels will be read in this order
  EmonLibCM_SetADC_IChannel(2, 90.91, 4.2);                //  90.91 for 100 A : 50 mA c.t. with 22R burden - v.t. leads c.t by ~4.2 degrees
  EmonLibCM_SetADC_IChannel(6, 16.67, 1.0);                //  16.67 for 100 A : 50 mA c.t. with 120R burden - v.t. leads c.t by ~1 degree

  EmonLibCM_setADC(10, 104);                               // ADC Bits (10 for emonTx & Arduino except Due=12 bits, ADC Duration 104 us for 16 MHz operation)
  EmonLibCM_ADCCal(3.3);                                   // ADC Reference voltage, (3.3 V for emonTx,  5.0 V for Arduino)
  
  EmonLibCM_cycles_per_second(50);                         // mains frequency 50Hz, 60Hz
  EmonLibCM_datalog_period(5);                            // period of readings in seconds - normal value for emoncms.org
  
  EmonLibCM_min_startup_cycles(10);                        // number of cycles to let ADC run before starting first actual measurement

  EmonLibCM_Init();                                        // Start continuous monitoring.

//  Wire.begin(8);                // join i2c bus with address #8
//  Wire.onRequest(requestEvent); // register event

}

void loop()             
{
  if (EmonLibCM_Ready())   
  {
    Serial.println(EmonLibCM_acPresent()?"AC present ":"AC missing ");
    waittime = millis();
    while (millis()-waittime < 5){    
    }
    SENT = 0;
  }
}

/*

void requestEvent() {
  bool acpresent = EmonLibCM_acPresent();
  Wire.write((byte *) &acpresent, sizeof(acpresent));
  if (SENT == 0){
   //Send to ESP32 via I2C
    Wire.write((byte *) &emontx.power1,sizeof(emontx.power1));
    Wire.write((byte *) &emontx.power1,sizeof(emontx.power2));
    SENT = 1;
                                           // 10 bytes Total 
  } else {
        // Nothing

  }

}
*/

I have just found something more during my testing.

EmonLibCM_acPresent() returns 1 as explained before
EmonLibCM_getLineFrequency() returns 0,00 → that should be the 50hz of my network ?

Does it help to find the origine of the issue ?

I think it means that your wire and I2C_Anything libraries are not actually letting emonLibCM run in the background.

Have you tried your sketch as I edited it, and if you add Serial.print(EmonLibCM_getVrms()); etc, do you get sensible values?

The thing is that I cannot use serial in my ATMEga (pins are not visible).

So following your advice I will take the problem the otherway around. I will use the ATMega as master and send the data through I2C within the if (EmonLibCM_Ready()) statement.
A bit like it is done in the original example with the radio module, but using I2C that time.

I will let you know if that changes anything.

Thanks

I struggled a it to set the opposite solution (ATmega Master sending throug I2c) because th ESP32 does not really like working as slave. There is specific libraries for that but I am not sure how well they are compatible with the regular wire library.
So next step for me will be to test bare-metal reading of the ADC without using EmonLibCM to be sure I have no hardware issue.

I will keep you informed.

Thanks

I think debugging would have been much easier for you, had you brought out TXD, RXD & RESET to a FTDI header.

All OEM sensor nodes work on the principle that they initiate transmission of the data. The libraries and sketches that are published here assume that way of working. It would be relatively easy for you to modify emonLibCM to report the averages since the last time it was asked for a value (instead of keeping time itself), but you would need to ensure that the sketch that handles the incoming request for data will allow emonLibCM to run continuously in the background, measuring every single cycle of mains electricity. You must never stop, or hold up, the interrupt routine that processes the ADC readings. It is called emonLibCM for exactly that reason - emonLibContinuousMonitoring. Your “master” device would then be responsible for polling the sensor device at regular intervals, spaced in time such that the internal accumulators that are used in the averaging process are never allowed to overflow, and that would then need to trigger the processing and sending of the average voltage & powers, and the accumulated energies, since the previous reading was sent.

Hello Robert,

That would have been much easier indeed :slight_smile:

I have totally clear in my mind that the ESP32 should not interfer with the ISR of the EmonLibCM. At the moment I continue with the investigation and if I can I will use the ATMEGA as master to send the data to the ESP, but from all what I have read, THE ESP32 is does not appreciate working in the slave position even if some specific library have been created for that.

I have another question concerning the fuses. I have not though a lot about it until this morning, when compiling my code in arduino, the fuses are as follows, is it coherent ?

image

I am not really sure of the impact of BOD, EEPRIM and Bootload on the normal behavior of the atmega.

Thank you

And here is what AVR dude tells me about my fuses :

Fuses OK (E:FF, H:D9, L:62)

BOD = Brown Out Detection, you’re setting it to 2.7V, so if VCC on the ATMEGA drops below 2.7 the brown out detection circuit will kick in. There’s a good article over at Adafruit that talks about how it operates and the importance of having it enabled → HERE

If you don’t have the bootloader enabled, you’ll not be able to program the Arduino using the Serial port, and will need to use the ISP header (or equivalent pins) and an ISP programmer (which it seems you’re doing anyway?)

EEPROM Retained is telling AVRDude not to overwrite/clear the EEPROM when it is updating the program code in Flash. It may or may not be useful to retain the EEPROM contents between code updates, but it probably depends on what you’re updating in the refreshed program being loaded onto the chip.

I can’t really comment on the values you have for the fuses, but standard “Arduino default” fuses should be perfectly acceptable.
Based on the boards.txt file I have in my Arduino installation, the default fuses for the Optiboot bootloader on an ATMega328p in Arduino are: E:0x05, H:0xDE, L:0x62.

This site will let you see what your fuse settings are enabling/disabling:
https://www.engbedded.com/fusecalc/

Thanks a lot for the clarification.

From what I read I understand brown-out is a reduction in the chip load to avoid it to “switchoff”.

After a bit more investigation and doing a blink test on the chip I realized I put the wrong fuse because the LED was bliking every 8s. Error of my part but really instructive to do the test.
The fuses went from
lfuse:w:0x4e:m -U hfuse:w:0xd9:m -U efuse:w:0xff:m
to
lfuse:w:0x4e:m -U hfuse:w:0xC9:m -U efuse:w:0xff:m

Still I am having some issue reading directly the ADC on the ATMEGA. It sends 255 all the times.

Long process but I am sure it is worth it. Really enjoying the debugging ! This is how one learns.

Thanks

Well the fuse solved it and I had an issue formatting the data for the serial.print.
And for the moment I can still use the ESP32 as master of the I2C network without perturbation on the EmonlibCM.

Thanks for helping on the debug.

So emonLibCM was not the problem?