Temperature to pressure

Since @johnerrington was kind enough to enter the data into Excel and generate a formula (see post #25), YOU don't have to mess with Excel, unless you need to go higher than 3 bar[*].

Look at the graph in post #25.

See the formula along the 3 bar line: P=blah blah blah?

P = gauge pressure
t = temp (deg C)

t2 = temperature squared; i.e., use t times t in your calculator or code

Edit: since P is very sensitive to t2, the first constant, 0.0009, should have more significant digits. Use this instead: 0.00085399

As a test, use your hand-held calculator to compare values from that formula to the ones in your TLV website.

If you are satisfied that they are close enough (and I'll eat my hat if they aren't), then use that formula in your code.

[*] or, if your high pressure is considerably smaller than 3, then it may be worth revisiting Excel, or use any of the available online calculators, such as https://arachnoid.com/polysolve/

Edit to add note about number of significant digits, and the following (using same data as @johnerrington):
image
and an even better fit:
image

1 Like

No. Do you now want to calculate the pressure in a sausage? Or cook sausages inside a coffee boiler at 45PSI?

Youve wasted a lot of contributors time on a nonsense made up project and you dont have the science knowledge to understand the answers youve been given.

MHBFY

Enjoy your sausages.

You only forgot to mention the fit given by @johnwasser in post #28, which might be more accurate and/or valid over a wider temperature range...

Maybe. Those natural logs, tho'...

image

I dont think a quadratic works too badly! R^2 = 0.9999; although EXCEL has rounded the multiplier for t^2.

In Libre office calc I see

image

Or if you want a fourth order

That’s unfortunately for the global fit but the devil is in the details. What’s the error distribution and Max error ?

If I’m not mistaken For t=100 we get 9 - 14,06 + 5.5388 = 0.4588 which is quite far from 0

HI JML; yes maybe the error is the rounding error in EXCEL - and I couldnt get it to display more figures!
Bring back my slide rule!

yes, even if you get 10 digits in excel (just press the image icon) that will be the challenge also with the poor float approximation (~6 digits) on a UNO as there is no double. when you start multiplying something by 10,000 or 100,000 (in case of x3 equation), the 6th or 7th decimals starts making lots of sense

You could take
P = 0.0000000142 T4 − 0.0000014978 T3 + 0.0001259751 T2 − 0.0007773431 T − 1.1036810629

it gives you

R2 = 0.9999999588 or Adjusted R2 = 0.9999999567

so pretty good but the standard error is still at 0.1705598045 and residual is pretty scattered

residual_plot

(math curtesy of online Polynomial Regression Calculator)

Which probably proves that the differences are caused by measurement errors and not by the fitted function...

No. Do you now want to calculate the pressure in a sausage? Or cook sausages inside a coffee boiler at 45PSI?

Youve wasted a lot of contributors time on a nonsense made up project and you dont have the science knowledge to understand the answers youve been given.

Apologies if people feel like they have wasted their time, that was not the intention.
Fortunately eventually johnwasser answered the question I was asking in post#32 and further more, J-M-L has been great in providing a great solution regarding the lookup table.
The project is not nonsense and made up, it is an alternative way to the task we already do and if the figures supplied to us do not match those provided by a formula then it will not be accepted.
I am at a loss as to how any project made up or not would not be welcomed on this site, after all surely the forum is about welcoming and encouraging people to get into the hobby/subject.
I resorted to the "sausage" explanation, to simplify the question being asked rather than getting explanations of how people thought it was iffy, dangerous or not up to their liking. It was obviously causing confusion and cooking sausages might have been more within their understanding.

I really appreciate the lengths people have gone to with this, including trying to solve a formula.

As the lookup table works exactly as intended, I have decided to go with this solution.

I am now trying to work out how the lookup table works.
I Think I have managed to get the code to use my temperature readings from the sensor and display both the temp and pressure in the serial monitor... I am now trying to work out how to display the pressure on the LCD display.
Also I'm trying to work out how it references the temperature to the pressure (eg. when at 100deg C it looks up the table and returns 0.00)
If I can work that out, I can hopefully change the figures to test the system at lower temperatures to prove the system is working.

Once again I apologise if I have made people feel like I have wasted their time and that I am not clever enough to work this out for myself... I have always been told that by both family and the education system, however I have never let that get in the way of trying to learn and improve my understandings.

that was exactly what that function was doing:

float pressureFromTemperature(long temp) {
  if (temp < 100) return TOO_COLD;
  if (temp > 160) return TOO_WARM;
  return pressure[temp-100]; // <=== LOOK HERE 
}

you have a sorted array (pressure) corresponding to pressure with a +1 increment starting at 100. So the pressure for temperature 100 is index 0, the pressure for temperature 101 is index 1, the pressure for temperature 102 is index 2, etc ➜ so the formula for the index is simply temp-100

Ah yes, I was just working the example through on the online Wokwi emulator. I had just sussed that when you put this up...

I don't understand what the" float TOO_COLD = -1.0f; float TOO_WARM = +10000.0f; " is/does...

I understand where the "100 deg C" set point to the table is now..
I also think the "void setup for (long" part starts the print at 98 the incrementally adds 1 until it reaches 163 using the ++.

Hopefully the more I work my way through exactly what is happening in the code, then I can "pull" the pressure reading to display on the LCD
I'm getting there very slowly!!!!

Thanks for your time.

I'm defining some constants values that will be returned in case it's too cold or too warm

  if (temp < 100) return TOO_COLD;
  if (temp > 160) return TOO_WARM;

(they should be declared const by the way with a meaningful comment )

const float TOO_COLD = -1.0f;      // add a meaningful comment
const float TOO_WARM = +10000.0f;  // add a meaningful comment

as the function always return a float. This way you can compare the returned value with those constants and decide what to display. (use <= and >= with float rather than == as precision might play tricks on you)
that's what I do there to print the result

  if (p <= TOO_COLD) Serial.println(F(" \t➜ too cold"));
  else if (p >= TOO_WARM) Serial.println(F(" \t➜ too warm"));
  else ...
1 Like

Okay, getting there...

This is the code I have done so far.. I suppose it's probably worth asking if I'm heading in the right direction... I don't want to head off down the wrong route..

#include <LiquidCrystal_I2C.h>
#include <Adafruit_MAX31865.h>

// Use software SPI: CS, DI, DO, CLK
Adafruit_MAX31865 thermo = Adafruit_MAX31865(10, 11, 12, 13);
// use hardware SPI, just pass in the CS pin
//Adafruit_MAX31865 thermo = Adafruit_MAX31865(10);

// The value of the Rref resistor. Use 430.0 for PT100 and 4300.0 for PT1000
#define RREF      4300.0
// The 'nominal' 0-degrees-C resistance of the sensor
// 100.0 for PT100, 1000.0 for PT1000
#define RNOMINAL  1000.0
//#define buzzer 7           //buzzer pin

LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x3F for a 16 chars and 2 line display

float TOO_COLD = -1.0f;
float TOO_HOT = +10000.0f;

const float pressure[] = {
  0.000, 0.038, 0.075, 0.114, 0.155, 0.196, 0.238, 0.282, 0.327, 0.373, // 100 ... 109
  0.421, 0.469, 0.520, 0.571, 0.624, 0.679, 0.734, 0.792, 0.851, 0.911, // 110 ... 119
  0.973, 1.037, 1.103, 1.170, 1.238, 1.309, 1.381, 1.456, 1.532, 1.609, // 120 ... 129
  1.689, 1.771, 1.855, 1.941, 2.029, 2.119, 2.211, 2.305, 2.402, 2.501, // 130 ... 139
  2.602, 2.705, 2.811, 2.919, 3.030, 3.143, 3.259, 3.377, 3.498, 3.622, // 140 ... 149
  3.748, 3.877, 4.009, 4.143, 4.281, 4.421, 4.564, 4.711, 4.860, 5.013, // 150 ... 159
  5.168                                                                 // 160
};

float pressureFromTemperature(long temp) {
  if (temp < 100) return TOO_COLD;
  if (temp > 160) return TOO_HOT;
  return pressure[temp-100];
}

void printPressureFor(long temp) {
  float p =  pressureFromTemperature(thermo.temperature(RNOMINAL, RREF)); //pressureFromTemperature(temp);
  Serial.print(F("T° = ")); Serial.print(temp);
  if (p <= TOO_COLD) Serial.println(F(" \t➜ Too Cold"));
  else if (p >= TOO_HOT) Serial.println(F(" \t➜ Too Hot"));
  else {
    Serial.print(F("\t➜ P = "));
    Serial.println(p, 3);
  }
}

void setup() {
  Serial.begin(115200);
  Serial.println("Adafruit MAX31865 PT100 Sensor Test!");
  lcd.init();
  lcd.clear();         
  lcd.backlight();      // Make sure backlight is on
  thermo.begin(MAX31865_3WIRE);  // set to 2WIRE or 4WIRE as necessary


void loop() {
  uint16_t rtd = thermo.readRTD();
  
  //Serial.print("RTD value: "); Serial.println(rtd);
  float ratio = rtd;
  ratio /= 32768;
  //Serial.print("Ratio = "); Serial.println(ratio,8);
  //Serial.print("Resistance = "); Serial.println(RREF*ratio,8);
  Serial.print("Temperature = "); Serial.println(); printPressureFor(thermo.temperature(RNOMINAL, RREF));

  lcd.clear();
  lcd.setCursor(0,0);   //Set cursor to character 0 on line 0
  lcd.clear();
      lcd.setCursor(0,0);     //Set cursor to character 2 on line 0
      lcd.print("Temp=  ");
      lcd.print(thermo.temperature(RNOMINAL, RREF));
      lcd.print((char)223);   //set Degrees symbol
      lcd.print("C");
      lcd.setCursor(0,1);
      lcd.print("Press= ");
      //lcd.print(???????);    //display reading of corrosponding pressure
      lcd.print("Bar");

// Check and print any faults
  uint8_t fault = thermo.readFault();
  if (fault) {
    Serial.print("Fault 0x"); Serial.println(fault, HEX);
    if (fault & MAX31865_FAULT_HIGHTHRESH) {
      Serial.println("RTD High Threshold"); 
      lcd.clear();
      lcd.setCursor(0,0);   //Move cursor to character 2 on line 1
      lcd.print("RTD High Threshold");
    }
    if (fault & MAX31865_FAULT_LOWTHRESH) {
      Serial.println("RTD Low Threshold"); 
      lcd.clear();
      lcd.setCursor(0,0);   //Move cursor to character 2 on line 1
      lcd.print("RTD Low Threshold");
    }
    if (fault & MAX31865_FAULT_REFINLOW) {
      Serial.println("REFIN- > 0.85 x Bias"); 
      lcd.clear();
      lcd.setCursor(0,0);   //Move cursor to character 2 on line 1
      lcd.print("RTD Low Threshold");
    }
    if (fault & MAX31865_FAULT_REFINHIGH) {
      Serial.println("REFIN- < 0.85 x Bias - FORCE- open"); 
      lcd.clear();
      lcd.setCursor(0,0);   //Move cursor to character 2 on line 1
      lcd.print("REFIN- < 0.85 x Bias - FORCE- open");
    }
    if (fault & MAX31865_FAULT_RTDINLOW) {
      Serial.println("RTDIN- < 0.85 x Bias - FORCE- open"); 
      lcd.clear();
      lcd.setCursor(0,0);   //Move cursor to character 2 on line 1
      lcd.print("RTDIN- < 0.85 x Bias - FORCE- open");
    }
    if (fault & MAX31865_FAULT_OVUV) {
      Serial.println("Under/Over voltage"); 
      lcd.clear();
      lcd.setCursor(0,0);   //Move cursor to character 2 on line 1
      lcd.print("Under/Over voltage");
    }
    thermo.clearFault();
  }
  Serial.println();
  delay(2000);
}

you are missing a closing } after the setup()

I would call thermo.temperature(RNOMINAL, RREF) only once in the loop and store the result in a local variable to work from. No need to call it many times (and it may return a varying number)

otherwise, that's the idea, yes

1 Like

Yes... I was trying to do that last night.. I was trying to define (if that's the correct saying) "MyTempRead = thermo.temperature(RNOMINAL, RREF)"
Then from then on instead of typing thermo.temperature(RNOMINAL, RREF) each time I would use the MyTempRead....
I guessed at #define MyTempRead = thermo.temperature(RNOMINAL, RREF) and failed :slight_smile:

After a very quick google I'm going to try "int"

So I got it woking by putting int MyTempReading = (thermo.temperature(RNOMINAL, RREF)); in the void loop.
I then attempted to use it as follows:

void printPressureFor(long temp) {
  float p =  pressureFromTemperature(MyTempReading); //pressureFromTemperature(temp);
  Serial.print(F("T° = ")); Serial.print(temp);
  if (p <= TOO_COLD) Serial.println(F(" \t➜ Too Cold"));
  else if (p >= TOO_HOT) Serial.println(F(" \t➜ Too Hot"));
  else {
    Serial.print(F("\t➜ P = "));
    Serial.println(p, 3);

However I get "MyTempReading" was not declared in this scope..

I thought I had to use the temp probe reading in the statement.. I'm not sure why I can't use the same in the "void printPressureFor(long temp)".

float p =  pressureFromTemperature(thermo.temperature(RNOMINAL, RREF));

I've also realized I'm only getting whole units for the temperature.. (eg. 27) I'm sure I used to get (eg. 27.3) I don't neccesarily need it, but it might look nicer.

You declared MyTempReading as int. So it can only hold integers...
Declare MyTempReading as float instead...

1 Like

Look up scope. Variables can be local or global. The {} guard the variables declared within them. If you need to use a variable outside it’s scope you need to find a way to pass it into the other function or use a global variable which is available to all.

That worked a treat thanks.