#linux-cnc #cnc #硬件抽象层 #抽象层 #API 绑定

linuxcnc-hal

LinuxCNC HAL子模块的安全、高级接口

6个版本

0.3.0 2022年11月15日
0.2.0 2021年1月6日
0.1.3 2020年1月29日

#676 in 硬件支持

MIT/Apache

220KB
4.5K SLoC

LinuxCNC HAL接口用于Rust

CircleCI Crates.io Docs.rs Liberapay

请考虑成为赞助者,以便我在业余时间继续维护这个crate!

文档

LinuxCNC HAL (硬件抽象层)模块的安全、高级接口。

对于低级、不安全的用法,请参阅linuxcnc-hal-sys crate。

开发环境搭建

bindgen必须正确设置。请遵循其文档中的要求部分

要运行和调试任何HAL组件,可以设置LinuxCNC模拟器。这里有Linux Mint(及其他Debian衍生版)的指南在此

项目设置

此crate依赖于linuxcnc-hal-sys crate,该crate需要将LINUXCNC_SRC环境变量设置为正确的值以正确生成C绑定。该值必须是LinuxCNC源代码根目录的绝对路径。

LinuxCNC源代码的版本必须与机器控制中使用的LinuxCNC版本相匹配。

# Clone LinuxCNC source code into linuxcnc/
git clone https://github.com/LinuxCNC/linuxcnc.git

# Check out a specific version tag. This may also be a commit, but must match the version in use by the machine control.
cd linuxcnc && git checkout v2.8.0 && cd ..

# Create your component lib
cargo new --lib my_comp

cd my_comp

# Add LinuxCNC HAL bindings as a Cargo dependency with cargo-edit
cargo add linuxcnc-hal

LINUXCNC_SRC=/path/to/linuxcnc/source/code cargo build

如果LinuxCNC配置为原地运行,则在启动时可能找不到liblinuxcnchal.so.0。为了修复,请尝试使用例如export LD_LIBRARY_PATH=~/Repositories/linuxcnc/lib设置库路径。

示例

创建具有输入和输出的组件

此示例创建了一个名为"pins"的组件,该组件具有单个输入("input-1")和输出引脚("output-1")。它进入一个无限循环,每秒更新output-1的值。LinuxCNC约定组件和引脚名称应该是连字符式

此示例可以用类似的.hal文件加载到LinuxCNC中,如下所示

loadusr -W /path/to/your/component/target/debug/comp_bin_name
net input-1 spindle.0.speed-out pins.input-1
net output-1 pins.output-1

引脚和其他资源使用 Resources 特性进行注册。本例创建了一个 Pins 结构体,该结构体包含两个引脚。 HalComponent::new 处理组件创建、资源(引脚、信号等)初始化以及 UNIX 信号处理程序注册。

use linuxcnc_hal::{
    error::PinRegisterError,
    hal_pin::{InputPin, OutputPin},
    prelude::*,
    HalComponent, RegisterResources, Resources,
};
use std::{
    error::Error,
    thread,
    time::{Duration, Instant},
};

struct Pins {
    input_1: InputPin<f64>,
    output_1: OutputPin<f64>,
}

impl Resources for Pins {
    type RegisterError = PinRegisterError;

    fn register_resources(comp: &RegisterResources) -> Result<Self, Self::RegisterError> {
        Ok(Pins {
            input_1: comp.register_pin::<InputPin<f64>>("input-1")?,
            output_1: comp.register_pin::<OutputPin<f64>>("output-1")?,
        })
    }
}

fn main() -> Result<(), Box<dyn Error>> {
    rtapi_logger::init();

    // Create a new HAL component called `rust-comp`
    let comp: HalComponent<Pins> = HalComponent::new("rust-comp")?;

    // Get a reference to the `Pins` struct
    let pins = comp.resources();

    let start = Instant::now();

    // Main control loop
    while !comp.should_exit() {
        let time = start.elapsed().as_secs() as i32;

        // Set output pin to elapsed seconds since component started
        pins.output_1.set_value(time.into())?;

        // Print the current value of the input pin
        println!("Input: {:?}", pins.input_1.value());

        // Sleep for 1000ms. This should be a lower time if the component needs to update more
        // frequently.
        thread::sleep(Duration::from_millis(1000));
    }

    // The custom implementation of `Drop` for `HalComponent` ensures that `hal_exit()` is called
    // at this point. Registered signal handlers are also deregistered.

    Ok(())
}

许可证

许可方式如下:

任选其一。

贡献

除非您明确表示,否则根据 Apache-2.0 许可证定义的,您有意提交并包含在本作品中的任何贡献,都将按照上述方式双许可,不附加任何额外条款或条件。

依赖项

~0.5–2.7MB
~55K SLoC