I am writing a program that reads a temperature from a wireless sensor and then takes the temperature value read and performs calculations on that temperature. So, for example, The sensor reads a value of 75 degress F and then I plug this value into the equation...
float e = 2.718281828459;
long int Thermistor_val;
int Ctemp=75;
Thermistor_val=24658*pow(e,(-0.027*Ctemp));
This works for many passes of the program. I then let this run overnight and when I checked on it in the morning I see that the Thermistor_val variable is at FFFF and stays there. If I restart the program again all is reset and the values look good. My question is, what condition would cause the value of Thermistor_val to go to FFFF and stay there? Is this caused by an overflow condition?
I need to point out that the Ctemp value, in the actual program, is a calculated value. I suppose Ctemp could be actually a bad value that is causing Thermistor_val to be calculated incorrectly. However when I stopped the program from running the only value that seemed bad was Thermistor_val. Is the way to get around this error to check all values before a calculation is performed to ensure that they are within an acceptable range? Right now my code "works" at least for many of the passes. What I am trying to do is make is more robust to avoid these 'bad data' situations. Any suggestions would be appreciated. Note, I am relatively new to serious error handling in programs.
... I see that the Thermistor_val variable is at FFFF and stays there. If I restart the program again all is reset and the values look good. My question is, what condition would cause the value of Thermistor_val to go to FFFF and stay there? Is this caused by an overflow condition?
Is it exactly FFFF (0x0000FFFF) or 0xFFFFFFFF?
Originally Posted by mikenycz
I need to point out that the Ctemp value, in the actual program, is a calculated value. I suppose Ctemp could be actually a bad value that is causing Thermistor_val to be calculated incorrectly.
So could it happen that Ctemp was some big negative value?
And how does your actual code look like?
Ctemp should be between 60 and 80 right now (I'm measuring temperatures in the room). The value for Ctemp is derived from an IEEE-754 encoded value that is sent by the temperature sensor. One possibility is that the IEEE-754 value received is bad or corrupted and so the calculation of Ctemp gets a bad value. What I was going to try was checking the results of all computations leading up to Ctemp to verify that the result is in an acceptable range. If it is not, throw out the bad data and wait for another value to be sent by the sensor.
The one question that I have is, if one of the variables does get an overflow value, does that invalidate any future results or can the overflow be reset inside of the program?
VictorN.. You asked about the code... I have attached the program to this post. The calculation section looks like this...
if (Bin_Buff[0] == '0') {
// Calculate exponent value of IEEE 754 number
Cexp = calc_exp(Bin_Buff);
//Calculate normalized exponent value of IEEE 754 number
Aexp = Cexp-127;
//Add "hidden 1 bit" to Temperature_bin
Temperature_bin[0]='1';
//Add bits past decimal point to Temperature_bin
for (i=9;i<=(8+Aexp);i++) {
Temperature_bin[i-8]=Bin_Buff[i];
}
//Calculate Temperature in Deg F
Ctemp = calc_temperature(Temperature_bin,Aexp);
//Plug Temp into equation to get equivalent Thermistor value
//This equation was derived empirically from one of the FA7226 sensors
Thermistor_val=24658*pow(e,(-0.027*Ctemp));
//Convert Thermistor_val to hex values needed for message
int junk2;
int junk = Thermistor_val;
char Thermistor_hexlo = junk;
for (i=0;i<=7;i++) {
junk2 = (junk >> 8);
}
char Thermistor_hexhi = junk2;
Here is the calc_exp() routine...
int calc_exp(unsigned char *input)
{
int power2=0;
int output=0;
int i;
for (i=1;i<=8;i++) {
if (input[i] == '1') {
switch (8-i) {
case 0: power2 = power2 +1;
break;
case 1: power2 = power2 +2;
break;
case 2: power2 = power2 +4;
break;
case 3: power2 = power2 +8;
break;
case 4: power2 = power2 +16;
break;
case 5: power2 = power2 +32;
break;
case 6: power2 = power2 +64;
break;
case 7: power2 = power2 +128;
break;
}
output=power2;
}
}
return output;
}
And here is the calc_temperature() routine.....
int calc_temperature(unsigned char *input, int length)
{
int power2=0;
int output=0;
int i;
for (i=0;i<=(length);i++) {
if (input[i] == '1') {
switch (length-i) {
case 0: power2 = power2 +1;
break;
case 1: power2 = power2 +2;
break;
case 2: power2 = power2 +4;
break;
case 3: power2 = power2 +8;
break;
case 4: power2 = power2 +16;
break;
case 5: power2 = power2 +32;
break;
case 6: power2 = power2 +64;
break;
case 7: power2 = power2 +128;
break;
//Find temperature using IEEE 754 format
if (Bin_Buff[0] == '0') {
// Calculate exponent value of IEEE 754 number
Cexp = calc_exp(Bin_Buff);
//Calculate normalized exponent value of IEEE 754 number
Aexp = Cexp-127;
You are using Aexp as a size of byte array calling then
Code:
//Calculate Temperature in Deg F
Ctemp = calc_temperature(Temperature_bin, Aexp);
But are you sure that calc_exp(Bin_Buff) will always return you the value >= 127?
If the IEEE-754 value is good then the answer is yes. The uncertainty is whether the value passed to calc_exp is good. Since this is wireless data being received via an RS232 connected receiver, if the data is corrupted during translation I could possibly get a bad value in Bin_Buff that would generate an erroneous Cexp. I should probably check the value of Cexp prior to using it. Thank you for the pointer. I'll look more closely at all calculated values to ensure they are in the expected range.
But my question remains... If a variable overflows during program execution, can I recover from the overflow during program execution or do I need to find out the reason for the overflow and prevent it from happening in the first place?
... I should probably check the value of Cexp prior to using it. Thank you for the pointer. I'll look more closely at all calculated values to ensure they are in the expected range.
Yes, you have to.
Originally Posted by mikenycz
... But my question remains... If a variable overflows during program execution, can I recover from the overflow during program execution or do I need to find out the reason for the overflow and prevent it from happening in the first place?
Sorry, I don't know. You should read the documentation of your c++ compiler + run-time library.
But my question remains... If a variable overflows during program execution, can I recover from the overflow during program execution or do I need to find out the reason for the overflow and prevent it from happening in the first place?
Depends on your compiler, runtime, CPU floating point handling and if CPU, certain CPU flags that control what happens when a "bad" FP calculation occurs.
For example, the Intel processors will mask floating point errors if a certain aspect of the processor is turned on/off. See functions such as _control87 for the Intel processors.
typically speaking... your program must be written in such a way that it properly handles ALL POSSIBLE VALUES (even extremes) that could be given as input. How to handle "exceptional" values is up to you.
Any time you get an input your program was not designed to handle "anything" may happen.
This is true for all programs out there, you're "Lucky" in that you can typically establish valid ranges the hardware will produce.
handling user input where they can type just anout anything and click just about anywhere in any order typically is a lot more complex.
it's not unusual to find a program has less code devoted to actual work, and more code in input processing/erroneous input handling.
typically speaking... your program must be written in such a way that it properly handles ALL POSSIBLE VALUES (even extremes) that could be given as input. How to handle "exceptional" values is up to you.
Any time you get an input your program was not designed to handle "anything" may happen.
This is true for all programs out there, you're "Lucky" in that you can typically establish valid ranges the hardware will produce.
handling user input where they can type just anout anything and click just about anywhere in any order typically is a lot more complex.
it's not unusual to find a program has less code devoted to actual work, and more code in input processing/erroneous input handling.
OK, I've put in checks to verify that all values leading up to using the pow(x,y) function are behaving themselves. The program runs well for a long time.... However, every once in awhile (hours or more) I get a situation where pow() generates a huge value even though the input values (x and y) look reasonable. One thing that is still slightly off is that from the pow() definition it looks like the variables that it expects should be both double variable types. In my case, the one value that I am feeding it is a constant multiplied by an int variable (i.e. -.027*Ctemp where Ctemp is int). Will this inconsistency get me into trouble? It seems to work at least most of the time. Can this inconsistency create problems in the value that gets calculated?
OK, I've put in checks to verify that all values leading up to using the pow(x,y) function are behaving themselves. The program runs well for a long time.... However, every once in awhile (hours or more) I get a situation where pow() generates a huge value even though the input values (x and y) look reasonable.
If the program you're running is anything like the program you posted previously, then there are some things that look suspicious.
Code:
int calc_temperature(unsigned char *input, int length)
{
int power2=0;
int output=0;
int i;
for (i=0;i<=(length);i++) {
if (input[i] == '1') {
Whenever I see a <= as an upper bound of a loop, and the loop variable is used as an index into an array, a red flag goes off. Are you overstepping the boundaries of the array here, causing a memory overwrite? You do this in other places also.
Let's see how you're calling these functions, not just the functions themselves.
If the program you're running is anything like the program you posted previously, then there are some things that look suspicious.
Code:
int calc_temperature(unsigned char *input, int length)
{
int power2=0;
int output=0;
int i;
for (i=0;i<=(length);i++) {
if (input[i] == '1') {
Whenever I see a <= as an upper bound of a loop, and the loop variable is used as an index into an array, a red flag goes off. Are you overstepping the boundaries of the array here, causing a memory overwrite? You do this in other places also.
Let's see how you're calling these functions, not just the functions themselves.
Regards,
Paul McKenzie
The code where these functions are called is shown in a previous part of this thread. However, I have made some additional changes that check the inputs into the functions. I will post them below....
if (Input_Buff1[1] == 0x1a){
for (bytenum=0;bytenum<=3;bytenum++){
single_byte = Input_Buff1[14+bytenum];
charbytetostring(single_byte,temp_bin_buff);
for (j=0;j<=7;j++) {
Bin_Buff[j+8*bytenum] = temp_bin_buff[j];
}
}
//Find temperature using IEEE 754 format
if (Bin_Buff[0] == '0') {
// Calculate exponent value of IEEE 754 number
Cexp = calc_exp(Bin_Buff);
//Calculate normalized exponent value of IEEE 754 number
Aexp = Cexp-127;
// Check Aexp value
if (Aexp <0 || Aexp >=8) {
clear_buffers();
Aexp=0;
break;
}
//Add "hidden 1 bit" to Temperature_bin
Temperature_bin[0]='1';
//Add bits past decimal point to Temperature_bin
for (i=9;i<=(8+Aexp);i++) {
Temperature_bin[i-8]=Bin_Buff[i];
}
//Calculate Temperature in Deg F
Ctemp = calc_temperature(Temperature_bin,Aexp);
//Check calculated temperature
if (Ctemp < -30 || Ctemp >120) {
clear_buffers();
Ctemp=0;
break;
}
//Plug Temp into equation to get equivalent Thermistor value
//This equation was derived empirically from one of the FA7226 sensors
expon = powl(e,(-.027*Ctemp));
Thermistor_val=24658*expon;
}
Prior to expon getting very large, the values of Aexp and Ctemp are what I expect them to be (i.e. Aexp = 6 and Ctemp = 71).
One thing that may be pertinent, The Ctemp variable is declared as int while expon and the powl() function use double. The question is, can the mixing of types in a calculation like this cause problems? Should I convert the Ctemp value to double before using it in the powl() function?
The code where these functions are called is shown in a previous part of this thread. However, I have made some additional changes that check the inputs into the functions. I will post them below....
Please format your code to use code tags, as the code you posted is practically unreadable:
When posting code, please format it properly first and use code tags. Go advanced, select the code and click '#'.
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
When posting code, please format it properly first and use code tags. Go advanced, select the code and click '#'.
Code:
if (Input_Buff1[1] == 0x1a){
for (bytenum=0;bytenum<=3;bytenum++){
single_byte = Input_Buff1[14+bytenum];
charbytetostring(single_byte,temp_bin_buff);
for (j=0;j<=7;j++) {
Bin_Buff[j+8*bytenum] = temp_bin_buff[j];
}
}
//Find temperature using IEEE 754 format
if (Bin_Buff[0] == '0') {
// Calculate exponent value of IEEE 754 number
Cexp = calc_exp(Bin_Buff);
//Calculate normalized exponent value of IEEE 754 number
Aexp = Cexp-127;
// Check Aexp value
if (Aexp <0 || Aexp >=8) {
clear_buffers();
Aexp=0;
break;
}
//Add "hidden 1 bit" to Temperature_bin
Temperature_bin[0]='1';
//Add bits past decimal point to Temperature_bin
for (i=9;i<=(8+Aexp);i++) {
Temperature_bin[i-8]=Bin_Buff[i];
}
//Calculate Temperature in Deg F
Ctemp = calc_temperature(Temperature_bin,Aexp);
//Check calculated temperature
if (Ctemp < -30 || Ctemp >120) {
clear_buffers();
Ctemp=0;
break;
}
//Plug Temp into equation to get equivalent Thermistor value
//This equation was derived empirically from one of the FA7226 sensors
// expon = powl(e,(-.027*Ctemp));
expon = exp(-.027*Ctemp);
Thermistor_val=24658*expon;
// Thermistor_val=24658*pow(e,(-0.027*Ctemp));
//Convert Thermistor_val to hex values needed for message
int junk2;
int junk = Thermistor_val;
char Thermistor_hexlo = junk;
for (i=0;i<=7;i++) {
junk2 = (junk >> 8);
}
char Thermistor_hexhi = junk2;
//Check Thermistor hex values
char bad_data = 0xff;
if (Thermistor_hexhi == bad_data && Thermistor_hexlo == bad_data) {
clear_buffers();
Thermistor_val=0;
Thermistor_hexhi = 0x00;
Thermistor_hexlo = 0x00;
expon = 0;
while(1){}
break;
}
* The Best Reasons to Target Windows 8
Learn some of the best reasons why you should seriously consider bringing your Android mobile development expertise to bear on the Windows 8 platform.