Condence Termister to yeild a decimal number or a text result

The project I am working on project that is a arduino temperature logger (to sd card) and uploadeder to a website (google chart)

I can read the sensor just fine. And using ‘double Thermister’ loop, am able to convert the 0-1024 value to a Fahrenheit value.

#include <math.h>

double Thermister(int RawADC) {
  double Temp;
  Temp = log(((10240000/RawADC) - 10000));
  Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp );
  Temp = Temp - 273.15;            // Convert Kelvin to Celcius
  Temp = (Temp * 9.0)/ 5.0 + 32.0; // Convert Celcius to Fahrenheit
  return Temp;
}

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println(float(Thermister(analogRead(0))));  // display Fahrenheit

}

The problem is. If the value is 0 (no sensor is attached) the ‘double Thermister’ will return an empty ‘nul’ (nothing exists) value. When this data is uploaded to the website, the chart crashes because it doesn’t know what to do with the ‘nul’. DO note. chart will accept the text “null” as a value and will work just fine.

So my first solution to this was: In the ‘double Thermister’ loop, I first ask if the raw value of the analog sensor in question is 0. If so, I thought I could have it return the text value “null”. This does not work:

double Thermister(int RawADC) {
  double Temp;
  if (RawADC == 0) {
    return "null";
  }
  Temp = log(((10240000 / RawADC) - 10000));
  Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp )) * Temp );
  Temp = Temp - 273.15;            // Convert Kelvin to Celcius
  Temp = (Temp * 9.0) / 5.0 + 32.0;
  return Temp;
}

Because this is a ‘Double’ It needs to have a number value. It will not accept text.

So my next work around for this is to give it a number value that the sensor would not normally read. In my case the value -500.00 works. So I plugged it in.

double Thermister(int RawADC) {
  double Temp;
  if (RawADC == 0) {
    return -500.00;
  }
  Temp = log(((10240000 / RawADC) - 10000));
  Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp )) * Temp );
  Temp = Temp - 273.15;            // Convert Kelvin to Celcius
  Temp = (Temp * 9.0) / 5.0 + 32.0;
  return Temp;
}

I then have to return to the original Serial.print, and force it to an if/then statement before print out the result.

if (float(Thermister(analogRead(0))) == -500.0)  Serial.print("null");
  else Serial.print(float(Thermister(analogRead(0))));

And all works fine. That is the simple version of my code. The issue I have is I have 7 sensors (so far). And this action occurs on various occasions. When Serial.print wants to view the values. When SD.Write wants to write the values to the SD card (myfile.println), and when Ethernet. wants to view the values and client.print them.

This is an overwhelming amount of extra code and I a trying to figure out how I can condence the code. Or better said, Modify the ‘double Thermister’ loop to be able to return a decimal value or “null”

My thinking would be:

Serial.println(Sensor_result(2))

^ this would go to the Sensor_result loop with the value of 2 (representing which sensor we want to read.

char Sensor_result() {
- Would now plug that sensor you want to read into a float(Thermister(analog(#)) space.
- The 'double Thermistor' loop would run, returning either -500.00 or a Fahrenheit value ( ex: 75.24)
- Now it would look at the return value of 'double Thermistor' and check to see if it is -500.00
- If it is -500.00 it would change the result to text "null". If not it would leave it alone as 75.24
- This would return with either "null" or 75.24
}

Serial.println could now print out either "null" or 75.24 for analog input sensor 2


> this could also return a result for client.print, or myfile.print

I am asking for suggestions on how I could build a loop that would accomplish this and be able to ‘return’ with a alphanumaric value to insert in the Sensor_result spot for the sensor it was requesting.

If the value is 0 (no sensor is attached) the 'double Thermister' will return an empty 'nul' (nothing exists) value.

Seems to me this is the root of the problem. Why are you trying to read a sensor that doesn't exist? A starting question should be: How do I avoid reading a non-existent sensor.

The problem is. If the value is 0 (no sensor is attached) the ‘double Thermister’ will return an empty ‘nul’ (nothing exists) value.

No, it returns a value that prints as not a number. Look at where rawADC is used in the function. The first operation is to divide a number by rawADC. Division by 0 is a colossally bad idea.

Or better said, Modify the ‘double Thermister’ loop to be able to return a decimal value or “null”

The function does not have to return a double. It could, since what you really seem to want is a string, return a boolean and store a string representation in an array that is passed in.

bool Thermistor(int rawADC, char *str)
{
   if(rawADC == 0)
   {
      strcpy(str, "dumbass");
      return false;
   }
   else
   {
      // Get the value as a float...
      dtostrf(theFloat, 8, 2, str);
      return true;
   }
}

Then, call the function:

char buffer[20];
if(Thermistor(analogRead(0), buffer))
{
   // Log the data (in buffer), since it's good
}

PaulS:

Trying the way you are suggesting, But I am resulting in either a 1 or 0 result when it serial.println’s.

#include <math.h>

float floatVal = 123.23;
char buffer[20];

double Thermister(int RawADC) {
  double Temp;
  Temp = log(((10240000 / RawADC) - 10000));
  Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp )) * Temp );
  Temp = Temp - 273.15;            // Convert Kelvin to Celcius
  Temp = (Temp * 9.0) / 5.0 + 32.0; // Convert Celcius to Fahrenheit
  return Temp;
}

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.print(analogRead(0));
  Serial.print(" , ");
  Serial.print(float(Thermister(analogRead(0)))); 
  Serial.print(" | ");
  Serial.print(analogRead(1));
  Serial.print(" , ");
  Serial.println(float(Thermister(analogRead(1))));

  Serial.println(Thermistor(analogRead(0), buffer));
  Serial.println(Thermistor(analogRead(1), buffer));
  delay(2000);
}

bool Thermistor(int rawADC, char *str)
{
  if (rawADC == 0)
  {
    strcpy(str, "dumbass");
    return false;
  }
  else
  {
    // Get the value as a float...
    // dtostrf(floatVal, 8, 2, str);
    dtostrf(Thermister(rawADC), 8, 2, str);
    return true;
  }
}
  Serial.print(float(Thermister(analogRead(0))));

A float and a double are the same size. The cast is useless.

Trying the way you are suggesting

I did not suggest printing the boolean value that the function returns.

PaulS, I kinda got the jist of what you are suggesting. But that is just returning a true and false statement as you said. Either way, you are still sticking me with an IF in the serial.print line.

as seen here:

if(Thermistor(analogRead(0), buffer))
{
// Log the data (in buffer), since it’s good
}

I need it to give me either a temperature value (ex: 75.24) or give me the text “null”

When this data gets written to SD or uploaded. a ‘non existent’ number/text will NOT work. There needs to be something printed.

is the sensor not available because it is not connected at all or because of a malfunction?

in the latter case one could use the last received value (sort of cache).

eqrunner: PaulS, I kinda got the jist of what you are suggesting. But that is just returning a true and false statement as you said. Either way, you are still sticking me with an IF in the serial.print line.

as seen here:

I need it to give me either a temperature value (ex: 75.24) or give me the text "null"

When this data gets written to SD or uploaded. a 'non existent' number/text will NOT work. There needs to be something printed.

The function should store the temperature as a string in some global array.

The true false is just there so the function can let you know if it put a valid value in that array or not. So you'll know if it is worth while to read and print it out.

I am using google charts to draw a line chart. The arduino writes all the sensors values to an sd card file every minute. in the format of [HH,mm,ss], sensor00, sensor01, sensor02, sensor03, sensor04, sensor05, sensor06

to insure the chart works, I need make sure there is a value for each sensor.

An example of code would be the following:

[[11,47,01], 74.13 , 74.61 , 74.13 , 73.65 , 73.81 , null , 73.34 ],
[[11,48,01], 74.61 , 75.24 , 74.76 , 73.81 , 73.97 , null , 73.81 ],
[[11,49,01], 74.13 , 74.61 , 73.97 , 73.65 , 73.65 , null , 73.18 ],
[[11,50,01], 74.61 , 75.24 , 74.61 , 73.81 , 73.97 , null , 73.65 ],
[[11,51,01], 74.29 , 74.92 , 74.45 , 73.81 , 73.97 , null , 73.49 ],
[[11,52,01], 74.45 , 75.24 , 75.24 , 74.29 , 74.45 , null , 73.81 ],
[[11,53,01], 74.29 , 75.08 , 74.92 , 74.61 , 74.61 , null , 73.49 ],
[[11,54,01], 74.92 , 75.72 , 75.40 , 75.24 , 74.92 , 81.89 , 73.81 ],
[[11,55,01], 74.76 , 75.56 , 75.24 , 74.61 , 74.76 , 81.04 , 73.81 ],
[[11,56,01], 74.29 , 74.76 , 74.61 , 74.29 , 74.45 , 81.04 , 73.65 ],
[[11,57,01], 74.61 , 75.24 , 74.92 , 74.29 , 74.45 , 81.04 , 73.97 ],
[[11,58,01], 74.76 , 75.40 , 74.92 , 74.45 , 74.61 , 81.04 , 73.81 ],
[[11,59,01], 74.45 , 75.24 , 74.76 , 74.29 , 74.45 , 81.04 , 73.65 ],
[[12,00,01], 74.61 , 75.24 , 74.92 , 74.45 , 74.45 , 81.04 , 73.81 ],
[[12,01,01], 74.45 , 75.24 , 74.92 , 74.45 , 74.45 , 81.04 , 73.65 ],

The above section shows that at one point, sensor05 did not exist. (To simulate a real world senerio) So the arduino writes 'null' there. If I left this empty, it would mess up the line chart causing the chart to fail to load.

robtillaart: is the sensor not available because it is not connected at all or because of a malfunction?

in the latter case one could use the last received value (sort of cache).

That is is not the point. I don't want it to show the last received value either. The temperature being read is critical. If the sensor has failed and continues to show that the temp is 80° for the past hour, when in reality the sensor failed, and the temp has dropped 20°. Then the arduino is a failure for producing false data. google charts will understand a 'null' and will just leave that spot on the chart blank. This will help verify that there is a problem.

But we have now gotten away from the original point of this post. It is not about why the sensor is broken or not. But how I could write a section of code that I can plug a number for the sensor into, have it see if the sensor is reading a value of 0,if so, return with a "null" value. If it is between 1 and 1024, then run the Thermisiter loop to calculate the sensors reading into a Farhiehight value that can then be used to println.

You've got the answer right up there.

Your function returns a double. But you're writing it to an SD card. You're not writing the actual number itself, but an ascii representation of the number. That means that at some point your number is being turned into a string and written to the SD card. If you do that step yourself, then you can substitute any string you want.

So you can either do it as PaulS suggested and let the function that now returns a double instead build the string and return you a boolean to let you know if it was any good or not.

Or you can leave the numbers as doubles and when you are ready to write to the SD card (or wherever else) check if the number is -500.0 and if it is write "null" instead of writing the number.

I don't get what part of that is confusing you.

Delta_G,

What is confusing to me is when I tried using PaulS's code, I get a True or False statement. Not a "null" or temperature value.

I am confused on how it is to be used in my code, as seen by the #3 post from me with the current code. I am confused about what a strcpy does, and how to use the new dtostrf used in his code.

Yes I have googled these actions, but have not been able to grasp my mind around how they are suppose to work, since I have been unable to find any examples that would relate to the objective I am trying to complete.

Along with If I use PaulS's if statment in his second haft of code. this defeats the whole purpose of trying to remove the if statments from each line I need to print.

if(Thermistor(analogRead(0), buffer))
{
   // Log the data (in buffer), since it's good
}

I am already doing this:

if (float(Thermister(analogRead(0))) == -500.0)  Serial.print("null");
  else Serial.print(float(Thermister(analogRead(0))));

So his way is just a different way to do so, it is not simplifying it.

Right, have you not been reading the replies here?

Let me see if I can explain PaulS solution a little simpler. It’s not going to return ANYTHING related to the temperature or anything you’re going to write to an SD card.

Imagine you had me with a thermometer and I was measuring the temperature and reporting numbers back to you by writing them on a card and handing them to you. So I am your function, the card is some global array where the string goes. But how do you know when I hand you a card that it has a new reading on it and not just some drivel a wrote because I couldn’t read the temp at that point.

SO maybe I tell you as I hand you the card. This one is good, use it, log it. This one is bad, chunck it and look for the next one. That’s the return value. It’s a true or false. Either the string was written or was not.

Your code has to look at that and decide whether or not to use the string. That string is not being returned, it’s a global array. It’s always going to be there. You can read it out and print it or send it to the SD card anytime you want. But it only makes sense to send it to the SD card if the function that filled the string tells you that it is a good one and it is time to log it.

So you’re not going to log what comes out of that function. You are going to use that return value to decide whether or not to log the global string that it created.

Like this:

if(thatFunction() == true){
   SD.print(theGlobalString);
}

If dtostrf and those other functions are confusing you, then look them up. Google “C++” and the name of the function you don’t know.

What is confusing to me is when I tried using PaulS's code, I get a True or False statement. Not a "null" or temperature value.

You ARE getting a string AND a boolean. If you don't care what the boolean value is, ignore it.

char buffer[20];
Thermistor(analogRead(0), buffer);
Serial.print("I don't care whether that worked or not. buffer contains: );
Serial.println(buffer);

Yes I have read over all the replies. And from what I can see, none of them are have the result I am looking for. Perhaps my way of thinking and my thought of how I wish for this to be accomplished is not in the 'normal' realm of coding for the arduino.

For the project that this is ultimately going to be used for has all this:

Ethernet:
client.print(" 
 ");
        if (float(Thermister(analogRead(0))) == -500.0)  client.print("null");
        else client.print(float(Thermister(analogRead(0))));
        client.print(" | ");
        if (float(Thermister(analogRead(1))) == -500.0)  client.print("null");
        else client.print(float(Thermister(analogRead(1))));
        client.print(" | ");
        if (float(Thermister(analogRead(2))) == -500.0)  client.print("null");
        else client.print(float(Thermister(analogRead(2))));
        client.print(" | ");
        if (float(Thermister(analogRead(3))) == -500.0)  client.print("null");
        else client.print(float(Thermister(analogRead(3))));
        client.print(" | ");
        if (float(Thermister(analogRead(4))) == -500.0)  client.print("null");
        else client.print(float(Thermister(analogRead(4))));
        client.print(" | ");
        if (float(Thermister(analogRead(5))) == -500.0)  client.print("null");
        else client.print(float(Thermister(analogRead(5))));
        client.print(" | ");
        if (float(Thermister(analogRead(6))) == -500.0)  client.print("null");
        else client.print(float(Thermister(analogRead(6))));

Serial Print:

  Serial.print("[[");
  Serial.print(time_format);  // should already be configured as HH,MM,SS
  Serial.print("], ");
  if (float(Thermister(analogRead(0))) == -500.0)  Serial.print("null");
  else Serial.print(float(Thermister(analogRead(0))));
  Serial.print(" , ");
  if (float(Thermister(analogRead(1))) == -500.0)  Serial.print("null");
  else Serial.print(float(Thermister(analogRead(1))));
  Serial.print(" , ");
  if (float(Thermister(analogRead(2))) == -500.0)  Serial.print("null");
  else Serial.print(float(Thermister(analogRead(2))));
  Serial.print(" , ");
  if (float(Thermister(analogRead(3))) == -500.0)  Serial.print("null");
  else Serial.print(float(Thermister(analogRead(3))));
  Serial.print(" , ");
  if (float(Thermister(analogRead(4))) == -500.0)  Serial.print("null");
  else Serial.print(float(Thermister(analogRead(4))));
  Serial.print(" , ");
  if (float(Thermister(analogRead(5))) == -500.0)  Serial.print("null");
  else Serial.print(float(Thermister(analogRead(5))));
  Serial.print(" , ");
  if (float(Thermister(analogRead(6))) == -500.0)  Serial.print("null");
  else Serial.print(float(Thermister(analogRead(6))));
  Serial.println(" ],");

SD Card Write:

Serial.print("Writing to todays text file...");
    myFile.print("[[");
    myFile.print(time_format);  // should already be configured as HH,MM,SS
    myFile.print("], ");
    if (float(Thermister(analogRead(0))) == -500.0)  myFile.print("null");
    else myFile.print(float(Thermister(analogRead(0))));
    myFile.print(" , ");
    if (float(Thermister(analogRead(1))) == -500.0)  myFile.print("null");
    else myFile.print(float(Thermister(analogRead(1))));
    myFile.print(" , ");
    if (float(Thermister(analogRead(2))) == -500.0)  myFile.print("null");
    else myFile.print(float(Thermister(analogRead(2))));
    myFile.print(" , ");
    if (float(Thermister(analogRead(3))) == -500.0)  myFile.print("null");
    else myFile.print(float(Thermister(analogRead(3))));
    myFile.print(" , ");
    if (float(Thermister(analogRead(4))) == -500.0)  myFile.print("null");
    else myFile.print(float(Thermister(analogRead(4))));
    myFile.print(" , ");
    if (float(Thermister(analogRead(5))) == -500.0)  myFile.print("null");
    else myFile.print(float(Thermister(analogRead(5))));
    myFile.print(" , ");
    if (float(Thermister(analogRead(6))) == -500.0)  myFile.print("null");
    else myFile.print(float(Thermister(analogRead(6))));
    myFile.println(" ],");

    // close the file:
    myFile.close();

And I want to change them into something simpler. Aka, getting rid of the IF's in each of the sections.

You are going to have to spell it out to me, line by line for your versions of codes, cause I clearly am not understanding what each line is doing in your code.

In my vision, this should be simple.

Take for example a serial.println.

Currently it is this:

if (float(Thermister(analogRead(0))) == -500.0)  Serial.print("null");
  else Serial.print(float(Thermister(analogRead(0))));

Why can it not be changed to say:

Serial.print(FinalResult(0));

The 0 representing the sensor I want to use.

This now goes to (I don't apparently know) a void? a loop? a while? a bool? a double? a float? Where it will begin taking that value in the () of FinalResult and plugging it in.

which_Sensor = FinalResult(0)

// then would plug that in to

float(Thermister(analogRead(which_Sensor))

// Then it could run the "double Thermister"


// in... 
double Thermister (int RawADC) 
// 'RawADC' would equal 'which_Sensor'

// The 'double Thermister would then return here with either a -500.00 or a value 72.54

// When it returned, it now looks at that number

If (return'ed value = -500.00) then change FinalResult("null")
else then change FinalResult(72.54);

// This of course would bring it full circle to the original

Serial.print(FinalResult(0)); which would now = Serial.print(FinalResult(72.54));  which would be Serial.print(72.54)

Now I can use that same setup "FinalResult()" to plug in all my sensors. Reducing it to a single line each time.

Serial.print would now look like this:

Serial Print:

  Serial.print("[[");
  Serial.print(time_format);  
  Serial.print("], ");
  Serial.print(FinalResult(0))
  Serial.print(" , ");
  Serial.print(FinalResult(1))
  Serial.print(" , ");
  Serial.print(FinalResult(2))
  Serial.print(" , ");
  Serial.print(FinalResult(3))
  Serial.print(" , ");
  Serial.print(FinalResult(4))
  Serial.print(" , ");
  Serial.print(FinalResult(5))
  Serial.print(" , ");
  Serial.print(FinalResult(6))
  Serial.println(" ],");

I know in example for 'Double Thermister' the value in the () is carried over from the call to it from " Serial.print(Thermister(analogRead(0)));"

My question is: How can I do that, but have the return be either a number or a text?

bool, double, float are all for numbers only. I don't see how I could use a char for this. A void does not come back with a 'return'

eqrunner: Perhaps my way of thinking and my thought of how I wish for this to be accomplished is not in the 'normal' realm of coding for the arduino.

I think you're right about that.

For the project that this is ultimately going to be used for has all this:

Ethernet:
client.print(" 
 ");
        if (float(Thermister(analogRead(0))) == -500.0)  client.print("null");
        else client.print(float(Thermister(analogRead(0))));
        client.print(" | ");
        if (float(Thermister(analogRead(1))) == -500.0)  client.print("null");
        else client.print(float(Thermister(analogRead(1))));
        client.print(" | ");
        if (float(Thermister(analogRead(2))) == -500.0)  client.print("null");
        else client.print(float(Thermister(analogRead(2))));
        client.print(" | ");
        ( ...and so forth )

Why not use a loop instead?

My question is: How can I do that, but have the return be either a number or a text?

You can't. You have to pick one or the other, and stick to it.

eqrunner:
bool, double, float are all for numbers only. I don’t see how I could use a char for this. A void does not come back with a ‘return’

You can’t. You get one return value and one type for it. I guess you could create a class and return that and do whatever you want with it, but that’s just wasteful. Certainly a lot more wasteful than an if statement. I get that you don’t like if statements for some reason, but that’s how it gets done.

If you don’t like having to write the same if statement over and over, use a for loop and write it once. That’s a whole lot easier than what you’re going through now.

If statements to me are fine. But I feel like they use up a lot of extra space when a redundent task is used, and only a single number or letter is changed.

I will see what I can do with a while loop and see if that helps remove some of the excess code.