112 lines
3.1 KiB
C
112 lines
3.1 KiB
C
/*
|
|
* @Date: 2025-07-04 13:05:24
|
|
* @Author: mypx
|
|
* @LastEditors: mypx mypx_coder@163.com
|
|
* @LastEditTime: 2025-07-10 13:28:55
|
|
* @FilePath: pt100x.c
|
|
* @Description:
|
|
* Copyright (c) 2025 by mypx, All Rights Reserved.
|
|
*/
|
|
#include "pt100x.h"
|
|
#include <math.h>
|
|
|
|
/*
|
|
* Low temperature region (T < 0°C):
|
|
* R(T) = R0(1 + A*T + B*T^2 + C*(T - R0)T^3)
|
|
* High temperature region (T >= 0°C):
|
|
* R(T) = R0(1 + A*T + B*T^2)
|
|
*/
|
|
#define A 3.9083e-3
|
|
#define B -5.775e-7
|
|
#define C -4.183e-12
|
|
|
|
#define PT100_R0 100
|
|
#define PT1000_R0 1000
|
|
|
|
/**
|
|
* @brief Calculate the temperature based on the resistance value of a PT100
|
|
* platinum resistor (precise calculation).
|
|
* @param resistance Measured resistance value (Ω).
|
|
* @param ptType Type of the PT sensor (PT100 or PT1000).
|
|
* @return Temperature value (°C), returns NaN if the resistance value is invalid.
|
|
*/
|
|
double pt_precise_temperature(double resistance, PtType ptType)
|
|
{
|
|
double R0 = (ptType == PT100) ? PT100_R0 : PT1000_R0;
|
|
|
|
if (resistance < R0)
|
|
{
|
|
// Build the cubic equation: a*T³ + b*T² + c*T + d = 0
|
|
double a = C * R0;
|
|
double b = B - 100 * C;
|
|
double c = A;
|
|
double d = 1 - resistance / R0;
|
|
|
|
// Use Newton's iteration method to solve the equation
|
|
double T = 0.0; // Initial guess value
|
|
int max_iterations = 100;
|
|
double tolerance = 1e-6;
|
|
|
|
for (int i = 0; i < max_iterations; i++)
|
|
{
|
|
// Calculate the polynomial value and its derivative
|
|
double f = a * T * T * T + b * T * T + c * T + d;
|
|
double df = 3 * a * T * T + 2 * b * T + c;
|
|
|
|
// Check if the derivative is close to zero
|
|
if (fabs(df) < tolerance) break;
|
|
|
|
// Iterative update
|
|
double delta = f / df;
|
|
T -= delta;
|
|
|
|
// Check convergence
|
|
if (fabs(delta) < tolerance) break;
|
|
}
|
|
|
|
return T;
|
|
}
|
|
else
|
|
{
|
|
// High temperature region (T ≥ 0°C): Solve the quadratic equation
|
|
// Quadratic equation: B*T² + A*T + (1 - R/R0) = 0
|
|
double discriminant = A * A - 4 * B * (1 - resistance / R0);
|
|
|
|
if (discriminant < 0)
|
|
{
|
|
return NAN;
|
|
}
|
|
|
|
// Take the positive root
|
|
return (-A + sqrt(discriminant)) / (2 * B);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Calculate the temperature based on the resistance value of a PT100 platinum resistor
|
|
* (engineering approximation).
|
|
* @param resistance Measured resistance value (Ω).
|
|
* @param type Type of the PT sensor (PT100 or PT1000).
|
|
* @return Temperature value (°C).
|
|
*/
|
|
double pt_approximate_temperature(double resistance, PtType type)
|
|
{
|
|
double R0 = (type == PT100) ? PT100_R0 : PT1000_R0;
|
|
return (resistance / R0 - 1) / 0.00385;
|
|
}
|
|
|
|
float pt_temperature_to_resistance(double t, PtType type)
|
|
{
|
|
float resistance;
|
|
float r0 = (type == PT100) ? PT100_R0 : PT1000_R0;
|
|
if (t >= 0.0f)
|
|
{
|
|
resistance = r0 * (1 + A * t + B * t * t);
|
|
}
|
|
else
|
|
{
|
|
resistance = r0 * (1 + A * t + B * t * t + C * (t - r0) * t * t * t);
|
|
}
|
|
return resistance;
|
|
}
|