#servo #herkulex #stm32f1xx #usart #servo-motor

herkulex-drs-0x01-stm32f1xx

使用USART在stm32f1xx上为伺服电机Herkulex DRS-0101和DRS-0201编写的驱动程序

3个版本

0.1.2 2022年10月4日
0.1.1 2022年9月20日
0.1.0 2022年9月15日

嵌入式开发中排名608

Apache-2.0

52KB
615

herkulex-stm32f1xx

Herkulex-stm3f1xx是一个Rust驱动程序,用于简化使用USART协议通过stm32f1xx控制Herkulex DRS 0101和DRS 0201伺服电机。

它扩展了drs-0x01,这是一个Rust驱动程序,用于为这些伺服电机创建消息内容。

您可以在此处找到Herkulex DRS 0101和0201的文档。选择Rust是因为它的内存安全特性。

我们在管理控制器以接收伺服电机消息的中断时遇到了一些麻烦。在某些条件下,它可能会卡在某个中断中。

此库的发送端已经过测试。然而,接收端尚未完全测试。

它应该与任何stm32f1xx兼容,但仅在stm32f103上进行了测试。

功能

  • 使用USART协议控制伺服电机
  • 使用相同的通信控制多个伺服电机

目录

使用方法和示例

如果您想设置速度或位置到伺服电机,请记住启用扭矩。

初始化stm32f1xx和驱动程序

有关更多信息,请参阅示例

extern crate herkulex_drs_0x01_stm32f1xx;

#[entry]
fn main() {
    let dp: Peripherals = pac::Peripherals::take().unwrap();
    let cp = cortex_m::Peripherals::take().unwrap();

    let rcc: Rcc = dp.RCC.constrain();

    let mut flash = dp.FLASH.constrain();
    let mut gpioa = dp.GPIOA.split();
    let mut afio = dp.AFIO.constrain();

    let clocks_serial = rcc.cfgr.freeze(&mut flash.acr);

    // USART1 on Pins A9 and A10
    let pin_tx = gpioa.pa9.into_alternate_push_pull(&mut gpioa.crh);
    let pin_rx = gpioa.pa10;

    let serial = Serial::usart1(
        dp.USART1,
        (pin_tx, pin_rx),
        &mut afio.mapr,
        Config::default().baudrate(115200.bps()), // baud rate defined in herkulex doc : 115200
        clocks_serial.clone(),
    );

    // Separate into tx and rx channels
    let (mut tx, rx) = serial.split();

    let communication = Communication::new(&mut tx, rx);
    let motors = Motors::new(communication);
    let motor0 = motors.new_motor(0x00);
}

发送数据

要发送数据,您需要在stm32f1xx上配置一个tx引脚。有关初始化stm32f1xx的信息,请参阅此处

设置ID

区分ram和eeprom命令非常重要。如果您在ram中写入,则在您重新启动伺服电机时,参数将采用其先前值。当您写入EEPROM时,即使重新启动后值也将保持。

RAM ID

ID的值将更改到所需的值,直到重新启动。

        // Create a communication
let communication = Communication::new( & mut tx, rx);

// Create a motors group associated with a communication
let motors = Motors::new(communication);
    
// Create a servomotor linked with the servo with the id 0x00
let motor0 = motors.new_motor(0x00);

let id = 0x00;
// The id will be set in the ram
// When you restart the servo, it will use the eeprom value of the id
motor0.set_id(id);

有关更多信息,请参阅示例

EEPROM ID

ID的值将在EEPROM中更改。它将在重新启动后生效。

    // Create a communication
let communication = Communication::new( & mut tx, rx);

// Create a motors group associated with a communication
let motors = Motors::new(communication);

// Create a servomotor linked with the servo with the id 0x00
let motor0 = motors.new_motor(0x00);

let id = 0x00;
// The id will be set in the eeprom
// When you restart the servo, it will be this id
motor0.set_id_eep(id);

motor0.reboot();

请参阅示例获取更多信息。

设置速度

要设置速度,您需要启用伺服电机的扭矩

    // Create a communication
let communication = Communication::new( & mut tx, rx);

// Create a motors group associated with a communication
let motors = Motors::new(communication);

// Create a servomotor linked with the servo with the id 0x00
let motor0 = motors.new_motor(0x00);

// Always enable torque to let the servo rotate
motor0.enable_torque();

// Set the position to 512 (refer to the manual p56)
// It is half max speed
// The rotation enum comes from the drs-0x01 driver
motor0.set_speed(512, Clockwise);

请参阅示例获取更多信息(包括初始化)。

设置位置

要设置速度,您需要启用伺服电机的扭矩

    // Create a communication
let communication = Communication::new( & mut tx, rx);

// Create a motors group associated with a communication
let motors = Motors::new(communication);

// Create a servomotor linked with the servo with the id 0x00
let motor0 = motors.new_motor(0x00);

// Always enable torque to let the servo rotate
motor0.enable_torque();

// Set the position to 512 (refer to the manual p56)
// It corresponds to 0.163 degrees
motor0.set_position(512);

请参阅此处获取更多信息(包括初始化)。

接收数据

请查看文档以了解您将获得数组还是整数。

⚠请注意广播ID,程序可能永远卡在中断中。

获取未知ID的伺服电机ID

  1. 连接一个伺服电机
  2. 使用广播ID(0xFE)创建一个电机
  3. 发送状态请求
  4. 接收答案
  5. 读取数据包的第四列

请参阅下面的示例

    // Create a communication
let communication = Communication::new( & mut tx, rx);

// Create a motors group associated with a communication
let motors = Motors::new(communication);

// Create a servomotor linked with the broadcast ID 0xFE
let motor0 = motors.new_motor(0xFE);

// Send a stat request
// A stat request ask the servo how it is doing
//
// You should get an answer : an entire packet
// The id of the motor will be in the 4th column of the array received
//
// You can check the manual about the stat command
let id = motor0.stat()[4];

请参阅此处获取更多信息。

贡献

请随时发送pull请求和提出问题。

请尝试创建可复现的bug报告

  • 可复现。包括重现问题的步骤。
  • 具体。尽可能提供详细信息:哪个版本,什么环境等。
  • 唯一。不要重复现有已打开的问题。
  • 针对单个bug。每个报告一个bug。

致谢

herkulex-stm32f1xx是由Ronan Bonnet创建的。

Joel为该项目做出了贡献,并帮助我解决了一些bug。

我想感谢Paul Florence为其drs-0x01驱动程序,它帮助我开发了此驱动程序。

许可证

此项目采用Apache-2.0许可。

请参阅LICENSE获取更多信息。

依赖关系

~19MB
~541K SLoC