RaspberryPi笔记[2]-控制舵机

发布时间 2023-08-16 06:53:54作者: qsBye

摘要

使用树莓派操控PWM舵机.

平台信息

硬件信息:

  • RaspberryPi zero 2w
  • GPIO18:MOTOR_1

开发语言:

  • Python
  • Rust

依赖库:

  • rppal = "0.14.1"
  • anyhow = "1.0.74"

树莓派40pin的GPIO几种编号方式

[https://pinout.xyz/pinout/pin12_gpio18/]
[https://blog.csdn.net/lanchunhui/article/details/79055895]
树莓派GPIO基本分为如下的三种编码方式:物理引脚BOARD编码,BCM编码,以及 wiringPi 编码.

  1. BOARD编码
  2. BCM编码
  3. WiringPi编码

RPPAL库

[https://github.com/golemparts/rppal]
A Rust library that provides access to the Raspberry Pi's GPIO, I2C, PWM, SPI and UART peripherals.

实现

[https://github.com/golemparts/rppal/blob/master/examples/pwm_servo.rs]
[https://github.com/golemparts/rppal/blob/master/examples/gpio_servo_softpwm.rs]

代码

项目目录:

.
├── Cargo.lock
├── Cargo.toml
├── src
│   └── main.rs
└── target
    ├── aarch64-unknown-linux-musl
    ├── armv7-unknown-linux-gnueabihf
    ├── CACHEDIR.TAG
    └── debug

Cargo.toml

[package]
name = "rpi_step_motor_rust"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
anyhow = "1.0.74"
rppal = "0.14.1"

[target.aarch64-unknown-linux-musl]
linker = "arm-linux-musleabihf-gcc"

[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"

main.rs

/* 
编译命令:
- cargo add rppal
- cargo add anyhow
- cargo run
*/
use std::error::Error;
use std::thread;
use std::time::Duration;

use rppal::gpio::Gpio;

// Gpio uses BCM pin numbering. BCM GPIO 18 is tied to physical pin 12.
const GPIO_PWM: u8 = 18;

// Servo configuration. Change these values based on your servo's verified safe
// minimum and maximum values.
// Period: 20 ms (50 Hz). Pulse width: min. 1200 µs, neutral 1500 µs, max. 1800 µs.
const PERIOD_MS: u64 = 20;
const PULSE_MIN_US: u64 = 1200;
const PULSE_NEUTRAL_US: u64 = 1500;
const PULSE_MAX_US: u64 = 1800;

fn main() -> Result<(), Box<dyn Error>> {
    // Retrieve the GPIO pin and configure it as an output.
    let mut pin = Gpio::new()?.get(GPIO_PWM)?.into_output();

    // Enable software-based PWM with the specified period, and rotate the servo by
    // setting the pulse width to its maximum value.
    pin.set_pwm(
        Duration::from_millis(PERIOD_MS),
        Duration::from_micros(PULSE_MAX_US),
    )?;

    // Sleep for 500 ms while the servo moves into position.
    thread::sleep(Duration::from_millis(500));

    // Rotate the servo to the opposite side.
    pin.set_pwm(
        Duration::from_millis(PERIOD_MS),
        Duration::from_micros(PULSE_MIN_US),
    )?;

    thread::sleep(Duration::from_millis(500));

    // Rotate the servo to its neutral (center) position in small steps.
    for pulse in (PULSE_MIN_US..=PULSE_NEUTRAL_US).step_by(10) {
        pin.set_pwm(
            Duration::from_millis(PERIOD_MS),
            Duration::from_micros(pulse),
        )?;
        thread::sleep(Duration::from_millis(20));
    }
    println!("Rotate the servo done!\n");

    Ok(())

    // When the pin variable goes out of scope, software-based PWM is automatically disabled.
    // You can manually disable PWM by calling the clear_pwm() method.

Python版本:

# -*- encoding:utf-8
from time import sleep
import RPi.GPIO as GPIO
 
GPIO.setmode(GPIO.BCM)#以BCM模式使用引脚
GPIO.setwarnings(False)# 去除GPIO警告
 
motor1_pin=18
 
def setServoAngle(servo, angle):#此函数将角度转换为占空比
    pwm = GPIO.PWM(servo, 50)#设置pwm波为50Hz,也就是20ms一周期
    pwm.start(8)#启动pwm

    dutyCycle = angle / 18. + 3.#此公式由舵机调零推算得出(+3是偏移量)(占空比=%2.5+(目标角度/180°)*(%12.5-%2.5))
    pwm.ChangeDutyCycle(dutyCycle)#调整pwm占空比
    sleep(0.3)
    pwm.stop()#关闭pwm
 
 
if __name__ == '__main__':
    import sys
 
    #servo = int(sys.argv[1])#外部输入参数
    GPIO.setup(motor1_pin, GPIO.OUT)#设置指定的引脚为输出模式

    while True:
        setServoAngle(motor1_pin, 90)
        sleep(1)
        setServoAngle(motor1_pin, 0)
        sleep(1)

    GPIO.cleanup()#清除引脚占用

编译&运行

#配置环境
export https_proxy=http://192.168.31.94:7890 http_proxy=http://192.168.31.94:7890 all_proxy=socks5://192.168.31.94:7890
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
#编译
cargo add rppal
cargo add anyhow
cargo run

效果