【外设移植】SG90舵机Ai-M61开发板

[复制链接]
查看1121 | 回复18 | 2024-3-28 15:36:40 | 显示全部楼层 |阅读模式

本帖最后由 zlook119 于 2024-3-28 15:48 编辑

本帖最后由 zlook119 于 2024-3-28 15:41 编辑

【外设移植】SG90舵机Ai-M61开发板

一、外设介绍

产品名称:SG90 9g 塑料齿数字舵机 产品净重: 9g 产品尺寸: 23*12.2*29mm 产品扭矩: 1.5kg/cm 反应速度: 0.3sec/60degree 工作电压: 4.2V-6V 使用温度: 0-55度 动作死区: 10us 齿轮介质: 塑料

1711608446756.png

该舵机有三根线黑/灰色为GND,红色为VCC,橙色为信号线

1711608888125.jpeg

SG90舵机分为180度和360度(连续旋转),本文仅仅讨论180度舵机 ,下图左侧为360度舵机,右侧为180度舵机。

1711608854258.jpeg

二、舵机驱动信号分析

阅读相关资料得知,该舵机为PWM信号驱动,信号周期为20ms,既下图中T时间为20ms

1711609143763.png

下图为高电平持续时间t对应的旋转角度的关系

1711609235838.png

下面为逻辑分析仪采集的相关角度的直观数据

0度时驱动信号的图像

1711609265676.png

90度时驱动信号的图像

1711609294398.png

180度时驱动信号的图像

1711609313645.png

即,M61输出相关PWM波形到舵机信号线,舵机就会旋转相应角度。

三、移植过程

M61和舵机的连接

1711609895661.png

3V3---->红色

GPIO19---->信号线(橙色)

GND---->黑色/灰色

接下来编写程序生成指定的PWM信号,可以参考阅读,小泽哥的这篇文章

(九)零基础开发小安派-Eyes-S1【外设篇】——PWM https://bbs.ai-thinker.com/forum.php?mod=viewthread&tid=622 (出处: 物联网开发者社区-安信可论坛)

这里粘贴一下bflb_servo.c的内容

#include "bflb_mtimer.h"        //mtimer定时器头文件
#include "bflb_pwm_v2.h"        //pwm_v2头文件
#include "bflb_clock.h"         //系统时钟头文件
#include "board.h"              //开发板头文件,包装的库
#include "bflb_gpio.h"          //gpio头文件
#include "bflb_servo.h"


struct bflb_servo_attr bflb_servo_attach(uint8_t pin, uint8_t ch){

    struct bflb_device_s *pwm;     //创建LHAL外设库结构体,名称为pwm
    struct bflb_device_s *gpio;    //初始化一个结构体指针作为外设句柄
    struct bflb_servo_attr servo_attr; // 创建要返回的结构体实例

    gpio = bflb_device_get_by_name("gpio");

    bflb_gpio_init(gpio, pin, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
    pwm = bflb_device_get_by_name("pwm_v2_0");  //给外设接口赋名pwm_v2_0

    /* period = .XCLK / .clk_div / .period = 40MHz / 16000 / 50 = 50Hz */
    struct bflb_pwm_v2_config_s cfg = {
        .clk_source = BFLB_SYSTEM_XCLK,
        .clk_div = 160,
        .period = 5000,
    };                //设置PWM的频率,选择时钟,分频,和周期。根据上面的公式算出最终的频率。


    /*初始化PWM输出*/
    bflb_pwm_v2_init(pwm, &cfg);

    // bflb_pwm_v2_channel_positive_start 开启正向通道(CHxP)输出
    // bflb_pwm_v2_channel_negative_start开启负向通道(CHxN) 从参数内可以查询

    bflb_pwm_v2_channel_positive_start(pwm, ch);  //IO19是正向通道3
    bflb_pwm_v2_start(pwm);  //将设置好的频率开启pwm输出

    servo_attr.dev = pwm;  
    servo_attr.pin = pin;  
    servo_attr.ch = ch;  

    return servo_attr;
}


int angle_to_pwm(int angle) {  
    if (angle < SERVO_ANGLE_MIN) angle = SERVO_ANGLE_MIN;  
    if (angle > SERVO_ANGLE_MAX) angle = SERVO_ANGLE_MAX;  

    // 线性插值计算PWM值  
    int range = SERVO_ANGLE_MAX - SERVO_ANGLE_MIN;  
    int pwm_range = PWM_MAX - PWM_MIN;  
    int pwm_value = PWM_MIN + ((angle - SERVO_ANGLE_MIN) * pwm_range / range);  

    return pwm_value;  
}

// 写入伺服角度值(以度为单位)  
void bflb_servo_write(struct bflb_servo_attr *servo, int angle) {

    // 将角度转换为PWM占空比  
    int pwm_value = angle_to_pwm(angle);
    // 调用pwm修改占空比
    bflb_pwm_v2_channel_set_threshold(servo->dev, servo->ch, 0, pwm_value);
}

void bflb_servo_stop(struct bflb_servo_attr *servo){
    // 停止PWM信号发生
    bflb_pwm_v2_channel_positive_stop(servo->dev, servo->ch);
}

bflb_servo.c实现了三个函数,

struct bflb_servo_attr bflb_servo_attach(uint8_t pin, uint8_t ch);传入引脚和PWM正向通道,生成servo设备,进行后续函数的操作。 void bflb_servo_write(struct bflb_servo_attr *servo, int value);传入servo设备和角度值,使舵机旋转到指定角度 void bflb_servo_stop(struct bflb_servo_attr *servo);传入设备,停止生成PWM信号

其中PWM的通道通过查 bl616_bl618_ds_zh_cn_1.4.pdf手册获取,如图。

1711610503806.png

下面粘贴一下测试用例

#include "bflb_mtimer.h"        //mtimer定时器头文件
#include "bflb_pwm_v2.h"      //pwm_v2头文件
#include "bflb_clock.h"           //系统时钟头文件
#include "board.h"                 //开发板头文件,包装的库
#include "bflb_gpio.h"           //gpio头文件
#include "bflb_servo.h"


int main(void)
{
    // int i;
    board_init(); //板子初始化
    struct bflb_servo_attr servo = bflb_servo_attach(GPIO_PIN_19, PWM_CH3); // 舵机初始化,此处只使用了正向通道,GPIO的正向通道可以从附件中查找

    bflb_servo_write(&servo, 0); 
    bflb_mtimer_delay_ms(2000);
    bflb_servo_write(&servo, 45);
    bflb_mtimer_delay_ms(2000);
    bflb_servo_write(&servo, 90);
    bflb_mtimer_delay_ms(2000);
    bflb_servo_write(&servo, 135);
    bflb_mtimer_delay_ms(2000);
    bflb_servo_write(&servo, 180);
    bflb_mtimer_delay_ms(2000);
    bflb_servo_stop(&servo);

    while (0) {
        // bflb_servo_write(&servo, 0);
        // bflb_mtimer_delay_ms(2000);
        // bflb_servo_write(&servo, 45);
        // bflb_mtimer_delay_ms(2000);
        // bflb_servo_write(&servo, 90);
        // bflb_mtimer_delay_ms(2000);
        // bflb_servo_write(&servo, 135);
        // bflb_mtimer_delay_ms(2000);
        // bflb_servo_write(&servo, 180);
        // bflb_mtimer_delay_ms(2000);
    }
}

测试的相关视频

<iframe src="https://player.bilibili.com/player.html?aid=1752273960&bvid=BV1vx421Q7rt&cid=1484810069&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>

最后,特特别注意

在驱动调试的过程中,可能因为PWM参数设置不正确,导致第一块M61烧坏了,后来又买了一块块儿,请大家确认程序运行完好后再给外设上电,最好上电前用逻辑分析仪测一下信号,谢谢大家看到这儿,小菜鸟给大家致敬啦。🫡

回复

使用道具 举报

zlook119 | 2024-3-28 15:42:30 | 显示全部楼层
下面是程序库附件和通道查找参考文件

AiPi-Servo.zip

3.25 KB, 下载次数: 6

bl616_bl618_ds_zh_cn_1.4.pdf

1023.13 KB, 下载次数: 4

回复 支持 反对

使用道具 举报

1084504793 | 2024-3-28 16:01:42 | 显示全部楼层
回复

使用道具 举报

bzhou830 | 2024-3-28 16:31:09 | 显示全部楼层
选择去发光,而不是被照亮
回复

使用道具 举报

爱笑 | 2024-3-28 16:46:10 | 显示全部楼层
用心做好保姆工作
回复

使用道具 举报

WT_0213 | 2024-3-29 08:48:35 | 显示全部楼层
回复

使用道具 举报

lazy | 2024-3-29 09:06:35 | 显示全部楼层
非常棒
回复

使用道具 举报

1055173307 | 2024-3-29 16:57:34 | 显示全部楼层
学习学习
回复

使用道具 举报

干簧管 | 2024-3-29 21:38:45 | 显示全部楼层
回复

使用道具 举报

noonezero | 2024-4-8 10:03:07 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则