基于立创梁山派的21年电赛F题智能送药小车: 基于立创梁山派的21年电赛F题 您所在的位置:网站首页 送药的软件叫什么 基于立创梁山派的21年电赛F题智能送药小车: 基于立创梁山派的21年电赛F题

基于立创梁山派的21年电赛F题智能送药小车: 基于立创梁山派的21年电赛F题

2024-06-29 23:58| 来源: 网络整理| 查看: 265

基于立创梁山派的21年电赛F题智能送药小车

⚙️简介::全国产化器件制作的基于立创梁山派的21年电赛F题智能送药小车

硬件部分:扩展板由电机驱动,国产姿态传感器及磁力计,蜂鸣器驱动,按键和药物检测,ADC电压采集,CAN芯片等组成。国产蓝牙模块实现双车通讯,K210实现数字识别和巡红线。 软件部分:国产RT-Thread,PID控制电机实现位置环和速度环,姿态解算,K210数字识别和红线识别,定义串口通讯协议并DMA接收+ringbufer缓存处理,各数据交换使用发布订阅机制。 教程部分:请点这里

简要视频:

赛题分析 电路设计 代码编写

简要文章:

赛题分析 电路设计

精简文档:

00_单个小车BOM表 01_组装文档 02_编译文档 03_软件工具与调试工具介绍 04_建立RT-Thread工程模板 05_Finsh控制台的使用 06_如何计算小车轮子转速 07_电机驱动-舵机-蜂鸣器PWM配置 08_直流减速电机PID速度环与位置环调试 09_国产IMU移植及姿态解算 10_小车角度环的调试与实现 11_K210更换固件-运行基础颜色识别例程 12_K210的KPU数字识别训练 13_K210功能实现代码讲解 14_立创梁山派与K210串口通信协议框架搭建 15_小车寻红线环的调试与实现 16_按键检测的消抖和实现 17_送药小车数据的发布与订阅 18_送药小车实现思路 一 目录结构 0_STL:小车上的3D打印文件。 1_Hardware:小车扩展板PCB以及底板PCB结构件。 2_Code:代码部分,包含梁山派MDK工程和K210程序。 3_Tool:常用软件工具。 4_Docs:文档说明。 二 使用说明 了解过 RT-Thread ENV 开发工具 克隆本仓库到本地。 进入2_Code目录,使用 ENV 工具执行 pkgs --update下载缺失的软件包。 使用 ENV 工具执行 scons --target=mdk5更新MDK5工程文件。 打开2_Code目录下的project.uvprojx即可正常编译使用了。 从来没用过RT-Thread 去RT-Thread文档中心了解了解。 进入仓库的发行版,下载附件2_code.zip。 解压后打开目录下的project.uvprojx即可正常编译使用了。 三 代码介绍

所有自己添加的文件都在applications目录下。

梁山派GD32端 RTOS选择并建立模板

​ 为了配合梁山派的全国产化,本次的RTOS选择国内优秀的RT-Thread,RT-Thread 是一款完全由国内团队开发维护的嵌入式实时操作系统(RTOS),具有完全的自主知识产权。经过 16 个年头的沉淀,伴随着物联网的兴起,它正演变成一个功能强大、组件丰富的物联网操作系统。

​ 它与其他RTOS最大的区别是他有一个软件包库,有许多开源的大佬分享自己做的软件包。如果你选用支持RT-Thread的芯片来开发项目,就可以使用它丰富的软件包。比如说想读取MPU6050的数据,直接在ENV工具中选择MUP6050的软件包,重新生成工程,运行例程就可以获得数据了。比如想做一个按键驱动,在软件包中搜索 按钮,就会有数个软件包供你选择,你可以专注于做应用,底层的大部分驱动都是可以复用的。

​ 梁山派目前已经适配基础版RT-Thread,链接.

​ 建议不要选择master分支进行开发,因为主分支处于一直开发的状态,可能会有意想不到的BUG。一般要选一个稳定的版本。我这里选用的RT-Thread-V4.1.1。

BSP底层初始化编写

​ 当前梁山派还没有适配RT-Thread的PWM,ENCODER等外设资源,所以需要我们自己进行初始化配置。

​ 主要有蜂鸣器PWM的配置,电机驱动PWM的配置,正交编码器的配置,舵机PWM的配置。

​ 以蜂鸣器初始化为例。

​ 首先要知道确切的系统时钟和定时器时钟频率。打开GD32参考手册的第四章节:复位和时钟单元(RCU)里面的图4-2.时钟树。再找到keil工程下面Drivers里面的board.c里面的SystemClock_Config。找到系统时钟之后找一下APB2和APB1的时钟频率。以蜂鸣器的PWM配置为例。可以看到BEEP_TIMER就是TIMER12,它挂在APB1时钟下,/* APB1 = AHB/4 /就是说APB1是60M,TIMER时钟由AHB时钟分频获得,它的频率可以等于CK_APBx、CK_APBx的两倍或CK_APBx 的四倍。详细信息请参考RCU_CFG1寄存器的TIMERSEL位,因为我们是给APB分频了的。所以定时器时钟等于 APB 时钟的两倍,所以这里的TIMER12时钟是60M2=120Mhz,在这里的30-1,要-1是因为这里的计数是从0开始的。接下来就是简单的除法计算了。//120Mhz/30=4000000Hz

这里用到了自动初始化:RT-Thread总共有六个初始化顺序

1 INIT_BOARD_EXPORT(fn)

非常早期的初始化,此时调度器还未启动

2 INIT_PREV_EXPORT(fn)

主要是用于纯软件的初始化、没有太多依赖的函数

3 INIT_DEVICE_EXPORT(fn)

外设驱动初始化相关,比如网卡设备

4 INIT_COMPONENT_EXPORT(fn)

组件初始化,比如文件系统或者 LWIP

5 INIT_ENV_EXPORT(fn)

系统环境初始化,比如挂载文件系统

6 INIT_APP_EXPORT(fn)

应用初始化,比如 GUI 应用

bsp_beep

这段代码是一个嵌入式系统中的示例程序,主要用于初始化和控制蜂鸣器(beep)的功能。

代码的主要功能如下:

导入头文件:包含了一些需要使用的头文件,包括stdio.h(标准输入输出)、rtthread.h(RT-Thread操作系统)、board.h(板级支持包)、gd32f4xx_libopt.h(GD32F4xx外设库)、bsp_beep.h(蜂鸣器驱动头文件)等。 beep_pwm_gpio_init函数:该函数用于初始化蜂鸣器的GPIO引脚。具体操作包括使能蜂鸣器所在的GPIO时钟、配置GPIO引脚为复用功能、设置GPIO输出选项等。 beep_timer_init函数:该函数用于初始化蜂鸣器的定时器(timer)。具体操作包括使能蜂鸣器定时器所在的时钟、重置定时器、配置定时器参数(如计数模式、时钟分频、计数方向、周期和预分频值等)、初始化定时器、配置定时器通道输出参数(如极性、输出使能、闲置状态等)、使能定时器等。 beep_pwm_pulse_set函数:该函数用于设置蜂鸣器的脉冲宽度。具体操作是通过配置定时器通道的脉冲值来控制蜂鸣器的输出。 beep函数:该函数用于控制蜂鸣器发出声音。具体操作是设置蜂鸣器的脉冲宽度为500,延时一段时间后再将脉冲宽度设置为0,实现蜂鸣器的开关控制。 beep_test函数:该函数是一个用于测试的函数,用于通过命令行输入参数来设置蜂鸣器的脉冲宽度。具体操作是通过输入参数获取脉冲宽度值,然后调用beep_pwm_pulse_set函数设置蜂鸣器的脉冲宽度。 beep_init函数:该函数用于初始化蜂鸣器。具体操作是调用beep_pwm_gpio_init函数和beep_timer_init函数来初始化蜂鸣器的GPIO引脚和定时器。 INIT_BOARD_EXPORT(beep_init):这是一个用于在系统初始化阶段自动执行的宏,将beep_init函数注册为系统初始化函数,以便在系统启动时自动初始化蜂鸣器。

总体来说,这段代码主要是用于初始化和控制蜂鸣器的功能,包括初始化GPIO引脚和定时器,以及设置蜂鸣器的脉冲宽度来控制声音的输出。

bsp_mootor motor_pwm_gpio_init():用于初始化电机驱动的PWM控制引脚。该函数通过配置引脚的模式和复用功能,将引脚设置为PWM输出模式。 motor_timer_init():用于初始化电机驱动的硬件定时器。该函数通过配置定时器的参数,包括时钟分频、计数方向、周期和占空比等,设置定时器为PWM模式。 motor1_in1_pwm_pulse_set()、motor1_in2_pwm_pulse_set()、motor2_in1_pwm_pulse_set()、motor2_in2_pwm_pulse_set():分别用于设置电机1和电机2的PWM脉宽值。这些函数通过配置定时器的通道和脉冲值,控制对应引脚的PWM输出。 motor1_pwm_value_set()、motor2_pwm_value_set():用于调节电机1和电机2的PWM值,即控制电机的速度。通过调整对应引脚的PWM脉宽值来实现速度调节。 motor_test():用于通过控制台输入命令来临时改变PWM值驱动电机转动。根据输入的命令和参数,调用相应的函数来控制电机的运动。

此外,代码还包括了一些初始化函数和命令导出,以便在系统启动时进行电机的初始化和在控制台中使用相应的命令来控制电机。

总体来说,这段代码实现了电机驱动的初始化和控制,通过配置硬件定时器和PWM引脚,可以实现对电机速度的控制。

bsp_encoder 引用了一些头文件,并定义了一些宏和结构体,包括编码器状态结构体(encoder_state_t)和主题定义(encoder_m1_topic、encoder_m2_topic)。 在encoder_gpio_init函数中,对编码器的GPIO进行初始化,包括设置引脚的工作模式和复用功能。 在encoder_timer_init函数中,对编码器的定时器进行初始化。这些定时器用于计算编码器的计数值和测量速度。函数中分别初始化了两个编码器(M1和M2)的定时器,并配置了输入捕获通道和编码器模式。还启用了定时器中断,并将相应的中断处理函数注册到中断向量表中。 encoder_count_timer_init函数用于初始化一个用于计数的定时器。 M1_TIMER_IRQHANDLER和M2_TIMER_IRQHANDLER是编码器定时器的中断处理函数。在中断处理函数中,根据定时器的计数值和重载值来判断编码器的溢出情况,并更新编码器的计数值。然后清除定时器的中断标志位。 ENCODER_COUNT_TIMER_IRQHANDLER是计数定时器的中断处理函数。在该函数中,根据定时器的中断标志位进行编码器计数值的更新,并计算编码器的速度。最后,清除计数定时器的中断标志位。 set_encoder_struct_to_default函数用于将编码器状态结构体初始化为默认值。 encoder_topic_echo函数是一个用于打印编码器状态的回调函数。它通过调用mcn_copy_from_hub函数从主题中获取编码器状态,并打印相关信息。 encoder_init函数是编码器的初始化函数。在该函数中,调用了前面提到的各个初始化函数,并将编码器状态结构体初始化为默认值。然后,通过调用mcn_advertise函数将回调函数注册为主题的广播函数,以便在接收到编码器状态更新时能够打印相关信息。

总体而言,这段代码完成了对编码器的引脚和定时器的初始化配置,并通过中断处理函数和回调函数实现了编码器状态的更新和打印。

bsp_servo

代码的主要功能是初始化舵机的GPIO和定时器,并提供了设置舵机脉冲宽度的函数。通过控制定时器的输出脉冲宽度,可以控制舵机的角度。

下面是代码的主要结构和功能解释:

首先,代码包含了一些头文件,包括stdio.h、rtthread.h、board.h等,这些头文件提供了所需的库函数和定义。 然后定义了两个静态函数:servo_pwm_gpio_init()和servo_timer_init()。这些函数用于初始化舵机的GPIO和定时器。 servo_pwm_gpio_init()函数中,首先使能了舵机的GPIO时钟,然后配置了GPIO的模式和复用功能。最后,设置了输出选项,包括输出类型、输出速度等。 servo_timer_init()函数中,首先使能了舵机所使用的定时器的时钟。然后进行了定时器的初始化设置,包括计数方向、计数模式、计数周期、预分频等参数。接着,配置了定时器的通道输出模式和脉冲值,并设置了定时器的输出极性和空闲状态。最后,使能了定时器和高级定时器的主输出。 servo1_pwm_pulse_set()和servo2_pwm_pulse_set()函数分别用于设置舵机1和舵机2的脉冲宽度。这些函数通过调用timer_channel_output_pulse_value_config()函数来设置定时器的通道输出脉冲值,从而控制舵机的角度。 servo_test()函数是一个用于测试舵机控制的命令函数。通过命令行输入参数来选择要控制的舵机和脉冲宽度,然后调用相应的设置函数来控制舵机。 最后,定义了一个servo_init()函数,用于初始化舵机控制。该函数调用了servo_pwm_gpio_init()和servo_timer_init()函数来进行初始化操作。

整体而言,这段代码通过初始化GPIO和定时器来控制舵机的角度。通过调用相应的设置函数,可以根据输入的脉冲宽度来改变舵机的位置。

FINSH控制台调试使用

​ RT-Thread控制台是我非常喜欢的一个功能,他可以让你和嵌入式设备产生交互,可以用来调试和查看系统信息。就有点像平时windos的cmd命令或者linux的命令控制台。

​ 可以让你自己定义控制台命令,比如说你配置好了电机PWM,想在运行中改变PWM的值,通过串口传入参数就可以修改了,如下面的代码块所示:

/** - @brief 电机的控制室命令,可以通过控制台输入命令来临时改变PWM值驱动电机转动 - @note None - @param argc:发给当前函数 命令行 总的参数的个数,他的值永远>=1。 argv: 是个字符串数组,用来存放指向字符串参数的指针数组,每一个元素指向一个以空格为分割的参数。 -如argv[0]指向程序运行的函数名称。 -如argv[1]指向解析出来的第一个参数,argv[2]指向再接下来的一个参数。 - @retval None */ static void motor_test(int argc, char**argv) { int16_t pwm_value = 0; /* 检查输入的变量是否有两个 */ if (argc


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有