Unexplained "nan" to monitor

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

Values are sent to the monitor about every 5 seconds

The code you posted does NOT produce the output you claim it does. Post a COMPLETE program that demonstrates the error. It is probably in your misunderstanding of integer arithmetic.

The sketch does not compile:

Arduino: 1.8.5 (Mac OS X), Board: "Arduino/Genuino Uno"

/Users/john/Documents/Arduino/sketch_oct31a/sketch_oct31a.ino: In function 'void setup()':
sketch_oct31a:31: error: 'DRIVERPIN' was not declared in this scope
   pinMode (DRIVERPIN, OUTPUT);
            ^
sketch_oct31a:32: error: 'MAININDICATORPIN' was not declared in this scope
   pinMode (MAININDICATORPIN, OUTPUT);
            ^
sketch_oct31a:33: error: 'INTERRUPTPIN' was not declared in this scope
   pinMode (INTERRUPTPIN, INPUT);
            ^
sketch_oct31a:34: error: 'LEDPIN' was not declared in this scope
   pinMode (LEDPIN, OUTPUT);
            ^
/Users/john/Documents/Arduino/sketch_oct31a/sketch_oct31a.ino: In function 'void loop()':
sketch_oct31a:55: error: 'rmsSupplyCurrent' was not declared in this scope
   rmsSupplyCurrent = (RMSCalc(sumSqrInPhaseCurrentSamples, ipSamples, AMPFACTOR )) -
   ^
/Users/john/Documents/Arduino/sketch_oct31a/sketch_oct31a.ino: In function 'void ReadAndSquare()':
sketch_oct31a:70: error: 'supplyVoltage' was not declared in this scope
   supplyVoltage = analogRead(A1) - centreTap;
   ^
sketch_oct31a:73: error: 'supplyCurrent' was not declared in this scope
   supplyCurrent = analogRead(A0) - centreTap;
   ^
exit status 1
'DRIVERPIN' was not declared in this scope

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Hi John. No, the code as posted will not compile because it is not the complete sketch. As I said, I only posted those parts that will affect the output of rmsSupplyCurrent. As for the output every 5 seconds, that's what my test code is supposed to do.

I'll have to think seriously about posting the complete code. It's only a test version of my project, but even that could give away too much.

There's no harm in simplifying the sketch, but it needs to compile and (when possible) demonstrate the problem.

In any case, you are likely passing noOfSamples as 0, hence the NaN. Your interpretation of the (invisible) printf's are then causing confusion.

BTW, since zeroCrossed is used in an interrupt context, it needs to be declared volatile.

Hi arduarn,

I accept that the code fragments that I posted won't compile, but even if I posted the complete test sketch and you were to compile and run it, without the associated interface hardware (current transformers, voltage conditioner, analogue input level shifters, and interupt generator, it would not produce any output as it would be stuck in a loop waiting for inputs and an interupt. However, thanks for the suggestions which I will follow up. BTW should I declare as volatile any boolean status flag that is being modified in multiple functions?
Also, prompted by paulS' by line about asking good questions I'm thinking I need to approach this differently and frame a question that seeks confirmation or otherwise of the correctness of the premis upon which my arithmetic is based. That way you guys may be able to point out the error in my thinking.

noOfSamples can = 0. Thats a good point that I had not thought of, and it can only happen in the case of no in or out of phase current, not the voltage. Incidentally, under conditions that would cause this, sumOfSqrSamples would also be 0 meaning I'm trying to take the square root of 0/0. I'll clearly need to trap that condition.
Thanks for the help arduarn.

meaning I'm trying to take the square root of 0/0.

What IS the square root of not a number?