rsiot/drivers_i2c/ads1115/
device.rs

1use std::{io::Cursor, sync::Arc, time::Duration};
2
3use byteorder::{BigEndian, ReadBytesExt};
4use tokio::{sync::Mutex, task::JoinSet, time::sleep};
5use tracing::warn;
6
7use crate::{executor::CmpInOut, message::MsgDataBound};
8
9use super::{
10    super::{I2cSlaveAddress, RsiotI2cDriverBase},
11    config,
12};
13
14/// АЦП ADS1115
15pub struct ADS1115<TMsg, Driver>
16where
17    TMsg: MsgDataBound,
18    Driver: RsiotI2cDriverBase,
19{
20    /// Адрес
21    pub address: I2cSlaveAddress,
22
23    /// Настройка
24    pub inputs: Vec<config::InputConfig<TMsg>>,
25
26    /// Ссылка на драйвер
27    pub driver: Arc<Mutex<Driver>>,
28
29    pub cmp_in_out: CmpInOut<TMsg>,
30}
31
32impl<TMsg, Driver> ADS1115<TMsg, Driver>
33where
34    TMsg: MsgDataBound + 'static,
35    Driver: RsiotI2cDriverBase + 'static,
36{
37    pub async fn spawn(&self) {
38        loop {
39            let mut task_set: JoinSet<Result<(), String>> = JoinSet::new();
40
41            for input in &self.inputs {
42                let driver = self.driver.clone();
43                let input = input.clone();
44                let cmp_in_out = self.cmp_in_out.clone();
45                let task = TaskInput {
46                    address: self.address,
47                    input,
48                    driver,
49                    cmp_in_out,
50                };
51                task_set.spawn(async move { task.spawn().await });
52            }
53
54            while let Some(res) = task_set.join_next().await {
55                warn!("ADS1150 stop execution: {:?}", res);
56                task_set.abort_all();
57            }
58
59            sleep(Duration::from_secs(2)).await;
60        }
61    }
62}
63
64fn convert_response_to_voltage(
65    response: &[u8],
66    amplfier: &config::Amplifier,
67) -> Result<f64, String> {
68    let mut rdr = Cursor::new(response);
69    let response = rdr.read_i16::<BigEndian>().unwrap();
70    let max_scale = amplfier.max_value();
71    let volt = response as f64 * max_scale / 32768.0;
72
73    Ok(volt)
74}
75
76struct TaskInput<TMsg, Driver>
77where
78    TMsg: MsgDataBound,
79    Driver: RsiotI2cDriverBase,
80{
81    pub address: I2cSlaveAddress,
82    pub input: config::InputConfig<TMsg>,
83    pub driver: Arc<Mutex<Driver>>,
84    pub cmp_in_out: CmpInOut<TMsg>,
85}
86
87impl<TMsg, Driver> TaskInput<TMsg, Driver>
88where
89    TMsg: MsgDataBound,
90    Driver: RsiotI2cDriverBase,
91{
92    pub async fn spawn(&self) -> Result<(), String> {
93        loop {
94            {
95                let mut driver = self.driver.lock().await;
96
97                // Посылаем конфигурацию
98                let mut request = vec![0x01];
99                request.extend(config::config_to_bytes(
100                    &self.input.mux_config,
101                    &self.input.amplifier,
102                ));
103
104                let _ = driver
105                    .write(self.address, &request, Duration::from_secs(2))
106                    .await;
107
108                sleep(Duration::from_millis(10)).await;
109
110                // Читаем ответ
111                let request = [0x00];
112                let response = driver
113                    .write_read(self.address, &request, 2, Duration::from_secs(2))
114                    .await
115                    .map_err(String::from)?;
116                let volt = convert_response_to_voltage(&response, &self.input.amplifier).unwrap();
117
118                // Обрабатываем исходящие сообщения
119                let msg = (self.input.fn_output)(volt);
120                let Some(msg) = msg else { continue };
121                self.cmp_in_out
122                    .send_output(msg)
123                    .await
124                    .map_err(|e| e.to_string())?;
125            }
126
127            sleep(self.input.period).await
128        }
129    }
130}