tinkerforge_async/bindings/
dc_v2_bricklet.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/Bricklets/DCV2_Bricklet_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 DcV2BrickletFunction {
24    SetEnabled,
25    GetEnabled,
26    SetVelocity,
27    GetVelocity,
28    GetCurrentVelocity,
29    SetMotion,
30    GetMotion,
31    FullBrake,
32    SetDriveMode,
33    GetDriveMode,
34    SetPwmFrequency,
35    GetPwmFrequency,
36    GetPowerStatistics,
37    SetErrorLedConfig,
38    GetErrorLedConfig,
39    SetEmergencyShutdownCallbackConfiguration,
40    GetEmergencyShutdownCallbackConfiguration,
41    SetVelocityReachedCallbackConfiguration,
42    GetVelocityReachedCallbackConfiguration,
43    SetCurrentVelocityCallbackConfiguration,
44    GetCurrentVelocityCallbackConfiguration,
45    GetSpitfpErrorCount,
46    SetBootloaderMode,
47    GetBootloaderMode,
48    SetWriteFirmwarePointer,
49    WriteFirmware,
50    SetStatusLedConfig,
51    GetStatusLedConfig,
52    GetChipTemperature,
53    Reset,
54    WriteUid,
55    ReadUid,
56    GetIdentity,
57    CallbackEmergencyShutdown,
58    CallbackVelocityReached,
59    CallbackCurrentVelocity,
60}
61impl From<DcV2BrickletFunction> for u8 {
62    fn from(fun: DcV2BrickletFunction) -> Self {
63        match fun {
64            DcV2BrickletFunction::SetEnabled => 1,
65            DcV2BrickletFunction::GetEnabled => 2,
66            DcV2BrickletFunction::SetVelocity => 3,
67            DcV2BrickletFunction::GetVelocity => 4,
68            DcV2BrickletFunction::GetCurrentVelocity => 5,
69            DcV2BrickletFunction::SetMotion => 6,
70            DcV2BrickletFunction::GetMotion => 7,
71            DcV2BrickletFunction::FullBrake => 8,
72            DcV2BrickletFunction::SetDriveMode => 9,
73            DcV2BrickletFunction::GetDriveMode => 10,
74            DcV2BrickletFunction::SetPwmFrequency => 11,
75            DcV2BrickletFunction::GetPwmFrequency => 12,
76            DcV2BrickletFunction::GetPowerStatistics => 13,
77            DcV2BrickletFunction::SetErrorLedConfig => 14,
78            DcV2BrickletFunction::GetErrorLedConfig => 15,
79            DcV2BrickletFunction::SetEmergencyShutdownCallbackConfiguration => 16,
80            DcV2BrickletFunction::GetEmergencyShutdownCallbackConfiguration => 17,
81            DcV2BrickletFunction::SetVelocityReachedCallbackConfiguration => 18,
82            DcV2BrickletFunction::GetVelocityReachedCallbackConfiguration => 19,
83            DcV2BrickletFunction::SetCurrentVelocityCallbackConfiguration => 20,
84            DcV2BrickletFunction::GetCurrentVelocityCallbackConfiguration => 21,
85            DcV2BrickletFunction::GetSpitfpErrorCount => 234,
86            DcV2BrickletFunction::SetBootloaderMode => 235,
87            DcV2BrickletFunction::GetBootloaderMode => 236,
88            DcV2BrickletFunction::SetWriteFirmwarePointer => 237,
89            DcV2BrickletFunction::WriteFirmware => 238,
90            DcV2BrickletFunction::SetStatusLedConfig => 239,
91            DcV2BrickletFunction::GetStatusLedConfig => 240,
92            DcV2BrickletFunction::GetChipTemperature => 242,
93            DcV2BrickletFunction::Reset => 243,
94            DcV2BrickletFunction::WriteUid => 248,
95            DcV2BrickletFunction::ReadUid => 249,
96            DcV2BrickletFunction::GetIdentity => 255,
97            DcV2BrickletFunction::CallbackEmergencyShutdown => 22,
98            DcV2BrickletFunction::CallbackVelocityReached => 23,
99            DcV2BrickletFunction::CallbackCurrentVelocity => 24,
100        }
101    }
102}
103pub const DC_V2_BRICKLET_DRIVE_MODE_DRIVE_BRAKE: u8 = 0;
104pub const DC_V2_BRICKLET_DRIVE_MODE_DRIVE_COAST: u8 = 1;
105pub const DC_V2_BRICKLET_ERROR_LED_CONFIG_OFF: u8 = 0;
106pub const DC_V2_BRICKLET_ERROR_LED_CONFIG_ON: u8 = 1;
107pub const DC_V2_BRICKLET_ERROR_LED_CONFIG_SHOW_HEARTBEAT: u8 = 2;
108pub const DC_V2_BRICKLET_ERROR_LED_CONFIG_SHOW_ERROR: u8 = 3;
109pub const DC_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER: u8 = 0;
110pub const DC_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE: u8 = 1;
111pub const DC_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT: u8 = 2;
112pub const DC_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT: u8 = 3;
113pub const DC_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT: u8 = 4;
114pub const DC_V2_BRICKLET_BOOTLOADER_STATUS_OK: u8 = 0;
115pub const DC_V2_BRICKLET_BOOTLOADER_STATUS_INVALID_MODE: u8 = 1;
116pub const DC_V2_BRICKLET_BOOTLOADER_STATUS_NO_CHANGE: u8 = 2;
117pub const DC_V2_BRICKLET_BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT: u8 = 3;
118pub const DC_V2_BRICKLET_BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT: u8 = 4;
119pub const DC_V2_BRICKLET_BOOTLOADER_STATUS_CRC_MISMATCH: u8 = 5;
120pub const DC_V2_BRICKLET_STATUS_LED_CONFIG_OFF: u8 = 0;
121pub const DC_V2_BRICKLET_STATUS_LED_CONFIG_ON: u8 = 1;
122pub const DC_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_HEARTBEAT: u8 = 2;
123pub const DC_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_STATUS: u8 = 3;
124
125#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
126pub struct Motion {
127    pub acceleration: u16,
128    pub deceleration: u16,
129}
130impl FromByteSlice for Motion {
131    fn bytes_expected() -> usize {
132        4
133    }
134    fn from_le_byte_slice(bytes: &[u8]) -> Motion {
135        Motion { acceleration: <u16>::from_le_byte_slice(&bytes[0..2]), deceleration: <u16>::from_le_byte_slice(&bytes[2..4]) }
136    }
137}
138
139#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
140pub struct PowerStatistics {
141    pub voltage: u16,
142    pub current: u16,
143}
144impl FromByteSlice for PowerStatistics {
145    fn bytes_expected() -> usize {
146        4
147    }
148    fn from_le_byte_slice(bytes: &[u8]) -> PowerStatistics {
149        PowerStatistics { voltage: <u16>::from_le_byte_slice(&bytes[0..2]), current: <u16>::from_le_byte_slice(&bytes[2..4]) }
150    }
151}
152
153#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
154pub struct CurrentVelocityCallbackConfiguration {
155    pub period: u32,
156    pub value_has_to_change: bool,
157}
158impl FromByteSlice for CurrentVelocityCallbackConfiguration {
159    fn bytes_expected() -> usize {
160        5
161    }
162    fn from_le_byte_slice(bytes: &[u8]) -> CurrentVelocityCallbackConfiguration {
163        CurrentVelocityCallbackConfiguration {
164            period: <u32>::from_le_byte_slice(&bytes[0..4]),
165            value_has_to_change: <bool>::from_le_byte_slice(&bytes[4..5]),
166        }
167    }
168}
169
170#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
171pub struct SpitfpErrorCount {
172    pub error_count_ack_checksum: u32,
173    pub error_count_message_checksum: u32,
174    pub error_count_frame: u32,
175    pub error_count_overflow: u32,
176}
177impl FromByteSlice for SpitfpErrorCount {
178    fn bytes_expected() -> usize {
179        16
180    }
181    fn from_le_byte_slice(bytes: &[u8]) -> SpitfpErrorCount {
182        SpitfpErrorCount {
183            error_count_ack_checksum: <u32>::from_le_byte_slice(&bytes[0..4]),
184            error_count_message_checksum: <u32>::from_le_byte_slice(&bytes[4..8]),
185            error_count_frame: <u32>::from_le_byte_slice(&bytes[8..12]),
186            error_count_overflow: <u32>::from_le_byte_slice(&bytes[12..16]),
187        }
188    }
189}
190
191#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
192pub struct Identity {
193    pub uid: String,
194    pub connected_uid: String,
195    pub position: char,
196    pub hardware_version: [u8; 3],
197    pub firmware_version: [u8; 3],
198    pub device_identifier: u16,
199}
200impl FromByteSlice for Identity {
201    fn bytes_expected() -> usize {
202        25
203    }
204    fn from_le_byte_slice(bytes: &[u8]) -> Identity {
205        Identity {
206            uid: <String>::from_le_byte_slice(&bytes[0..8]),
207            connected_uid: <String>::from_le_byte_slice(&bytes[8..16]),
208            position: <char>::from_le_byte_slice(&bytes[16..17]),
209            hardware_version: <[u8; 3]>::from_le_byte_slice(&bytes[17..20]),
210            firmware_version: <[u8; 3]>::from_le_byte_slice(&bytes[20..23]),
211            device_identifier: <u16>::from_le_byte_slice(&bytes[23..25]),
212        }
213    }
214}
215
216/// Drives one brushed DC motor with up to 28V and 5A (peak)
217#[derive(Clone)]
218pub struct DcV2Bricklet {
219    device: Device,
220}
221impl DcV2Bricklet {
222    pub const DEVICE_IDENTIFIER: u16 = 2165;
223    pub const DEVICE_DISPLAY_NAME: &'static str = "DC Bricklet 2.0";
224    /// Creates an object with the unique device ID `uid`. This object can then be used after the IP Connection `ip_connection` is connected.
225    pub fn new(uid: Uid, connection: AsyncIpConnection) -> DcV2Bricklet {
226        let mut result = DcV2Bricklet { device: Device::new([2, 0, 10], uid, connection, Self::DEVICE_DISPLAY_NAME) };
227        result.device.response_expected[u8::from(DcV2BrickletFunction::SetEnabled) as usize] = ResponseExpectedFlag::False;
228        result.device.response_expected[u8::from(DcV2BrickletFunction::GetEnabled) as usize] = ResponseExpectedFlag::AlwaysTrue;
229        result.device.response_expected[u8::from(DcV2BrickletFunction::SetVelocity) as usize] = ResponseExpectedFlag::False;
230        result.device.response_expected[u8::from(DcV2BrickletFunction::GetVelocity) as usize] = ResponseExpectedFlag::AlwaysTrue;
231        result.device.response_expected[u8::from(DcV2BrickletFunction::GetCurrentVelocity) as usize] = ResponseExpectedFlag::AlwaysTrue;
232        result.device.response_expected[u8::from(DcV2BrickletFunction::SetMotion) as usize] = ResponseExpectedFlag::False;
233        result.device.response_expected[u8::from(DcV2BrickletFunction::GetMotion) as usize] = ResponseExpectedFlag::AlwaysTrue;
234        result.device.response_expected[u8::from(DcV2BrickletFunction::FullBrake) as usize] = ResponseExpectedFlag::False;
235        result.device.response_expected[u8::from(DcV2BrickletFunction::SetDriveMode) as usize] = ResponseExpectedFlag::False;
236        result.device.response_expected[u8::from(DcV2BrickletFunction::GetDriveMode) as usize] = ResponseExpectedFlag::AlwaysTrue;
237        result.device.response_expected[u8::from(DcV2BrickletFunction::SetPwmFrequency) as usize] = ResponseExpectedFlag::False;
238        result.device.response_expected[u8::from(DcV2BrickletFunction::GetPwmFrequency) as usize] = ResponseExpectedFlag::AlwaysTrue;
239        result.device.response_expected[u8::from(DcV2BrickletFunction::GetPowerStatistics) as usize] = ResponseExpectedFlag::AlwaysTrue;
240        result.device.response_expected[u8::from(DcV2BrickletFunction::SetErrorLedConfig) as usize] = ResponseExpectedFlag::False;
241        result.device.response_expected[u8::from(DcV2BrickletFunction::GetErrorLedConfig) as usize] = ResponseExpectedFlag::AlwaysTrue;
242        result.device.response_expected[u8::from(DcV2BrickletFunction::SetEmergencyShutdownCallbackConfiguration) as usize] =
243            ResponseExpectedFlag::True;
244        result.device.response_expected[u8::from(DcV2BrickletFunction::GetEmergencyShutdownCallbackConfiguration) as usize] =
245            ResponseExpectedFlag::AlwaysTrue;
246        result.device.response_expected[u8::from(DcV2BrickletFunction::SetVelocityReachedCallbackConfiguration) as usize] =
247            ResponseExpectedFlag::True;
248        result.device.response_expected[u8::from(DcV2BrickletFunction::GetVelocityReachedCallbackConfiguration) as usize] =
249            ResponseExpectedFlag::AlwaysTrue;
250        result.device.response_expected[u8::from(DcV2BrickletFunction::SetCurrentVelocityCallbackConfiguration) as usize] =
251            ResponseExpectedFlag::True;
252        result.device.response_expected[u8::from(DcV2BrickletFunction::GetCurrentVelocityCallbackConfiguration) as usize] =
253            ResponseExpectedFlag::AlwaysTrue;
254        result.device.response_expected[u8::from(DcV2BrickletFunction::GetSpitfpErrorCount) as usize] = ResponseExpectedFlag::AlwaysTrue;
255        result.device.response_expected[u8::from(DcV2BrickletFunction::SetBootloaderMode) as usize] = ResponseExpectedFlag::AlwaysTrue;
256        result.device.response_expected[u8::from(DcV2BrickletFunction::GetBootloaderMode) as usize] = ResponseExpectedFlag::AlwaysTrue;
257        result.device.response_expected[u8::from(DcV2BrickletFunction::SetWriteFirmwarePointer) as usize] = ResponseExpectedFlag::False;
258        result.device.response_expected[u8::from(DcV2BrickletFunction::WriteFirmware) as usize] = ResponseExpectedFlag::AlwaysTrue;
259        result.device.response_expected[u8::from(DcV2BrickletFunction::SetStatusLedConfig) as usize] = ResponseExpectedFlag::False;
260        result.device.response_expected[u8::from(DcV2BrickletFunction::GetStatusLedConfig) as usize] = ResponseExpectedFlag::AlwaysTrue;
261        result.device.response_expected[u8::from(DcV2BrickletFunction::GetChipTemperature) as usize] = ResponseExpectedFlag::AlwaysTrue;
262        result.device.response_expected[u8::from(DcV2BrickletFunction::Reset) as usize] = ResponseExpectedFlag::False;
263        result.device.response_expected[u8::from(DcV2BrickletFunction::WriteUid) as usize] = ResponseExpectedFlag::False;
264        result.device.response_expected[u8::from(DcV2BrickletFunction::ReadUid) as usize] = ResponseExpectedFlag::AlwaysTrue;
265        result.device.response_expected[u8::from(DcV2BrickletFunction::GetIdentity) as usize] = ResponseExpectedFlag::AlwaysTrue;
266        result
267    }
268
269    /// Returns the response expected flag for the function specified by the function ID parameter.
270    /// It is true if the function is expected to send a response, false otherwise.
271    ///
272    /// For getter functions this is enabled by default and cannot be disabled, because those
273    /// functions will always send a response. For callback configuration functions it is enabled
274    /// by default too, but can be disabled by [`set_response_expected`](crate::dc_v2_bricklet::DcV2Bricklet::set_response_expected).
275    /// For setter functions it is disabled by default and can be enabled.
276    ///
277    /// Enabling the response expected flag for a setter function allows to detect timeouts
278    /// and other error conditions calls of this setter as well. The device will then send a response
279    /// for this purpose. If this flag is disabled for a setter function then no response is sent
280    /// and errors are silently ignored, because they cannot be detected.
281    ///
282    /// See [`set_response_expected`](crate::dc_v2_bricklet::DcV2Bricklet::set_response_expected) for the list of function ID constants available for this function.
283    pub fn get_response_expected(&mut self, fun: DcV2BrickletFunction) -> Result<bool, GetResponseExpectedError> {
284        self.device.get_response_expected(u8::from(fun))
285    }
286
287    /// Changes the response expected flag of the function specified by the function ID parameter.
288    /// This flag can only be changed for setter (default value: false) and callback configuration
289    /// functions (default value: true). For getter functions it is always enabled.
290    ///
291    /// Enabling the response expected flag for a setter function allows to detect timeouts and
292    /// other error conditions calls of this setter as well. The device will then send a response
293    /// for this purpose. If this flag is disabled for a setter function then no response is sent
294    /// and errors are silently ignored, because they cannot be detected.
295    pub fn set_response_expected(&mut self, fun: DcV2BrickletFunction, response_expected: bool) -> Result<(), SetResponseExpectedError> {
296        self.device.set_response_expected(u8::from(fun), response_expected)
297    }
298
299    /// Changes the response expected flag for all setter and callback configuration functions of this device at once.
300    pub fn set_response_expected_all(&mut self, response_expected: bool) {
301        self.device.set_response_expected_all(response_expected)
302    }
303
304    /// Returns the version of the API definition (major, minor, revision) implemented by this API bindings.
305    /// This is neither the release version of this API bindings nor does it tell you anything about the represented Brick or Bricklet.
306    pub fn get_api_version(&self) -> [u8; 3] {
307        self.device.api_version
308    }
309
310    /// This receiver is triggered if either the current consumption
311    /// is too high (above 5A) or the temperature of the driver chip is too high
312    /// (above 175°C). These two possibilities are essentially the same, since the
313    /// temperature will reach this threshold immediately if the motor consumes too
314    /// much current. In case of a voltage below 3.3V (external or stack) this
315    /// receiver is triggered as well.
316    ///
317    /// If this receiver is triggered, the driver chip gets disabled at the same time.
318    /// That means, [`set_enabled`] has to be called to drive the motor again.
319    ///
320    /// # Note
321    ///  This receiver only works in Drive/Brake mode (see [`set_drive_mode`]). In
322    ///  Drive/Coast mode it is unfortunately impossible to reliably read the
323    ///  overcurrent/overtemperature signal from the driver chip.
324    ///
325    /// [`set_enabled`]: #method.set_enabled
326    /// [`set_drive_mode`]: #method.set_drive_mode
327    pub async fn get_emergency_shutdown_callback_receiver(&mut self) -> impl Stream<Item = ()> {
328        self.device.get_callback_receiver(u8::from(DcV2BrickletFunction::CallbackEmergencyShutdown)).await.map(|_p| ())
329    }
330
331    /// This receiver is triggered whenever a set velocity is reached. For example:
332    /// If a velocity of 0 is present, acceleration is set to 5000 and velocity
333    /// to 10000, the [`get_velocity_reached_callback_receiver`] receiver will be triggered after about
334    /// 2 seconds, when the set velocity is actually reached.
335    ///
336    /// # Note
337    ///  Since we can't get any feedback from the DC motor, this only works if the
338    ///  acceleration (see [`set_motion`]) is set smaller or equal to the
339    ///  maximum acceleration of the motor. Otherwise the motor will lag behind the
340    ///  control value and the receiver will be triggered too early.
341    pub async fn get_velocity_reached_callback_receiver(&mut self) -> impl Stream<Item = i16> {
342        self.device
343            .get_callback_receiver(u8::from(DcV2BrickletFunction::CallbackVelocityReached))
344            .await
345            .map(|p| i16::from_le_byte_slice(p.body()))
346    }
347
348    /// This receiver is triggered with the period that is set by
349    /// [`set_current_velocity_callback_configuration`]. The parameter is the *current*
350    /// velocity used by the motor.
351    ///
352    /// The [`get_current_velocity_callback_receiver`] receiver is only triggered after the set period
353    /// if there is a change in the velocity.
354    pub async fn get_current_velocity_callback_receiver(&mut self) -> impl Stream<Item = i16> {
355        self.device
356            .get_callback_receiver(u8::from(DcV2BrickletFunction::CallbackCurrentVelocity))
357            .await
358            .map(|p| i16::from_le_byte_slice(p.body()))
359    }
360
361    /// Enables/Disables the driver chip. The driver parameters can be configured
362    /// (velocity, acceleration, etc) before it is enabled.
363    pub async fn set_enabled(&mut self, enabled: bool) -> Result<(), TinkerforgeError> {
364        let mut payload = [0; 1];
365        enabled.write_to_slice(&mut payload[0..1]);
366
367        #[allow(unused_variables)]
368        let result = self.device.set(u8::from(DcV2BrickletFunction::SetEnabled), &payload).await?;
369        Ok(())
370    }
371
372    /// Returns *true* if the driver chip is enabled, *false* otherwise.
373    pub async fn get_enabled(&mut self) -> Result<bool, TinkerforgeError> {
374        let payload = [0; 0];
375
376        #[allow(unused_variables)]
377        let result = self.device.get(u8::from(DcV2BrickletFunction::GetEnabled), &payload).await?;
378        Ok(bool::from_le_byte_slice(result.body()))
379    }
380
381    /// Sets the velocity of the motor. Whereas -32767 is full speed backward,
382    /// 0 is stop and 32767 is full speed forward. Depending on the
383    /// acceleration (see [`set_motion`]), the motor is not immediately
384    /// brought to the velocity but smoothly accelerated.
385    ///
386    /// The velocity describes the duty cycle of the PWM with which the motor is
387    /// controlled, e.g. a velocity of 3277 sets a PWM with a 10% duty cycle.
388    /// You can not only control the duty cycle of the PWM but also the frequency,
389    /// see [`set_pwm_frequency`].
390    pub async fn set_velocity(&mut self, velocity: i16) -> Result<(), TinkerforgeError> {
391        let mut payload = [0; 2];
392        velocity.write_to_slice(&mut payload[0..2]);
393
394        #[allow(unused_variables)]
395        let result = self.device.set(u8::from(DcV2BrickletFunction::SetVelocity), &payload).await?;
396        Ok(())
397    }
398
399    /// Returns the velocity as set by [`set_velocity`].
400    pub async fn get_velocity(&mut self) -> Result<i16, TinkerforgeError> {
401        let payload = [0; 0];
402
403        #[allow(unused_variables)]
404        let result = self.device.get(u8::from(DcV2BrickletFunction::GetVelocity), &payload).await?;
405        Ok(i16::from_le_byte_slice(result.body()))
406    }
407
408    /// Returns the *current* velocity of the motor. This value is different
409    /// from [`get_velocity`] whenever the motor is currently accelerating
410    /// to a goal set by [`set_velocity`].
411    pub async fn get_current_velocity(&mut self) -> Result<i16, TinkerforgeError> {
412        let payload = [0; 0];
413
414        #[allow(unused_variables)]
415        let result = self.device.get(u8::from(DcV2BrickletFunction::GetCurrentVelocity), &payload).await?;
416        Ok(i16::from_le_byte_slice(result.body()))
417    }
418
419    /// Sets the acceleration and deceleration of the motor. It is given in *velocity/s*.
420    /// An acceleration of 10000 means, that every second the velocity is increased
421    /// by 10000 (or about 30% duty cycle).
422    ///
423    /// For example: If the current velocity is 0 and you want to accelerate to a
424    /// velocity of 16000 (about 50% duty cycle) in 10 seconds, you should set
425    /// an acceleration of 1600.
426    ///
427    /// If acceleration and deceleration is set to 0, there is no speed ramping, i.e. a
428    /// new velocity is immediately given to the motor.
429    pub async fn set_motion(&mut self, acceleration: u16, deceleration: u16) -> Result<(), TinkerforgeError> {
430        let mut payload = [0; 4];
431        acceleration.write_to_slice(&mut payload[0..2]);
432        deceleration.write_to_slice(&mut payload[2..4]);
433
434        #[allow(unused_variables)]
435        let result = self.device.set(u8::from(DcV2BrickletFunction::SetMotion), &payload).await?;
436        Ok(())
437    }
438
439    /// Returns the acceleration/deceleration as set by [`set_motion`].
440    pub async fn get_motion(&mut self) -> Result<Motion, TinkerforgeError> {
441        let payload = [0; 0];
442
443        #[allow(unused_variables)]
444        let result = self.device.get(u8::from(DcV2BrickletFunction::GetMotion), &payload).await?;
445        Ok(Motion::from_le_byte_slice(result.body()))
446    }
447
448    /// Executes an active full brake.
449    ///
450    /// # Warning
451    ///  This function is for emergency purposes,
452    ///  where an immediate brake is necessary. Depending on the current velocity and
453    ///  the strength of the motor, a full brake can be quite violent.
454    ///
455    /// Call [`set_velocity`] with 0 if you just want to stop the motor.
456    pub async fn full_brake(&mut self) -> Result<(), TinkerforgeError> {
457        let payload = [0; 0];
458
459        #[allow(unused_variables)]
460        let result = self.device.set(u8::from(DcV2BrickletFunction::FullBrake), &payload).await?;
461        Ok(())
462    }
463
464    /// Sets the drive mode. Possible modes are:
465    ///
466    /// * 0 = Drive/Brake
467    /// * 1 = Drive/Coast
468    ///
469    /// These modes are different kinds of motor controls.
470    ///
471    /// In Drive/Brake mode, the motor is always either driving or braking. There
472    /// is no freewheeling. Advantages are: A more linear correlation between
473    /// PWM and velocity, more exact accelerations and the possibility to drive
474    /// with slower velocities.
475    ///
476    /// In Drive/Coast mode, the motor is always either driving or freewheeling.
477    /// Advantages are: Less current consumption and less demands on the motor and
478    /// driver chip.
479    ///
480    /// Associated constants:
481    /// * DC_V2_BRICKLET_DRIVE_MODE_DRIVE_BRAKE
482    ///	* DC_V2_BRICKLET_DRIVE_MODE_DRIVE_COAST
483    pub async fn set_drive_mode(&mut self, mode: u8) -> Result<(), TinkerforgeError> {
484        let mut payload = [0; 1];
485        mode.write_to_slice(&mut payload[0..1]);
486
487        #[allow(unused_variables)]
488        let result = self.device.set(u8::from(DcV2BrickletFunction::SetDriveMode), &payload).await?;
489        Ok(())
490    }
491
492    /// Returns the drive mode, as set by [`set_drive_mode`].
493    ///
494    /// Associated constants:
495    /// * DC_V2_BRICKLET_DRIVE_MODE_DRIVE_BRAKE
496    ///	* DC_V2_BRICKLET_DRIVE_MODE_DRIVE_COAST
497    pub async fn get_drive_mode(&mut self) -> Result<u8, TinkerforgeError> {
498        let payload = [0; 0];
499
500        #[allow(unused_variables)]
501        let result = self.device.get(u8::from(DcV2BrickletFunction::GetDriveMode), &payload).await?;
502        Ok(u8::from_le_byte_slice(result.body()))
503    }
504
505    /// Sets the frequency of the PWM with which the motor is driven.
506    /// Often a high frequency
507    /// is less noisy and the motor runs smoother. However, with a low frequency
508    /// there are less switches and therefore fewer switching losses. Also with
509    /// most motors lower frequencies enable higher torque.
510    ///
511    /// If you have no idea what all this means, just ignore this function and use
512    /// the default frequency, it will very likely work fine.
513    pub async fn set_pwm_frequency(&mut self, frequency: u16) -> Result<(), TinkerforgeError> {
514        let mut payload = [0; 2];
515        frequency.write_to_slice(&mut payload[0..2]);
516
517        #[allow(unused_variables)]
518        let result = self.device.set(u8::from(DcV2BrickletFunction::SetPwmFrequency), &payload).await?;
519        Ok(())
520    }
521
522    /// Returns the PWM frequency as set by [`set_pwm_frequency`].
523    pub async fn get_pwm_frequency(&mut self) -> Result<u16, TinkerforgeError> {
524        let payload = [0; 0];
525
526        #[allow(unused_variables)]
527        let result = self.device.get(u8::from(DcV2BrickletFunction::GetPwmFrequency), &payload).await?;
528        Ok(u16::from_le_byte_slice(result.body()))
529    }
530
531    /// Returns input voltage and current usage of the driver.
532    pub async fn get_power_statistics(&mut self) -> Result<PowerStatistics, TinkerforgeError> {
533        let payload = [0; 0];
534
535        #[allow(unused_variables)]
536        let result = self.device.get(u8::from(DcV2BrickletFunction::GetPowerStatistics), &payload).await?;
537        Ok(PowerStatistics::from_le_byte_slice(result.body()))
538    }
539
540    /// Configures the error LED to be either turned off, turned on, blink in
541    /// heartbeat mode or show an error.
542    ///
543    /// If the LED is configured to show errors it has three different states:
544    ///
545    /// * Off: No error present.
546    /// * 1s interval blinking: Input voltage too low (below 6V).
547    /// * 250ms interval blinking: Overtemperature or overcurrent.
548    ///
549    /// Associated constants:
550    /// * DC_V2_BRICKLET_ERROR_LED_CONFIG_OFF
551    ///	* DC_V2_BRICKLET_ERROR_LED_CONFIG_ON
552    ///	* DC_V2_BRICKLET_ERROR_LED_CONFIG_SHOW_HEARTBEAT
553    ///	* DC_V2_BRICKLET_ERROR_LED_CONFIG_SHOW_ERROR
554    pub async fn set_error_led_config(&mut self, config: u8) -> Result<(), TinkerforgeError> {
555        let mut payload = [0; 1];
556        config.write_to_slice(&mut payload[0..1]);
557
558        #[allow(unused_variables)]
559        let result = self.device.set(u8::from(DcV2BrickletFunction::SetErrorLedConfig), &payload).await?;
560        Ok(())
561    }
562
563    /// Returns the LED configuration as set by [`set_error_led_config`]
564    ///
565    /// Associated constants:
566    /// * DC_V2_BRICKLET_ERROR_LED_CONFIG_OFF
567    ///	* DC_V2_BRICKLET_ERROR_LED_CONFIG_ON
568    ///	* DC_V2_BRICKLET_ERROR_LED_CONFIG_SHOW_HEARTBEAT
569    ///	* DC_V2_BRICKLET_ERROR_LED_CONFIG_SHOW_ERROR
570    pub async fn get_error_led_config(&mut self) -> Result<u8, TinkerforgeError> {
571        let payload = [0; 0];
572
573        #[allow(unused_variables)]
574        let result = self.device.get(u8::from(DcV2BrickletFunction::GetErrorLedConfig), &payload).await?;
575        Ok(u8::from_le_byte_slice(result.body()))
576    }
577
578    /// Enable/Disable [`get_emergency_shutdown_callback_receiver`] receiver.
579    pub async fn set_emergency_shutdown_callback_configuration(&mut self, enabled: bool) -> Result<(), TinkerforgeError> {
580        let mut payload = [0; 1];
581        enabled.write_to_slice(&mut payload[0..1]);
582
583        #[allow(unused_variables)]
584        let result = self.device.set(u8::from(DcV2BrickletFunction::SetEmergencyShutdownCallbackConfiguration), &payload).await?;
585        Ok(())
586    }
587
588    /// Returns the receiver configuration as set by
589    /// [`set_emergency_shutdown_callback_configuration`].
590    pub async fn get_emergency_shutdown_callback_configuration(&mut self) -> Result<bool, TinkerforgeError> {
591        let payload = [0; 0];
592
593        #[allow(unused_variables)]
594        let result = self.device.get(u8::from(DcV2BrickletFunction::GetEmergencyShutdownCallbackConfiguration), &payload).await?;
595        Ok(bool::from_le_byte_slice(result.body()))
596    }
597
598    /// Enable/Disable [`get_velocity_reached_callback_receiver`] receiver.
599    pub async fn set_velocity_reached_callback_configuration(&mut self, enabled: bool) -> Result<(), TinkerforgeError> {
600        let mut payload = [0; 1];
601        enabled.write_to_slice(&mut payload[0..1]);
602
603        #[allow(unused_variables)]
604        let result = self.device.set(u8::from(DcV2BrickletFunction::SetVelocityReachedCallbackConfiguration), &payload).await?;
605        Ok(())
606    }
607
608    /// Returns the receiver configuration as set by
609    /// [`set_velocity_reached_callback_configuration`].
610    pub async fn get_velocity_reached_callback_configuration(&mut self) -> Result<bool, TinkerforgeError> {
611        let payload = [0; 0];
612
613        #[allow(unused_variables)]
614        let result = self.device.get(u8::from(DcV2BrickletFunction::GetVelocityReachedCallbackConfiguration), &payload).await?;
615        Ok(bool::from_le_byte_slice(result.body()))
616    }
617
618    /// The period is the period with which the [`get_current_velocity_callback_receiver`]
619    /// receiver is triggered periodically. A value of 0 turns the receiver off.
620    ///
621    /// If the `value has to change`-parameter is set to true, the receiver is only
622    /// triggered after the value has changed. If the value didn't change within the
623    /// period, the receiver is triggered immediately on change.
624    ///
625    /// If it is set to false, the receiver is continuously triggered with the period,
626    /// independent of the value.
627    pub async fn set_current_velocity_callback_configuration(
628        &mut self,
629        period: u32,
630        value_has_to_change: bool,
631    ) -> Result<(), TinkerforgeError> {
632        let mut payload = [0; 5];
633        period.write_to_slice(&mut payload[0..4]);
634        value_has_to_change.write_to_slice(&mut payload[4..5]);
635
636        #[allow(unused_variables)]
637        let result = self.device.set(u8::from(DcV2BrickletFunction::SetCurrentVelocityCallbackConfiguration), &payload).await?;
638        Ok(())
639    }
640
641    /// Returns the receiver configuration as set by
642    /// [`set_current_velocity_callback_configuration`].
643    pub async fn get_current_velocity_callback_configuration(&mut self) -> Result<CurrentVelocityCallbackConfiguration, TinkerforgeError> {
644        let payload = [0; 0];
645
646        #[allow(unused_variables)]
647        let result = self.device.get(u8::from(DcV2BrickletFunction::GetCurrentVelocityCallbackConfiguration), &payload).await?;
648        Ok(CurrentVelocityCallbackConfiguration::from_le_byte_slice(result.body()))
649    }
650
651    /// Returns the error count for the communication between Brick and Bricklet.
652    ///
653    /// The errors are divided into
654    ///
655    /// * ACK checksum errors,
656    /// * message checksum errors,
657    /// * framing errors and
658    /// * overflow errors.
659    ///
660    /// The errors counts are for errors that occur on the Bricklet side. All
661    /// Bricks have a similar function that returns the errors on the Brick side.
662    pub async fn get_spitfp_error_count(&mut self) -> Result<SpitfpErrorCount, TinkerforgeError> {
663        let payload = [0; 0];
664
665        #[allow(unused_variables)]
666        let result = self.device.get(u8::from(DcV2BrickletFunction::GetSpitfpErrorCount), &payload).await?;
667        Ok(SpitfpErrorCount::from_le_byte_slice(result.body()))
668    }
669
670    /// Sets the bootloader mode and returns the status after the requested
671    /// mode change was instigated.
672    ///
673    /// You can change from bootloader mode to firmware mode and vice versa. A change
674    /// from bootloader mode to firmware mode will only take place if the entry function,
675    /// device identifier and CRC are present and correct.
676    ///
677    /// This function is used by Brick Viewer during flashing. It should not be
678    /// necessary to call it in a normal user program.
679    ///
680    /// Associated constants:
681    /// * DC_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER
682    ///	* DC_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE
683    ///	* DC_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT
684    ///	* DC_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT
685    ///	* DC_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT
686    ///	* DC_V2_BRICKLET_BOOTLOADER_STATUS_OK
687    ///	* DC_V2_BRICKLET_BOOTLOADER_STATUS_INVALID_MODE
688    ///	* DC_V2_BRICKLET_BOOTLOADER_STATUS_NO_CHANGE
689    ///	* DC_V2_BRICKLET_BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT
690    ///	* DC_V2_BRICKLET_BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT
691    ///	* DC_V2_BRICKLET_BOOTLOADER_STATUS_CRC_MISMATCH
692    pub async fn set_bootloader_mode(&mut self, mode: u8) -> Result<u8, TinkerforgeError> {
693        let mut payload = [0; 1];
694        mode.write_to_slice(&mut payload[0..1]);
695
696        #[allow(unused_variables)]
697        let result = self.device.get(u8::from(DcV2BrickletFunction::SetBootloaderMode), &payload).await?;
698        Ok(u8::from_le_byte_slice(result.body()))
699    }
700
701    /// Returns the current bootloader mode, see [`set_bootloader_mode`].
702    ///
703    /// Associated constants:
704    /// * DC_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER
705    ///	* DC_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE
706    ///	* DC_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT
707    ///	* DC_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT
708    ///	* DC_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT
709    pub async fn get_bootloader_mode(&mut self) -> Result<u8, TinkerforgeError> {
710        let payload = [0; 0];
711
712        #[allow(unused_variables)]
713        let result = self.device.get(u8::from(DcV2BrickletFunction::GetBootloaderMode), &payload).await?;
714        Ok(u8::from_le_byte_slice(result.body()))
715    }
716
717    /// Sets the firmware pointer for [`write_firmware`]. The pointer has
718    /// to be increased by chunks of size 64. The data is written to flash
719    /// every 4 chunks (which equals to one page of size 256).
720    ///
721    /// This function is used by Brick Viewer during flashing. It should not be
722    /// necessary to call it in a normal user program.
723    pub async fn set_write_firmware_pointer(&mut self, pointer: u32) -> Result<(), TinkerforgeError> {
724        let mut payload = [0; 4];
725        pointer.write_to_slice(&mut payload[0..4]);
726
727        #[allow(unused_variables)]
728        let result = self.device.set(u8::from(DcV2BrickletFunction::SetWriteFirmwarePointer), &payload).await?;
729        Ok(())
730    }
731
732    /// Writes 64 Bytes of firmware at the position as written by
733    /// [`set_write_firmware_pointer`] before. The firmware is written
734    /// to flash every 4 chunks.
735    ///
736    /// You can only write firmware in bootloader mode.
737    ///
738    /// This function is used by Brick Viewer during flashing. It should not be
739    /// necessary to call it in a normal user program.
740    pub async fn write_firmware(&mut self, data: &[u8; 64]) -> Result<u8, TinkerforgeError> {
741        let mut payload = [0; 64];
742        data.write_to_slice(&mut payload[0..64]);
743
744        #[allow(unused_variables)]
745        let result = self.device.get(u8::from(DcV2BrickletFunction::WriteFirmware), &payload).await?;
746        Ok(u8::from_le_byte_slice(result.body()))
747    }
748
749    /// Sets the status LED configuration. By default the LED shows
750    /// communication traffic between Brick and Bricklet, it flickers once
751    /// for every 10 received data packets.
752    ///
753    /// You can also turn the LED permanently on/off or show a heartbeat.
754    ///
755    /// If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
756    ///
757    /// Associated constants:
758    /// * DC_V2_BRICKLET_STATUS_LED_CONFIG_OFF
759    ///	* DC_V2_BRICKLET_STATUS_LED_CONFIG_ON
760    ///	* DC_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_HEARTBEAT
761    ///	* DC_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_STATUS
762    pub async fn set_status_led_config(&mut self, config: u8) -> Result<(), TinkerforgeError> {
763        let mut payload = [0; 1];
764        config.write_to_slice(&mut payload[0..1]);
765
766        #[allow(unused_variables)]
767        let result = self.device.set(u8::from(DcV2BrickletFunction::SetStatusLedConfig), &payload).await?;
768        Ok(())
769    }
770
771    /// Returns the configuration as set by [`set_status_led_config`]
772    ///
773    /// Associated constants:
774    /// * DC_V2_BRICKLET_STATUS_LED_CONFIG_OFF
775    ///	* DC_V2_BRICKLET_STATUS_LED_CONFIG_ON
776    ///	* DC_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_HEARTBEAT
777    ///	* DC_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_STATUS
778    pub async fn get_status_led_config(&mut self) -> Result<u8, TinkerforgeError> {
779        let payload = [0; 0];
780
781        #[allow(unused_variables)]
782        let result = self.device.get(u8::from(DcV2BrickletFunction::GetStatusLedConfig), &payload).await?;
783        Ok(u8::from_le_byte_slice(result.body()))
784    }
785
786    /// Returns the temperature as measured inside the microcontroller. The
787    /// value returned is not the ambient temperature!
788    ///
789    /// The temperature is only proportional to the real temperature and it has bad
790    /// accuracy. Practically it is only useful as an indicator for
791    /// temperature changes.
792    pub async fn get_chip_temperature(&mut self) -> Result<i16, TinkerforgeError> {
793        let payload = [0; 0];
794
795        #[allow(unused_variables)]
796        let result = self.device.get(u8::from(DcV2BrickletFunction::GetChipTemperature), &payload).await?;
797        Ok(i16::from_le_byte_slice(result.body()))
798    }
799
800    /// Calling this function will reset the Bricklet. All configurations
801    /// will be lost.
802    ///
803    /// After a reset you have to create new device objects,
804    /// calling functions on the existing ones will result in
805    /// undefined behavior!
806    pub async fn reset(&mut self) -> Result<(), TinkerforgeError> {
807        let payload = [0; 0];
808
809        #[allow(unused_variables)]
810        let result = self.device.set(u8::from(DcV2BrickletFunction::Reset), &payload).await?;
811        Ok(())
812    }
813
814    /// Writes a new UID into flash. If you want to set a new UID
815    /// you have to decode the Base58 encoded UID string into an
816    /// integer first.
817    ///
818    /// We recommend that you use Brick Viewer to change the UID.
819    pub async fn write_uid(&mut self, uid: u32) -> Result<(), TinkerforgeError> {
820        let mut payload = [0; 4];
821        uid.write_to_slice(&mut payload[0..4]);
822
823        #[allow(unused_variables)]
824        let result = self.device.set(u8::from(DcV2BrickletFunction::WriteUid), &payload).await?;
825        Ok(())
826    }
827
828    /// Returns the current UID as an integer. Encode as
829    /// Base58 to get the usual string version.
830    pub async fn read_uid(&mut self) -> Result<u32, TinkerforgeError> {
831        let payload = [0; 0];
832
833        #[allow(unused_variables)]
834        let result = self.device.get(u8::from(DcV2BrickletFunction::ReadUid), &payload).await?;
835        Ok(u32::from_le_byte_slice(result.body()))
836    }
837
838    /// Returns the UID, the UID where the Bricklet is connected to,
839    /// the position, the hardware and firmware version as well as the
840    /// device identifier.
841    ///
842    /// The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
843    /// A Bricklet connected to an [Isolator Bricklet](isolator_bricklet) is always at
844    /// position 'z'.
845    ///
846    /// The device identifier numbers can be found [here](device_identifier).
847    /// |device_identifier_constant|
848    pub async fn get_identity(&mut self) -> Result<Identity, TinkerforgeError> {
849        let payload = [0; 0];
850
851        #[allow(unused_variables)]
852        let result = self.device.get(u8::from(DcV2BrickletFunction::GetIdentity), &payload).await?;
853        Ok(Identity::from_le_byte_slice(result.body()))
854    }
855}