Skip to main content

pamoja_sensors/ads1115/
sim.rs

1//! An ADS1115 that is not there.
2//!
3//! A conversion comes back as a count of the full-scale range the gain selects, so
4//! [`reporting`] takes the same gain a driver is given with
5//! [`with_gain`](super::Ads1115::with_gain), and holds the count that voltage converts to. The
6//! part keeps whatever configuration a driver writes, so a conversion a driver starts reads as
7//! finished. [`part`] reads 1.65 V, half a 3.3 V supply, at the gain a driver starts with.
8
9use pamoja_hal::sim::WordPart;
10
11use super::{register, Config, Pga};
12
13/// The voltage [`part`] reports.
14pub const VOLTS: f32 = 1.65;
15
16/// An ADS1115 answering at an address, reading [`VOLTS`] at the gain a driver starts with.
17///
18/// # Arguments
19///
20/// * `address` - the address its ADDR pin selects.
21///
22/// # Returns
23///
24/// The part.
25#[must_use]
26pub fn part(address: u8) -> WordPart {
27    reporting(address, Config::default().pga, VOLTS)
28}
29
30/// An ADS1115 that reads what it is asked to.
31///
32/// # Arguments
33///
34/// * `address` - the address it answers to.
35/// * `pga` - the gain the driver converts at.
36/// * `volts` - the voltage it reports, held to the gain's full-scale range.
37///
38/// # Returns
39///
40/// The part. Its reading lands on the nearest of the 32768 steps either side of zero the gain
41/// divides its range into.
42///
43/// # Examples
44///
45/// ```
46/// use pamoja_hal::script::DelayLog;
47/// use pamoja_sensors::ads1115::{address, sim, Ads1115, Pga};
48///
49/// let mut adc = Ads1115::new(sim::reporting(address::GND, Pga::Fsr4_096, 3.0), address::GND, DelayLog::new())
50///     .with_gain(Pga::Fsr4_096);
51/// let sample = adc.sample().expect("the part answers");
52/// assert!((sample.volts() - 3.0).abs() < 0.001);
53/// ```
54#[must_use]
55pub fn reporting(address: u8, pga: Pga, volts: f32) -> WordPart {
56    let full_scale = pga.full_scale_microvolts() as f32;
57    let counts = volts * 1_000_000.0 / full_scale * 32_768.0;
58    let raw = if counts >= 0.0 {
59        (counts + 0.5).min(f32::from(i16::MAX))
60    } else {
61        (counts - 0.5).max(f32::from(i16::MIN))
62    } as i16;
63    WordPart::new(address)
64        .holding(register::CONFIG, Config::default().bits())
65        .holding(register::CONVERSION, raw as u16)
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71    use crate::ads1115::{address, Ads1115};
72    use pamoja_hal::script::DelayLog;
73
74    #[test]
75    fn a_driver_at_the_same_gain_reads_the_voltage() {
76        let mut adc = Ads1115::new(part(address::VDD), address::VDD, DelayLog::new());
77        let sample = adc.sample().expect("a sample");
78        assert!((sample.volts() - VOLTS).abs() < 0.001);
79
80        let mut adc = Ads1115::new(
81            reporting(address::SDA, Pga::Fsr0_256, -0.1),
82            address::SDA,
83            DelayLog::new(),
84        )
85        .with_gain(Pga::Fsr0_256);
86        let sample = adc.sample().expect("a sample");
87        assert!((sample.volts() + 0.1).abs() < 0.0001);
88    }
89}