-
Notifications
You must be signed in to change notification settings - Fork 2
XTREM
The xtrem crate talks to GRAM XTREM / XTREM-S weighing modules over UDP. It implements
protocol version 3.007.
An XTREM is an ADPD weighing module certified to OIML R76:2006 and EN45501:2015. It drives a load cell and reports the weight over a communication interface:
- UART0 is always plain RS232C.
- UART1 can optionally carry Wi-Fi 802.11, RS485 or wired Ethernet.
This crate only implements UDP over the network interface. RS232 and RS485 carry the same frame format over a different transport, and aren't implemented.
A hardware sealing switch locks writes to the legally relevant calibration registers, and enables a separate software-protection handshake. Both protect the module's legal-for-trade certification. This crate doesn't try to work around either one.
| Page | Read it when you want to… |
|---|---|
| XTREM protocol | understand the frame format, the registers, and how payloads are decoded |
| XTREM bus and discovery | open the UDP socket, find modules on a subnet, and give them unique device IDs |
| XTREM scale driver | read weights from a control loop with XtremScale, and send tare and zero |
| Module | Contents | Does I/O? |
|---|---|---|
protocol |
Frame encode/decode, DataAddress, Function, register value parsing, LRC |
no |
transport |
XtremBus: one shared UDP socket, with incoming frames routed by ID_O
|
yes |
discovery |
discover, read_once, assign_device_id (all async) |
yes |
devices |
the XtremDevice polling trait and the XtremScale driver |
yes |
The crate root re-exports the common types: XtremBus, XtremBusConfig, XtremBusHandle,
XtremScale, ScaleMode, Reading, XtremDevice, XtremError, XtremProbe, discover, Frame,
DataAddress, Function, ProtocolError, Weight, WeighingRegister.
Weights come back as units::Mass (see Units). The receive task runs on the shared
multi-threaded runtime common::get_async_runtime(), not on the EtherCAT HAL's runtime.
use std::time::Duration;
use common::get_async_runtime;
use units::mass::gram;
use xtrem::{ScaleMode, XtremDevice, XtremScale, discovery};
use xtrem::transport::{XtremBus, XtremBusConfig};
let bus = XtremBus::open(XtremBusConfig {
bind_addr: "0.0.0.0:5555".parse()?, // register 0700h default: module → host
broadcast_addr: "192.168.4.255:4444".parse()?, // register 0701h default: host → module
host_id: 0x00,
verify_lrc: true,
crlf: true,
})?;
// discover() is async; drive it from the shared runtime.
let probes = get_async_runtime().block_on(discovery::discover(&bus, Duration::from_secs(2)))?;
let mut scale = XtremScale::from_probe(&bus, &probes[0], ScaleMode::Poll);
// Non-blocking, one call each per tick of a synchronous loop.
loop {
scale.send_next_request()?;
scale.handle_response()?;
if let Some(reading) = scale.reading {
println!("{:.1} g net", reading.net.get::<gram>());
}
if let Some(err) = scale.take_error() {
eprintln!("{err}");
}
std::thread::sleep(Duration::from_millis(10));
}bind_addr must be 0.0.0.0. The module replies to the broadcast address, never to the
requester's IP, so a socket bound to one interface address never receives anything. XtremBus::open
refuses such an address. See Why 0.0.0.0.
The examples live in xtrem/examples/. The crate isn't part of a Cargo workspace, so run them from
inside xtrem/ (the -p xtrem shown in some of their doc comments doesn't work):
cd xtrem
cargo run --example discover -- --bind 0.0.0.0:5555 --broadcast 192.168.4.255:4444
cargo run --example assign_ids -- --bind 0.0.0.0:5555 --broadcast 192.168.4.255:4444 --dry-run
cargo run --example poll_multi -- --bind 0.0.0.0:5555 --broadcast 192.168.4.255:4444| Example | What it does | Extra flags |
|---|---|---|
discover |
sweeps the subnet, prints every module, then polls the first one |
--no-lrc, --stream <ms>
|
assign_ids |
gives every module a unique device ID, one at a time over unicast |
--dry-run, --start-id <n> (default 2), --no-lrc
|
poll_multi |
polls every discovered module concurrently on one bus | --no-lrc |
discover defaults --bind and --broadcast to the factory ports (0.0.0.0:5555 and
255.255.255.255:4444). assign_ids and poll_multi require both flags.
cd xtrem && cargo test # protocol unit tests + tests/loopback.rs + doctest
cd xtrem && cargo test --test loopback <name> # one loopback test- Protocol unit tests are anchored to byte sequences taken from the specification's worked examples and its §17 UDP capture, not to invented fixtures.
-
tests/loopback.rsruns a fake XTREM module on127.0.0.1that speaks the real wire format. It covers discovery, polling, streaming (including re-arming a stream that never starts), tare,Dropstopping the stream, and ignoring frames from other modules. None of it needs hardware.
When you change protocol or transport behaviour, extend the loopback suite. It catches timing, multi-device and cleanup bugs that frame-codec tests can't.
EtherCAT HAL
EtherCAT Devices
XTREM
Other crates