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
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
Re: EmonLib Errors related with calcIrms() function
I'm curious, what sort of sampling rate do you anticipate while running 15 CTs?
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).
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 ("");
}
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"
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.
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.)
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.