EmonLib Errors related with calcIrms() function

Dear Friends, 

I am using EmonLib (Version April 27 2010) .

I am trying to use Library EmonLib on custom designed hardware based on Arduino Mega2560. I am having a strange trouble with calcIrms() function. I have 15 current sensors. When I use each sensor individually they work fine and always return a positive current value. However when I enable multiple sensors then some sensors start to return negative values. 

I traced down by adding prints in the Emonlib.cpp at various places and finally found that the trouble is related with readVCC() function. The readVCC function some times return errornous value of "-1".The regular value for this function is around 512. 

I am copying the readVCC() function for your review:

long EnergyMonitor::readVcc() {
  long result;

  #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined (__AVR_ATmega328P__)
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); 
  #elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  ADMUX = _BV(MUX5) | _BV(MUX0);
  #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
  ADMUX = _BV(MUX3) | _BV(MUX2);
  #endif

  delay(2);     // Wait for Vref to settle 
  ADCSRA |= _BV(ADSC);    // Convert
  while (bit_is_set(ADCSRA,ADSC));
  result = ADCL;
  result |= ADCH<<8;
  result = 1126400L / result;   //1100mV*1024 ADC steps http://openenergymonitor.org/emon/node/1186
  return result;
}

----------------

Can someone suggest what might be wrong with readVCC function that it sometimes returns -1?

Regards

 

 

 

 

Robert Wall's picture

Re: EmonLib Errors related with calcIrms() function

"I have 15 current sensors. When I use each sensor individually they work fine and always return a positive current value. However when I enable multiple sensors then some sensors start to return negative values. "

I've not seen anyone complain of this before. When you say you have 15 sensors, how are you defining them? And how do you enable and use them? Are you running out of memory?  I would be looking for an out-of-memory error or an overflow for this fault. Take a look at this: http://playground.arduino.cc/Code/AvailableMemory  or this:  http://forum.pololu.com/viewtopic.php?f=10&t=989&view=unread#p4218

 

dBC's picture

Re: EmonLib Errors related with calcIrms() function

I'm curious, what sort of sampling rate do you anticipate while running 15 CTs?

Robert Wall's picture

Re: EmonLib Errors related with calcIrms() function

"I'm curious, what sort of sampling rate do you anticipate while running 15 CTs?"
It depends on how many samples or how many half-cycles you ask for, and whether you're using the standard emonLib functions or the more advanced free-running or the interrupt-driven sketches, whether you interleave samples or c.t's. But it would nonetheless be fairly slow. If you read calypso-rae's threads, you can see what sort of rates are obtainable with one c.t. then divide by 15!

Which approach you take depends very much on what you want to do with the data, and without doing the sums I'd have thought a hybrid approach would be the best (i.e. maybe interleave 3 c.t's, then repeat for the 5 groups of 3).

asimlink's picture

Re: EmonLib Errors related with calcIrms() function

For me it doesnt really matter if the calcIrms function takes time. my logging of power is very slow. Problem is with readVCC function() if multiple sensors are enabled the readVCC returns un-reliable values often containing -1.

I am doing this experiment on Arduino Mega 2560 board. Maybe you all have tested things on Arduino UNO and not on Mega 2560. I would suggest if you have Arduino Mega just try to run this code (no matter if you have any sensor connected with analog pins) the return values for all analog inputs should be "about" same.

Interesting thing is that when i replaced following line :

int SUPPLYVOLTAGE = readVcc(); with 

int SUPPLYVOLTAGE = 5000;

 

here is EmonLib.cpp function that i edited:

-------------------------------------

double EnergyMonitor::calcIrms(int NUMBER_OF_SAMPLES)

{
//int SUPPLYVOLTAGE = readVcc(); // disabled by me

 

int SUPPLYVOLTAGE = 5000;  // added by me

--------------------------------------

The calcIrms runs without any problems. So the trouble is with readVCC function for sure. I would like you guys to test readVCC function over Arduino Mega 2560.

here is my main code:

#include "EmonLib.h" // Include Emon Library

 

EnergyMonitor emon1; //instance for sensor 01
EnergyMonitor emon2; //instance for sensor 02
EnergyMonitor emon3; //instance for sensor 03                      
EnergyMonitor emon4; //instance for sensor 04
EnergyMonitor emon5; //instance for sensor 05
EnergyMonitor emon6; //instance for sensor 06
EnergyMonitor emon7; //instance for sensor 07
EnergyMonitor emon8; //instance for sensor 08
EnergyMonitor emon9; //instance for sensor 09
EnergyMonitor emon10;//instance for sensor 10
EnergyMonitor emon11;//instance for sensor 11
EnergyMonitor emon12;//instance for sensor 12
EnergyMonitor emon13;//instance for sensor 13
EnergyMonitor emon14;//instance for sensor 14
EnergyMonitor emon15;//instance for sensor 15

void setup()

  Serial.begin(9600);

  emon1.current(1, 17.5);     // Current: input pin, calibration. for 200R
  emon2.current(2, 17.5);     // Current: input pin, calibration. for 200R
  emon3.current(3, 17.5);     // Current: input pin, calibration. for 200R
  emon4.current(4, 7.1);      // Current: input pin, calibration. for 510R
  emon5.current(5, 7.1);      // Current: input pin, calibration. for 510R
  emon6.current(6, 7.1);      // Current: input pin, calibration. for 510R
  emon7.current(7, 7.1);      // Current: input pin, calibration. for 510R
  emon8.current(8, 7.1);      // Current: input pin, calibration. for 510R
  emon9.current(9, 7.1);      // Current: input pin, calibration. for 510R
  emon10.current(10, 7.1);    // Current: input pin, calibration. for 510R
  emon11.current(11, 7.1);    // Current: input pin, calibration. for 510R
  emon12.current(12, 7.1);    // Current: input pin, calibration. for 510R
  emon13.current(13, 7.1);    // Current: input pin, calibration. for 510R
  emon14.current(14, 7.1);    // Current: input pin, calibration. for 510R
  emon15.current(15, 7.1);    // Current: input pin, calibration. for 510R
 
}

void loop()
{
  // calculates Irms for all 15 sensors
  double Irms1 = emon1.calcIrms(1480);  // Calculate Irms only
  double Irms2 = emon2.calcIrms(1480);  // Calculate Irms only
  double Irms3 = emon3.calcIrms(1480);  // Calculate Irms only
  double Irms4 = emon4.calcIrms(1480);  // Calculate Irms only
  double Irms5 = emon5.calcIrms(1480);  // Calculate Irms only
  double Irms6 = emon6.calcIrms(1480);  // Calculate Irms only
  double Irms7 = emon7.calcIrms(1480);  // Calculate Irms only
  double Irms8 = emon8.calcIrms(1480);  // Calculate Irms only
  double Irms9 = emon9.calcIrms(1480);  // Calculate Irms only
  double Irms10 = emon10.calcIrms(1480);  // Calculate Irms only
  double Irms11 = emon11.calcIrms(1480);  // Calculate Irms only
  double Irms12 = emon12.calcIrms(1480);  // Calculate Irms only
  double Irms13 = emon13.calcIrms(1480);  // Calculate Irms only
  double Irms14 = emon14.calcIrms(1480);  // Calculate Irms only
  double Irms15 = emon15.calcIrms(1480);  // Calculate Irms only 
 
  // print Apparent power for all 15 sensors
 
  Serial.print("S1:"); Serial.print(Irms1*230.0);     Serial.print("\t");
  Serial.print("S2:"); Serial.print(Irms2*230.0);     Serial.print("\t");
  Serial.print("S3:"); Serial.print(Irms3*230.0);     Serial.print("\t");
  Serial.print("S4:"); Serial.print(Irms4*230.0);     Serial.print("\t"); 
  Serial.print("S5:"); Serial.print(Irms5*230.0);     Serial.print("\t");
  Serial.print("S6:"); Serial.print(Irms6*230.0);     Serial.print("\t");
  Serial.print("S7:"); Serial.print(Irms7*230.0);     Serial.print("\t");
  Serial.print("S8:"); Serial.print(Irms8*230.0);     Serial.print("\t");
  Serial.print("S9:"); Serial.print(Irms9*230.0);     Serial.print("\t");
  Serial.print("S10:"); Serial.print(Irms10*230.0);   Serial.print("\t");
  Serial.print("S11:"); Serial.print(Irms11*230.0);   Serial.print("\t");
  Serial.print("S12:"); Serial.print(Irms12*230.0);   Serial.print("\t");
  Serial.print("S13:"); Serial.print(Irms13*230.0);   Serial.print("\t");
  Serial.print("S14:"); Serial.print(Irms14*230.0);   Serial.print("\t");
  Serial.print("S15:"); Serial.println(Irms15*230.0);
  Serial.println ("");
 
}

 

Robert Wall's picture

Re: EmonLib Errors related with calcIrms() function

Presumably you "disable" and "enable" channels by commenting / uncommenting them? Is there a critical point at which the number of active instances creates the fault - irrespective of which channels are active?

So can you look again at this: "Are you running out of memory?  I would be looking for an out-of-memory error or an overflow for this fault. Take a look at this: http://playground.arduino.cc/Code/AvailableMemory  or this:  http://forum.pololu.com/viewtopic.php?f=10&t=989&view=unread#p4218"

 

dBC's picture

Re: EmonLib Errors related with calcIrms() function

I'm not sure the logic behind readVCC() is sound anyway, so it may be your solution gives a better result.   It appears to be using a Vref of 5V and using that to measure the 1.1V internal bandgap voltage.  Any discrepancy then gets booked to the 5V supply.  In my experience those internal bandgap voltages are not very accurate at all, and vary from device to device.   I've got a Mega2560 here on my bench whose 2.56V internal reference would appear to be more like 2.499V.  The datasheet says anywhere from 2.4V to 2.8V (and 1.0V to 1.2V for the 1.1V reference).

If you're running your Arduino off a long cheap USB cable from already overloaded computer USB ports, then I could imagine the bandgap voltages might be better than the 5V supply.  But if you've got a half decent 5V regulator onboard, then I'd put my money on the 5V rather than the internal voltages.

I'm not familiar with emonlib but I'd imagine the absolute voltage is probably not that relevant anyway.  Presumably any inaccuracies there get calibrated away?  And doing it on every measurement of current seems pretty wasteful of your most precious resource... the A/D converter.    You might actually improve accuracy by assuming Vcc is stable, and keeping the A/D busy tracking the things that really mater (V and I).  Especially given that any drift you do detect wth readVCC() might be bandgap voltage drift and not Vcc drift.

None of that explains what you're seeing though, so I'm afraid this doesn't get you off the hook from finding your problem.

Robert Wall's picture

Re: EmonLib Errors related with calcIrms() function

The argument is that the internal bandgap reference might not be more accurate, but it is more stable, than the 5 V supply.

Therefore as you say the inaccuracy gets calibrated out. You cannot calibrate out instability.

It's really there for the people who run off batteries. In that case, using the bandgap reference to calibrate Aref - which is the battery voltage - is essential.

(dBC: I got the impression the OP was a bit cheesed off by you sidetracking 'his' thread - better start a new one if you want to discuss this further.)

dBC's picture

Re: EmonLib Errors related with calcIrms() function

In that case, you might get better results using one of the internal voltages as the Vref for the A/D  and adjust the burden resistors, mid-voltages, and op-amps accordingly.   If the 5V is noisy, and it's being used as the Vref for the A/D, then checking its value 110usecs before or after using it as a reference doesn't sound too good.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.