tinkerforge_async/bindings/
dc_brick.rs

1/* ***********************************************************
2 * This file was automatically generated on 2024-02-16.      *
3 *                                                           *
4 * Rust Bindings Version 2.0.20                              *
5 *                                                           *
6 * If you have a bugfix for this file and want to commit it, *
7 * please fix the bug in the generator. You can find a link  *
8 * to the generators git repository on tinkerforge.com       *
9 *************************************************************/
10
11//! Drives one brushed DC motor with up to 28V and 5A (peak).
12//!
13//! See also the documentation [here](https://www.tinkerforge.com/en/doc/Software/Bricks/DC_Brick_Rust.html).
14#[allow(unused_imports)]
15use crate::{
16    base58::Uid, byte_converter::*, device::*, error::TinkerforgeError, ip_connection::async_io::AsyncIpConnection,
17    low_level_traits::LowLevelRead,
18};
19#[allow(unused_imports)]
20use futures_core::Stream;
21#[allow(unused_imports)]
22use tokio_stream::StreamExt;
23pub enum DcBrickFunction {
24    SetVelocity,
25    GetVelocity,
26    GetCurrentVelocity,
27    SetAcceleration,
28    GetAcceleration,
29    SetPwmFrequency,
30    GetPwmFrequency,
31    FullBrake,
32    GetStackInputVoltage,
33    GetExternalInputVoltage,
34    GetCurrentConsumption,
35    Enable,
36    Disable,
37    IsEnabled,
38    SetMinimumVoltage,
39    GetMinimumVoltage,
40    SetDriveMode,
41    GetDriveMode,
42    SetCurrentVelocityPeriod,
43    GetCurrentVelocityPeriod,
44    SetSpitfpBaudrateConfig,
45    GetSpitfpBaudrateConfig,
46    GetSendTimeoutCount,
47    SetSpitfpBaudrate,
48    GetSpitfpBaudrate,
49    GetSpitfpErrorCount,
50    EnableStatusLed,
51    DisableStatusLed,
52    IsStatusLedEnabled,
53    GetProtocol1BrickletName,
54    GetChipTemperature,
55    Reset,
56    WriteBrickletPlugin,
57    ReadBrickletPlugin,
58    GetIdentity,
59    CallbackUnderVoltage,
60    CallbackEmergencyShutdown,
61    CallbackVelocityReached,
62    CallbackCurrentVelocity,
63}
64impl From<DcBrickFunction> for u8 {
65    fn from(fun: DcBrickFunction) -> Self {
66        match fun {
67            DcBrickFunction::SetVelocity => 1,
68            DcBrickFunction::GetVelocity => 2,
69            DcBrickFunction::GetCurrentVelocity => 3,
70            DcBrickFunction::SetAcceleration => 4,
71            DcBrickFunction::GetAcceleration => 5,
72            DcBrickFunction::SetPwmFrequency => 6,
73            DcBrickFunction::GetPwmFrequency => 7,
74            DcBrickFunction::FullBrake => 8,
75            DcBrickFunction::GetStackInputVoltage => 9,
76            DcBrickFunction::GetExternalInputVoltage => 10,
77            DcBrickFunction::GetCurrentConsumption => 11,
78            DcBrickFunction::Enable => 12,
79            DcBrickFunction::Disable => 13,
80            DcBrickFunction::IsEnabled => 14,
81            DcBrickFunction::SetMinimumVoltage => 15,
82            DcBrickFunction::GetMinimumVoltage => 16,
83            DcBrickFunction::SetDriveMode => 17,
84            DcBrickFunction::GetDriveMode => 18,
85            DcBrickFunction::SetCurrentVelocityPeriod => 19,
86            DcBrickFunction::GetCurrentVelocityPeriod => 20,
87            DcBrickFunction::SetSpitfpBaudrateConfig => 231,
88            DcBrickFunction::GetSpitfpBaudrateConfig => 232,
89            DcBrickFunction::GetSendTimeoutCount => 233,
90            DcBrickFunction::SetSpitfpBaudrate => 234,
91            DcBrickFunction::GetSpitfpBaudrate => 235,
92            DcBrickFunction::GetSpitfpErrorCount => 237,
93            DcBrickFunction::EnableStatusLed => 238,
94            DcBrickFunction::DisableStatusLed => 239,
95            DcBrickFunction::IsStatusLedEnabled => 240,
96            DcBrickFunction::GetProtocol1BrickletName => 241,
97            DcBrickFunction::GetChipTemperature => 242,
98            DcBrickFunction::Reset => 243,
99            DcBrickFunction::WriteBrickletPlugin => 246,
100            DcBrickFunction::ReadBrickletPlugin => 247,
101            DcBrickFunction::GetIdentity => 255,
102            DcBrickFunction::CallbackUnderVoltage => 21,
103            DcBrickFunction::CallbackEmergencyShutdown => 22,
104            DcBrickFunction::CallbackVelocityReached => 23,
105            DcBrickFunction::CallbackCurrentVelocity => 24,
106        }
107    }
108}
109pub const DC_BRICK_DRIVE_MODE_DRIVE_BRAKE: u8 = 0;
110pub const DC_BRICK_DRIVE_MODE_DRIVE_COAST: u8 = 1;
111pub const DC_BRICK_COMMUNICATION_METHOD_NONE: u8 = 0;
112pub const DC_BRICK_COMMUNICATION_METHOD_USB: u8 = 1;
113pub const DC_BRICK_COMMUNICATION_METHOD_SPI_STACK: u8 = 2;
114pub const DC_BRICK_COMMUNICATION_METHOD_CHIBI: u8 = 3;
115pub const DC_BRICK_COMMUNICATION_METHOD_RS485: u8 = 4;
116pub const DC_BRICK_COMMUNICATION_METHOD_WIFI: u8 = 5;
117pub const DC_BRICK_COMMUNICATION_METHOD_ETHERNET: u8 = 6;
118pub const DC_BRICK_COMMUNICATION_METHOD_WIFI_V2: u8 = 7;
119
120#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
121pub struct SpitfpBaudrateConfig {
122    pub enable_dynamic_baudrate: bool,
123    pub minimum_dynamic_baudrate: u32,
124}
125impl FromByteSlice for SpitfpBaudrateConfig {
126    fn bytes_expected() -> usize {
127        5
128    }
129    fn from_le_byte_slice(bytes: &[u8]) -> SpitfpBaudrateConfig {
130        SpitfpBaudrateConfig {
131            enable_dynamic_baudrate: <bool>::from_le_byte_slice(&bytes[0..1]),
132            minimum_dynamic_baudrate: <u32>::from_le_byte_slice(&bytes[1..5]),
133        }
134    }
135}
136
137#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
138pub struct SpitfpErrorCount {
139    pub error_count_ack_checksum: u32,
140    pub error_count_message_checksum: u32,
141    pub error_count_frame: u32,
142    pub error_count_overflow: u32,
143}
144impl FromByteSlice for SpitfpErrorCount {
145    fn bytes_expected() -> usize {
146        16
147    }
148    fn from_le_byte_slice(bytes: &[u8]) -> SpitfpErrorCount {
149        SpitfpErrorCount {
150            error_count_ack_checksum: <u32>::from_le_byte_slice(&bytes[0..4]),
151            error_count_message_checksum: <u32>::from_le_byte_slice(&bytes[4..8]),
152            error_count_frame: <u32>::from_le_byte_slice(&bytes[8..12]),
153            error_count_overflow: <u32>::from_le_byte_slice(&bytes[12..16]),
154        }
155    }
156}
157
158#[derive(Clone)]
159pub struct Protocol1BrickletName {
160    pub protocol_version: u8,
161    pub firmware_version: [u8; 3],
162    pub name: String,
163}
164impl FromByteSlice for Protocol1BrickletName {
165    fn bytes_expected() -> usize {
166        44
167    }
168    fn from_le_byte_slice(bytes: &[u8]) -> Protocol1BrickletName {
169        Protocol1BrickletName {
170            protocol_version: <u8>::from_le_byte_slice(&bytes[0..1]),
171            firmware_version: <[u8; 3]>::from_le_byte_slice(&bytes[1..4]),
172            name: <String>::from_le_byte_slice(&bytes[4..44]),
173        }
174    }
175}
176
177#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
178pub struct Identity {
179    pub uid: String,
180    pub connected_uid: String,
181    pub position: char,
182    pub hardware_version: [u8; 3],
183    pub firmware_version: [u8; 3],
184    pub device_identifier: u16,
185}
186impl FromByteSlice for Identity {
187    fn bytes_expected() -> usize {
188        25
189    }
190    fn from_le_byte_slice(bytes: &[u8]) -> Identity {
191        Identity {
192            uid: <String>::from_le_byte_slice(&bytes[0..8]),
193            connected_uid: <String>::from_le_byte_slice(&bytes[8..16]),
194            position: <char>::from_le_byte_slice(&bytes[16..17]),
195            hardware_version: <[u8; 3]>::from_le_byte_slice(&bytes[17..20]),
196            firmware_version: <[u8; 3]>::from_le_byte_slice(&bytes[20..23]),
197            device_identifier: <u16>::from_le_byte_slice(&bytes[23..25]),
198        }
199    }
200}
201
202/// Drives one brushed DC motor with up to 28V and 5A (peak)
203#[derive(Clone)]
204pub struct DcBrick {
205    device: Device,
206}
207impl DcBrick {
208    pub const DEVICE_IDENTIFIER: u16 = 11;
209    pub const DEVICE_DISPLAY_NAME: &'static str = "DC Brick";
210    /// Creates an object with the unique device ID `uid`. This object can then be used after the IP Connection `ip_connection` is connected.
211    pub fn new(uid: Uid, connection: AsyncIpConnection) -> DcBrick {
212        let mut result = DcBrick { device: Device::new([2, 0, 10], uid, connection, Self::DEVICE_DISPLAY_NAME) };
213        result.device.response_expected[u8::from(DcBrickFunction::SetVelocity) as usize] = ResponseExpectedFlag::False;
214        result.device.response_expected[u8::from(DcBrickFunction::GetVelocity) as usize] = ResponseExpectedFlag::AlwaysTrue;
215        result.device.response_expected[u8::from(DcBrickFunction::GetCurrentVelocity) as usize] = ResponseExpectedFlag::AlwaysTrue;
216        result.device.response_expected[u8::from(DcBrickFunction::SetAcceleration) as usize] = ResponseExpectedFlag::False;
217        result.device.response_expected[u8::from(DcBrickFunction::GetAcceleration) as usize] = ResponseExpectedFlag::AlwaysTrue;
218        result.device.response_expected[u8::from(DcBrickFunction::SetPwmFrequency) as usize] = ResponseExpectedFlag::False;
219        result.device.response_expected[u8::from(DcBrickFunction::GetPwmFrequency) as usize] = ResponseExpectedFlag::AlwaysTrue;
220        result.device.response_expected[u8::from(DcBrickFunction::FullBrake) as usize] = ResponseExpectedFlag::False;
221        result.device.response_expected[u8::from(DcBrickFunction::GetStackInputVoltage) as usize] = ResponseExpectedFlag::AlwaysTrue;
222        result.device.response_expected[u8::from(DcBrickFunction::GetExternalInputVoltage) as usize] = ResponseExpectedFlag::AlwaysTrue;
223        result.device.response_expected[u8::from(DcBrickFunction::GetCurrentConsumption) as usize] = ResponseExpectedFlag::AlwaysTrue;
224        result.device.response_expected[u8::from(DcBrickFunction::Enable) as usize] = ResponseExpectedFlag::False;
225        result.device.response_expected[u8::from(DcBrickFunction::Disable) as usize] = ResponseExpectedFlag::False;
226        result.device.response_expected[u8::from(DcBrickFunction::IsEnabled) as usize] = ResponseExpectedFlag::AlwaysTrue;
227        result.device.response_expected[u8::from(DcBrickFunction::SetMinimumVoltage) as usize] = ResponseExpectedFlag::True;
228        result.device.response_expected[u8::from(DcBrickFunction::GetMinimumVoltage) as usize] = ResponseExpectedFlag::AlwaysTrue;
229        result.device.response_expected[u8::from(DcBrickFunction::SetDriveMode) as usize] = ResponseExpectedFlag::False;
230        result.device.response_expected[u8::from(DcBrickFunction::GetDriveMode) as usize] = ResponseExpectedFlag::AlwaysTrue;
231        result.device.response_expected[u8::from(DcBrickFunction::SetCurrentVelocityPeriod) as usize] = ResponseExpectedFlag::True;
232        result.device.response_expected[u8::from(DcBrickFunction::GetCurrentVelocityPeriod) as usize] = ResponseExpectedFlag::AlwaysTrue;
233        result.device.response_expected[u8::from(DcBrickFunction::SetSpitfpBaudrateConfig) as usize] = ResponseExpectedFlag::False;
234        result.device.response_expected[u8::from(DcBrickFunction::GetSpitfpBaudrateConfig) as usize] = ResponseExpectedFlag::AlwaysTrue;
235        result.device.response_expected[u8::from(DcBrickFunction::GetSendTimeoutCount) as usize] = ResponseExpectedFlag::AlwaysTrue;
236        result.device.response_expected[u8::from(DcBrickFunction::SetSpitfpBaudrate) as usize] = ResponseExpectedFlag::False;
237        result.device.response_expected[u8::from(DcBrickFunction::GetSpitfpBaudrate) as usize] = ResponseExpectedFlag::AlwaysTrue;
238        result.device.response_expected[u8::from(DcBrickFunction::GetSpitfpErrorCount) as usize] = ResponseExpectedFlag::AlwaysTrue;
239        result.device.response_expected[u8::from(DcBrickFunction::EnableStatusLed) as usize] = ResponseExpectedFlag::False;
240        result.device.response_expected[u8::from(DcBrickFunction::DisableStatusLed) as usize] = ResponseExpectedFlag::False;
241        result.device.response_expected[u8::from(DcBrickFunction::IsStatusLedEnabled) as usize] = ResponseExpectedFlag::AlwaysTrue;
242        result.device.response_expected[u8::from(DcBrickFunction::GetProtocol1BrickletName) as usize] = ResponseExpectedFlag::AlwaysTrue;
243        result.device.response_expected[u8::from(DcBrickFunction::GetChipTemperature) as usize] = ResponseExpectedFlag::AlwaysTrue;
244        result.device.response_expected[u8::from(DcBrickFunction::Reset) as usize] = ResponseExpectedFlag::False;
245        result.device.response_expected[u8::from(DcBrickFunction::WriteBrickletPlugin) as usize] = ResponseExpectedFlag::False;
246        result.device.response_expected[u8::from(DcBrickFunction::ReadBrickletPlugin) as usize] = ResponseExpectedFlag::AlwaysTrue;
247        result.device.response_expected[u8::from(DcBrickFunction::GetIdentity) as usize] = ResponseExpectedFlag::AlwaysTrue;
248        result
249    }
250
251    /// Returns the response expected flag for the function specified by the function ID parameter.
252    /// It is true if the function is expected to send a response, false otherwise.
253    ///
254    /// For getter functions this is enabled by default and cannot be disabled, because those
255    /// functions will always send a response. For callback configuration functions it is enabled
256    /// by default too, but can be disabled by [`set_response_expected`](crate::dc_brick::DcBrick::set_response_expected).
257    /// For setter functions it is disabled by default and can be enabled.
258    ///
259    /// Enabling the response expected flag for a setter function allows to detect timeouts
260    /// and other error conditions calls of this setter as well. The device will then send a response
261    /// for this purpose. If this flag is disabled for a setter function then no response is sent
262    /// and errors are silently ignored, because they cannot be detected.
263    ///
264    /// See [`set_response_expected`](crate::dc_brick::DcBrick::set_response_expected) for the list of function ID constants available for this function.
265    pub fn get_response_expected(&mut self, fun: DcBrickFunction) -> Result<bool, GetResponseExpectedError> {
266        self.device.get_response_expected(u8::from(fun))
267    }
268
269    /// Changes the response expected flag of the function specified by the function ID parameter.
270    /// This flag can only be changed for setter (default value: false) and callback configuration
271    /// functions (default value: true). For getter functions it is always enabled.
272    ///
273    /// Enabling the response expected flag for a setter function allows to detect timeouts and
274    /// other error conditions calls of this setter as well. The device will then send a response
275    /// for this purpose. If this flag is disabled for a setter function then no response is sent
276    /// and errors are silently ignored, because they cannot be detected.
277    pub fn set_response_expected(&mut self, fun: DcBrickFunction, response_expected: bool) -> Result<(), SetResponseExpectedError> {
278        self.device.set_response_expected(u8::from(fun), response_expected)
279    }
280
281    /// Changes the response expected flag for all setter and callback configuration functions of this device at once.
282    pub fn set_response_expected_all(&mut self, response_expected: bool) {
283        self.device.set_response_expected_all(response_expected)
284    }
285
286    /// Returns the version of the API definition (major, minor, revision) implemented by this API bindings.
287    /// This is neither the release version of this API bindings nor does it tell you anything about the represented Brick or Bricklet.
288    pub fn get_api_version(&self) -> [u8; 3] {
289        self.device.api_version
290    }
291
292    /// This receiver is triggered when the input voltage drops below the value set by
293    /// [`set_minimum_voltage`]. The parameter is the current voltage.
294    ///
295    /// [`set_minimum_voltage`]: #method.set_minimum_voltage
296    pub async fn get_under_voltage_callback_receiver(&mut self) -> impl Stream<Item = u16> {
297        self.device.get_callback_receiver(u8::from(DcBrickFunction::CallbackUnderVoltage)).await.map(|p| u16::from_le_byte_slice(p.body()))
298    }
299
300    /// This receiver is triggered if either the current consumption
301    /// is too high (above 5A) or the temperature of the driver chip is too high
302    /// (above 175°C). These two possibilities are essentially the same, since the
303    /// temperature will reach this threshold immediately if the motor consumes too
304    /// much current. In case of a voltage below 3.3V (external or stack) this
305    /// receiver is triggered as well.
306    ///
307    /// If this receiver is triggered, the driver chip gets disabled at the same time.
308    /// That means, [`enable`] has to be called to drive the motor again.
309    ///
310    /// # Note
311    ///  This receiver only works in Drive/Brake mode (see [`set_drive_mode`]). In
312    ///  Drive/Coast mode it is unfortunately impossible to reliably read the
313    ///  overcurrent/overtemperature signal from the driver chip.
314    pub async fn get_emergency_shutdown_callback_receiver(&mut self) -> impl Stream<Item = ()> {
315        self.device.get_callback_receiver(u8::from(DcBrickFunction::CallbackEmergencyShutdown)).await.map(|_p| ())
316    }
317
318    /// This receiver is triggered whenever a set velocity is reached. For example:
319    /// If a velocity of 0 is present, acceleration is set to 5000 and velocity
320    /// to 10000, the [`get_velocity_reached_callback_receiver`] receiver will be triggered after about
321    /// 2 seconds, when the set velocity is actually reached.
322    ///
323    /// # Note
324    ///  Since we can't get any feedback from the DC motor, this only works if the
325    ///  acceleration (see [`set_acceleration`]) is set smaller or equal to the
326    ///  maximum acceleration of the motor. Otherwise the motor will lag behind the
327    ///  control value and the receiver will be triggered too early.
328    pub async fn get_velocity_reached_callback_receiver(&mut self) -> impl Stream<Item = i16> {
329        self.device
330            .get_callback_receiver(u8::from(DcBrickFunction::CallbackVelocityReached))
331            .await
332            .map(|p| i16::from_le_byte_slice(p.body()))
333    }
334
335    /// This receiver is triggered with the period that is set by
336    /// [`set_current_velocity_period`]. The parameter is the *current*
337    /// velocity used by the motor.
338    ///
339    /// The [`get_current_velocity_callback_receiver`] receiver is only triggered after the set period
340    /// if there is a change in the velocity.
341    pub async fn get_current_velocity_callback_receiver(&mut self) -> impl Stream<Item = i16> {
342        self.device
343            .get_callback_receiver(u8::from(DcBrickFunction::CallbackCurrentVelocity))
344            .await
345            .map(|p| i16::from_le_byte_slice(p.body()))
346    }
347
348    /// Sets the velocity of the motor. Whereas -32767 is full speed backward,
349    /// 0 is stop and 32767 is full speed forward. Depending on the
350    /// acceleration (see [`set_acceleration`]), the motor is not immediately
351    /// brought to the velocity but smoothly accelerated.
352    ///
353    /// The velocity describes the duty cycle of the PWM with which the motor is
354    /// controlled, e.g. a velocity of 3277 sets a PWM with a 10% duty cycle.
355    /// You can not only control the duty cycle of the PWM but also the frequency,
356    /// see [`set_pwm_frequency`].
357    pub async fn set_velocity(&mut self, velocity: i16) -> Result<(), TinkerforgeError> {
358        let mut payload = [0; 2];
359        velocity.write_to_slice(&mut payload[0..2]);
360
361        #[allow(unused_variables)]
362        let result = self.device.set(u8::from(DcBrickFunction::SetVelocity), &payload).await?;
363        Ok(())
364    }
365
366    /// Returns the velocity as set by [`set_velocity`].
367    pub async fn get_velocity(&mut self) -> Result<i16, TinkerforgeError> {
368        let payload = [0; 0];
369
370        #[allow(unused_variables)]
371        let result = self.device.get(u8::from(DcBrickFunction::GetVelocity), &payload).await?;
372        Ok(i16::from_le_byte_slice(result.body()))
373    }
374
375    /// Returns the *current* velocity of the motor. This value is different
376    /// from [`get_velocity`] whenever the motor is currently accelerating
377    /// to a goal set by [`set_velocity`].
378    pub async fn get_current_velocity(&mut self) -> Result<i16, TinkerforgeError> {
379        let payload = [0; 0];
380
381        #[allow(unused_variables)]
382        let result = self.device.get(u8::from(DcBrickFunction::GetCurrentVelocity), &payload).await?;
383        Ok(i16::from_le_byte_slice(result.body()))
384    }
385
386    /// Sets the acceleration of the motor. It is given in *velocity/s*. An
387    /// acceleration of 10000 means, that every second the velocity is increased
388    /// by 10000 (or about 30% duty cycle).
389    ///
390    /// For example: If the current velocity is 0 and you want to accelerate to a
391    /// velocity of 16000 (about 50% duty cycle) in 10 seconds, you should set
392    /// an acceleration of 1600.
393    ///
394    /// If acceleration is set to 0, there is no speed ramping, i.e. a new velocity
395    /// is immediately given to the motor.
396    pub async fn set_acceleration(&mut self, acceleration: u16) -> Result<(), TinkerforgeError> {
397        let mut payload = [0; 2];
398        acceleration.write_to_slice(&mut payload[0..2]);
399
400        #[allow(unused_variables)]
401        let result = self.device.set(u8::from(DcBrickFunction::SetAcceleration), &payload).await?;
402        Ok(())
403    }
404
405    /// Returns the acceleration as set by [`set_acceleration`].
406    pub async fn get_acceleration(&mut self) -> Result<u16, TinkerforgeError> {
407        let payload = [0; 0];
408
409        #[allow(unused_variables)]
410        let result = self.device.get(u8::from(DcBrickFunction::GetAcceleration), &payload).await?;
411        Ok(u16::from_le_byte_slice(result.body()))
412    }
413
414    /// Sets the frequency of the PWM with which the motor is driven.
415    /// Often a high frequency
416    /// is less noisy and the motor runs smoother. However, with a low frequency
417    /// there are less switches and therefore fewer switching losses. Also with
418    /// most motors lower frequencies enable higher torque.
419    ///
420    /// If you have no idea what all this means, just ignore this function and use
421    /// the default frequency, it will very likely work fine.
422    pub async fn set_pwm_frequency(&mut self, frequency: u16) -> Result<(), TinkerforgeError> {
423        let mut payload = [0; 2];
424        frequency.write_to_slice(&mut payload[0..2]);
425
426        #[allow(unused_variables)]
427        let result = self.device.set(u8::from(DcBrickFunction::SetPwmFrequency), &payload).await?;
428        Ok(())
429    }
430
431    /// Returns the PWM frequency as set by [`set_pwm_frequency`].
432    pub async fn get_pwm_frequency(&mut self) -> Result<u16, TinkerforgeError> {
433        let payload = [0; 0];
434
435        #[allow(unused_variables)]
436        let result = self.device.get(u8::from(DcBrickFunction::GetPwmFrequency), &payload).await?;
437        Ok(u16::from_le_byte_slice(result.body()))
438    }
439
440    /// Executes an active full brake.
441    ///
442    /// # Warning
443    ///  This function is for emergency purposes,
444    ///  where an immediate brake is necessary. Depending on the current velocity and
445    ///  the strength of the motor, a full brake can be quite violent.
446    ///
447    /// Call [`set_velocity`] with 0 if you just want to stop the motor.
448    pub async fn full_brake(&mut self) -> Result<(), TinkerforgeError> {
449        let payload = [0; 0];
450
451        #[allow(unused_variables)]
452        let result = self.device.set(u8::from(DcBrickFunction::FullBrake), &payload).await?;
453        Ok(())
454    }
455
456    /// Returns the stack input voltage. The stack input voltage is the
457    /// voltage that is supplied via the stack, i.e. it is given by a
458    /// Step-Down or Step-Up Power Supply.
459    pub async fn get_stack_input_voltage(&mut self) -> Result<u16, TinkerforgeError> {
460        let payload = [0; 0];
461
462        #[allow(unused_variables)]
463        let result = self.device.get(u8::from(DcBrickFunction::GetStackInputVoltage), &payload).await?;
464        Ok(u16::from_le_byte_slice(result.body()))
465    }
466
467    /// Returns the external input voltage. The external input voltage is
468    /// given via the black power input connector on the DC Brick.
469    ///
470    /// If there is an external input voltage and a stack input voltage, the motor
471    /// will be driven by the external input voltage. If there is only a stack
472    /// voltage present, the motor will be driven by this voltage.
473    ///
474    /// # Warning
475    ///  This means, if you have a high stack voltage and a low external voltage,
476    ///  the motor will be driven with the low external voltage. If you then remove
477    ///  the external connection, it will immediately be driven by the high
478    ///  stack voltage.
479    pub async fn get_external_input_voltage(&mut self) -> Result<u16, TinkerforgeError> {
480        let payload = [0; 0];
481
482        #[allow(unused_variables)]
483        let result = self.device.get(u8::from(DcBrickFunction::GetExternalInputVoltage), &payload).await?;
484        Ok(u16::from_le_byte_slice(result.body()))
485    }
486
487    /// Returns the current consumption of the motor.
488    pub async fn get_current_consumption(&mut self) -> Result<u16, TinkerforgeError> {
489        let payload = [0; 0];
490
491        #[allow(unused_variables)]
492        let result = self.device.get(u8::from(DcBrickFunction::GetCurrentConsumption), &payload).await?;
493        Ok(u16::from_le_byte_slice(result.body()))
494    }
495
496    /// Enables the driver chip. The driver parameters can be configured (velocity,
497    /// acceleration, etc) before it is enabled.
498    pub async fn enable(&mut self) -> Result<(), TinkerforgeError> {
499        let payload = [0; 0];
500
501        #[allow(unused_variables)]
502        let result = self.device.set(u8::from(DcBrickFunction::Enable), &payload).await?;
503        Ok(())
504    }
505
506    /// Disables the driver chip. The configurations are kept (velocity,
507    /// acceleration, etc) but the motor is not driven until it is enabled again.
508    ///
509    /// # Warning
510    ///  Disabling the driver chip while the motor is still turning can damage the
511    ///  driver chip. The motor should be stopped calling [`set_velocity`] with 0
512    ///  before disabling the motor power. The [`set_velocity`] function will **not**
513    ///  wait until the motor is actually stopped. You have to explicitly wait for the
514    ///  appropriate time after calling the [`set_velocity`] function before calling
515    ///  the [`disable`] function.
516    pub async fn disable(&mut self) -> Result<(), TinkerforgeError> {
517        let payload = [0; 0];
518
519        #[allow(unused_variables)]
520        let result = self.device.set(u8::from(DcBrickFunction::Disable), &payload).await?;
521        Ok(())
522    }
523
524    /// Returns *true* if the driver chip is enabled, *false* otherwise.
525    pub async fn is_enabled(&mut self) -> Result<bool, TinkerforgeError> {
526        let payload = [0; 0];
527
528        #[allow(unused_variables)]
529        let result = self.device.get(u8::from(DcBrickFunction::IsEnabled), &payload).await?;
530        Ok(bool::from_le_byte_slice(result.body()))
531    }
532
533    /// Sets the minimum voltage, below which the [`get_under_voltage_callback_receiver`] receiver
534    /// is triggered. The minimum possible value that works with the DC Brick is 6V.
535    /// You can use this function to detect the discharge of a battery that is used
536    /// to drive the motor. If you have a fixed power supply, you likely do not need
537    /// this functionality.
538    pub async fn set_minimum_voltage(&mut self, voltage: u16) -> Result<(), TinkerforgeError> {
539        let mut payload = [0; 2];
540        voltage.write_to_slice(&mut payload[0..2]);
541
542        #[allow(unused_variables)]
543        let result = self.device.set(u8::from(DcBrickFunction::SetMinimumVoltage), &payload).await?;
544        Ok(())
545    }
546
547    /// Returns the minimum voltage as set by [`set_minimum_voltage`]
548    pub async fn get_minimum_voltage(&mut self) -> Result<u16, TinkerforgeError> {
549        let payload = [0; 0];
550
551        #[allow(unused_variables)]
552        let result = self.device.get(u8::from(DcBrickFunction::GetMinimumVoltage), &payload).await?;
553        Ok(u16::from_le_byte_slice(result.body()))
554    }
555
556    /// Sets the drive mode. Possible modes are:
557    ///
558    /// * 0 = Drive/Brake
559    /// * 1 = Drive/Coast
560    ///
561    /// These modes are different kinds of motor controls.
562    ///
563    /// In Drive/Brake mode, the motor is always either driving or braking. There
564    /// is no freewheeling. Advantages are: A more linear correlation between
565    /// PWM and velocity, more exact accelerations and the possibility to drive
566    /// with slower velocities.
567    ///
568    /// In Drive/Coast mode, the motor is always either driving or freewheeling.
569    /// Advantages are: Less current consumption and less demands on the motor and
570    /// driver chip.
571    ///
572    /// Associated constants:
573    /// * DC_BRICK_DRIVE_MODE_DRIVE_BRAKE
574    ///	* DC_BRICK_DRIVE_MODE_DRIVE_COAST
575    pub async fn set_drive_mode(&mut self, mode: u8) -> Result<(), TinkerforgeError> {
576        let mut payload = [0; 1];
577        mode.write_to_slice(&mut payload[0..1]);
578
579        #[allow(unused_variables)]
580        let result = self.device.set(u8::from(DcBrickFunction::SetDriveMode), &payload).await?;
581        Ok(())
582    }
583
584    /// Returns the drive mode, as set by [`set_drive_mode`].
585    ///
586    /// Associated constants:
587    /// * DC_BRICK_DRIVE_MODE_DRIVE_BRAKE
588    ///	* DC_BRICK_DRIVE_MODE_DRIVE_COAST
589    pub async fn get_drive_mode(&mut self) -> Result<u8, TinkerforgeError> {
590        let payload = [0; 0];
591
592        #[allow(unused_variables)]
593        let result = self.device.get(u8::from(DcBrickFunction::GetDriveMode), &payload).await?;
594        Ok(u8::from_le_byte_slice(result.body()))
595    }
596
597    /// Sets a period with which the [`get_current_velocity_callback_receiver`] receiver is triggered.
598    /// A period of 0 turns the receiver off.
599    pub async fn set_current_velocity_period(&mut self, period: u16) -> Result<(), TinkerforgeError> {
600        let mut payload = [0; 2];
601        period.write_to_slice(&mut payload[0..2]);
602
603        #[allow(unused_variables)]
604        let result = self.device.set(u8::from(DcBrickFunction::SetCurrentVelocityPeriod), &payload).await?;
605        Ok(())
606    }
607
608    /// Returns the period as set by [`set_current_velocity_period`].
609    pub async fn get_current_velocity_period(&mut self) -> Result<u16, TinkerforgeError> {
610        let payload = [0; 0];
611
612        #[allow(unused_variables)]
613        let result = self.device.get(u8::from(DcBrickFunction::GetCurrentVelocityPeriod), &payload).await?;
614        Ok(u16::from_le_byte_slice(result.body()))
615    }
616
617    /// The SPITF protocol can be used with a dynamic baudrate. If the dynamic baudrate is
618    /// enabled, the Brick will try to adapt the baudrate for the communication
619    /// between Bricks and Bricklets according to the amount of data that is transferred.
620    ///
621    /// The baudrate will be increased exponentially if lots of data is sent/received and
622    /// decreased linearly if little data is sent/received.
623    ///
624    /// This lowers the baudrate in applications where little data is transferred (e.g.
625    /// a weather station) and increases the robustness. If there is lots of data to transfer
626    /// (e.g. Thermal Imaging Bricklet) it automatically increases the baudrate as needed.
627    ///
628    /// In cases where some data has to transferred as fast as possible every few seconds
629    /// (e.g. RS485 Bricklet with a high baudrate but small payload) you may want to turn
630    /// the dynamic baudrate off to get the highest possible performance.
631    ///
632    /// The maximum value of the baudrate can be set per port with the function
633    /// [`set_spitfp_baudrate`]. If the dynamic baudrate is disabled, the baudrate
634    /// as set by [`set_spitfp_baudrate`] will be used statically.
635    ///
636    ///
637    /// .. versionadded:: 2.3.5$nbsp;(Firmware)
638    pub async fn set_spitfp_baudrate_config(
639        &mut self,
640        enable_dynamic_baudrate: bool,
641        minimum_dynamic_baudrate: u32,
642    ) -> Result<(), TinkerforgeError> {
643        let mut payload = [0; 5];
644        enable_dynamic_baudrate.write_to_slice(&mut payload[0..1]);
645        minimum_dynamic_baudrate.write_to_slice(&mut payload[1..5]);
646
647        #[allow(unused_variables)]
648        let result = self.device.set(u8::from(DcBrickFunction::SetSpitfpBaudrateConfig), &payload).await?;
649        Ok(())
650    }
651
652    /// Returns the baudrate config, see [`set_spitfp_baudrate_config`].
653    ///
654    ///
655    /// .. versionadded:: 2.3.5$nbsp;(Firmware)
656    pub async fn get_spitfp_baudrate_config(&mut self) -> Result<SpitfpBaudrateConfig, TinkerforgeError> {
657        let payload = [0; 0];
658
659        #[allow(unused_variables)]
660        let result = self.device.get(u8::from(DcBrickFunction::GetSpitfpBaudrateConfig), &payload).await?;
661        Ok(SpitfpBaudrateConfig::from_le_byte_slice(result.body()))
662    }
663
664    /// Returns the timeout count for the different communication methods.
665    ///
666    /// The methods 0-2 are available for all Bricks, 3-7 only for Master Bricks.
667    ///
668    /// This function is mostly used for debugging during development, in normal operation
669    /// the counters should nearly always stay at 0.
670    ///
671    ///
672    /// .. versionadded:: 2.3.3$nbsp;(Firmware)
673    ///
674    /// Associated constants:
675    /// * DC_BRICK_COMMUNICATION_METHOD_NONE
676    ///	* DC_BRICK_COMMUNICATION_METHOD_USB
677    ///	* DC_BRICK_COMMUNICATION_METHOD_SPI_STACK
678    ///	* DC_BRICK_COMMUNICATION_METHOD_CHIBI
679    ///	* DC_BRICK_COMMUNICATION_METHOD_RS485
680    ///	* DC_BRICK_COMMUNICATION_METHOD_WIFI
681    ///	* DC_BRICK_COMMUNICATION_METHOD_ETHERNET
682    ///	* DC_BRICK_COMMUNICATION_METHOD_WIFI_V2
683    pub async fn get_send_timeout_count(&mut self, communication_method: u8) -> Result<u32, TinkerforgeError> {
684        let mut payload = [0; 1];
685        communication_method.write_to_slice(&mut payload[0..1]);
686
687        #[allow(unused_variables)]
688        let result = self.device.get(u8::from(DcBrickFunction::GetSendTimeoutCount), &payload).await?;
689        Ok(u32::from_le_byte_slice(result.body()))
690    }
691
692    /// Sets the baudrate for a specific Bricklet port.
693    ///
694    /// If you want to increase the throughput of Bricklets you can increase
695    /// the baudrate. If you get a high error count because of high
696    /// interference (see [`get_spitfp_error_count`]) you can decrease the
697    /// baudrate.
698    ///
699    /// If the dynamic baudrate feature is enabled, the baudrate set by this
700    /// function corresponds to the maximum baudrate (see [`set_spitfp_baudrate_config`]).
701    ///
702    /// Regulatory testing is done with the default baudrate. If CE compatibility
703    /// or similar is necessary in your applications we recommend to not change
704    /// the baudrate.
705    ///
706    ///
707    /// .. versionadded:: 2.3.3$nbsp;(Firmware)
708    pub async fn set_spitfp_baudrate(&mut self, bricklet_port: char, baudrate: u32) -> Result<(), TinkerforgeError> {
709        let mut payload = [0; 5];
710        bricklet_port.write_to_slice(&mut payload[0..1]);
711        baudrate.write_to_slice(&mut payload[1..5]);
712
713        #[allow(unused_variables)]
714        let result = self.device.set(u8::from(DcBrickFunction::SetSpitfpBaudrate), &payload).await?;
715        Ok(())
716    }
717
718    /// Returns the baudrate for a given Bricklet port, see [`set_spitfp_baudrate`].
719    ///
720    ///
721    /// .. versionadded:: 2.3.3$nbsp;(Firmware)
722    pub async fn get_spitfp_baudrate(&mut self, bricklet_port: char) -> Result<u32, TinkerforgeError> {
723        let mut payload = [0; 1];
724        bricklet_port.write_to_slice(&mut payload[0..1]);
725
726        #[allow(unused_variables)]
727        let result = self.device.get(u8::from(DcBrickFunction::GetSpitfpBaudrate), &payload).await?;
728        Ok(u32::from_le_byte_slice(result.body()))
729    }
730
731    /// Returns the error count for the communication between Brick and Bricklet.
732    ///
733    /// The errors are divided into
734    ///
735    /// * ACK checksum errors,
736    /// * message checksum errors,
737    /// * framing errors and
738    /// * overflow errors.
739    ///
740    /// The errors counts are for errors that occur on the Brick side. All
741    /// Bricklets have a similar function that returns the errors on the Bricklet side.
742    ///
743    ///
744    /// .. versionadded:: 2.3.3$nbsp;(Firmware)
745    pub async fn get_spitfp_error_count(&mut self, bricklet_port: char) -> Result<SpitfpErrorCount, TinkerforgeError> {
746        let mut payload = [0; 1];
747        bricklet_port.write_to_slice(&mut payload[0..1]);
748
749        #[allow(unused_variables)]
750        let result = self.device.get(u8::from(DcBrickFunction::GetSpitfpErrorCount), &payload).await?;
751        Ok(SpitfpErrorCount::from_le_byte_slice(result.body()))
752    }
753
754    /// Enables the status LED.
755    ///
756    /// The status LED is the blue LED next to the USB connector. If enabled is is
757    /// on and it flickers if data is transfered. If disabled it is always off.
758    ///
759    /// The default state is enabled.
760    ///
761    ///
762    /// .. versionadded:: 2.3.1$nbsp;(Firmware)
763    pub async fn enable_status_led(&mut self) -> Result<(), TinkerforgeError> {
764        let payload = [0; 0];
765
766        #[allow(unused_variables)]
767        let result = self.device.set(u8::from(DcBrickFunction::EnableStatusLed), &payload).await?;
768        Ok(())
769    }
770
771    /// Disables the status LED.
772    ///
773    /// The status LED is the blue LED next to the USB connector. If enabled is is
774    /// on and it flickers if data is transfered. If disabled it is always off.
775    ///
776    /// The default state is enabled.
777    ///
778    ///
779    /// .. versionadded:: 2.3.1$nbsp;(Firmware)
780    pub async fn disable_status_led(&mut self) -> Result<(), TinkerforgeError> {
781        let payload = [0; 0];
782
783        #[allow(unused_variables)]
784        let result = self.device.set(u8::from(DcBrickFunction::DisableStatusLed), &payload).await?;
785        Ok(())
786    }
787
788    /// Returns *true* if the status LED is enabled, *false* otherwise.
789    ///
790    ///
791    /// .. versionadded:: 2.3.1$nbsp;(Firmware)
792    pub async fn is_status_led_enabled(&mut self) -> Result<bool, TinkerforgeError> {
793        let payload = [0; 0];
794
795        #[allow(unused_variables)]
796        let result = self.device.get(u8::from(DcBrickFunction::IsStatusLedEnabled), &payload).await?;
797        Ok(bool::from_le_byte_slice(result.body()))
798    }
799
800    /// Returns the firmware and protocol version and the name of the Bricklet for a
801    /// given port.
802    ///
803    /// This functions sole purpose is to allow automatic flashing of v1.x.y Bricklet
804    /// plugins.
805    pub async fn get_protocol1_bricklet_name(&mut self, port: char) -> Result<Protocol1BrickletName, TinkerforgeError> {
806        let mut payload = [0; 1];
807        port.write_to_slice(&mut payload[0..1]);
808
809        #[allow(unused_variables)]
810        let result = self.device.get(u8::from(DcBrickFunction::GetProtocol1BrickletName), &payload).await?;
811        Ok(Protocol1BrickletName::from_le_byte_slice(result.body()))
812    }
813
814    /// Returns the temperature as measured inside the microcontroller. The
815    /// value returned is not the ambient temperature!
816    ///
817    /// The temperature is only proportional to the real temperature and it has an
818    /// accuracy of ±15%. Practically it is only useful as an indicator for
819    /// temperature changes.
820    pub async fn get_chip_temperature(&mut self) -> Result<i16, TinkerforgeError> {
821        let payload = [0; 0];
822
823        #[allow(unused_variables)]
824        let result = self.device.get(u8::from(DcBrickFunction::GetChipTemperature), &payload).await?;
825        Ok(i16::from_le_byte_slice(result.body()))
826    }
827
828    /// Calling this function will reset the Brick. Calling this function
829    /// on a Brick inside of a stack will reset the whole stack.
830    ///
831    /// After a reset you have to create new device objects,
832    /// calling functions on the existing ones will result in
833    /// undefined behavior!
834    pub async fn reset(&mut self) -> Result<(), TinkerforgeError> {
835        let payload = [0; 0];
836
837        #[allow(unused_variables)]
838        let result = self.device.set(u8::from(DcBrickFunction::Reset), &payload).await?;
839        Ok(())
840    }
841
842    /// Writes 32 bytes of firmware to the bricklet attached at the given port.
843    /// The bytes are written to the position offset * 32.
844    ///
845    /// This function is used by Brick Viewer during flashing. It should not be
846    /// necessary to call it in a normal user program.
847    pub async fn write_bricklet_plugin(&mut self, port: char, offset: u8, chunk: &[u8; 32]) -> Result<(), TinkerforgeError> {
848        let mut payload = [0; 34];
849        port.write_to_slice(&mut payload[0..1]);
850        offset.write_to_slice(&mut payload[1..2]);
851        chunk.write_to_slice(&mut payload[2..34]);
852
853        #[allow(unused_variables)]
854        let result = self.device.set(u8::from(DcBrickFunction::WriteBrickletPlugin), &payload).await?;
855        Ok(())
856    }
857
858    /// Reads 32 bytes of firmware from the bricklet attached at the given port.
859    /// The bytes are read starting at the position offset * 32.
860    ///
861    /// This function is used by Brick Viewer during flashing. It should not be
862    /// necessary to call it in a normal user program.
863    pub async fn read_bricklet_plugin(&mut self, port: char, offset: u8) -> Result<Box<[u8; 32]>, TinkerforgeError> {
864        let mut payload = [0; 2];
865        port.write_to_slice(&mut payload[0..1]);
866        offset.write_to_slice(&mut payload[1..2]);
867
868        #[allow(unused_variables)]
869        let result = self.device.get(u8::from(DcBrickFunction::ReadBrickletPlugin), &payload).await?;
870        Ok(Box::<[u8; 32]>::from_le_byte_slice(result.body()))
871    }
872
873    /// Returns the UID, the UID where the Brick is connected to,
874    /// the position, the hardware and firmware version as well as the
875    /// device identifier.
876    ///
877    /// The position is the position in the stack from '0' (bottom) to '8' (top).
878    ///
879    /// The device identifier numbers can be found [here](device_identifier).
880    /// |device_identifier_constant|
881    pub async fn get_identity(&mut self) -> Result<Identity, TinkerforgeError> {
882        let payload = [0; 0];
883
884        #[allow(unused_variables)]
885        let result = self.device.get(u8::from(DcBrickFunction::GetIdentity), &payload).await?;
886        Ok(Identity::from_le_byte_slice(result.body()))
887    }
888}