xy_modbus/lib.rs
1//! Driver for the XY7025 programmable buck converter (and protocol-compatible
2//! siblings via `Model::Custom`).
3//!
4//! These modules share a common Modbus-RTU register layout — see the
5//! crate's `README.md` for the full protocol reference.
6//!
7//! ```no_run
8//! # use xy_modbus::{ModbusTransport, RtuError};
9//! # struct MyTransport;
10//! # impl ModbusTransport for MyTransport {
11//! # fn read_holding(&mut self, _: u8, _: u16, _: &mut [u16]) -> Result<(), RtuError> { unimplemented!() }
12//! # fn write_single_holding(&mut self, _: u8, _: u16, _: u16) -> Result<(), RtuError> { unimplemented!() }
13//! # fn write_multiple_holdings(&mut self, _: u8, _: u16, _: &[u16]) -> Result<(), RtuError> { unimplemented!() }
14//! # }
15//! # fn main() -> Result<(), RtuError> {
16//! # let my_transport = MyTransport;
17//! use xy_modbus::{Model, Xy, SafetyLimits};
18//!
19//! let mut xy = Xy::new(my_transport, Model::Xy7025);
20//! xy.set_protection(SafetyLimits { lvp_v: 22.0, ovp_v: 15.0, ocp_a: 15.0 })?;
21//! xy.set_voltage(13.5)?;
22//! xy.set_current_limit(10.0)?;
23//! xy.set_output(true)?;
24//!
25//! let s = xy.read_status()?;
26//! println!("{:.2} V @ {:.2} A", s.v_out, s.i_out);
27//! # Ok(())
28//! # }
29//! ```
30//!
31//! The crate is `no_std`. With the default `embedded-io` feature, the
32//! [`uart`] module provides a ready-to-use [`ModbusTransport`] over any
33//! `embedded-io` UART. To use a different transport, disable default
34//! features and implement [`ModbusTransport`] yourself; the [`framing`]
35//! module exposes the on-wire codec.
36//!
37//! For `esp-idf-hal` users, the `esp-idf-hal` feature ships a convenience
38//! constructor so you don't need to write a UART wrapper:
39//!
40//! ```ignore
41//! use xy_modbus::{Model, Xy};
42//!
43//! let mut xy = Xy::from_esp_uart(uart, Model::Xy7025);
44//! xy.set_voltage(13.5)?;
45//! ```
46
47#![no_std]
48
49// ─── Modules ─────────────────────────────────────────────────────────────────
50
51mod device;
52mod types;
53
54pub mod framing;
55pub(crate) mod regs;
56pub mod transport;
57
58#[cfg(feature = "embedded-io")]
59pub mod uart;
60
61// `esp-idf-hal` itself is target-conditional (only present when targeting
62// `target_os = "espidf"`), so this module is too — enabling the feature on
63// host builds is harmless.
64#[cfg(all(feature = "esp-idf-hal", target_os = "espidf"))]
65pub mod esp_idf;
66
67// ─── Re-exports ──────────────────────────────────────────────────────────────
68
69pub use device::Xy;
70pub use framing::FrameError;
71pub use transport::{BlockingRead, ModbusError, ModbusTransport, RtuError};
72pub use types::{
73 BaudRate, GroupParams, Model, ModelCheck, OnTime, ProtectionStatus, RegMode, SafetyLimits,
74 Setpoints, Status, TempUnit, Temperatures, Totals,
75};
76
77#[cfg(feature = "embedded-io")]
78pub use uart::UartTransport;