traited sdo writing #251
Replies: 2 comments 2 replies
-
Better SDO init is something I would very much like in EtherCrab. The current API is a low level, simple implementation to just get a feel for how everything needs to work. That said, I'm not sure what a higher level design should look like right now. I need to begin implementing a better DS402 interface soon and that work will either include or guide a higher level SDO init API, so while it's a bit painful in its current state, please save your efforts in writing a new API method :) |
Beta Was this translation helpful? Give feedback.
-
For more future references, I made a simple trait to make type safe configuration of sdo parameters, using the above trait. #[macro_export]
macro_rules! define_value_type_internal {
(
$name:ident,
$type:ty,
$bytes:expr,
$bits:expr,
$default:expr,
$index:expr,
$subindex:expr
) => {
#[derive(
Debug,
ethercrab_wire::EtherCrabWireWrite,
serde::Serialize,
serde::Deserialize,
schemars::JsonSchema,
Copy,
Clone,
)]
#[wire(bytes = $bytes)]
#[serde(transparent)]
struct $name {
#[wire(bits = $bits)]
value: $type,
}
impl Default for $name {
fn default() -> Self {
Self { value: $default }
}
}
impl Index for $name {
const INDEX: u16 = $index;
const SUBINDEX: u8 = $subindex;
}
};
}
#[macro_export]
macro_rules! define_value_type {
($name:ident, u16, $default:expr, $index:expr, $subindex:expr) => {
$crate::define_value_type_internal!($name, u16, 2, 16, $default, $index, $subindex);
};
($name:ident, u32, $default:expr, $index:expr, $subindex:expr) => {
$crate::define_value_type_internal!($name, u32, 4, 32, $default, $index, $subindex);
};
($name:ident, f32, $default:expr, $index:expr, $subindex:expr) => {
$crate::define_value_type_internal!($name, f32, 4, 32, $default, $index, $subindex);
};
} Example of usage, // Struct name, value type, default value, index, subindex
define_value_type!(NominalValue, f32, 1.0, 0x8000, 0x23);
define_value_type!(Gravity, f32, 9.806650, 0x8000, 0x26);
define_value_type!(ZeroBalance, f32, 0.0, 0x8000, 0x25);
#[derive(Serialize, Deserialize, JsonSchema, Debug)]
struct Config {
filter: Filter,
nominal_load: f32, // kg
calibration_load: f32, // kg
#[schemars(
description = "Nominal characteristic value of the sensor element, Set to 1 if you wan't raw value from load cell. mV/V"
)]
nominal_value: Option<NominalValue>,
#[schemars(
description = "Gravity of earth, default: None is 9.80665 m/s^2. Set to 1 if you want raw value from load cell"
)]
gravity: Option<Gravity>,
#[schemars(
description = "Zero balance of the sensor element. mV/V. Set to 0 if you want raw value from load cell"
)]
zero_balance: Option<ZeroBalance>,
}
async fn setup<'maindevice, 'group>(
&mut self,
device: &mut SubDeviceRef<'maindevice, AtomicRefMut<'group, SubDevice>>,
) -> Result<(), Box<dyn Error>> {
if let Some(nominal_value) = self.config.read().nominal_value {
device.sdo_write_value_index(nominal_value).await?;
}
if let Some(gravity) = self.config.read().gravity {
device.sdo_write_value_index(gravity).await?;
}
if let Some(zero_balance) = self.config.read().zero_balance {
device.sdo_write_value_index(zero_balance).await?;
}
} Not related to the subject but I am really sad that metaprogramming features of rust are so far from cpp. |
Beta Was this translation helpful? Give feedback.
-
Prereq, let's use this enum for example purposes:
I found it to be repetative to write the following, since I write filter in
So I added those two traits
So then I could use it like the following:
Is this something you would like added to ethercrab?
If so I can make a PR, and the namings can be discussed.
Beta Was this translation helpful? Give feedback.
All reactions