Split thermistor functions into separate logical units and add TODO

This commit is contained in:
2024-09-19 19:54:28 +02:00
parent b3fda53036
commit 1f01f92291
5 changed files with 74 additions and 52 deletions

View File

@@ -14,11 +14,6 @@
#define TW_MR_SLA_NACK 0x48 // SLA+R transmitted, NACK received
#define TW_MR_DATA_ACK 0x50 // Data received, ACK returned
// NTC conversion constants
#define NTC01 1.009249522e-3
#define NTC02 2.378405444e-4
#define NTC03 2.019202697e-7
// TODO: Error handling and recovery besides watchdog timer.
// TODO: Add more documentation from the atmel data sheet.
// TODO: ADS1115 continuous mode instead of single-shot?
@@ -477,7 +472,7 @@ static bool I2C_ADS1115_IsReady(void)
return reg & BIT(15);
}
word I2C_ADS1115_Read(int channel)
word I2C_ADS1115_ReadRaw(int channel)
{
word config;
word os, mode, rate, gain, mux;
@@ -563,21 +558,3 @@ word I2C_ADS1115_Read(int channel)
return I2C_ADS1115_ReadRegister(0x00);
}
float I2C_ADS1115_ReadThermistor(int channel)
{
word raw;
float r1, t;
float logr2;
// TODO: Improve readability
// https://en.wikipedia.org/wiki/Steinhart%E2%80%93Hart_equation
raw = I2C_ADS1115_Read(channel);
r1 = (float) raw / 264.8f * 0.05f;
logr2 = log(10000.0f / (5.0f / r1 - 1.0f));
t = 1.0f / (NTC01 + NTC02 * logr2 + NTC03 * pow(logr2, 3));
return t - 273.15f; // Convert fahrenheit to celsius
}

View File

@@ -28,7 +28,6 @@ int I2C_AHT20_Init(void);
int I2C_AHT20_Read(float *temp, float *rhum);
// ADS1115 analog to digital converter
word I2C_ADS1115_Read(int channel);
float I2C_ADS1115_ReadThermistor(int channel);
word I2C_ADS1115_ReadRaw(int channel);
#endif // MAD_CORE_BUS_I2C_H

View File

@@ -2,29 +2,67 @@
#include <math.h>
// https://bmcnoldy.earth.miami.edu/Humidity.html
// https://en.wikipedia.org/wiki/Steinhart%E2%80%93Hart_equation
// https://onlinelibrary.wiley.com/doi/abs/10.1002/andp.18280890511
// https://onlinelibrary.wiley.com/doi/abs/10.1002/andp.18441370202
// https://bmcnoldy.earth.miami.edu/Humidity.html
// TODO: Make sure all results for conversion functions are correct.
// TODO: Is resistance function semantically correct?
// TODO: Check results for humidity conversion functions.
// Conversion constants
static const float C1 = 100.0f;
static const float C2 = 243.04f;
static const float C3 = 17.625f;
// Thermistor coeficients
static const float SC1 = 1.009249522e-3f;
static const float SC2 = 2.378405444e-4f;
static const float SC3 = 2.019202697e-7f;
static const float R1 = 10000.0f;
// Humidity conversion constants
static const float TH1 = 100.0f;
static const float TH2 = 243.04f;
static const float TH3 = 17.625f;
float Resistance(int adc_raw)
{
float r2;
// TODO: Improve readability.
// TODO: Make sure output is correct.
// [GND] - [10K RESISTOR] - [ADC INPUT] - [THERMISTOR] - [VCC]
r2 = (float) adc_raw / 264.8f * 0.05f;
// XXX: Ohms Law solved for resistance?
// R = V / I
return R1 / (5.0f / r2 - 1.0f);
}
// Resistance to temperature
float SteinhartHart(float res)
{
float logr, t;
// 25C = 10000 Ohms
// 100C = 6744 Ohms
logr = log(res);
t = 1.0f / (SC1 + SC2 * logr + SC3 * pow(logr, 3));
return t - 273.15f; // Kelvin to celsius
}
// Dewpoint TD
float Dewp(float t, float rh)
{
float a, b;
a = log(rh / C1);
b = C3 * t / (C2 + t);
// 243.04*(LN(RH/100)+((17.625*T)/(243.04+T)))/
// (17.625-LN(RH/100)-((17.625*T)/(243.04+T)))
return C2 * (a + b) / (C3 - a - b);
a = log(rh / TH1);
b = TH3 * t / (TH2 + t);
return TH2 * (a + b) / (TH3 - a - b);
}
// Temperature T
@@ -32,13 +70,13 @@ float Temp(float td, float rh)
{
float a, b;
a = log(rh / C1);
b = C3 * td / (C2 + td);
// 243.04*(((17.625*TD)/(243.04+TD))-LN(RH/100))/
// (17.625+LN(RH/100)-((17.625*TD)/(243.04+TD)))
return C2 * (b - a) / (C3 + a - b);
a = log(rh / TH1);
b = TH3 * td / (TH2 + td);
return TH2 * (b - a) / (TH3 + a - b);
}
// Relative Humidity RH
@@ -46,11 +84,11 @@ float Rhum(float t, float td)
{
float a, b;
a = C3 * td / (C2 + td);
b = C3 * t / (C2 + t);
// 100*(EXP((17.625*TD)/(243.04+TD))/
// EXP((17.625*T)/(243.04+T)))
return C1 * (exp(a) / exp(b));
a = TH3 * td / (TH2 + td);
b = TH3 * t / (TH2 + t);
return TH1 * (exp(a) / exp(b));
}

View File

@@ -1,6 +1,9 @@
#ifndef MAD_CORE_COMMON_MATH_H
#define MAD_CORE_COMMON_MATH_H
float Resistance(int adc_raw);
float SteinhartHart(float res);
float Dewp(float t, float rh);
float Temp(float td, float rh);
float Rhum(float t, float td);

View File

@@ -110,8 +110,8 @@ static int Init(void)
static void Update(void)
{
float t[3], rh[3];
float adct[3];
float t[6], rh[3];
word raw;
Info("Reading sensor values...");
@@ -124,13 +124,18 @@ static void Update(void)
I2C_SetChannel(AHT03);
I2C_AHT20_Read(&t[2], &rh[2]);
adct[0] = I2C_ADS1115_ReadThermistor(ADS01);
adct[1] = I2C_ADS1115_ReadThermistor(ADS02);
adct[2] = I2C_ADS1115_ReadThermistor(ADS03);
raw = I2C_ADS1115_ReadRaw(ADS01);
t[3] = SteinhartHart(Resistance(raw));
Info("T1=%.2fC, RH1=%.2f%%, ADCT1=%.2fC", t[0], rh[0], adct[0]);
Info("T2=%.2fC, RH2=%.2f%%, ADCT2=%.2fC", t[1], rh[1], adct[1]);
Info("T3=%.2fC, RH3=%.2f%%, ADCT3=%.2fC", t[2], rh[2], adct[2]);
raw = I2C_ADS1115_ReadRaw(ADS02);
t[4] = SteinhartHart(Resistance(raw));
raw = I2C_ADS1115_ReadRaw(ADS03);
t[5] = SteinhartHart(Resistance(raw));
Info("T1=%.2fC, RH1=%.2f%%, NT1=%.2fC", t[0], rh[0], t[3]);
Info("T2=%.2fC, RH2=%.2f%%, NT2=%.2fC", t[1], rh[1], t[4]);
Info("T3=%.2fC, RH3=%.2f%%, NT3=%.2fC", t[2], rh[2], t[5]);
// TODO: Implement state machine
// TODO: Handle serial commands