nanonis_rs/client/current.rs
1use super::NanonisClient;
2use crate::error::NanonisError;
3use crate::types::NanonisValue;
4
5impl NanonisClient {
6 /// Get the current tunneling current value.
7 ///
8 /// Returns the instantaneous tunneling current measurement from the current amplifier.
9 /// This is one of the most fundamental measurements in STM, providing direct information
10 /// about the tip-sample conductance.
11 ///
12 /// # Returns
13 /// Current value in Amperes (A).
14 ///
15 /// # Errors
16 /// Returns `NanonisError` if communication fails or protocol error occurs.
17 ///
18 /// # Examples
19 /// ```no_run
20 /// use nanonis_rs::NanonisClient;
21 ///
22 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
23 ///
24 /// let current = client.current_get()?;
25 /// println!("Tunneling current: {:.3e} A", current);
26 ///
27 /// // Convert to more convenient units
28 /// if current.abs() < 1e-9 {
29 /// println!("Current: {:.1} pA", current * 1e12);
30 /// } else {
31 /// println!("Current: {:.1} nA", current * 1e9);
32 /// }
33 /// # Ok::<(), Box<dyn std::error::Error>>(())
34 /// ```
35 pub fn current_get(&mut self) -> Result<f32, NanonisError> {
36 let result = self.quick_send("Current.Get", vec![], vec![], vec!["f"])?;
37
38 match result.first() {
39 Some(value) => Ok(value.as_f32()?),
40 None => Err(NanonisError::Protocol(
41 "No current value returned".to_string(),
42 )),
43 }
44 }
45
46 /// Get the current value from the "Current 100" module.
47 ///
48 /// Returns the tunneling current from the specialized Current 100 module,
49 /// which may have different gain or filtering characteristics than the main
50 /// current amplifier.
51 ///
52 /// # Returns
53 /// Current 100 value in Amperes (A).
54 ///
55 /// # Errors
56 /// Returns `NanonisError` if communication fails or protocol error occurs.
57 ///
58 /// # Examples
59 /// ```no_run
60 /// use nanonis_rs::NanonisClient;
61 ///
62 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
63 ///
64 /// let current_100 = client.current_100_get()?;
65 /// println!("Current 100 module: {:.3e} A", current_100);
66 /// # Ok::<(), Box<dyn std::error::Error>>(())
67 /// ```
68 pub fn current_100_get(&mut self) -> Result<f32, NanonisError> {
69 let result = self.quick_send("Current.100Get", vec![], vec![], vec!["f"])?;
70
71 match result.first() {
72 Some(value) => Ok(value.as_f32()?),
73 None => Err(NanonisError::Protocol(
74 "No current 100 value returned".to_string(),
75 )),
76 }
77 }
78
79 /// Get the BEEM current value from the corresponding module.
80 ///
81 /// Returns the Ballistic Electron Emission Microscopy (BEEM) current value
82 /// in systems equipped with BEEM capabilities. BEEM measures hot electrons
83 /// transmitted through thin metal films.
84 ///
85 /// # Returns
86 /// BEEM current value in Amperes (A).
87 ///
88 /// # Errors
89 /// Returns `NanonisError` if:
90 /// - BEEM module is not available or not configured
91 /// - Communication fails or protocol error occurs
92 ///
93 /// # Examples
94 /// ```no_run
95 /// use nanonis_rs::NanonisClient;
96 ///
97 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
98 ///
99 /// let beem_current = client.current_beem_get()?;
100 /// println!("BEEM current: {:.3e} A", beem_current);
101 /// # Ok::<(), Box<dyn std::error::Error>>(())
102 /// ```
103 pub fn current_beem_get(&mut self) -> Result<f32, NanonisError> {
104 let result = self.quick_send("Current.BEEMGet", vec![], vec![], vec!["f"])?;
105
106 match result.first() {
107 Some(value) => Ok(value.as_f32()?),
108 None => Err(NanonisError::Protocol(
109 "No BEEM current value returned".to_string(),
110 )),
111 }
112 }
113
114 /// Set the gain and filter of the current amplifier.
115 ///
116 /// Configures the current amplifier's gain and filtering characteristics.
117 /// Use `current_gains_get()` to retrieve the available gain and filter options
118 /// before setting specific indices.
119 ///
120 /// # Arguments
121 /// * `gain_index` - Index from the list of available gains
122 /// * `filter_index` - Index from the list of available filters
123 ///
124 /// # Errors
125 /// Returns `NanonisError` if:
126 /// - Invalid gain or filter index provided
127 /// - Communication fails or protocol error occurs
128 ///
129 /// # Examples
130 /// ```no_run
131 /// use nanonis_rs::NanonisClient;
132 ///
133 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
134 ///
135 /// // Get available options first
136 /// let (gains, current_gain_idx, filters, current_filter_idx) = client.current_gains_get()?;
137 /// println!("Available gains: {:?}", gains);
138 /// println!("Available filters: {:?}", filters);
139 ///
140 /// // Set to high gain (index 3) with medium filtering (index 1)
141 /// client.current_gain_set(3, 1)?;
142 /// # Ok::<(), Box<dyn std::error::Error>>(())
143 /// ```
144 pub fn current_gain_set(
145 &mut self,
146 gain_index: i32,
147 filter_index: i32,
148 ) -> Result<(), NanonisError> {
149 self.quick_send(
150 "Current.GainSet",
151 vec![
152 NanonisValue::I32(gain_index),
153 NanonisValue::I32(filter_index),
154 ],
155 vec!["i", "i"],
156 vec![],
157 )?;
158 Ok(())
159 }
160
161 /// Get the available gains and filters of the current amplifier.
162 ///
163 /// Returns all selectable gains and filters for the current amplifier, along with
164 /// the currently selected indices. This information is needed for `current_gain_set()`.
165 ///
166 /// # Returns
167 /// A tuple containing:
168 /// - `Vec<String>` - Array of available gain descriptions
169 /// - `u16` - Index of currently selected gain
170 /// - `Vec<String>` - Array of available filter descriptions
171 /// - `i32` - Index of currently selected filter
172 ///
173 /// # Errors
174 /// Returns `NanonisError` if communication fails or protocol error occurs.
175 ///
176 /// # Examples
177 /// ```no_run
178 /// use nanonis_rs::NanonisClient;
179 ///
180 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
181 ///
182 /// let (gains, gain_idx, filters, filter_idx) = client.current_gains_get()?;
183 ///
184 /// println!("Current gain: {} (index {})", gains[gain_idx as usize], gain_idx);
185 /// println!("Current filter: {} (index {})", filters[filter_idx as usize], filter_idx);
186 ///
187 /// // List all available options
188 /// for (i, gain) in gains.iter().enumerate() {
189 /// println!("Gain {}: {}", i, gain);
190 /// }
191 /// # Ok::<(), Box<dyn std::error::Error>>(())
192 /// ```
193 pub fn current_gains_get(
194 &mut self,
195 ) -> Result<(Vec<String>, u16, Vec<String>, i32), NanonisError> {
196 let result = self.quick_send(
197 "Current.GainsGet",
198 vec![],
199 vec![],
200 vec!["i", "i", "*+c", "i", "i", "i", "*+c", "i"],
201 )?;
202
203 if result.len() >= 8 {
204 let gains = result[2].as_string_array()?.to_vec();
205 let gain_index = result[3].as_u16()?;
206 let filters = result[6].as_string_array()?.to_vec();
207 let filter_index = result[7].as_i32()?;
208 Ok((gains, gain_index, filters, filter_index))
209 } else {
210 Err(NanonisError::Protocol(
211 "Invalid current gains response".to_string(),
212 ))
213 }
214 }
215
216 /// Set the calibration and offset for a specific gain in the Current module.
217 ///
218 /// Configures the calibration parameters for accurate current measurements.
219 /// Each gain setting can have its own calibration and offset values.
220 ///
221 /// # Arguments
222 /// * `gain_index` - Index of the gain to calibrate (-1 for currently selected gain)
223 /// * `calibration` - Calibration factor (typically A/V or similar)
224 /// * `offset` - Offset value in the same units
225 ///
226 /// # Errors
227 /// Returns `NanonisError` if communication fails or invalid parameters provided.
228 ///
229 /// # Examples
230 /// ```no_run
231 /// use nanonis_rs::NanonisClient;
232 ///
233 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
234 ///
235 /// // Calibrate currently selected gain
236 /// client.current_calibr_set(-1, 1.0e-9, 0.0)?;
237 ///
238 /// // Calibrate specific gain (index 2) with offset correction
239 /// client.current_calibr_set(2, 9.87e-10, -1.5e-12)?;
240 /// # Ok::<(), Box<dyn std::error::Error>>(())
241 /// ```
242 pub fn current_calibr_set(
243 &mut self,
244 gain_index: i32,
245 calibration: f64,
246 offset: f64,
247 ) -> Result<(), NanonisError> {
248 self.quick_send(
249 "Current.CalibrSet",
250 vec![
251 NanonisValue::I32(gain_index),
252 NanonisValue::F64(calibration),
253 NanonisValue::F64(offset),
254 ],
255 vec!["i", "d", "d"],
256 vec![],
257 )?;
258 Ok(())
259 }
260
261 /// Get the calibration and offset for a specific gain in the Current module.
262 ///
263 /// Returns the calibration parameters for the specified gain setting.
264 ///
265 /// # Arguments
266 /// * `gain_index` - Index of the gain to query (-1 for currently selected gain)
267 ///
268 /// # Returns
269 /// A tuple containing:
270 /// - `f64` - Calibration factor
271 /// - `f64` - Offset value
272 ///
273 /// # Errors
274 /// Returns `NanonisError` if communication fails or invalid gain index.
275 ///
276 /// # Examples
277 /// ```no_run
278 /// use nanonis_rs::NanonisClient;
279 ///
280 /// let mut client = NanonisClient::new("127.0.0.1", 6501)?;
281 ///
282 /// // Get calibration for currently selected gain
283 /// let (calibration, offset) = client.current_calibr_get(-1)?;
284 /// println!("Current calibration: {:.3e}, offset: {:.3e}", calibration, offset);
285 ///
286 /// // Check calibration for specific gain
287 /// let (cal, off) = client.current_calibr_get(2)?;
288 /// # Ok::<(), Box<dyn std::error::Error>>(())
289 /// ```
290 pub fn current_calibr_get(&mut self, gain_index: i32) -> Result<(f64, f64), NanonisError> {
291 let result = self.quick_send(
292 "Current.CalibrGet",
293 vec![NanonisValue::I32(gain_index)],
294 vec!["i"],
295 vec!["d", "d"],
296 )?;
297
298 if result.len() >= 2 {
299 let calibration = result[0].as_f64()?;
300 let offset = result[1].as_f64()?;
301 Ok((calibration, offset))
302 } else {
303 Err(NanonisError::Protocol(
304 "Invalid current calibration response".to_string(),
305 ))
306 }
307 }
308}