atm90e32_async/lib.rs
1// SPDX-License-Identifier: (GPL-2.0-or-later OR Apache-2.0)
2// Copyright (c) Viacheslav Bocharov <v@baodeep.com> and JetHome (r)
3
4//! Async `no_std` driver for the Microchip / Atmel **ATM90E32** 3-phase
5//! SPI power metering IC.
6//!
7//! This crate provides a lightweight, portable driver built on top of
8//! [`embedded-hal-async`](https://crates.io/crates/embedded-hal-async).
9//! It has no dependency on any specific async runtime and works with
10//! Embassy, RTIC2, or any other executor that implements
11//! [`SpiDevice`](embedded_hal_async::spi::SpiDevice) and
12//! [`DelayNs`](embedded_hal_async::delay::DelayNs).
13//!
14//! ## Architecture
15//!
16//! The crate follows a **sans-I/O** split:
17//!
18//! * [`proto`] — pure functions: byte-frame building, response parsing,
19//! raw → engineering unit conversions, and the post-reset init
20//! sequence expressed as data. No I/O, no async — 100% host-testable.
21//! * [`driver`] — async transport: owns the SPI device and delay,
22//! invokes the `proto` helpers, maps errors, and sequences the init
23//! writes.
24//!
25//! ## Features
26//!
27//! * `defmt` *(optional)* — derives
28//! [`defmt::Format`](https://docs.rs/defmt/latest/defmt/trait.Format.html)
29//! on public types for ergonomic logging with the `defmt` ecosystem.
30//!
31//! ## Quick start
32//!
33//! ```no_run
34//! # use atm90e32_async::{Atm90e32, Config, LineFreq, PgaGain};
35//! # async fn demo<SPI, D>(spi: SPI, delay: D) -> Result<(), atm90e32_async::Error<SPI::Error>>
36//! # where
37//! # SPI: embedded_hal_async::spi::SpiDevice,
38//! # D: embedded_hal_async::delay::DelayNs,
39//! # {
40//! let mut meter = Atm90e32::new(spi, delay);
41//! meter.probe().await?;
42//!
43//! let cfg = Config::default()
44//! .with_voltage_gain([39470, 39470, 39470])
45//! .with_current_gain([65327, 65327, 65327])
46//! .with_line_freq(LineFreq::Hz50)
47//! .with_pga_gain(PgaGain::X2);
48//! meter.init(&cfg).await?;
49//!
50//! loop {
51//! let r = meter.read_all_phases().await?;
52//! // use r.voltage, r.current, r.power, r.reactive, r.pf, r.frequency
53//! # break;
54//! }
55//! # Ok(())
56//! # }
57//! ```
58//!
59//! ## What's implemented
60//!
61//! The driver covers the measurement set used by production JetHome
62//! PM380 meters: RMS voltage/current, active and reactive power,
63//! power factor, mains frequency, **phase angle**, **chip temperature**,
64//! and **phase status** (overcurrent, overvoltage, voltage sag, phase
65//! loss) on all three phases. Not yet implemented (contributions
66//! welcome): energy accumulation, apparent power, harmonic analysis,
67//! zero-crossing interrupts, and ATM90E36 family support.
68//!
69//! ## License
70//!
71//! Dual-licensed under either
72//! [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0) or
73//! [GPL-2.0-or-later](https://www.gnu.org/licenses/old-licenses/gpl-2.0.html)
74//! at the user's option.
75
76#![no_std]
77#![deny(unsafe_code)]
78#![warn(missing_docs)]
79
80pub mod config;
81pub mod driver;
82pub mod error;
83pub mod proto;
84pub mod readings;
85pub mod registers;
86pub mod status;
87
88pub use crate::config::{Config, LineFreq, PgaGain};
89pub use crate::driver::{Atm90e32, Phase};
90pub use crate::error::{Error, InitStage};
91pub use crate::readings::PhaseReadings;
92pub use crate::status::PhaseStatus;