From 40883a0ef0f35e9f1c220fd78bc5c8a1e7e2dcc6 Mon Sep 17 00:00:00 2001 From: Rob Tillaart Date: Sun, 9 Jan 2022 11:04:58 +0100 Subject: [PATCH] add temperatureConvertor class (#14) * add temperatureConvertor class * add baroToSeaLevelC() --- README.md | 63 ++++++++++- .../tempConvertor_test/tempConvertor_test.ino | 106 ++++++++++++++++++ keywords.txt | 43 +++++++ library.json | 2 +- library.properties | 2 +- temperature.h | 80 ++++++++++--- test/unit_test_001.cpp | 52 +++++++++ 7 files changed, 330 insertions(+), 18 deletions(-) create mode 100644 examples/tempConvertor_test/tempConvertor_test.ino create mode 100644 keywords.txt diff --git a/README.md b/README.md index f632cd6..c355125 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ Note: pre-0.3.1 versions have incorrect heat-index. - **float Celsius(float Fahrenheit)** idem. - **float Kelvin(float Celsius)** idem. +More converters are implemented in tne **temperatureConverter()** below. + ### DewPoint, humidex @@ -61,6 +63,7 @@ Indicative table | 105-129 | 40-54 | very hot | red | | > 130 | > 54 | extreme hot | purple | + #### 0.3.1 Fixed the adjustment which was incorrectly added. @@ -76,6 +79,62 @@ else ==> formula assumes wind speed @ 1.5 meter - **float WindChill_C_mps(float Celsius, float meterPerSecond, bool convert = true)** +## temperatureConverter + +Since version 0.3.2 a temperature convertor class is added to convert to and from +other (less known) temperature scales. +The idea is to set a value in one scale and retrieve it in the other. +As the converter holds the last value set, multiple conversions are easy. +See example. + +The scales are typically named after their inventor. +Check Wikipedia for details about the scales. + +| Name | units | 1° in °K | 0°C | 100°C | notes | +|:------------|:-----:|:--------:|--------:|--------:|:------| +| Celsius | °C | 1.000000 | 0.00 | 100.00 | +} Delisle | °De | 0.666666 | -100.00 | 50.00 | +| Fahrenheit | °F | 0.555556 | 32.00 | 212.00 | +| Kelvin | °K | 1.000000 | 273.15 | 373.15 | +| Newton | -- | 3.030303 | 0.00 | 33.00 | not the force. +| Rankine | °Ra | 0.555556 | 491.76 | 671.67 | 0°Ra == 0°K, steps == Fahrenheit. +| Reamur | °Re | 1.250000 | 0.00 | 80.00 | +| Romer | °Ro | 1.904762 | 7.50 | 60.00 | + +Note: units to be verified. + +Note: this class is slightly slower than direct conversion, but it +prevents to have 8 x 7 optimized functions. + + +#### Constructor + +- **temperatureConverter()** Constructor sets the default to zero degrees C. + + +#### setters + +- **void setKelvin(float value = 0)** +- **void setCelsius(float value = 0)** +- **void setFahrenheit(float value = 0)** +- **void setReamur(float value = 0)** +- **void setRankine(float value = 0)** +- **void setDelisle(float value = 0)** +- **void setNewton(float value = 0)** +- **void setRomer(float value = 0)** + +#### getters + +- **void getKelvin()** +- **void getCelsius()** +- **void getFahrenheit()** +- **void getReamur()** +- **void getRankine()** +- **void getDelisle()** +- **void getNewton()** +- **void getRomer()** + + ## Operations The functions have a limited scope so one cannot use it for all input values possible. @@ -89,6 +148,6 @@ See examples for typical usage. # Future - improve documentation -- expand number of formulas + - add short explanation? +- add more scales to temperatureConverter if exist - - diff --git a/examples/tempConvertor_test/tempConvertor_test.ino b/examples/tempConvertor_test/tempConvertor_test.ino new file mode 100644 index 0000000..89c2962 --- /dev/null +++ b/examples/tempConvertor_test/tempConvertor_test.ino @@ -0,0 +1,106 @@ +// +// FILE: temperatureConvertor.ino +// AUTHOR: Rob Tillaart +// PURPOSE: test +// DATE: 2022-01-08 + + +#include "temperature.h" + +temperatureConverter TC; + +void setup() +{ + Serial.begin(115200); + while(!Serial); + Serial.println(__FILE__); + + Serial.println(); + + for (int celsius = -20; celsius <= 125; celsius++) + { + TC.setCelsius(celsius); + float C = TC.getCelsius(); + float K = TC.getKelvin(); + float F = TC.getFahrenheit(); + float De = TC.getDelisle(); + float Re = TC.getReamur(); + float Ra = TC.getRankine(); + float Ne = TC.getNewton(); + float Ro = TC.getRomer(); + + if (celsius % 20 == 0) + { + Serial.println(); + Serial.print("\t C \t K \t F \t\t De \t Re \t Ra \t\t Ne \t Ro \n"); + } + + Serial.print("\t"); + Serial.print(C); + Serial.print("\t"); + Serial.print(K); + Serial.print("\t"); + Serial.print(F); + Serial.print("\t\t"); + Serial.print(De); + Serial.print("\t"); + Serial.print(Re); + Serial.print("\t"); + Serial.print(Ra); + Serial.print("\t\t"); + Serial.print(Ne); + Serial.print("\t"); + Serial.print(Ro); + Serial.print("\n"); + } + + + /* + for (int celsius = 0; celsius <= 100; celsius += 100) + { + TC.setCelsius(celsius); + float C = TC.getCelsius(); + float K = TC.getKelvin(); + float F = TC.getFahrenheit(); + float De = TC.getDelisle(); + float Re = TC.getReamur(); + float Ra = TC.getRankine(); + float Ne = TC.getNewton(); + float Ro = TC.getRomer(); + + if (celsius % 20 == 0) + { + Serial.println(); + Serial.print("\t C \t K \t F \t\t De \t Re \t Ra \t\t Ne \t Ro \n"); + } + + Serial.print("\t"); + Serial.print(C); + Serial.print("\t"); + Serial.print(K); + Serial.print("\t"); + Serial.print(F); + Serial.print("\t\t"); + Serial.print(De); + Serial.print("\t"); + Serial.print(Re); + Serial.print("\t"); + Serial.print(Ra); + Serial.print("\t\t"); + Serial.print(Ne); + Serial.print("\t"); + Serial.print(Ro); + Serial.print("\n"); + } + */ + + Serial.print("Done..."); +} + + +void loop() +{ +} + + +// -- END OF FILE -- diff --git a/keywords.txt b/keywords.txt new file mode 100644 index 0000000..552f940 --- /dev/null +++ b/keywords.txt @@ -0,0 +1,43 @@ +# Syntax Colouring Map For temperature + + +# Data types (KEYWORD1) +temperatureConverter KEYWORD1 + + +# Methods and Functions (KEYWORD2) +Fahrenheit KEYWORD2 +Celsius KEYWORD2 +Kelvin KEYWORD2 +dewPoint KEYWORD2 +dewPointFast KEYWORD2 +humidex KEYWORD2 +heatIndex KEYWORD2 +heatIndexC KEYWORD2 +WindChill_F_mph KEYWORD2 +WindChill_C_kmph KEYWORD2 +WindChill_C_mps KEYWORD2 + + +# temperatureConverter class +setKelvin KEYWORD2 +setCelsius KEYWORD2 +setFahrenheit KEYWORD2 +setReamur KEYWORD2 +setRankine KEYWORD2 +setDelisle KEYWORD2 +setNewton KEYWORD2 +setRomer KEYWORD2 + +getKelvin KEYWORD2 +getCelsius KEYWORD2 +getFahrenheit KEYWORD2 +getReamur KEYWORD2 +getRankine KEYWORD2 +getDelisle KEYWORD2 +getNewton KEYWORD2 +getRomer KEYWORD2 + + +# Constants (LITERAL1) + diff --git a/library.json b/library.json index 7341d46..7098129 100644 --- a/library.json +++ b/library.json @@ -15,7 +15,7 @@ "type": "git", "url": "https://github.com/RobTillaart/Temperature" }, - "version": "0.3.1", + "version": "0.3.2", "license": "MIT", "frameworks": "arduino", "platforms": "*", diff --git a/library.properties b/library.properties index 616af33..e2461ad 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Temperature -version=0.3.1 +version=0.3.2 author=Rob Tillaart maintainer=Rob Tillaart sentence=Library with weather related functions. diff --git a/temperature.h b/temperature.h index 7d2d605..7e122b1 100644 --- a/temperature.h +++ b/temperature.h @@ -1,7 +1,7 @@ #pragma once // // FILE: temperature.h -// VERSION: 0.3.0 +// VERSION: 0.3.2 // DATE: 2015-03-29 // PURPOSE: collection temperature functions // @@ -16,11 +16,16 @@ // 0.2.3 2020-08-27 fix #5 order of functions, typo, fixed 1 example // 0.2.4 2021-01-08 Arduino-CI + unit tests // 0.2.5 2021-12-28 Arduino-CI, library.json, readme.md, license, minor edits +// // 0.3.0 2022-01-05 fix #10 update HeatIndex function // compared with https://www.calculator.net/heat-index-calculator.html +// 0.3.1 2022-01-07 fix adjustments +// 0.3.2 2022-01-08 Renamed Celcius to Celsius. +// added a TempConvertor class for more exotic scales. +// added baroToSeaLevel() - kudos to RobertDB59 -#define TEMPERATURE_VERSION (F("0.3.0")) +#define TEMPERATURE_VERSION (F("0.3.2")) inline float Fahrenheit(float celsius) @@ -134,13 +139,13 @@ float heatIndex(float TF, float RH) // 0.3.0 => https://www.wpc.ncep.noaa.gov/html/heatindex_equation.shtml // previous https://en.wikipedia.org/wiki/Heat_index -// TODO add valid range for TF & R +// TODO add valid range for TF & RH // TODO optimize? -float heatIndexC(float celcius, float humidity) +float heatIndexC(float C, float humidity) { - float TF = celcius * (9.0 / 5.0) + 32; - float HI = (heatIndex(TF, humidity) - 32) * (5.0 / 9.0); - return HI; + float TF = Fahrenheit(C); + return Celsius(heatIndex(TF, humidity)); + /* const float c1 = -8.78469475556; const float c2 = 1.61139411; @@ -152,9 +157,9 @@ float heatIndexC(float celcius, float humidity) const float c8 = 0.00072546; const float c9 = -0.000003582; - float A = (( c5 * celcius) + c2) * celcius + c1; - float B = (((c7 * celcius) + c4) * celcius + c3) * humidity; - float C = (((c9 * celcius) + c8) * celcius + c6) * humidity * humidity; + float A = (( c5 * Celsius) + c2) * Celsius + c1; + float B = (((c7 * Celsius) + c4) * Celsius + c3) * humidity; + float C = (((c9 * Celsius) + c8) * Celsius + c6) * humidity * humidity; return A + B + C; */ @@ -179,19 +184,66 @@ float WindChill_F_mph(const float fahrenheit, const float milesPerHour, const bo // METRIC -float WindChill_C_kmph(const float celcius, const float kilometerPerHour, const bool convert = true) +float WindChill_C_kmph(const float Celsius, const float kilometerPerHour, const bool convert = true) { float windSpeed = kilometerPerHour; if (convert) windSpeed = pow(kilometerPerHour, 0.16); - return 13.12 + 0.6215 * celcius + (0.3965 * celcius - 11.37) * windSpeed; + return 13.12 + 0.6215 * Celsius + (0.3965 * Celsius - 11.37) * windSpeed; +} + + +float WindChill_C_mps(const float Celsius, const float meterPerSecond, const bool convert = true) +{ + return WindChill_C_kmph(Celsius, meterPerSecond * 3.6, convert); } -float WindChill_C_mps(const float celcius, const float meterPerSecond, const bool convert = true) +// https://www.engineeringtoolbox.com/air-altitude-pressure-d_462.html +// Does not have the temperature correction ==> it has almost the -5.257 exponent +// https://www.omnicalculator.com/physics/air-pressure-at-altitude +// similar to https://en.wikipedia.org/wiki/Barometric_formula +// +// Note: altitude in meters. +float baroToSeaLevelC( float pressure, float celsius, float altitude) { - return WindChill_C_kmph(celcius, meterPerSecond * 3.6, convert); + float altitudeFactor = 0.0065 * altitude; + float kelvin = celsius + 273.15; + return pressure * pow( 1 - (altitudeFactor / (kelvin + altitudeFactor)), -5.257); } +///////////////////////////////////////////////////////////// +// +// TEMPERATURE CONVERTER CLASS +// +class temperatureConverter +{ + // used Celsius as internal unit, to minimize math + public: + temperatureConverter() { _temp = 0; }; + + void setKelvin(float value = 0) { _temp = value - 273.15; }; + void setCelsius(float value = 0) { _temp = value; }; + void setFahrenheit(float value = 0) { _temp = (value - 32.0) / 1.8; }; + void setReamur(float value = 0) { _temp = value * 1.25; }; + void setRankine(float value = 0) { _temp = (value - 491.67) / 1.8; }; + void setDelisle(float value = 0) { _temp = (value + 100) / 1.5; }; + void setNewton(float value = 0) { _temp = value / 0.33; }; + void setRomer(float value = 0) { _temp = (value - 7.5) / 0.525; }; + + float getKelvin() { return _temp + 273.15; }; + float getCelsius() { return _temp; }; + float getFahrenheit() { return _temp * 1.8 + 32; }; + float getReamur() { return _temp * 0.8; }; + float getRankine() { return _temp * 1.8 + 491.67; }; + float getDelisle() { return _temp * 1.5 - 100.0; }; + float getNewton() { return _temp * 0.33; }; + float getRomer() { return _temp * 0.525 + 7.5; }; + + private: + float _temp = 0; +}; + + // -- END OF FILE -- diff --git a/test/unit_test_001.cpp b/test/unit_test_001.cpp index 075f566..2dc81c9 100644 --- a/test/unit_test_001.cpp +++ b/test/unit_test_001.cpp @@ -119,6 +119,58 @@ unittest(test_windChill) } +unittest(test_converter) +{ + temperatureConverter TC; + + fprintf(stderr, "\n 0°C\n"); + TC.setCelsius(0); + assertEqualFloat( 273.15, TC.getKelvin(), 0.01); + assertEqualFloat( 0.00, TC.getCelsius(), 0.01); + assertEqualFloat( 32.00, TC.getFahrenheit(), 0.01); + assertEqualFloat( 0.00, TC.getReamur(), 0.01); + assertEqualFloat( 491.67, TC.getRankine(), 0.01); + assertEqualFloat(-100.00, TC.getDelisle(), 0.01); + assertEqualFloat( 0.00, TC.getNewton(), 0.01); + assertEqualFloat( 7.50, TC.getRomer(), 0.01); + + fprintf(stderr, "\n 100°C\n"); + TC.setCelsius(100); + assertEqualFloat( 373.15, TC.getKelvin(), 0.01); + assertEqualFloat( 100.00, TC.getCelsius(), 0.01); + assertEqualFloat( 212.00, TC.getFahrenheit(), 0.01); + assertEqualFloat( 80.00, TC.getReamur(), 0.01); + assertEqualFloat( 671.67, TC.getRankine(), 0.01); + assertEqualFloat( 50.00, TC.getDelisle(), 0.01); + assertEqualFloat( 33.00, TC.getNewton(), 0.01); + assertEqualFloat( 60.00, TC.getRomer(), 0.01); +} + + +unittest(test_set_get) +{ + temperatureConverter TC; + + fprintf(stderr, "\n 42°C\n"); + TC.setKelvin(42); + assertEqualFloat( 42.00, TC.getKelvin(), 0.01); + TC.setCelsius(42); + assertEqualFloat( 42.00, TC.getCelsius(), 0.01); + TC.setFahrenheit(42); + assertEqualFloat( 42.00, TC.getFahrenheit(), 0.01); + TC.setReamur(42); + assertEqualFloat( 42.00, TC.getReamur(), 0.01); + TC.setRankine(42); + assertEqualFloat( 42.00, TC.getRankine(), 0.01); + TC.setDelisle(42); + assertEqualFloat( 42.00, TC.getDelisle(), 0.01); + TC.setNewton(42); + assertEqualFloat( 42.00, TC.getNewton(), 0.01); + TC.setRomer(42); + assertEqualFloat( 42.00, TC.getRomer(), 0.01); +} + + unittest_main() // --------