changed el3024

This commit is contained in:
93094049+kraemr@users.noreply.github.com committed 2025-03-28 14:38:57 +01:00
1 parent e5b6c950df
commit b6f15dc2d2
4 files changed
+184 -173

No files matched your search

+70 -14
View File
@@ -1,23 +1,40 @@
use crate::{
coe::{ConfigurableDevice, Configuration}, pdo::{
el30xx::{AiCompact, AiStandard},
PredefinedPdoAssignment, TxPdo,
}, shared_config::el30xx::{EL30XXConfiguration, EL30XXPresentation}, signing::Integer16
PredefinedPdoAssignment,
}, shared_config::el30xx::{EL30XXChannelConfiguration, EL30XXPresentation}, signing::Integer16
};
use crate::{
io::analog_input::{AnalogInputDevice, AnalogInputInput, AnalogInputState},
types::EthercrabSubDevicePreoperational,
};
use ethercat_hal_derive::{Device, RxPdo, TxPdo};
use super::{NewDevice, SubDeviceIdentityTuple};
use crate::pdo::RxPdo;
use crate::pdo::TxPdo;
#[derive(Debug, Clone)]
pub struct EL3024Configuration {
pub pdo_assignment: EL3024PdoPreset,
// Input1+ and Input1-
pub channel1 : EL30XXChannelConfiguration,
// Input2+ and Input2-
pub channel2 : EL30XXChannelConfiguration,
// Input3+ and Input3-
pub channel3 : EL30XXChannelConfiguration,
// Input4+ and Input4-
pub channel4 : EL30XXChannelConfiguration
}
#[derive(Device)]
pub struct EL3024 {
pub input_ts: u64,
pub configuration: EL3024Configuration,
pub txpdo: EL3024TxPdo,
pub configuration: EL30XXConfiguration<EL3024PdoPreset,EL3024TxPdo,EL3024RxPdo>,
pub rxpdo: EL3024RxPdo,
pub output_ts: u64,
pub input_ts: u64,
}
impl std::fmt::Debug for EL3024 {
@@ -32,13 +49,27 @@ impl Default for EL3024PdoPreset {
}
}
impl Default for EL3024Configuration {
fn default() -> Self {
Self {
pdo_assignment: EL3024PdoPreset::Standard,
channel1: EL30XXChannelConfiguration::default(),
channel2: EL30XXChannelConfiguration::default(),
channel3: EL30XXChannelConfiguration::default(),
channel4: EL30XXChannelConfiguration::default(),
}
}
}
impl NewDevice for EL3024 {
fn new() -> Self {
let configuration: EL30XXConfiguration<EL3024PdoPreset,EL3024TxPdo,EL3024RxPdo> = EL30XXConfiguration::default();
let configuration = EL3024Configuration::default(); // Initialize first
Self {
input_ts: 0,
configuration: configuration.clone(),
txpdo: configuration.pdo_assignment.txpdo_assignment(),
configuration,
rxpdo: configuration.pdo_assignment.rxpdo_assignment(),
output_ts: 0,
input_ts: 0,
}
}
}
@@ -92,11 +123,22 @@ impl AnalogInputDevice<EL3024Port> for EL3024 {
},
};
let raw_value = Integer16::from(raw_value);
let value: i16 = match self.configuration.presentation {
println!("{}",raw_value);
let presentation = match port {
EL3024Port::AI1 => self.configuration.channel1.presentation,
EL3024Port::AI2 => self.configuration.channel2.presentation,
EL3024Port::AI3 => self.configuration.channel3.presentation,
EL3024Port::AI4 => self.configuration.channel4.presentation
};
let value: i16 = match presentation {
EL30XXPresentation::Unsigned => raw_value.into_unsigned() as i16,
EL30XXPresentation::Signed => raw_value.into_signed(),
EL30XXPresentation::SignedMagnitude => raw_value.into_signed_magnitude(),
};
let normalized = f32::from(value) / f32::from(i16::MAX);
AnalogInputState {
input_ts: self.input_ts,
@@ -105,11 +147,11 @@ impl AnalogInputDevice<EL3024Port> for EL3024 {
}
}
impl ConfigurableDevice<EL30XXConfiguration<EL3024PdoPreset,EL3024TxPdo,EL3024RxPdo>> for EL3024 {
impl ConfigurableDevice<EL3024Configuration> for EL3024 {
async fn write_config<'maindevice>(
&mut self,
device: &EthercrabSubDevicePreoperational<'maindevice>,
config: &EL30XXConfiguration<EL3024PdoPreset,EL3024TxPdo,EL3024RxPdo>,
config: &EL3024Configuration,
) -> Result<(), anyhow::Error> {
config.write_config(device).await?;
self.configuration = config.clone();
@@ -117,7 +159,7 @@ impl ConfigurableDevice<EL30XXConfiguration<EL3024PdoPreset,EL3024TxPdo,EL3024Rx
Ok(())
}
fn get_config(&self) -> EL30XXConfiguration<EL3024PdoPreset,EL3024TxPdo,EL3024RxPdo> {
fn get_config(&self) -> EL3024Configuration {
self.configuration.clone()
}
}
@@ -156,12 +198,26 @@ pub struct EL3024TxPdo {
#[derive(Debug, Clone, RxPdo)]
pub struct EL3024RxPdo {}
impl Configuration for EL30XXConfiguration<EL3024PdoPreset,EL3024TxPdo,EL3024RxPdo> {
impl Configuration for EL3024Configuration {
async fn write_config<'a>(
&self,
device: &EthercrabSubDevicePreoperational<'a>,
) -> Result<(), anyhow::Error> {
// Write configuration for Channel 1
self.channel1.write_channel_config(device, 0x8000)
.await?;
// Write configuration for Channel 2
self.channel2.write_channel_config(device, 0x8010)
.await?;
// Write configuration for Channel 3
self.channel3.write_channel_config(device, 0x8020)
.await?;
// Write configuration for Channel 4
self.channel4.write_channel_config(device, 0x8030)
.await?;
self.pdo_assignment
.txpdo_assignment()
.write_config(device)
+103 -155
View File
@@ -1,178 +1,131 @@
use crate::coe::Configuration;
use crate::pdo::PredefinedPdoAssignment;
use crate::types::EthercrabSubDevicePreoperational;
use std::marker::PhantomData; // needed to avoid compile error
/// 0x8000 CoE
#[derive(Debug, Clone)]
pub struct EL30XXConfiguration<T,A,B> where T:PredefinedPdoAssignment<A,B> {
/// # 0x8000:01
/// Enable user scale
///
/// default: `false`
pub enable_user_scale: bool,
/// # 0x8000:02
/// Presentation
///
/// default: `Signed`
pub presentation: EL30XXPresentation,
/// # 0x8000:05
/// Siemens bits
///
/// default: `false`
pub siemens_bits: bool,
/// # 0x8000:06
/// Enable filter
///
/// default: `true`
pub enable_filter: bool,
/// # 0x8000:07
/// Enable limit 1
///
/// default: `false`
pub enable_limit_1: bool,
/// # 0x8000:08
/// Enable limit 2
///
/// default: `false`
pub enable_limit_2: bool,
/// # 0x8000:0A
/// Enable user calibration
///
/// default: `false`
pub enable_user_calibration: bool,
/// # 0x8000:0B
/// Enable vendor calibration
///
/// default: `true`
pub enable_vendor_calibration: bool,
/// # 0x8000:0E
/// Swap limit bits
///
/// default: `false`
pub swap_limit_bits: bool,
/// # 0x8000:11
/// User scale offset
///
/// default: `0`
pub user_scale_offset: i16,
/// # 0x8000:12
/// User scale gain
///
/// default: `65536`
pub user_scale_gain: i32,
/// # 0x8000:13
/// Limit 1
///
/// default: `0`
pub limit_1: i16,
/// # 0x8000:14
/// Limit 2
///
/// default: `0`
pub limit_2: i16,
/// # 0x8000:15
/// Filter settings
///
/// default: `50 Hz FIR`
pub filter_settings: EL30XXFilterSettings,
/// # 0x8000:17
/// User calibration offset
///
/// default: `0`
pub user_calibration_offset: i16,
/// # 0x8000:18
/// User calibration gain
///
/// default: `16384`
pub user_calibration_gain: i16,
/// # 0x1400 & 0x1600
pub pdo_assignment: T,
// PhantomData ensures A and B are "used" without being stored
pub _marker_a: PhantomData<A>, // needed to avoid compile error
pub _marker_b: PhantomData<B>, // needed to avoid compile error
}
impl<T, A, B> Configuration for EL30XXConfiguration<T, A, B>
where
T: PredefinedPdoAssignment<A, B> + Configuration,
A: Configuration, // Ensures pdo_assignment can call write_config()
B: Configuration
{
async fn write_config<'a>(
impl EL30XXChannelConfiguration {
pub async fn write_channel_config<'a>(
&self,
device: &EthercrabSubDevicePreoperational<'a>,
base_index: u16,
) -> Result<(), anyhow::Error> {
device
.sdo_write(0x8000, 0x01, self.enable_user_scale)
.sdo_write(base_index, 0x01, self.enable_user_scale)
.await?;
device
.sdo_write(0x8000, 0x02, u8::from(self.presentation))
.sdo_write(base_index, 0x02, u8::from(self.presentation))
.await?;
device.sdo_write(0x8000, 0x05, self.siemens_bits).await?;
device.sdo_write(0x8000, 0x06, self.enable_filter).await?;
device.sdo_write(0x8000, 0x07, self.enable_limit_1).await?;
device.sdo_write(0x8000, 0x08, self.enable_limit_2).await?;
device.sdo_write(base_index, 0x05, self.siemens_bits).await?;
device.sdo_write(base_index, 0x06, self.enable_filter).await?;
device.sdo_write(base_index, 0x07, self.enable_limit_1).await?;
device.sdo_write(base_index, 0x08, self.enable_limit_2).await?;
device
.sdo_write(0x8000, 0x0A, self.enable_user_calibration)
.sdo_write(base_index, 0x0A, self.enable_user_calibration)
.await?;
device
.sdo_write(0x8000, 0x0B, self.enable_vendor_calibration)
.sdo_write(base_index, 0x0B, self.enable_vendor_calibration)
.await?;
device.sdo_write(0x8000, 0x0E, self.swap_limit_bits).await?;
device.sdo_write(base_index, 0x0E, self.swap_limit_bits).await?;
device
.sdo_write(0x8000, 0x11, self.user_scale_offset)
.sdo_write(base_index, 0x11, self.user_scale_offset)
.await?;
device.sdo_write(0x8000, 0x12, self.user_scale_gain).await?;
device.sdo_write(0x8000, 0x13, self.limit_1).await?;
device.sdo_write(0x8000, 0x14, self.limit_2).await?;
device.sdo_write(base_index, 0x12, self.user_scale_gain).await?;
device.sdo_write(base_index, 0x13, self.limit_1).await?;
device.sdo_write(base_index, 0x14, self.limit_2).await?;
device
.sdo_write(0x8000, 0x15, u16::from(self.filter_settings))
.sdo_write(base_index, 0x15, u16::from(self.filter_settings))
.await?;
device
.sdo_write(0x8000, 0x17, self.user_calibration_offset)
.sdo_write(base_index, 0x17, self.user_calibration_offset)
.await?;
device
.sdo_write(0x8000, 0x18, self.user_calibration_gain)
.await?;
self.pdo_assignment
.txpdo_assignment()
.write_config(device)
.await?;
self.pdo_assignment
.rxpdo_assignment()
.write_config(device)
.sdo_write(base_index, 0x18, self.user_calibration_gain)
.await?;
Ok(())
}
}
impl<T, A, B> Default for EL30XXConfiguration<T, A, B>
where
T: PredefinedPdoAssignment<A, B>,
T: Default, // Ensure `T` has a default value
#[derive(Debug, Clone)]
pub struct EL30XXChannelConfiguration {
// 80n0:01 User Scaling is Active
pub enable_user_scale : bool,
// 80n0:02
// 0: Signed presentation
// 1: Unsigned presentation
// 2: Absolute value with MSB as sign
// Signed amount representation
pub presentation : EL30XXPresentation,
// 80n0:03
// the S5 bits are displayed in the three low-order bits
pub siemens_bits : bool,
// 80n0:04
// Enable filter, which makes PLC-cycle-synchronous
// data exchange unnecessary
pub enable_filter : bool,
// 80n0:05
// limit 1 enabled
pub enable_limit_1 : bool,
// 80n0:06
// limit2 enabled
pub enable_limit_2 : bool,
// 80n0:07
// enabling of user_calibration
pub enable_user_calibration : bool,
// 80n0:08
// enabling of vendor_calibration
pub enable_vendor_calibration : bool,
// 80n0:09
// Swap Limit Bits
pub swap_limit_bits : bool,
// 80n0:10
// User Scaling Offset
pub user_scale_offset : i16,
// 80n0:11
// Gain of the user scaling
// The gain has a fixed-point-representation with the factor
// 2^-16 The value 1 corresponds to 65535 and is limited to +/- 0x7FFFFF
pub user_scale_gain : i32,
// 80n0:12
// First limit value for setting the status bits
pub limit_1: i16,
// 80n0:13
// Second limit value for setting the status bits
pub limit_2: i16,
// 80n0:14
/*
This object determines the digital filter settings if it is
active via Enable filter (Index base_index:06 [} 320]).
The possible settings are numbered consecutively.
0: 50 Hz FIR
1: 60 Hz FIR
2: IIR 1
3: IIR 2
...
9: IIR 8
*/
pub filter_settings: EL30XXFilterSettings,
// 80n0:15
// User calibration offset
pub user_calibration_offset: i16,
// 80n0:16
// User calibration gain
pub user_calibration_gain: i16
}
impl Default for EL30XXChannelConfiguration
{
fn default() -> Self {
Self {
@@ -191,16 +144,11 @@ where
limit_2: 0,
filter_settings: EL30XXFilterSettings::FIR50Hz,
user_calibration_offset: 0,
user_calibration_gain: 16384,
pdo_assignment: T::default(), // Use the default for `T`
_marker_a: PhantomData, // needed to avoid compile error
_marker_b: PhantomData // needed to avoid compile error
user_calibration_gain: 16384,
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum EL30XXPresentation {
Signed,
+9 -1
View File
@@ -7,11 +7,14 @@ use crate::{
ethercat::config::{MAX_FRAMES, MAX_PDU_DATA, MAX_SUBDEVICES, PDI_LEN},
};
use bitvec::prelude::*;
use control_core::actors::analog_input_getter::{AnalogInputDevice, AnalogInputGetter};
use control_core::actors::Actor;
use control_core::identification::identify_device_groups;
use control_core::socketio::event::EventBuilder;
use control_core::socketio::room::RoomCacheingLogic;
use ethercat_hal::devices::devices_from_subdevices;
use ethercat_hal::devices::el3024::{EL3024Port, EL3024};
use ethercat_hal::devices::{devices_from_subdevices, downcast_device};
use ethercat_hal::io::analog_input::AnalogInput;
use ethercrab::std::{ethercat_now, tx_rx_task};
use ethercrab::{MainDevice, MainDeviceConfig, PduStorage, RetryBehaviour, Timeouts};
use smol::lock::RwLock;
@@ -133,6 +136,11 @@ pub async fn setup_loop(interface: &str, app_state: Arc<AppState>) -> Result<(),
}
}
let el3024 = downcast_device::<EL3024>(devices.get(1).unwrap().clone()).await.unwrap();
let analog_input = AnalogInput::new(el3024, EL3024Port::AI1);
let analog_input_getter = AnalogInputGetter::new(analog_input, AnalogInputDevice::EL305x.into());
actors.push(Arc::new(RwLock::new(analog_input_getter)));
// Write all this stuff to `app_state`
{
let mut ethercat_setup_guard = app_state.ethercat_setup.write().await;
+2 -3
View File
@@ -16,7 +16,7 @@ use ethercat_hal::devices::el2521::{EL2521Configuration, EL2521Port, EL2521};
use ethercat_hal::devices::el2522::{
EL2522ChannelConfiguration, EL2522Configuration, EL2522Port, EL2522,
};
use ethercat_hal::devices::el3001::{EL3001PdoPreset, EL3001Port, EL3001};
use ethercat_hal::devices::el3001::{EL3001Configuration, EL3001PdoPreset, EL3001Port, EL3001};
use ethercat_hal::devices::{downcast_device, subdevice_identity_to_tuple, Device};
use ethercat_hal::devices::{
ek1100::EK1100_IDENTITY_A,
@@ -28,7 +28,6 @@ use ethercat_hal::devices::{
use ethercat_hal::io::analog_input::AnalogInput;
use ethercat_hal::io::digital_output::DigitalOutput;
use ethercat_hal::io::pulse_train_output::PulseTrainOutput;
use ethercat_hal::shared_config::el30xx::EL30XXConfiguration;
use ethercat_hal::types::EthercrabSubDevicePreoperational;
use futures::executor::block_on;
use smol::lock::RwLock;
@@ -120,7 +119,7 @@ impl MachineNewTrait for WinderV1 {
.await
.write_config(
&subdevice,
&EL30XXConfiguration {
&EL3001Configuration {
pdo_assignment: EL3001PdoPreset::Compact,
..Default::default()
},