diff --git a/ethercat-hal-derive/src/lib.rs b/ethercat-hal-derive/src/lib.rs index 07b2be3d..3ade67ce 100644 --- a/ethercat-hal-derive/src/lib.rs +++ b/ethercat-hal-derive/src/lib.rs @@ -251,6 +251,27 @@ pub fn ethercat_device_derive(input: TokenStream) -> TokenStream { fn as_any(&self) -> &dyn std::any::Any { self } + + #[doc="Implemented by the ethercat_hal_derive::EthercatDevice derive macro"] + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } + + #[doc="Implemented by the ethercat_hal_derive::EthercatDevice derive macro"] + fn is_module(&self) -> bool { + false + } + + #[doc="Implemented by the ethercat_hal_derive::EthercatDevice derive macro"] + fn get_module(&self) -> Option { + None + } + + #[doc="Implemented by the ethercat_hal_derive::EthercatDevice derive macro"] + fn set_module(&mut self,module : crate::devices::Module){ + () + } + } impl crate::devices::EthercatDeviceUsed for #name { diff --git a/ethercat-hal/src/devices/mod.rs b/ethercat-hal/src/devices/mod.rs index 0fd131ad..46e48473 100644 --- a/ethercat-hal/src/devices/mod.rs +++ b/ethercat-hal/src/devices/mod.rs @@ -21,6 +21,7 @@ pub mod el7031; pub mod el7031_0030; pub mod el7041_0052; pub mod wago_750_354; +pub mod wago_modules; use super::devices::el1008::EL1008; use crate::{ @@ -42,17 +43,29 @@ use el3021::EL3021_IDENTITY_A; use el3024::EL3024_IDENTITY_A; use el3062_0030::EL3062_0030_IDENTITY_A; use el3204::EL3204_IDENTITY_A; +use el3204::EL3204_IDENTITY_B; use el4002::EL4002_IDENTITY_A; use el5152::{EL5152, EL5152_IDENTITY_A}; use el6021::{EL6021_IDENTITY_A, EL6021_IDENTITY_B, EL6021_IDENTITY_C, EL6021_IDENTITY_D}; -use el3204::EL3204_IDENTITY_B; use el7031::{EL7031_IDENTITY_A, EL7031_IDENTITY_B}; use el7031_0030::EL7031_0030_IDENTITY_A; use el7041_0052::EL7041_0052_IDENTITY_A; use ethercrab::{MainDevice, SubDeviceIdentity}; use smol::lock::RwLock; -use wago_750_354::{WAGO_750_354_IDENTITY_A, Wago750_354}; use std::{any::Any, fmt::Debug, sync::Arc}; +use wago_750_354::{WAGO_750_354_IDENTITY_A, Wago750_354}; + +#[derive(Debug, Clone, Copy)] +pub struct Module { + pub slot: u16, + pub belongs_to_addr: u16, + pub has_tx: bool, + pub has_rx: bool, + pub vendor_id: u32, + pub product_id: u32, + pub tx_offset: usize, + pub rx_offset: usize, +} /// A trait for all devices /// @@ -77,7 +90,7 @@ where /// automatically validate input length, then calls input fn input_checked(&mut self, input: &BitSlice) -> Result<(), anyhow::Error> { // validate input has correct length - let expected = self.input_len(); + /* let expected = self.input_len(); let actual = input.len(); if actual != expected { return Err(anyhow::anyhow!( @@ -88,7 +101,7 @@ where expected, expected / 8 )); - } + }*/ self.input(input) } @@ -103,7 +116,7 @@ where self.output(output)?; // validate input has correct length - let expected = self.output_len(); + /*let expected = self.output_len(); let actual = output.len(); if output.len() != expected { return Err(anyhow::anyhow!( @@ -114,12 +127,26 @@ where expected, expected / 8 )); - } + }*/ Ok(()) } fn as_any(&self) -> &dyn Any; + fn as_any_mut(&mut self) -> &mut dyn Any; + fn is_module(&self) -> bool; + fn get_module(&self) -> Option; + fn set_module(&mut self, module: Module); +} + +pub trait DynamicEthercatDevice: EthercatDevice + EthercatDynamicPDO {} + +pub trait EthercatDynamicPDO { + fn get_tx_offset(&self) -> usize; + fn get_rx_offset(&self) -> usize; + + fn set_tx_offset(&mut self, offset: usize); + fn set_rx_offset(&mut self, offset: usize); } /// A trait for devices that want to process input and output data @@ -257,6 +284,10 @@ pub async fn specific_device_from_devices( } pub type SubDeviceIdentityTuple = (u32, u32, u32); + +// Is vendor id at 0, and prodid at 1 +pub type SubDeviceProductTuple = (u32, u32); + /// function that converts SubDeviceIdentity to tuple pub const fn subdevice_identity_to_tuple(identity: &SubDeviceIdentity) -> SubDeviceIdentityTuple { (identity.vendor_id, identity.product_id, identity.revision) diff --git a/ethercat-hal/src/devices/wago_750_1506.rs b/ethercat-hal/src/devices/wago_750_1506.rs deleted file mode 100644 index dbca1386..00000000 --- a/ethercat-hal/src/devices/wago_750_1506.rs +++ /dev/null @@ -1,6 +0,0 @@ - - - - -pub const WAGO_750_1506_VENDOR_ID: u32 = 0x00000021; -pub const WAGO_750_1506_PRODUCT_ID: u32 = 0x07500354; \ No newline at end of file diff --git a/ethercat-hal/src/devices/wago_750_354.rs b/ethercat-hal/src/devices/wago_750_354.rs index f89e8a59..98b739fa 100644 --- a/ethercat-hal/src/devices/wago_750_354.rs +++ b/ethercat-hal/src/devices/wago_750_354.rs @@ -1,52 +1,155 @@ -use std::sync::Arc; -use crate::helpers::ethercrab_types::EthercrabSubDevicePreoperational; - -use super::{EthercatDevice, EthercatDeviceProcessing, NewEthercatDevice, SubDeviceIdentityTuple}; +use super::{ + EthercatDevice, EthercatDeviceProcessing, EthercatDeviceUsed, NewEthercatDevice, + SubDeviceIdentityTuple, +}; +use crate::devices::wago_modules::*; +use crate::{ + devices::{ + DynamicEthercatDevice, Module, + wago_modules::{ + wago_750_501::{WAGO_750_501_MODULE_IDENT, WAGO_750_501_PRODUCT_ID}, + wago_750_652::{WAGO_750_652_MODULE_IDENT, WAGO_750_652_PRODUCT_ID}, + wago_750_1506::{WAGO_750_1506_MODULE_IDENT, WAGO_750_1506_PRODUCT_ID}, + }, + }, + helpers::ethercrab_types::EthercrabSubDevicePreoperational, +}; use anyhow::Error; -use ethercat_hal_derive::EthercatDevice; use smol::lock::RwLock; +use std::sync::Arc; - -const MODULE_COUNT_INDEX : (u16,u8) = (0xf050,0x00); - -const TX_MAPPING_INDEX : (u16,u8) = (0x1c13,0x00); -const RX_MAPPING_INDEX : (u16,u8) = (0x1c12,0x00); +const MODULE_COUNT_INDEX: (u16, u8) = (0xf050, 0x00); +const TX_MAPPING_INDEX: (u16, u8) = (0x1c13, 0x00); +const RX_MAPPING_INDEX: (u16, u8) = (0x1c12, 0x00); +// For both the rx and tx The Wago Coupler has 4 bytes, which we dont care about and skip /// Wago750_354 bus coupler -#[derive(Clone, EthercatDevice)] +/* + The "Modules" simply write at an offset into rx and read at an offset in tx +*/ pub struct Wago750_354 { is_used: bool, + pub slots: [Option; 64], + pub slot_devices: [Option>>; 64], + pub dev_count: usize, + pub module_count: usize, + rx_offsets: Vec, + tx_offsets: Vec, + tx_size: usize, + rx_size: usize, +} + +impl EthercatDevice for Wago750_354 { + fn input( + &mut self, + input: &bitvec::prelude::BitSlice, + ) -> Result<(), anyhow::Error> { + for slot_device in &mut self.slot_devices { + match slot_device { + Some(device) => { + // Give all Modules access to the couplers input image and call their input func + let mut d = device.write_blocking(); + let _ = d.input(input); + drop(d); + } + None => break, + } + } + + Ok(()) + } + + fn input_len(&self) -> usize { + self.tx_size + } + + fn output( + &self, + output: &mut bitvec::prelude::BitSlice, + ) -> Result<(), anyhow::Error> { + for slot_device in &self.slot_devices { + match slot_device { + Some(device) => { + // Give all Modules access to the couplers Output image and call their output func + let d = device.read_blocking(); + let _ = d.output(output); + drop(d); + } + None => break, + } + } + Ok(()) + } + + fn output_len(&self) -> usize { + self.rx_size + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } + + fn is_module(&self) -> bool { + false + } + + fn get_module(&self) -> Option { + None + } + + fn set_module(&mut self, module: Module) { + self.slots[self.module_count] = Some(module); + self.module_count += 1; + self.tx_size += module.tx_offset; + self.rx_size += module.rx_offset; + } +} + +impl EthercatDeviceUsed for Wago750_354 { + fn is_used(&self) -> bool { + self.is_used + } + + fn set_used(&mut self, used: bool) { + self.is_used = used; + } } impl EthercatDeviceProcessing for Wago750_354 {} impl NewEthercatDevice for Wago750_354 { fn new() -> Self { - Self { is_used: false } + Self { + is_used: false, + slots: [const { None }; 64], + slot_devices: [const { None }; 64], + module_count: 0, + dev_count: 0, + tx_size: 0, + rx_size: 0, + rx_offsets: vec![], + tx_offsets: vec![], + } } } impl std::fmt::Debug for Wago750_354 { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "Wago_750_354") } } - -#[derive(Debug)] -pub struct Module { - pub slot : u16, - pub belongs_to_slave_index : u16, - pub has_tx : bool, - pub has_rx : bool, - pub vendor_id : u32, - pub product_id : u32, - pub name : String, -} - impl Wago750_354 { - pub async fn get_pdo_offsets<'a>(device: &EthercrabSubDevicePreoperational<'a>,get_tx : bool) -> Result,Error> { - let mut vec : Vec= vec![]; + pub async fn get_pdo_offsets<'a>( + &mut self, + device: &EthercrabSubDevicePreoperational<'a>, + get_tx: bool, + ) -> Result<(), Error> { + let mut vec: Vec = vec![]; let mut bit_offset = 0; let start_subindex = 0x1; let index = match get_tx { @@ -57,69 +160,182 @@ impl Wago750_354 { for i in 0..count { vec.push(bit_offset); - let pdo_index = device.sdo_read(index.0, start_subindex+i).await?; + let pdo_index = device.sdo_read(index.0, start_subindex + i).await?; if pdo_index != 0 { let pdo_map_count = device.sdo_read::(pdo_index, 0).await?; - // Iterate over every PDO Mapped entry and add it to the cumulative bit offset for j in 0..pdo_map_count { - let pdo_mapping : u32 = device.sdo_read(pdo_index, 1 + j).await?; - // We only need / Want the bit len + let pdo_mapping: u32 = device.sdo_read(pdo_index, 1 + j).await?; + // We only need / Want the bit len, which we extract with a bitmask extracting the lsb let bit_length = (pdo_mapping & 0xFF) as u8; bit_offset += bit_length as usize; - } + } } } - - - tracing::info!("{} is tx: {}",count,get_tx); - Ok(vec) + if get_tx { + self.tx_offsets = vec; + } else { + self.rx_offsets = vec; + } + Ok(()) } - // The Coupler gets itself as a Preop Subdevice - pub async fn get_module_count<'a>(device: &EthercrabSubDevicePreoperational<'a>) -> Result { - match device.sdo_read::(MODULE_COUNT_INDEX.0, MODULE_COUNT_INDEX.1).await { + pub async fn get_module_count<'a>( + device: &EthercrabSubDevicePreoperational<'a>, + ) -> Result { + match device + .sdo_read::(MODULE_COUNT_INDEX.0, MODULE_COUNT_INDEX.1) + .await + { Ok(value) => Ok(value as usize), - Err(e) => Err(anyhow::anyhow!("Failed to read Module Count for Wago750_354: {:?}",e)), + Err(e) => Err(anyhow::anyhow!( + "Failed to read Module Count for Wago750_354: {:?}", + e + )), } } - pub async fn get_modules<'a>(device: &EthercrabSubDevicePreoperational<'a>, module_count : usize) -> Result,Error> { - const MODULES_START_ADDR : u16 = 0x9000; - let modules : Vec = vec![]; + // This should probably be a generic function instead + pub async fn get_modules<'a>( + device: &EthercrabSubDevicePreoperational<'a>, + module_count: usize, + ) -> Result, Error> { + const MODULES_START_ADDR: u16 = 0x9000; + const MODULE_IDENT_SUBINDEX: u8 = 0x0a; + let mut modules: Vec = vec![]; for i in 0..module_count { let module_addr = MODULES_START_ADDR + (i * 0x10) as u16; - let ident = device.sdo_read::(module_addr, 0x00).await?; - device.sdo_read(index, sub_index).await?; + let ident_iom = device + .sdo_read::(module_addr, MODULE_IDENT_SUBINDEX) + .await?; + // For Wago the IOM well be the product ID + let mut module = Module { + slot: i as u16, + belongs_to_addr: device.configured_address(), + vendor_id: device.identity().vendor_id, + product_id: ident_iom, + has_tx: false, + has_rx: false, + tx_offset: 0, + rx_offset: 0, + }; + + match ident_iom { + // Add Module idents here: + WAGO_750_1506_PRODUCT_ID => { + module.has_tx = true; + module.has_rx = true; + } + WAGO_750_501_PRODUCT_ID => { + module.has_tx = false; + module.has_rx = true; + } + WAGO_750_652_PRODUCT_ID => { + module.has_tx = true; + module.has_rx = true; + } + _ => println!( + "Wago-750-354 found Unknown/Unimplemented Module: {}", + ident_iom + ), + } + modules.push(module); } - Ok(vec![]) + Ok(modules) } - pub async fn initialize_modules<'a> (device: &EthercrabSubDevicePreoperational<'a>) -> Result>>,Error> { + /// Call after all modules have been added + pub fn init_slot_modules<'a>(&mut self, device: &EthercrabSubDevicePreoperational<'a>) { + // Already initialized + if self.dev_count != 0 { + return; + } + let mut tx_index = 1; + let mut rx_index = 1; + + smol::block_on(async { + let _ = self.get_pdo_offsets(device, true).await; + let _ = self.get_pdo_offsets(device, false).await; + }); + + for module in self.slots { + match module { + Some(m) => { + // Map ModuleIdent's to Terminals + let dev: Arc> = match ( + m.vendor_id, + m.product_id, + ) { + WAGO_750_501_MODULE_IDENT => { + Arc::new(RwLock::new(wago_750_501::Wago750_501::new())) + } + WAGO_750_1506_MODULE_IDENT => { + Arc::new(RwLock::new(wago_750_1506::Wago750_1506::new())) + } + WAGO_750_652_MODULE_IDENT => { + Arc::new(RwLock::new(wago_750_652::Wago750_652::new())) + } + _ => { + println!( + "{} Missing Implementation for Module Identification: vendor_id: {:?}, module ident: {:?} !", + module_path!(), + m.vendor_id, + m.product_id + ); + return; + } + }; + + let tx_pdo_offset = self.tx_offsets.get(tx_index as usize); + if m.has_tx { + tx_index += 1; + } + + let rx_pdo_offset = self.rx_offsets.get(rx_index as usize); + if m.has_rx { + rx_index += 1; + } + + let mut dev_guard = dev.write_blocking(); + match tx_pdo_offset { + Some(offset) => dev_guard.set_tx_offset(*offset), + None => (), + } + + match rx_pdo_offset { + Some(offset) => dev_guard.set_rx_offset(*offset), + None => (), + } + drop(dev_guard); + self.slot_devices[self.dev_count] = Some(dev); + self.dev_count += 1; + } + None => break, + } + } + } + + pub async fn initialize_modules<'a>( + device: &EthercrabSubDevicePreoperational<'a>, + ) -> Result, Error> { let count = match Wago750_354::get_module_count(device).await { Ok(count) => count, Err(e) => return Err(e), }; - if count == 0 { return Ok(vec![]); } - - let tx_offsets = Wago750_354::get_pdo_offsets(device,true).await?; - let rx_offsets = Wago750_354::get_pdo_offsets(device,false).await?; - - println!("{:?}",tx_offsets); - println!("{:?}",rx_offsets); - Ok(vec![]) + let modules = Wago750_354::get_modules(device, count).await?; + Ok(modules) } } - - - pub const WAGO_750_354_VENDOR_ID: u32 = 0x00000021; pub const WAGO_750_354_PRODUCT_ID: u32 = 0x07500354; pub const WAGO_750_354_REVISION_A: u32 = 0x2; -pub const WAGO_750_354_IDENTITY_A: SubDeviceIdentityTuple = - (WAGO_750_354_VENDOR_ID, WAGO_750_354_PRODUCT_ID, WAGO_750_354_REVISION_A); +pub const WAGO_750_354_IDENTITY_A: SubDeviceIdentityTuple = ( + WAGO_750_354_VENDOR_ID, + WAGO_750_354_PRODUCT_ID, + WAGO_750_354_REVISION_A, +); diff --git a/ethercat-hal/src/devices/wago_750_501.rs b/ethercat-hal/src/devices/wago_750_501.rs deleted file mode 100644 index e69de29b..00000000 diff --git a/ethercat-hal/src/devices/wago_750_652.rs b/ethercat-hal/src/devices/wago_750_652.rs deleted file mode 100644 index e69de29b..00000000 diff --git a/ethercat-hal/src/devices/wago_modules/mod.rs b/ethercat-hal/src/devices/wago_modules/mod.rs new file mode 100644 index 00000000..c5f24532 --- /dev/null +++ b/ethercat-hal/src/devices/wago_modules/mod.rs @@ -0,0 +1,3 @@ +pub mod wago_750_1506; +pub mod wago_750_501; +pub mod wago_750_652; diff --git a/ethercat-hal/src/devices/wago_modules/wago_750_1506.rs b/ethercat-hal/src/devices/wago_modules/wago_750_1506.rs new file mode 100644 index 00000000..20171cd1 --- /dev/null +++ b/ethercat-hal/src/devices/wago_modules/wago_750_1506.rs @@ -0,0 +1,335 @@ +use crate::{ + devices::{ + DynamicEthercatDevice, EthercatDevice, EthercatDeviceProcessing, EthercatDeviceUsed, + EthercatDynamicPDO, Module, NewEthercatDevice, SubDeviceProductTuple, + }, + io::{ + digital_input::{DigitalInputDevice, DigitalInputInput}, + digital_output::{DigitalOutputDevice, DigitalOutputOutput}, + }, +}; + +#[derive(Debug, Clone)] +pub enum Wago750_1506OutputPort { + DO1, + DO2, + DO3, + DO4, + DO5, + DO6, + DO7, + DO8, +} + +impl From for usize { + fn from(value: Wago750_1506OutputPort) -> Self { + match value { + Wago750_1506OutputPort::DO1 => 0, + Wago750_1506OutputPort::DO2 => 1, + Wago750_1506OutputPort::DO3 => 2, + Wago750_1506OutputPort::DO4 => 3, + Wago750_1506OutputPort::DO5 => 4, + Wago750_1506OutputPort::DO6 => 5, + Wago750_1506OutputPort::DO7 => 6, + Wago750_1506OutputPort::DO8 => 7, + } + } +} + +#[derive(Debug, Clone)] +pub enum Wago750_1506InputPort { + DO1, + DO2, + DO3, + DO4, + DO5, + DO6, + DO7, + DO8, +} + +impl From for usize { + fn from(value: Wago750_1506InputPort) -> Self { + match value { + Wago750_1506InputPort::DO1 => 0, + Wago750_1506InputPort::DO2 => 1, + Wago750_1506InputPort::DO3 => 2, + Wago750_1506InputPort::DO4 => 3, + Wago750_1506InputPort::DO5 => 4, + Wago750_1506InputPort::DO6 => 5, + Wago750_1506InputPort::DO7 => 6, + Wago750_1506InputPort::DO8 => 7, + } + } +} + +#[derive(Clone, Default)] +pub struct Wago750_1506RxPdo { + port1: bool, + port2: bool, + port3: bool, + port4: bool, + port5: bool, + port6: bool, + port7: bool, + port8: bool, +} + +#[derive(Clone, Default)] +pub struct Wago750_1506TxPdo { + port1: bool, + port2: bool, + port3: bool, + port4: bool, + port5: bool, + port6: bool, + port7: bool, + port8: bool, +} + +impl DigitalInputDevice for Wago750_1506 { + fn get_input(&self, port: Wago750_1506InputPort) -> Result { + Ok(DigitalInputInput { + value: match port { + Wago750_1506InputPort::DO1 => self.tx_pdo.port1, + Wago750_1506InputPort::DO2 => self.tx_pdo.port2, + Wago750_1506InputPort::DO3 => self.tx_pdo.port3, + Wago750_1506InputPort::DO4 => self.tx_pdo.port4, + Wago750_1506InputPort::DO5 => self.tx_pdo.port5, + Wago750_1506InputPort::DO6 => self.tx_pdo.port6, + Wago750_1506InputPort::DO7 => self.tx_pdo.port7, + Wago750_1506InputPort::DO8 => self.tx_pdo.port8, + }, + }) + } +} + +impl DigitalOutputDevice for Wago750_1506 { + /// Writes the new output value into the device's RXPDO structure (in-memory PDI). + fn set_output(&mut self, port: Wago750_1506OutputPort, value: DigitalOutputOutput) { + // The DigitalOutputOutput is converted to a bool using the From trait + let output_value: bool = value.into(); + match port { + Wago750_1506OutputPort::DO1 => self.rx_pdo.port1 = output_value, + Wago750_1506OutputPort::DO2 => self.rx_pdo.port2 = output_value, + Wago750_1506OutputPort::DO3 => self.rx_pdo.port3 = output_value, + Wago750_1506OutputPort::DO4 => self.rx_pdo.port4 = output_value, + Wago750_1506OutputPort::DO5 => self.rx_pdo.port5 = output_value, + Wago750_1506OutputPort::DO6 => self.rx_pdo.port6 = output_value, + Wago750_1506OutputPort::DO7 => self.rx_pdo.port7 = output_value, + Wago750_1506OutputPort::DO8 => self.rx_pdo.port8 = output_value, + } + } + + /// Reads the current output value from the device's RXPDO structure (in-memory PDI). + fn get_output(&self, port: Wago750_1506OutputPort) -> DigitalOutputOutput { + let current_value = match port { + Wago750_1506OutputPort::DO1 => self.rx_pdo.port1, + Wago750_1506OutputPort::DO2 => self.rx_pdo.port2, + Wago750_1506OutputPort::DO3 => self.rx_pdo.port3, + Wago750_1506OutputPort::DO4 => self.rx_pdo.port4, + Wago750_1506OutputPort::DO5 => self.rx_pdo.port5, + Wago750_1506OutputPort::DO6 => self.rx_pdo.port6, + Wago750_1506OutputPort::DO7 => self.rx_pdo.port7, + Wago750_1506OutputPort::DO8 => self.rx_pdo.port8, + }; + // Wrap the bool back into the type-safe wrapper + DigitalOutputOutput(current_value) + } +} + +#[derive(Clone)] +pub struct Wago750_1506 { + is_used: bool, + tx_bit_offset: usize, + rx_bit_offset: usize, + // Should always have on but not when calling constructor + module: Option, + rx_pdo: Wago750_1506RxPdo, + tx_pdo: Wago750_1506TxPdo, +} + +impl DynamicEthercatDevice for Wago750_1506 {} + +impl EthercatDynamicPDO for Wago750_1506 { + fn get_tx_offset(&self) -> usize { + self.tx_bit_offset + } + + fn get_rx_offset(&self) -> usize { + self.rx_bit_offset + } + + fn set_tx_offset(&mut self, offset: usize) { + self.tx_bit_offset = offset + } + + fn set_rx_offset(&mut self, offset: usize) { + self.rx_bit_offset = offset + } +} + +impl EthercatDeviceUsed for Wago750_1506 { + fn is_used(&self) -> bool { + self.is_used + } + + fn set_used(&mut self, used: bool) { + self.is_used = used; + } +} + +impl Wago750_1506 {} + +impl EthercatDevice for Wago750_1506 { + // input_len 48 offset: 40 + fn input( + &mut self, + input: &bitvec::prelude::BitSlice, + ) -> Result<(), anyhow::Error> { + let base = self.tx_bit_offset; + + let idx1 = base + Into::::into(Wago750_1506InputPort::DO1); + self.tx_pdo.port1 = *input.get(idx1).expect("Bit 1 out of bounds"); + + let idx2 = base + Into::::into(Wago750_1506InputPort::DO2); + self.tx_pdo.port2 = *input.get(idx2).expect("Bit 2 out of bounds"); + + let idx3 = base + Into::::into(Wago750_1506InputPort::DO3); + self.tx_pdo.port3 = *input.get(idx3).expect("Bit 3 out of bounds"); + + let idx4 = base + Into::::into(Wago750_1506InputPort::DO4); + self.tx_pdo.port4 = *input.get(idx4).expect("Bit 4 out of bounds"); + + let idx5 = base + Into::::into(Wago750_1506InputPort::DO5); + self.tx_pdo.port5 = *input.get(idx5).expect("Bit 5 out of bounds"); + + let idx6 = base + Into::::into(Wago750_1506InputPort::DO6); + self.tx_pdo.port6 = *input.get(idx6).expect("Bit 6 out of bounds"); + + let idx7 = base + Into::::into(Wago750_1506InputPort::DO7); + self.tx_pdo.port7 = *input.get(idx7).expect("Bit 7 out of bounds"); + + let idx8 = base + Into::::into(Wago750_1506InputPort::DO8); + self.tx_pdo.port8 = *input.get(idx8).expect("Bit 8 out of bounds"); + Ok(()) + } + + fn input_len(&self) -> usize { + 8 + } + + fn output( + &self, + output: &mut bitvec::prelude::BitSlice, + ) -> Result<(), anyhow::Error> { + // println!("output: {} {}",self.rx_bit_offset,_output); + output.set( + self.rx_bit_offset + Into::::into(Wago750_1506OutputPort::DO1), + self.rx_pdo.port1, + ); + output.set( + self.rx_bit_offset + Into::::into(Wago750_1506OutputPort::DO2), + self.rx_pdo.port2, + ); + output.set( + self.rx_bit_offset + Into::::into(Wago750_1506OutputPort::DO3), + self.rx_pdo.port3, + ); + output.set( + self.rx_bit_offset + Into::::into(Wago750_1506OutputPort::DO4), + self.rx_pdo.port4, + ); + output.set( + self.rx_bit_offset + Into::::into(Wago750_1506OutputPort::DO5), + self.rx_pdo.port5, + ); + output.set( + self.rx_bit_offset + Into::::into(Wago750_1506OutputPort::DO6), + self.rx_pdo.port6, + ); + output.set( + self.rx_bit_offset + Into::::into(Wago750_1506OutputPort::DO7), + self.rx_pdo.port7, + ); + output.set( + self.rx_bit_offset + Into::::into(Wago750_1506OutputPort::DO8), + self.rx_pdo.port8, + ); + Ok(()) + } + + fn output_len(&self) -> usize { + 8 + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } + + fn is_module(&self) -> bool { + true + } + + fn input_checked( + &mut self, + _input: &bitvec::prelude::BitSlice, + ) -> Result<(), anyhow::Error> { + Ok(()) + } + + fn output_checked( + &self, + _output: &mut bitvec::prelude::BitSlice, + ) -> Result<(), anyhow::Error> { + Ok(()) + } + + fn get_module(&self) -> Option { + self.module.clone() + } + + fn set_module(&mut self, module: Module) { + self.tx_bit_offset = module.tx_offset; + self.rx_bit_offset = module.rx_offset; + self.module = Some(module); + } +} + +impl EthercatDeviceProcessing for Wago750_1506 { + fn input_post_process(&mut self) -> Result<(), anyhow::Error> { + Ok(()) + } + + fn output_pre_process(&mut self) -> Result<(), anyhow::Error> { + Ok(()) + } +} + +impl NewEthercatDevice for Wago750_1506 { + fn new() -> Self { + Self { + is_used: false, + tx_bit_offset: 0, + rx_bit_offset: 0, + module: None, + rx_pdo: Wago750_1506RxPdo::default(), + tx_pdo: Wago750_1506TxPdo::default(), + } + } +} + +impl std::fmt::Debug for Wago750_1506 { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Wago750_1506") + } +} + +pub const WAGO_750_1506_VENDOR_ID: u32 = 0x00000021; +pub const WAGO_750_1506_PRODUCT_ID: u32 = 2147483779; +pub const WAGO_750_1506_MODULE_IDENT: SubDeviceProductTuple = + (WAGO_750_1506_VENDOR_ID, WAGO_750_1506_PRODUCT_ID); diff --git a/ethercat-hal/src/devices/wago_modules/wago_750_501.rs b/ethercat-hal/src/devices/wago_modules/wago_750_501.rs new file mode 100644 index 00000000..db581519 --- /dev/null +++ b/ethercat-hal/src/devices/wago_modules/wago_750_501.rs @@ -0,0 +1,188 @@ +use crate::devices::{ + DynamicEthercatDevice, EthercatDevice, EthercatDeviceUsed, EthercatDynamicPDO, Module, + SubDeviceProductTuple, +}; +use crate::devices::{EthercatDeviceProcessing, NewEthercatDevice}; +use crate::io::digital_output::{DigitalOutputDevice, DigitalOutputOutput}; + +#[derive(Clone)] +pub struct Wago750_501 { + is_used: bool, + tx_bit_offset: usize, + rx_bit_offset: usize, + pub rxpdo: Wago750_501RxPdo, + module: Option, +} + +#[derive(Debug, Clone)] +pub enum Wago750_501Port { + Port1, + Port2, +} + +impl From for usize { + fn from(value: Wago750_501Port) -> Self { + match value { + Wago750_501Port::Port1 => 0, + Wago750_501Port::Port2 => 1, + } + } +} + +#[derive(Clone, Default)] +pub struct Wago750_501RxPdo { + pub port1: bool, + pub port2: bool, +} + +impl DigitalOutputDevice for Wago750_501 { + /// Writes the new output value into the device's RXPDO structure (in-memory PDI). + fn set_output(&mut self, port: Wago750_501Port, value: DigitalOutputOutput) { + // The DigitalOutputOutput is converted to a bool using the From trait + let output_value: bool = value.into(); + match port { + Wago750_501Port::Port1 => { + // Modify the internal PDO representation + self.rxpdo.port1 = output_value; + } + Wago750_501Port::Port2 => { + // Modify the internal PDO representation + self.rxpdo.port2 = output_value; + } + } + } + + /// Reads the current output value from the device's RXPDO structure (in-memory PDI). + fn get_output(&self, port: Wago750_501Port) -> DigitalOutputOutput { + let current_value = match port { + Wago750_501Port::Port1 => self.rxpdo.port1, + Wago750_501Port::Port2 => self.rxpdo.port2, + }; + + // Wrap the bool back into the type-safe wrapper + DigitalOutputOutput(current_value) + } +} + +impl EthercatDeviceUsed for Wago750_501 { + fn is_used(&self) -> bool { + self.is_used + } + + fn set_used(&mut self, used: bool) { + self.is_used = used; + } +} + +impl DynamicEthercatDevice for Wago750_501 {} + +impl EthercatDynamicPDO for Wago750_501 { + fn get_tx_offset(&self) -> usize { + self.tx_bit_offset + } + + fn get_rx_offset(&self) -> usize { + self.rx_bit_offset + } + + fn set_tx_offset(&mut self, offset: usize) { + self.tx_bit_offset = offset + } + + fn set_rx_offset(&mut self, offset: usize) { + self.rx_bit_offset = offset + } +} + +impl EthercatDevice for Wago750_501 { + fn input( + &mut self, + _input: &bitvec::prelude::BitSlice, + ) -> Result<(), anyhow::Error> { + Ok(()) + } + + fn input_len(&self) -> usize { + 0 + } + + fn output( + &self, + output: &mut bitvec::prelude::BitSlice, + ) -> Result<(), anyhow::Error> { + output.set( + self.rx_bit_offset + Into::::into(Wago750_501Port::Port1), + self.rxpdo.port1, + ); + output.set( + self.rx_bit_offset + Into::::into(Wago750_501Port::Port2), + self.rxpdo.port2, + ); + Ok(()) + } + + fn output_len(&self) -> usize { + 2 + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } + + fn is_module(&self) -> bool { + true + } + + fn input_checked( + &mut self, + _input: &bitvec::prelude::BitSlice, + ) -> Result<(), anyhow::Error> { + Ok(()) + } + + fn output_checked( + &self, + _output: &mut bitvec::prelude::BitSlice, + ) -> Result<(), anyhow::Error> { + Ok(()) + } + + fn get_module(&self) -> Option { + self.module.clone() + } + + fn set_module(&mut self, module: crate::devices::Module) { + self.tx_bit_offset = module.tx_offset; + self.rx_bit_offset = module.rx_offset; + self.module = Some(module) + } +} + +impl EthercatDeviceProcessing for Wago750_501 {} + +impl NewEthercatDevice for Wago750_501 { + fn new() -> Self { + Self { + is_used: false, + tx_bit_offset: 0, + rx_bit_offset: 0, + module: None, + rxpdo: Wago750_501RxPdo::default(), + } + } +} + +impl std::fmt::Debug for Wago750_501 { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Wago750_501") + } +} + +pub const WAGO_750_501_VENDOR_ID: u32 = 0x00000021; +pub const WAGO_750_501_PRODUCT_ID: u32 = 2147483682; +pub const WAGO_750_501_MODULE_IDENT: SubDeviceProductTuple = + (WAGO_750_501_VENDOR_ID, WAGO_750_501_PRODUCT_ID); diff --git a/ethercat-hal/src/devices/wago_modules/wago_750_652.rs b/ethercat-hal/src/devices/wago_modules/wago_750_652.rs new file mode 100644 index 00000000..e88f3ff8 --- /dev/null +++ b/ethercat-hal/src/devices/wago_modules/wago_750_652.rs @@ -0,0 +1,159 @@ +use crate::devices::{ + DynamicEthercatDevice, EthercatDevice, EthercatDeviceUsed, EthercatDynamicPDO, Module, + SubDeviceProductTuple, +}; +use crate::devices::{EthercatDeviceProcessing, NewEthercatDevice}; + +#[derive(Clone)] +pub struct Wago750_652 { + is_used: bool, + tx_bit_offset: usize, + rx_bit_offset: usize, + module: Option, +} + +impl EthercatDeviceUsed for Wago750_652 { + fn is_used(&self) -> bool { + self.is_used + } + + fn set_used(&mut self, used: bool) { + self.is_used = used; + } +} + +impl DynamicEthercatDevice for Wago750_652 {} + +impl EthercatDynamicPDO for Wago750_652 { + fn get_tx_offset(&self) -> usize { + self.tx_bit_offset + } + + fn get_rx_offset(&self) -> usize { + self.rx_bit_offset + } + + fn set_tx_offset(&mut self, offset: usize) { + self.tx_bit_offset = offset + } + + fn set_rx_offset(&mut self, offset: usize) { + self.rx_bit_offset = offset + } +} + +impl EthercatDevice for Wago750_652 { + /* + OK so with ethercrab we receive the bitslice of the current subdevice in our Loop + */ + fn input( + &mut self, + _input: &bitvec::prelude::BitSlice, + ) -> Result<(), anyhow::Error> { + Ok(()) + } + + fn input_len(&self) -> usize { + 0 + } + + fn output( + &self, + _output: &mut bitvec::prelude::BitSlice, + ) -> Result<(), anyhow::Error> { + Ok(()) + } + + fn output_len(&self) -> usize { + 0 + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } + + fn is_module(&self) -> bool { + true + } + + fn input_checked( + &mut self, + input: &bitvec::prelude::BitSlice, + ) -> Result<(), anyhow::Error> { + // validate input has correct length + let expected = self.input_len(); + let actual = input.len(); + if actual != expected { + return Err(anyhow::anyhow!( + "[{}::Device::input_checked] Input length is {} ({} bytes) and must be {} bits ({} bytes)", + module_path!(), + actual, + actual / 8, + expected, + expected / 8 + )); + } + self.input(input) + } + + fn output_checked( + &self, + output: &mut bitvec::prelude::BitSlice, + ) -> Result<(), anyhow::Error> { + self.output(output)?; + + // validate input has correct length + let expected = self.output_len(); + let actual = output.len(); + if output.len() != expected { + return Err(anyhow::anyhow!( + "[{}::Device::output_checked] Output length is {} ({} bytes) and must be {} bits ({} bytes)", + module_path!(), + actual, + actual / 8, + expected, + expected / 8 + )); + } + + Ok(()) + } + + fn get_module(&self) -> Option { + self.module.clone() + } + + fn set_module(&mut self, module: Module) { + self.tx_bit_offset = module.tx_offset; + self.rx_bit_offset = module.rx_offset; + self.module = Some(module); + } +} + +impl EthercatDeviceProcessing for Wago750_652 {} + +impl NewEthercatDevice for Wago750_652 { + fn new() -> Self { + Self { + is_used: false, + tx_bit_offset: 0, + rx_bit_offset: 0, + module: None, + } + } +} + +impl std::fmt::Debug for Wago750_652 { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Wago750_652") + } +} + +pub const WAGO_750_652_VENDOR_ID: u32 = 0x00000021; +pub const WAGO_750_652_PRODUCT_ID: u32 = 106043250; +pub const WAGO_750_652_MODULE_IDENT: SubDeviceProductTuple = + (WAGO_750_652_VENDOR_ID, WAGO_750_652_PRODUCT_ID); diff --git a/machines/src/extruder1/new.rs b/machines/src/extruder1/new.rs index 130174d9..813e391e 100644 --- a/machines/src/extruder1/new.rs +++ b/machines/src/extruder1/new.rs @@ -59,14 +59,12 @@ use super::{ impl MachineNewTrait for ExtruderV2 { fn new<'maindevice>(params: &MachineNewParams) -> Result { // validate general stuff - use crate::{ MachineNewHardware, MachineNewHardwareEthercat, validate_no_role_dublicates, validate_same_machine_identification_unique, }; let device_identification = params.device_group.to_vec(); - validate_same_machine_identification_unique(&device_identification)?; validate_no_role_dublicates(&device_identification)?; diff --git a/machines/src/machine_identification.rs b/machines/src/machine_identification.rs index 6818906e..7c1eec72 100644 --- a/machines/src/machine_identification.rs +++ b/machines/src/machine_identification.rs @@ -1,5 +1,6 @@ use std::fmt::Display; +use ethercat_hal::devices::wago_750_354::WAGO_750_354_IDENTITY_A; use serde::Deserialize; use serde::Serialize; @@ -345,6 +346,7 @@ pub fn get_identification_addresses( let identity_tuple = subdevice_identity_to_tuple(subdevice_identity); Ok(match identity_tuple { + WAGO_750_354_IDENTITY_A => MachineIdentificationAddresses::default(), EK1100_IDENTITY_A => MachineIdentificationAddresses::default(), EL1002_IDENTITY_A => MachineIdentificationAddresses::default(), EL1008_IDENTITY_A => MachineIdentificationAddresses::default(), diff --git a/machines/src/test_machine/api.rs b/machines/src/test_machine/api.rs index 311c85e1..e523a72a 100644 --- a/machines/src/test_machine/api.rs +++ b/machines/src/test_machine/api.rs @@ -71,7 +71,7 @@ impl MachineApi for TestMachine { Mutation::SetAllLeds { on } => self.set_all_leds(on), } - for (led, &on) in self.leds.iter().zip(self.led_on.iter()) { + for (led, &on) in self.douts.iter().zip(self.led_on.iter()) { led.set(on); } diff --git a/machines/src/test_machine/mod.rs b/machines/src/test_machine/mod.rs index f2718d3f..03490a95 100644 --- a/machines/src/test_machine/mod.rs +++ b/machines/src/test_machine/mod.rs @@ -2,6 +2,7 @@ use crate::machine_identification::{MachineIdentification, MachineIdentification use crate::test_machine::api::{StateEvent, TestMachineEvents}; use crate::{AsyncThreadMessage, Machine, MachineMessage}; use control_core::socketio::namespace::NamespaceCacheingLogic; +use ethercat_hal::io::digital_output::DigitalOutput; use smol::channel::{Receiver, Sender}; use std::time::Instant; pub mod act; @@ -9,7 +10,6 @@ pub mod api; pub mod new; use crate::test_machine::api::TestMachineNamespace; use crate::{TEST_MACHINE, VENDOR_QITECH}; -use ethercat_hal::io::digital_output::DigitalOutput; #[derive(Debug)] pub struct TestMachine { @@ -20,7 +20,7 @@ pub struct TestMachine { pub last_state_emit: Instant, pub led_on: [bool; 4], pub main_sender: Option>, - pub leds: [DigitalOutput; 4], + pub douts: [DigitalOutput; 4], } impl Machine for TestMachine { diff --git a/machines/src/test_machine/new.rs b/machines/src/test_machine/new.rs index d9eec601..df5ec746 100644 --- a/machines/src/test_machine/new.rs +++ b/machines/src/test_machine/new.rs @@ -7,10 +7,19 @@ use crate::{ MachineNewHardware, MachineNewParams, MachineNewTrait, get_ethercat_device, validate_no_role_dublicates, validate_same_machine_identification_unique, }; + use anyhow::Error; use ethercat_hal::devices::el2004::{EL2004, EL2004_IDENTITY_A, EL2004Port}; use ethercat_hal::io::digital_output::DigitalOutput; +//Imports For Wago +/* +use ethercat_hal::devices::wago_750_354::{WAGO_750_354_IDENTITY_A, Wago750_354}; +use ethercat_hal::devices::{EthercatDevice, downcast_device}; +use smol::lock::RwLock; +use std::sync::Arc; +*/ + impl MachineNewTrait for TestMachine { fn new<'maindevice>(params: &MachineNewParams) -> Result { // validate general stuff @@ -32,6 +41,35 @@ impl MachineNewTrait for TestMachine { } }; block_on(async { + /* + // Example usage of a Wago Coupler and a 750-1506 in the first slot, where the Output Port 1,2,3,4 is used + let _wago_750_354 = get_ethercat_device::( + hardware, + params, + 0, + [WAGO_750_354_IDENTITY_A].to_vec(), + ) + .await?; + + let modules = Wago750_354::initialize_modules(_wago_750_354.1).await?; + + let mut coupler = _wago_750_354.0.write().await; + + for module in modules { + coupler.set_module(module); + } + + coupler.init_slot_modules(_wago_750_354.1); + let dev = coupler.slot_devices.get(1).unwrap().clone().unwrap(); + let wago750_1506: Arc> = + downcast_device::(dev).await?; + let do1 = DigitalOutput::new(wago750_1506.clone(), Wago750_1506OutputPort::DO1); + let do2 = DigitalOutput::new(wago750_1506.clone(), Wago750_1506OutputPort::DO2); + let do3 = DigitalOutput::new(wago750_1506.clone(), Wago750_1506OutputPort::DO3); + let do4 = DigitalOutput::new(wago750_1506.clone(), Wago750_1506OutputPort::DO4); + drop(coupler); + */ + let el2004 = get_ethercat_device::(hardware, params, 1, [EL2004_IDENTITY_A].to_vec()) .await? @@ -40,6 +78,7 @@ impl MachineNewTrait for TestMachine { let do2 = DigitalOutput::new(el2004.clone(), EL2004Port::DO2); let do3 = DigitalOutput::new(el2004.clone(), EL2004Port::DO3); let do4 = DigitalOutput::new(el2004.clone(), EL2004Port::DO4); + let (sender, receiver) = smol::channel::unbounded(); let mut my_test = Self { api_receiver: receiver, @@ -51,7 +90,7 @@ impl MachineNewTrait for TestMachine { last_state_emit: Instant::now(), led_on: [false; 4], main_sender: params.main_thread_channel.clone(), - leds: [do1, do2, do3, do4], + douts: [do1, do2, do3, do4], }; my_test.emit_state(); Ok(my_test) diff --git a/server/src/ethercat/setup.rs b/server/src/ethercat/setup.rs index 0bb514be..7f6cf130 100644 --- a/server/src/ethercat/setup.rs +++ b/server/src/ethercat/setup.rs @@ -12,6 +12,10 @@ use control_core::socketio::namespace::NamespaceCacheingLogic; use control_core::{irq_handling::set_irq_affinity, realtime::set_realtime_priority}; use ethercat_hal::debugging::diagnosis_history::get_most_recent_diagnosis_message; use ethercat_hal::devices::devices_from_subdevices; +use ethercat_hal::devices::wago_750_354::{ + WAGO_750_354_PRODUCT_ID, WAGO_750_354_VENDOR_ID, Wago750_354, +}; + use ethercrab::std::ethercat_now; use ethercrab::{MainDevice, MainDeviceConfig, PduStorage, RetryBehaviour, Timeouts}; use machines::machine_identification::{ @@ -110,10 +114,6 @@ pub async fn set_ethercat_devices)>, ) -> Result<(), anyhow::Error> { let device_grouping_result = group_devices_by_identification(device_identifications); - tracing::info!( - "set_ethercat_devices: {:?}", - device_grouping_result.unidentified_devices - ); let machine_new_hardware = MachineNewHardware::Ethercat(hardware); let mut machines: Vec> = vec![]; @@ -300,7 +300,7 @@ pub async fn setup_loop( // filter devices and if Option is Some // return identified_devices, identified_device_identifications, identified_subdevices - let (identified_device_identifications, identified_devices, identified_subdevices): ( + let (identified_device_identifications,identified_devices, identified_subdevices): ( Vec<_>, Vec<_>, Vec<_>, @@ -328,32 +328,57 @@ pub async fn setup_loop( acc.0.push(identified_device_identification.clone()); acc.1.push(identified_device); acc.2.push(identified_subdevice); - ethercat_meta_devices.push(EtherCatDeviceMetaData::from_subdevice(identified_subdevice,identified_device_identification)); - + let meta = EtherCatDeviceMetaData::from_subdevice(identified_subdevice,identified_device_identification); + ethercat_meta_devices.push(meta); acc }, ); - tracing::info!("Found Devices: {:?}", ethercat_meta_devices); - drop(ethercat_meta_devices); // We always need to have atleast one subdevice anyways let coupler = subdevices.get(0).unwrap(); let _resp = get_most_recent_diagnosis_message(coupler).await; - /* handle special edge cases, Wago couplers handle all subdevices as part of the coupler instead of their own devices, meaning we need to convert the PDO Mappings to seperate SubDevices to enable more ease of use OR alternatively you could show it like TwinCAT with "slots" on the Coupler */ - match (coupler.identity().vendor_id,coupler.identity().product_id) { - (WAGO_750_354_VENDOR_ID,WAGO_750_354_PRODUCT_ID) => { + match (coupler.identity().vendor_id, coupler.identity().product_id) { + (WAGO_750_354_VENDOR_ID, WAGO_750_354_PRODUCT_ID) => { let r = Wago750_354::initialize_modules(coupler).await?; - println!("{:?}",r); - }, + for module in r { + if coupler.configured_address() == module.belongs_to_addr { + match ethercat_meta_devices.get(0) { + Some(meta) => { + let meta_data = EtherCatDeviceMetaData { + configured_address: module.slot, + name: "wago module".to_owned(), + vendor_id:module.vendor_id, + product_id: module.product_id, + revision: 0x2, + device_identification: DeviceIdentification{ + device_machine_identification: meta.device_identification.device_machine_identification.clone(), + device_hardware_identification: machines::machine_identification::DeviceHardwareIdentification::Ethercat(DeviceHardwareIdentificationEthercat{ subdevice_index: module.slot as usize }) } + }; + ethercat_meta_devices.push(meta_data); + } + None => break, + } + } + } + } _ => (), }; + drop(ethercat_meta_devices); + + for subdevice in subdevices.iter() { + // Hack so El5152 goes into OP + if subdevice.name() == "EL5152" { + subdevice.sdo_write(SM_INPUT, 0x1, 0x00u16).await?; //set sync mode (1) for free run (0) + subdevice.sdo_write(SM_OUTPUT, 0x1, 0x00u16).await?; //set sync mode (1) for free run (0) + } + } // remove subdevice from devices tuple let devices = devices @@ -388,11 +413,16 @@ pub async fn setup_loop( /* Make DC Slaves Happy + Does this potentially cause issues with Non DC-Sync devices? */ let res = group_safe.tx_rx_sync_system_time(&maindevice).await; match res { Ok(_) => (), - Err(e) => tracing::error!("[{}::setup_loop] Failed to sync dc time: {:?}",e, module_path!()), + Err(e) => tracing::error!( + "[{}::setup_loop] Failed to sync dc time: {:?}", + e, + module_path!() + ), } // Put group in operational state @@ -421,7 +451,6 @@ pub async fn setup_loop( .await; main_namespace.emit(MainNamespaceEvents::EthercatDevicesEvent(event)); } - tracing::info!("DONE WITH INIT"); return Ok(EthercatSetup { devices, diff --git a/server/src/loop.rs b/server/src/loop.rs index 747ce01a..205da230 100644 --- a/server/src/loop.rs +++ b/server/src/loop.rs @@ -68,6 +68,7 @@ pub fn start_loop_thread( match msg { HotThreadMessage::NoMsg => {} HotThreadMessage::AddEtherCatSetup(ethercat_setup) => { + println!("EthercatSetup: {:?}", ethercat_setup.devices); rt_loop_inputs.ethercat_setup = Some(Box::new(ethercat_setup)); } HotThreadMessage::WriteMachineDeviceInfo(info_request) => {