diff --git a/src/bus/i2c.c b/src/bus/i2c.c index 789e131..e5764ee 100644 --- a/src/bus/i2c.c +++ b/src/bus/i2c.c @@ -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 -} diff --git a/src/bus/i2c.h b/src/bus/i2c.h index e6a543d..ce80d80 100644 --- a/src/bus/i2c.h +++ b/src/bus/i2c.h @@ -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 diff --git a/src/common/math.c b/src/common/math.c index 7ed003a..5473b2d 100644 --- a/src/common/math.c +++ b/src/common/math.c @@ -2,29 +2,67 @@ #include -// 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)); } diff --git a/src/common/math.h b/src/common/math.h index 624dd03..c3a195e 100644 --- a/src/common/math.h +++ b/src/common/math.h @@ -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); diff --git a/src/main.c b/src/main.c index a33ef5d..414f566 100644 --- a/src/main.c +++ b/src/main.c @@ -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