Expand description
A performant, async
-first EtherCAT MainDevice written in pure Rust.
§Crate features
std
(enabled by default) - exposes thestd
module, containing helpers to run the TX/RX loop on desktop operating systems.defmt
- enable logging with thedefmt
crate.log
- enable logging with thelog
crate. This is enabled by default when thestd
feature is enabled.serde
- enableserde
impls for some public items.
For no_std
targets, it is recommended to add this crate with
cargo add --no-default-features --features defmt
§Examples
This example increments the output bytes of all detected SubDevices every tick. It is tested on an EK1100 with output modules but may work on other basic SubDevices.
Run with e.g.
Linux
RUST_LOG=debug cargo run --example ek1100 --release -- eth0
Windows
$env:RUST_LOG="debug" ; cargo run --example ek1100 --release -- '\Device\NPF_{FF0ACEE6-E8CD-48D5-A399-619CD2340465}'
use env_logger::Env;
use ethercrab::{
error::Error, std::{ethercat_now, tx_rx_task}, MainDevice, MainDeviceConfig, PduStorage, Timeouts
};
use std::{sync::Arc, time::Duration};
use tokio::time::MissedTickBehavior;
/// Maximum number of SubDevices that can be stored. This must be a power of 2 greater than 1.
const MAX_SUBDEVICES: usize = 16;
/// Maximum PDU data payload size - set this to the max PDI size or higher.
const MAX_PDU_DATA: usize = 1100;
/// Maximum number of EtherCAT frames that can be in flight at any one time.
const MAX_FRAMES: usize = 16;
/// Maximum total PDI length.
const PDI_LEN: usize = 64;
static PDU_STORAGE: PduStorage<MAX_FRAMES, MAX_PDU_DATA> = PduStorage::new();
#[tokio::main]
async fn main() -> Result<(), Error> {
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
let interface = std::env::args()
.nth(1)
.expect("Provide network interface as first argument.");
log::info!("Starting EK1100 demo...");
log::info!("Ensure an EK1100 is the first SubDevice, with any number of modules connected after");
log::info!("Run with RUST_LOG=ethercrab=debug or =trace for debug information");
let (tx, rx, pdu_loop) = PDU_STORAGE.try_split().expect("can only split once");
let maindevice = Arc::new(MainDevice::new(
pdu_loop,
Timeouts {
wait_loop_delay: Duration::from_millis(2),
mailbox_response: Duration::from_millis(1000),
..Default::default()
},
MainDeviceConfig::default(),
));
tokio::spawn(tx_rx_task(&interface, tx, rx).expect("spawn TX/RX task"));
let mut group = maindevice
.init_single_group::<MAX_SUBDEVICES, PDI_LEN>(ethercat_now)
.await
.expect("Init");
log::info!("Discovered {} SubDevices", group.len());
for subdevice in group.iter(&maindevice) {
// Special case: if an EL3004 module is discovered, it needs some specific config during
// init to function properly
if subdevice.name() == "EL3004" {
log::info!("Found EL3004. Configuring...");
subdevice.sdo_write(0x1c12, 0, 0u8).await?;
subdevice.sdo_write(0x1c13, 0, 0u8).await?;
subdevice.sdo_write(0x1c13, 1, 0x1a00u16).await?;
subdevice.sdo_write(0x1c13, 2, 0x1a02u16).await?;
subdevice.sdo_write(0x1c13, 3, 0x1a04u16).await?;
subdevice.sdo_write(0x1c13, 4, 0x1a06u16).await?;
subdevice.sdo_write(0x1c13, 0, 4u8).await?;
}
}
let mut group = group.into_op(&maindevice).await.expect("PRE-OP -> OP");
for subdevice in group.iter(&maindevice) {
let io = subdevice.io_raw();
log::info!(
"-> SubDevice {:#06x} {} inputs: {} bytes, outputs: {} bytes",
subdevice.configured_address(),
subdevice.name(),
io.inputs().len(),
io.outputs().len()
);
}
let mut tick_interval = tokio::time::interval(Duration::from_millis(5));
tick_interval.set_missed_tick_behavior(MissedTickBehavior::Skip);
loop {
group.tx_rx(&maindevice).await.expect("TX/RX");
// Increment every output byte for every SubDevice by one
for mut subdevice in group.iter(&maindevice) {
let mut io = subdevice.io_raw_mut();
for byte in io.outputs().iter_mut() {
*byte = byte.wrapping_add(1);
}
}
tick_interval.tick().await;
}
}
Re-exports§
pub use subdevice_group::SubDeviceGroup;
pub use subdevice_group::TxRxResponse;
Modules§
- error
- EtherCrab error types.
- std
- Items required for running in
std
environments. - subdevice_
group - A group of SubDevices.
Structs§
- Main
Device - The main EtherCAT controller.
- Main
Device Config - Configuration passed to
MainDevice
. - PduLoop
- The core EtherCrab network communications driver.
- PduRx
- EtherCAT frame receive adapter.
- PduStorage
- Stores PDU frames that are currently being prepared to send, in flight, or being received and processed.
- PduTx
- EtherCAT frame transmit adapter.
- Sendable
Frame - An EtherCAT frame that is ready to be sent over the network.
- SubDevice
- SubDevice device metadata. See
SubDeviceRef
for richer behaviour. - SubDevice
Identity - SubDevice identity information (vendor ID, product ID, etc).
- SubDevice
Pdi - Process Data Image (PDI) segments for a given SubDevice.
- SubDevice
Ref - A wrapper around a
SubDevice
and additional state for richer behaviour. - Timeouts
- Timeout configuration for the EtherCrab master.
- Wrapped
Read - A wrapped version of a
Reads
exposing a builder API used to send/receive data over the wire. - Wrapped
Write - A wrapped version of a
Writes
exposing a builder API used to send/receive data over the wire.
Enums§
- AlStatus
Code - AL (Application Layer) Status Code.
- Command
- PDU command.
- DcSupport
- SubDevice DC support status.
- DcSync
- DC sync configuration for a SubDevice.
- Reads
- Read commands that send no data.
- Receive
Action - What happened to a received Ethernet frame.
- Register
Address - SubDevice device register address abstraction.
- Retry
Behaviour - Network communication retry policy.
- SubDevice
State - AL (application layer) state for a single SubDevice.
- SubIndex
- Subindex access.
- Writes
- Write commands.
Traits§
- Ether
Crab Wire Read - A type to be received from the wire, according to EtherCAT spec rules (packed bits, little endian).
- Ether
Crab Wire Read Sized - A readable type that has a size known at compile time.
- Ether
Crab Wire Read Write - A type that can be both written to the wire and read back from it.
- Ether
Crab Wire Sized - Implemented for types with a known size at compile time.
- Ether
Crab Wire Write - A type to be sent/received on the wire, according to EtherCAT spec rules (packed bits, little endian).
- Ether
Crab Wire Write Sized - Implemented for writeable types with a known size at compile time.
Derive Macros§
- Ether
Crab Wire Read - Items that can only be read from the wire.
- Ether
Crab Wire Read Write - Items that can be written to and read from the wire.
- Ether
Crab Wire Write - Items that can only be written to the wire.