I have an issue that's bugging me. It does not seem to affect the working of the sketch, but I hate things I can't explain. I won't include the whole sketch because most is irrelevant, but the parts are are relevant are below.
In summary, a mathematical calculation involving byte, long, and float data types is having its output sent to the monitor for testing purposes. Throughtout most of the range of possible numerical values, 15 through zero to -15, the correct value is seen in the monitor. However, what is expected to be a small -ve value (calculated to be around -0.3) the output is not a number - "nan". I'm thinking an issue with Casting or sqrt, but why only small -ve numbers? Advice welcome.
Here are the relevant pieces of the sketch:
// The following two const float statements are applicable to an EXTERNAL reference voltage of 3V.
const float VOLTFACTOR = 1.498; // The conversion factor A-D input to actual voltage (Volts per bit).
const float AMPFACTOR = 0.091; // The conversion factor A-D input to actual current (Amps per bit).
//Declare variables for measurement, calculations and status flags.
float rmsVoltage = 0;
float rmsCurrent = 0;
int voltage = 0;
int current = 0;
int centreTap = 512;
long sumSqrVoltageSamples = 0;
long sumSqrInPhaseCurrentSamples = 0;
long sumSqrOutPhaseCurrentSamples = 0;
boolean zeroCrossed = false;
byte voltageSamples = 0;
byte ipSamples = 0;
byte oopSamples = 0;
void setup()
{
//Initalise serial monitor link.
Serial.begin(115200);
//Initialise hardware for supply and load measurements and immersion control
pinMode (DRIVERPIN, OUTPUT);
pinMode (MAININDICATORPIN, OUTPUT);
pinMode (INTERRUPTPIN, INPUT);
pinMode (LEDPIN, OUTPUT);
digitalWrite (INTERRUPTPIN, HIGH); //Assign internal pull up resistor to pin 2
attachInterrupt (0, ZeroCrossing, RISING);
analogReference(EXTERNAL); // Set Arduino to use an external reference of 3V.
delay (5000); // Delay start to allow interface power supplies to stabilise
}
//Main loop
void loop()
{
//Irrelevant code has been removed. Only the second statement gives the error, but is
// also the only one required to deliver -ve outputs. large -ve values are correct.
// Only very small -ve values yield nan
while (!zeroCrossed)
{
ReadAndSquare();
}
rmsVoltage = RMSCalc( sumSqrVoltageSamples, voltageSamples, VOLTFACTOR );
rmsSupplyCurrent = (RMSCalc(sumSqrInPhaseCurrentSamples, ipSamples, AMPFACTOR )) -
(RMSCalc(sumSqrOutPhaseCurrentSamples, oopSamples, AMPFACTOR ));
}
float RMSCalc(long sumOfSqrSamples, byte noOfSamples, const float CONVERSIONFACTOR)
{
return float ( CONVERSIONFACTOR * sqrt (sumOfSqrSamples / noOfSamples));
}
void ReadAndSquare()
{
centreTap = analogRead(A2);
supplyVoltage = analogRead(A1) - centreTap;
sumSqrVoltageSamples = sumSqrVoltageSamples + sq((long)supplyVoltage);
voltageSamples ++;
supplyCurrent = analogRead(A0) - centreTap;
if (((supplyVoltage > 0) && (supplyCurrent > 0)) || ((supplyVoltage < 0) && (supplyCurrent < 0))) // Square and add in phase current samples.
{
ipSamples ++ ;
sumSqrInPhaseCurrentSamples = sumSqrInPhaseCurrentSamples + sq((long)supplyCurrent);
}
else // Square and add out of phase current samples.
{
oopSamples ++ ;
sumSqrOutPhaseCurrentSamples = sumSqrOutPhaseCurrentSamples + sq((long)supplyCurrent);
}
}
void ZeroCrossing()
{
zeroCrossed = true;
}
I've checked for consistency of variable type declarations between global and local. rmsVoltage will correctly return values down to zero, but I cant test that with the current as the Arduino's current is included in the measurement, deliberately.
Values are sent to the monitor about every 5 seconds, so if I change the current in between, the output looks like this:
Voltage samples taken = 44
RMS Supply Voltage = 242.57
RMS Supply Current = -1.56
Voltage samples taken = 43
RMS Supply Voltage = 245.06
RMS Supply Current = -1.48
Voltage samples taken = 44
RMS Supply Voltage = 242.63
RMS Supply Current = nan Note: Expected -0.3
Voltage samples taken = 44
RMS Supply Voltage = 244.11
RMS Supply Current = 0.09 Note: Arduino and interface current
Voltage samples taken = 43
RMS Supply Voltage = 240.43
RMS Supply Current = 9.60