feat(examples): add ethercat-real-bus (EK1100 + EL1008)#8
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces the ethercat-real-bus example, demonstrating real-world EtherCAT integration with Beckhoff hardware using the taktora framework. It includes a custom RawByteCodec for 8-bit digital inputs and comprehensive setup documentation for Linux hosts. Review feedback suggests optimizing state management in main.rs by removing an unnecessary Arc<Mutex> wrapper for a variable used only within a single closure, which avoids redundant synchronization and allocation overhead.
| let last_value: Arc<Mutex<Option<u8>>> = Arc::new(Mutex::new(None)); | ||
| let last_value_for_item = Arc::clone(&last_value); |
There was a problem hiding this comment.
The last_value state does not need to be wrapped in an Arc<Mutex> because it is only used within a single ExecutableItem closure. Since the closure is move and the executor treats items as FnMut, you can simply capture a local Option<u8> variable. This avoids unnecessary synchronization and allocation overhead.
| let last_value: Arc<Mutex<Option<u8>>> = Arc::new(Mutex::new(None)); | |
| let last_value_for_item = Arc::clone(&last_value); | |
| let mut last_value: Option<u8> = None; |
| let mut last = last_value_for_item.lock().expect("poisoned"); | ||
| if last.as_ref().copied() != Some(v) { | ||
| let elapsed_ms = started_at.elapsed().as_millis(); | ||
| println!("t=+{elapsed_ms:>6}ms bits=0b{v:08b} decimal={v}"); | ||
| *last = Some(v); | ||
| } |
Summary
Adds
examples/ethercat-real-bus/— a standalone Cargo crate that drives a real Beckhoff EK1100 + EL1008 from a Linux host (Raspberry Pi the canonical target) viaEthercrabBusDriver. Reads the EL1008's 8 digital input bits at 10 ms cadence and prints the byte every time it changes.Fourth integration example in
examples/; CI compiles it but does NOT run it (no NIC, no hardware in CI). Mirrors the establishedexamples/*standalone-crate conventions (empty[workspace],[patch.crates-io]marker block,/target.gitignore,publish = false, no.runnablemarker).What this shows
EthercrabBusDriver::new(&PDU_STORAGE, opts)— real-bus driver construction (bus-integrationfeature ontaktora-connector-ethercat).Connecting → Uphealth handshake viaConnector::subscribe_health.ChannelReader<u8, N>over anEthercatRoutingPDO slice — same surface every other connector in this workspace exposes.RawByteCodecdefined inline (JsonCodeccan't decode raw PDI bytes). Purpose-built for this example; intentionally not promoted totaktora-connector-codec.Files
New crate under
examples/ethercat-real-bus/:Cargo.toml— pinstaktora-* = "0.1"(andtaktora-connector-core = "0.2"), enablesbus-integrationontaktora-connector-ethercat.Cargo.lock— committed (application crate)..gitignore—/target.README.md— hardware checklist, host setup,setcaprecipe, run instructions, troubleshooting.src/main.rs— ~250 LoC: CLI (--nic,--ticks),RawByteCodecimpl + 4 unit tests, bring-up wiring, health-polling item (250 ms), scan-and-print item (10 ms).Workspace plumbing:
examples/README.md— fourth row in the "What's here" table.README.md(root) — fourth row in the Integration examples table..github/workflows/ci.yml—examples/ethercat-real-busadded to theexamplesjob's rust-cacheworkspaces:list.Test plan
cargo build --releasein the example crate.cargo test --release— 4RawByteCodecround-trip + error tests pass.cargo clippy --release --all-targets -- -D warnings— clean../scripts/check-examples.sh— green; new example reportsskipping run (no .runnable marker).cargo test --workspace --all-features -- --test-threads=1— 394 passing, 0 failing.Spec / design
docs/superpowers/specs/2026-05-21-ethercat-real-bus-design.md(local;docs/superpowers/is gitignored).docs/superpowers/plans/2026-05-21-ethercat-real-bus.md.