Skip to content

pavver/AS5600-Driver

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

37 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

AS5600_Driver

Crates.io Docs.rs Rust CI License: MIT OR Apache-2.0 no_std embedded-hal

A comprehensive, low-level, platform-agnostic Rust driver for the AS5600 magnetic rotary encoder (12-bit contactless potentiometer). Built on embedded-hal 1.0, it provides direct access to all device registers and OTP programming functions.

๐Ÿ“Œ Table of Contents

๐Ÿš€ Key Features

  • no_std Support: Ready for bare-metal microcontrollers (ESP32, STM32, nRF, etc.).
  • Full Register Map: Complete coverage of ZPOS, MPOS, MANG, CONF, STATUS, RAW_ANGLE, ANGLE, AGC, and MAGNITUDE.
  • Hardware Configuration: Support for Hysteresis, Power Modes, PWM settings, and Fast/Slow Filters.
  • Diagnostics: Methods to monitor magnet detection, magnetic field strength, and Automatic Gain Control (AGC).
  • OTP Programming: Permanent burning of settings protected by a Command Token pattern to prevent accidental execution.
  • AS5600L Support: Change and permanently store custom I2C addresses (requires AS5600L feature).
  • Unified Async/Sync: Identical logic for both modes thanks to internal macro unification. Full compatibility with embedded-hal-async 1.0.
  • Optimized Reads: Fetch both angle and magnet status in a single I2C transaction via read_angle_with_status.
  • Fluent Validation: Chainable health checks for magnet detection and field strength.
  • Mocking Support: Built-in hardware emulator for testing and simulation, including I2C bus failure simulation.
  • defmt Support: High-efficiency logging for embedded systems (behind the defmt feature).
  • Smart Configuration: Builder pattern with intelligent Read-Modify-Write logic to preserve unedited settings.
  • Trait-based Interface: AS5600Interface and AS5600AsyncInterface traits allow easy swapping between real hardware and mocks.
  • Cross-Platform: Support for Linux (SBCs like Raspberry Pi), ESP32 (std & no_std), and any other platform implementing embedded-hal.

๐Ÿ“ฆ Installation

Add this to your Cargo.toml:

[dependencies]
# Minimal synchronous version (no-std compatible by default)
AS5600-Driver = "0.1.2"

# Full version with async, mock and AS5600L support
AS5600-Driver = { version = "0.1.2", features = ["async", "mock", "AS5600L"] }

โš™๏ธ Features

  • async: Enables asynchronous support using embedded-hal-async.
  • mock: Enables the hardware mock emulator (requires std).
  • std: Enables standard library support.
  • anyhow: Enables integration with anyhow crate (requires std).
  • defmt: Enables defmt::Format implementation for all public structures.
  • AS5600L: Enables support for AS5600L specific features (I2C address management).

๐Ÿ›  Usage Examples

Single-Transaction Read with Validation (Recommended)

This method is the most efficient and safest way to get data, as it verifies magnet health and reads the angle in one I2C go.

// Chainable validation: check if magnet exists and field strength is OK
let result = encoder.read_angle_with_status()?
    .check_magnet_all()?;

println!("Angle: {}, Magnet Detected: {}", result.angle, result.status.detected);

Manual Individual Reads

let i2c = I2cdev::new("/dev/i2c-1")?;
// Use default address (0x36)
let mut encoder = AS5600Driver::new(i2c);

// OR use a custom address (useful for AS5600L)
// let mut encoder = AS5600Driver::with_address(i2c, 0x42);

let raw = encoder.read_raw_angle()?;
let filtered = encoder.read_angle()?;
let status = encoder.get_magnet_status()?;
let magnitude = encoder.get_magnitude()?;
let agc = encoder.get_agc()?;

let burn_count = encoder.get_burn_count()?;
let conf = encoder.get_config()?;

let det_sym = if status.detected { "โœ… YES" } else { "โŒ NO " };
let low_sym = if status.too_weak { "โš ๏ธ LOW " } else { "โœ… OK  " };
let high_sym = if status.too_strong { "โš ๏ธ HIGH" } else { "โœ… OK  " };

let wd_status = if conf.watchdog { "โšก ON " } else { "๐Ÿ’ค OFF" };
let pm_str = format!("{:?}", conf.power_mode);
let hyst_str = format!("{:?}", conf.hysteresis);
let out_str = format!("{:?}", conf.output_stage);
let pwm_str = format!("{:?}", conf.pwm_frequency);
let slow_str = format!("{:?}", conf.slow_filter);
let fast_str = format!("{:?}", conf.fast_filter_threshold);

All examples provide a real-time monitoring dashboard as shown below:

AS5600 Dashboard Preview
Typical real-time diagnostic output from the provided examples.

We provide several ready-to-use examples for different environments:

Smart Configuration (Builder Pattern)

The driver features a "smart" configuration system that minimizes I2C traffic and prevents accidental overwriting of settings. Using the apply_config method with a ConfigurationBuilder, only the registers containing modified fields are accessed.

If a register needs partial update, the driver performs a Read-Modify-Write cycle; if all fields in a register are set, it performs a direct Write.

// Only changes watchdog and power mode, preserving other settings
encoder.apply_config(
    Configuration::builder()
        .watchdog(false)
        .power_mode(PowerMode::LPM1)
)?;

Changing I2C Address (AS5600L only)

// 1. Change address in volatile memory (applied immediately)
encoder.set_address(0x42)?;

// 2. (Optional) Burn the new address permanently
let token = BurnToken::confirm_permanent_burn();
encoder.permanent_burn_address(token)?;

Quick Start: Decoupled Interface (Traits)

Using AS5600Interface or AS5600AsyncInterface allows your application logic to be independent of the specific I2C implementation.

use AS5600_Driver::AS5600Interface;

// This function works with ANY synchronous sensor implementation (Real or Mock)
fn run_diagnostic(encoder: &mut impl AS5600Interface) -> anyhow::Result<()> {
    let diag = encoder.read_all_diagnostics()?;
    println!("Position: {}, Detected: {}", diag.angle, diag.magnet_status.detected);
    Ok(())
}

๐Ÿ”„ Sharing the I2C Bus

The AS5600 has a fixed I2C address (0x36).

Multiple Sensors

To use multiple AS5600 sensors on the same bus, you must use an I2C multiplexer (e.g., TCA9548A).

Shared Bus with Other Devices

To share the bus with other device types, use a bus manager like embedded-hal-bus:

// Using a reference (&mut) to the I2C bus
let mut bus = I2cDriver::new(...)?;
let mut encoder1 = AS5600Driver::new(&mut bus);
// Other sensors on the same bus must have different addresses
let mut other_sensor = OtherSensor::new(&mut bus, 0x42); 

โš ๏ธ Safety Warning: OTP Programming

The AS5600 supports permanent burning of settings to its One-Time Programmable (OTP) memory. This is an irreversible operation. To prevent accidental execution, the driver uses the Command Token pattern.

use AS5600_Driver::BurnToken;

// 1. Create a token to confirm your intent
let token = BurnToken::confirm_permanent_burn();

// 2. Perform the burn
sensor.permanent_burn_settings(token)?;
  • permanent_burn_settings(token): Programs ZPOS and MPOS. Max 3 times.
  • permanent_burn_config(token): Programs CONF register. ONLY ONCE.

Support the Project / ะŸั–ะดั‚ั€ะธะผะฐั‚ะธ ะฟั€ะพะตะบั‚

If you find this extension useful and want to support development or speed up new features:

Donate via:

  • ๐Ÿ‡บ๐Ÿ‡ฆ Donatello โ€” Ukrainian service supporting:
    • ๐Ÿ’ณ Visa/Mastercard
    • ๐Ÿช™ Cryptocurrency (USDT)
    • ๐Ÿฆ Other payment methods
  • ๐ŸŒ PayPal: [email protected]

Your support helps keep this project alive and growing. Thank you! / ะ”ัะบัƒัŽ ะทะฐ ะฟั–ะดั‚ั€ะธะผะบัƒ! ๐Ÿ’™๐Ÿ’›


You can contact me via telegram or [email protected].

๐Ÿ“„ License

Licensed under either of:

About

Ultimate AS5600 Rust driver: โšก embedded-hal 1.0 & async support ๐Ÿ›  Smart I2C config (Read-Modify-Write) ๐Ÿ”’ Safe OTP burning with Command Tokens ๐Ÿ“ก Comprehensive diagnostics ๐Ÿฆ€ 100% no_std bare-metal ready.

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages