ad5700 0.1.0

AD5700-1 HART modem driver for embedded-hal with blocking and async support
Documentation

hart-rs

A no_std HART protocol implementation for embedded systems, written in Rust.

CI

What it is

HART (Highway Addressable Remote Transducer) is an industrial protocol layered over a 4-20 mA current loop. This workspace implements the full protocol stack — codec, modem driver, and async master — as three no_std crates targeting embedded microcontrollers such as the STM32H7 with an AD5700-1 HART modem.

Crate architecture

hart-protocol          (codec: encode, decode, typed commands)
      ^
      |
   ad5700              (AD5700-1 modem driver: blocking + async)
      ^
      |
embassy-hart           (async HART master via Embassy + embassy-time)

hart-protocol is a standalone codec with no hardware dependencies. ad5700 wraps the modem with embedded-hal traits and uses hart-protocol. embassy-hart builds on ad5700's async driver and adds timeout management.

Supported commands

Universal read commands

Cmd Description
0 Read unique identifier (device ID)
1 Read primary variable
2 Read loop current and percent range
3 Read dynamic variables

Common-practice read commands

Cmd Description
9 Read device variables with status
11 Read unique identifier by tag
12 Read message
13 Read tag, descriptor, and date
14 Read primary variable transducer info
15 Read device info
16 Read final assembly number
20 Read long tag
48 Read additional device status

Write commands

Cmd Description
6 Write polling address
17 Write message
18 Write tag, descriptor, and date
19 Write final assembly number
22 Write long tag
38 Reset configuration changed flag

Quick start

Encode a Command 0 request frame and decode a response using hart-protocol (no hardware or I/O involved):

use hart_protocol::encode::encode_frame;
use hart_protocol::decode::Decoder;
use hart_protocol::types::{Address, FrameType, MasterRole};
use hart_protocol::commands::read_device_id::{ReadDeviceIdRequest, ReadDeviceIdResponse};
use hart_protocol::commands::{CommandRequest, CommandResponse};
use hart_protocol::consts::MIN_PREAMBLE_COUNT;

// --- Encode a Command 0 request ---
let address = Address::Short {
    master: MasterRole::Primary,
    burst: false,
    poll_address: 0,
};

let req = ReadDeviceIdRequest;
let mut data_buf = [0u8; 4];
let data_len = req.encode_data(&mut data_buf).unwrap();

let mut frame_buf = [0u8; 32];
let frame_len = encode_frame(
    FrameType::Request,
    &address,
    ReadDeviceIdRequest::COMMAND_NUMBER,
    &data_buf[..data_len],
    MIN_PREAMBLE_COUNT,
    &mut frame_buf,
).unwrap();

// frame_buf[..frame_len] is ready to send to the modem.

// --- Decode a Command 0 response byte-by-byte ---
let raw_response: &[u8] = &[
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF,       // preamble
    0x06,                               // delimiter: response short
    0x80,                               // address
    0x00,                               // command 0
    0x0E,                               // byte count (14 = 2 status + 12 data)
    0x00, 0x00,                         // response status bytes
    0xFE, 0x1A, 0x2B, 0x05, 0x07,
    0x01, 0x03, 0x04, 0x00, 0x11, 0x22, 0x33, // device identity
    0x00,                               // checksum (illustrative)
];

let mut decoder = Decoder::new();
let mut raw_frame = None;
for &byte in raw_response {
    if let Some(frame) = decoder.feed(byte).unwrap_or(None) {
        raw_frame = Some(frame);
        break;
    }
}

if let Some(frame) = raw_frame {
    // Strip the two response status bytes before decoding the command payload.
    let payload = &frame.data[2..];
    let resp = ReadDeviceIdResponse::decode_data(payload).unwrap();
    let _ = resp.device_id;
}

Hardware target

This stack is designed for the STM32H7 microcontroller paired with the Analog Devices AD5700-1 HART modem. The ad5700 and embassy-hart crates depend on embedded-hal and Embassy respectively, keeping the codec (hart-protocol) portable to any platform.

Releasing

  1. Update version in root Cargo.toml ([workspace.package] version = "X.Y.Z")
  2. Commit: release: vX.Y.Z
  3. Tag: git tag vX.Y.Z
  4. Push: git push && git push --tags

CI will verify tests pass, check the tag matches Cargo.toml, and publish all crates to crates.io in dependency order.

Requires CARGO_REGISTRY_TOKEN secret in GitHub repository settings.

License

Licensed under either of:

at your option.