I have a simple program, I create a float array with 4 elements as a global variable and then at one point in the program I try to do different math functions i.e.
float temp = 5;
myArray[0] += temp;
But when I look using Serial.println(myArray[0]); it's always equal to zero.
The follow code
float temp = 5;
myArray[0] = temp;
will show that myArray[0] does equal 5 like you would expect and
myArray[0] = 5;
float temp = myArray[0];
Will also equal 5, but as soon as I do something like
My gut tells me that my array is not behaving like I think it should. That somehow instead of telling it to equal the actual value in myArray[0], I'm telling it to equal the memory location, and when I tell it to add 5 I'm moving it 5 indexies down the array line to some random memory address (which coincidently is zero). Can someone point me in the right direction here to make sure that I'm accessing the actual value stored in a specific index?
#include <Wire.h>
#include <math.h>
#define I2C_ADDR 0x03 // Set I2C Address of Arduino
#define NUM_PROBES 2 // The maximum number of probes connected to the Arduino
#define PROBE1 14 // The One Wire Pin used for Probe 1
#define PROBE2 15 // The One Wire Pin used for Probe 2
#define COMMINTERVAL 140 // Time to wait in seconds before assuming there is a comm failure
float Temperature[2*NUM_PROBES]; // Each Probe stores two temperatures C and F
int CommCheck = 0; // used to check comm status between Arduino and Raspbery Pi
unsigned long LastComm = 0; // time (in millis) that last comm occured
int scanCount = 0; // Number of scans between readings, used to average temperature readings
int CommCounter = 0;
// Prepare program
void setup()
{
Serial.begin(9600);
Wire.begin(I2C_ADDR);
Wire.onRequest(requestEvent); // Register i2c request handler
for (int x = 0; x < 4; x++){
Temperature[x] = 0;
}
}
// Main program area
void loop()
{
delay(250);
commCheck();
getTemp();
delay(5000);
}
// Function sends current conents of temperature readings
void requestEvent()
{
for (int x = 0; x < (NUM_PROBES*2); x++) {
Temperature[x] /= scanCount;
Serial.print("Temp #");Serial.print(x);Serial.print(": ");Serial.println(Temperature[x]);
}
Wire.write((byte*) &Temperature[0], 2*NUM_PROBES*sizeof(float));
CommCounter += 1;
if (CommCounter >= 32766) {
CommCounter = 0;
}
LastComm = millis();
scanCount = 0;
// Make sure all values are zero at the beginning of each loop
for (int i = 0; i<4; i++)
{
Temperature[i] = 0.0;
}
}
// Gets current values from temperature ADC and converts reading to temperature
void getTemp()
{
float p1TempC = 0.0;
float p2TempC = 0.0;
p1TempC = 25.0;
float tempTemp = Temperature[0];
tempTemp += p1TempC;
Temperature[0] = tempTemp;
Temperature[1] += (p1TempC*1.8)+32;
Temperature[2] += p2TempC;
Temperature[3] += (p2TempC*1.8)+32;
for (int x = 0; x < 4; x++){
Serial.println(Temperature[x]);
}
scanCount += 1;
}
// Basic check to see if communications are working between pi and arduino
// Does not check to see if data is actually transferred or if data is corrupted
void commCheck() {
// Get the current up time, millis represents milliseconds elapsed since the arduino was turned on,
// it reaches its max value and rolls over back to 0 approximately every 49 days.
unsigned long currentTime = millis();
// Check to see if milliseconds have rolled over to zero since the last comm occured
if (currentTime < LastComm) {
LastComm = currentTime;
}
Serial.println(LastComm);
Serial.println(currentTime);
// If the CommCheck does not equal the CommCounter then there was a comm request, update the CommCheck variable
if (CommCheck != CommCounter) {
CommCheck = CommCounter;
// Otherwise, check to see if the time between comms has been greater than the comm time out variable
} else {
if ((currentTime - LastComm) > (COMMINTERVAL * 1000)) {
} else {
}
}
}
Wire.onRequest(requestEvent); // Register i2c request handler
...
// Function sends current conents of temperature readings
void requestEvent()
{
for (int x = 0; x < (NUM_PROBES*2); x++) {
Temperature[x] /= scanCount;
Serial.print("Temp #");Serial.print(x);Serial.print(": ");Serial.println(Temperature[x]);
}
Don't do serial prints inside an ISR.
float Temperature[2*NUM_PROBES]; // Each Probe stores two temperatures C and F
Since you share Temperature between and ISR and a not-ISR it should be declared volatile.
for (int x = 0; x < 4; x++){
Temperature[x] = 0;
}
Prefer:
for (int x = 0; x < (2*NUM_PROBES); x++){
Temperature[x] = 0;
}
Actually Nick, don't worry about it, the statement you made about it acting like the values where NAN, got me looking through my code and yes, at one point I had accidentally set my array to empty data. I know it doesn't show it in the code, but like I said I had to type it in (I'm not able to copy/paste it from the IDE with the way things are set up between this computer and where I'm developing) and I missed that line :-[
What I did to fix this problem, was to add a simple isnan(p1TempC) check before doing all my math stuff and it started working the way you'd expect. Thanks so much!
Because the end application will be I take a set of readings from some probes and the code here is just me fleshing things out and testing functionality. If I ask for a temperature reading and it doesn't have one yet (such as in the event of an initial power on) I don't want a bunch of bad data messing up my code. So a simple isnan check confirms that the data is at least not blatantly bad.
abishur:
... at one point I had accidentally set my array to empty data. I know it doesn't show it in the code, ...
A while back we noticed that NaN was printing as zero, and suggested that the library be changed to show NaN and Inf where applicable. That early version of the IDE probably does not do that.
Egads...I do both of those! I understand when it's zero, but doing it consistently makes you also do it when the constant is non-zero; something that can cause problems in mixed-type expressions. I also do explicit casts when the compiler will do a silent cast for me. And, as I said before, such things do document your intentions.
I'm wary of unnecessary explicit casts, because one day you will cast something to a type you didn't mean, and you have just done away with a compiler warning or error.