Skip to content

Commit d9d4d34

Browse files
committed
Add no-std version of humidity calculations
1 parent cd02bf1 commit d9d4d34

File tree

2 files changed

+40
-14
lines changed

2 files changed

+40
-14
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ license = "MIT"
1515
readme = "README.md"
1616

1717
[features]
18-
no_std = []
18+
no_std = [ "libm" ]
1919
from_str = ["regex"]
2020

2121
[dependencies]
2222
serde = { version = "1.0", optional = true, features = ["derive"] }
2323
regex = { version = "1", optional = true }
24+
libm = { version = "0.2", optional = true }

src/humidity.rs

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
//! Types and constants for handling humidity.
22
33
use super::measurement::*;
4-
#[cfg(not(feature = "no_std"))]
54
use density::Density;
6-
#[cfg(not(feature = "no_std"))]
75
use pressure::Pressure;
8-
#[cfg(not(feature = "no_std"))]
96
use temperature::Temperature;
107

118
/// The `Humidity` struct can be used to deal with relative humidity
@@ -35,9 +32,7 @@ use temperature::Temperature;
3532
///
3633
/// let humidity = Humidity::from_percent(85.0);
3734
/// let temp = Temperature::from_celsius(18.0);
38-
/// #[cfg(not(feature="no_std"))]
3935
/// let dewpoint = humidity.as_dewpoint(temp);
40-
/// #[cfg(not(feature="no_std"))]
4136
/// println!("At {} humidity, air at {} has a dewpoint of {}", humidity, temp, dewpoint);
4237
///
4338
/// ```
@@ -82,6 +77,20 @@ impl Humidity {
8277
/ (17.625 - humidity.ln() - ((17.625 * celsius) / (243.04 + celsius)));
8378
Temperature::from_celsius(dewpoint)
8479
}
80+
81+
/// Calculates Dewpoint from humidity and air temperature using the Magnus-Tetens
82+
/// approximation, with coefficients derived by Alduchov and Eskridge (1996). The formulas assume
83+
// standard atmospheric pressure.
84+
#[cfg(feature = "no_std")]
85+
pub fn as_dewpoint(&self, temp: Temperature) -> Temperature {
86+
let humidity = self.relative_humidity / 100.0;
87+
let celsius = temp.as_celsius();
88+
let humidity_ln = libm::log(humidity);
89+
let dewpoint: f64 = 243.04 * (humidity_ln + ((17.625 * celsius) / (243.04 + celsius)))
90+
/ (17.625 - humidity_ln - ((17.625 * celsius) / (243.04 + celsius)));
91+
Temperature::from_celsius(dewpoint)
92+
}
93+
8594
/// Calculates the actual vapour pressure in the air, based on the air temperature and humidity
8695
/// at standard atmospheric pressure (1013.25 mb), using the Buck formula (accurate to +/- 0.02%
8796
/// between 0 deg C and 50 deg C)
@@ -93,9 +102,19 @@ impl Humidity {
93102
Pressure::from_kilopascals((self.relative_humidity * saturation_vapor_pressure) / 100.0)
94103
}
95104

105+
/// Calculates the actual vapour pressure in the air, based on the air temperature and humidity
106+
/// at standard atmospheric pressure (1013.25 mb), using the Buck formula (accurate to +/- 0.02%
107+
/// between 0 deg C and 50 deg C)
108+
#[cfg(feature = "no_std")]
109+
pub fn as_vapor_pressure(&self, temp: Temperature) -> Pressure {
110+
let temp = temp.as_celsius();
111+
let saturation_vapor_pressure =
112+
0.61121 * libm::exp((18.678 - (temp / 234.5)) * (temp / (257.14 + temp)));
113+
Pressure::from_kilopascals((self.relative_humidity * saturation_vapor_pressure) / 100.0)
114+
}
115+
96116
/// Calculates the absolute humidity (i.e. the density of water vapor in the air (kg/m3)), using
97117
/// the Ideal Gas Law equation.
98-
#[cfg(not(feature = "no_std"))]
99118
pub fn as_absolute_humidity(&self, temp: Temperature) -> Density {
100119
// use the Ideal Gas Law equation (Density = Pressure / (Temperature * [gas constant
101120
// for water vapor= 461.5 (J/kg*Kelvin)]))
@@ -115,6 +134,19 @@ impl Humidity {
115134
/ ((17.625 * temp) / (243.04 + temp)).exp());
116135
Humidity::from_percent(rh)
117136
}
137+
138+
/// Calculates humidity from dewpoint and air temperature using the Magnus-Tetens
139+
/// Approximation, with coefficients derived by Alduchov and Eskridge (1996). The formulas assume
140+
// standard atmospheric pressure.
141+
#[cfg(feature = "no_std")]
142+
pub fn from_dewpoint(dewpoint: Temperature, temp: Temperature) -> Humidity {
143+
let dewpoint = dewpoint.as_celsius();
144+
let temp = temp.as_celsius();
145+
let rh = 100.0
146+
* (libm::exp((17.625 * dewpoint) / (243.04 + dewpoint))
147+
/ libm::exp((17.625 * temp) / (243.04 + temp)));
148+
Humidity::from_percent(rh)
149+
}
118150
}
119151

120152
impl Measurement for Humidity {
@@ -167,47 +199,41 @@ mod test {
167199
assert_almost_eq(o, 0.1);
168200
}
169201
// Dewpoint calculation
170-
#[cfg(not(feature = "no_std"))]
171202
#[test]
172203
fn to_dewpoint1() {
173204
let humidity = Humidity::from_percent(85.0);
174205
let temp = Temperature::from_celsius(18.0);
175206
let dewpoint = humidity.as_dewpoint(temp);
176207
assert_almost_eq(dewpoint.as_celsius(), 15.44);
177208
}
178-
#[cfg(not(feature = "no_std"))]
179209
#[test]
180210
fn to_dewpoint2() {
181211
let humidity = Humidity::from_percent(40.0);
182212
let temp = Temperature::from_celsius(5.0);
183213
let dewpoint = humidity.as_dewpoint(temp);
184214
assert_almost_eq(dewpoint.as_celsius(), -7.5);
185215
}
186-
#[cfg(not(feature = "no_std"))]
187216
#[test]
188217
fn to_dewpoint3() {
189218
let humidity = Humidity::from_percent(95.0);
190219
let temp = Temperature::from_celsius(30.0);
191220
let dewpoint = humidity.as_dewpoint(temp);
192221
assert_almost_eq(dewpoint.as_celsius(), 29.11);
193222
}
194-
#[cfg(not(feature = "no_std"))]
195223
#[test]
196224
fn from_dewpoint1() {
197225
let temp = Temperature::from_celsius(18.0);
198226
let dewpoint = Temperature::from_celsius(15.44);
199227
let rh = Humidity::from_dewpoint(dewpoint, temp);
200228
assert_almost_eq(rh.as_percent(), 85.0);
201229
}
202-
#[cfg(not(feature = "no_std"))]
203230
#[test]
204231
fn vapour_pressure() {
205232
let humidity = Humidity::from_percent(60.0);
206233
let temp = Temperature::from_celsius(25.0);
207234
let vp = humidity.as_vapor_pressure(temp);
208235
assert_almost_eq(vp.as_hectopascals(), 19.011);
209236
}
210-
#[cfg(not(feature = "no_std"))]
211237
#[test]
212238
// also tests as_vapor_pressure() on the fly
213239
fn absolute_humidity() {
@@ -216,7 +242,6 @@ mod test {
216242
let density = humidity.as_absolute_humidity(temp);
217243
assert_almost_eq(density.as_kilograms_per_cubic_meter(), 0.0138166);
218244
}
219-
#[cfg(not(feature = "no_std"))]
220245
#[test]
221246
// round-trip test
222247
fn from_dewpoint2() {

0 commit comments

Comments
 (0)