changed el3024
This commit is contained in:
1 parent
e5b6c950df
commit
b6f15dc2d2
4 files changed
+184
-173
No files matched your search
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user