keithley_2230_series/
lib.rs

1use std::str::FromStr;
2use visa_api::*;
3pub struct Keithley2230 {
4    pub inner: visa_api::Instrument,
5}
6
7pub const MANUFACTURER: &str = "Keithley Instruments";
8pub const MODEL: &str = "2230";
9
10#[derive(Clone, Copy, Debug, thiserror::Error)]
11pub enum Error {
12    #[error(transparent)]
13    VisaApiError(#[from] visa_api::Error),
14    #[error(transparent)]
15    StrumParseError(#[from] strum::ParseError),
16    #[error("No Instrument found")]
17    NoInstrumentFound(),
18}
19
20pub type Result<T> = std::result::Result<T, Error>;
21
22#[derive(Debug, PartialEq, strum::AsRefStr, strum::Display, Default, strum::EnumString)]
23pub enum Channel {
24    #[default]
25    #[strum(serialize = "CH1")]
26    CH1,
27    #[strum(serialize = "CH2")]
28    CH2,
29    #[strum(serialize = "CH3")]
30    CH3,
31}
32
33#[derive(Debug, PartialEq, strum::AsRefStr, strum::Display, Default)]
34pub enum State {
35    #[default]
36    #[strum(serialize = "ON", serialize = "1")]
37    ON,
38    #[strum(serialize = "OFF", serialize = "0")]
39    OFF,
40}
41#[derive(Debug, Default)]
42pub struct Meas {
43    pub ch1: ChMeas,
44    pub ch2: ChMeas,
45    pub ch3: ChMeas,
46}
47
48#[derive(Debug, Default)]
49pub struct ChMeas {
50    pub v: f32,
51    pub i: f32,
52    pub p: f32,
53}
54
55impl ChMeas {
56    pub fn new(v: f32, i: f32, p: f32) -> Self {
57        Self { v, i, p }
58    }
59}
60
61impl Keithley2230 {
62    pub fn new(rm: &DefaultRM) -> Result<Self> {
63        let session = Instrument::new_session(&rm, MANUFACTURER, MODEL)?;
64        if let Some(session) = session {
65            Ok(Self { inner: session })
66        } else {
67            Err(Error::NoInstrumentFound())
68        }
69    }
70
71    pub fn set_channel(&mut self, ch: Channel, v: f32, i: f32) -> Result<()> {
72        let cmd = format!("APPL {}, {}, {}", ch, v, i);
73        self.inner.write(&cmd)?;
74        Ok(())
75    }
76
77    pub fn enable_output(&mut self, state: State) -> Result<()> {
78        let cmd = format!("OUTP:ENAB {}", state);
79        self.inner.write(&cmd)?;
80        Ok(())
81    }
82
83    pub fn enable_channel(&mut self, ch: Channel, state: State) -> Result<()> {
84        let prev_ch = self.get_channel()?;
85        self.select_channel(ch)?;
86        let cmd = format!("CHAN:OUTP {}", state);
87        self.inner.write(&cmd)?;
88        self.select_channel(prev_ch)?;
89        Ok(())
90    }
91
92    pub fn get_channel(&mut self) -> Result<Channel> {
93        self.inner.write("INST?")?;
94        let ch = self.inner.read()?;
95        let ch = Channel::from_str(&ch)?;
96        Ok(ch)
97    }
98
99    pub fn select_channel(&mut self, ch: Channel) -> Result<()> {
100        let cmd = format!("INST {}", ch);
101        self.inner.write(&cmd)?;
102        Ok(())
103    }
104
105    pub fn front_panel_ctrl(&mut self) -> Result<()> {
106        self.inner.write("SYST:LOC")?;
107        Ok(())
108    }
109
110    pub fn remote_ctrl(&mut self) -> Result<()> {
111        self.inner.write("SYST:REM")?;
112        Ok(())
113    }
114
115    pub fn read_i(&mut self) -> Result<(f32, f32, f32)> {
116        self.inner.write("FETC:CURR? ALL")?;
117        let response = self.inner.read()?;
118
119        let response = response
120            .split(',')
121            .map(|x| x.trim().parse::<f32>().ok().unwrap_or(0.0))
122            .collect::<Vec<f32>>();
123
124        if response.len() == 3 {
125            Ok((response[0], response[1], response[2]))
126        } else {
127            Ok((0.0, 0.0, 0.0))
128        }
129    }
130
131    pub fn read_v(&mut self) -> Result<(f32, f32, f32)> {
132        self.inner.write("FETC:VOLT? ALL")?;
133        let response = self.inner.read()?;
134
135        let response = response
136            .split(',')
137            .map(|x| x.trim().parse::<f32>().ok().unwrap_or(0.0))
138            .collect::<Vec<f32>>();
139
140        if response.len() == 3 {
141            Ok((response[0], response[1], response[2]))
142        } else {
143            Ok((0.0, 0.0, 0.0))
144        }
145    }
146
147    pub fn read_p(&mut self) -> Result<(f32, f32, f32)> {
148        self.inner.write("FETC:POW? ALL")?;
149        let response = self.inner.read()?;
150
151        let response = response
152            .split(',')
153            .map(|x| x.trim().parse::<f32>().ok().unwrap_or(0.0))
154            .collect::<Vec<f32>>();
155
156        if response.len() == 3 {
157            Ok((response[0], response[1], response[2]))
158        } else {
159            Ok((0.0, 0.0, 0.0))
160        }
161    }
162
163    pub fn read_all(&mut self) -> Result<Meas> {
164        let v = self.read_v()?;
165        let i = self.read_i()?;
166        let p = self.read_p()?;
167
168        let meas = Meas {
169            ch1: ChMeas::new(v.0, i.0, p.0),
170            ch2: ChMeas::new(v.1, i.1, p.1),
171            ch3: ChMeas::new(v.2, i.2, p.2),
172        };
173
174        Ok(meas)
175    }
176
177    pub fn set_paralel(&mut self, state: State) -> Result<()> {
178        let cmd = format!("OUT:PAR {}", state);
179        self.inner.write(&cmd)?;
180        Ok(())
181    }
182
183    pub fn set_series(&mut self, state: State) -> Result<()> {
184        let cmd = format!("OUT:SER {}", state);
185        self.inner.write(&cmd)?;
186        Ok(())
187    }
188}