发作品签到
专业版

基于梁山派的智能小车

工程标签

1.0k
0
0
0

简介

基于梁山派进行智能小车的设计,实现蓝牙遥控,循迹避障等功能

简介:基于梁山派进行智能小车的设计,实现蓝牙遥控,循迹避障等功能

开源协议

GPL 3.0

创建时间:2022-11-09 05:44:10更新时间:2022-12-12 01:29:11

描述

基于GD32F450智能小车

  1. 设计目标

通过蓝牙模块控制小车的运动,同时可以调节速度,和关闭开启车灯,舵机云台实现避障功能,循迹模块实现循迹功能,OLED显示运动信息以及小车电池的实时电压。

  1. 总体设计方案和思路

RZ8bNHZjAT1CBgTLS9MZlSOfH32FujJedcYcoS6q.jpeg

  1. 器件准备和焊接

蓝牙模块、5V稳压模块、超声波模块、MG90S、循迹模块、GD32F450,四个电机,0.96寸OLED等。

5wlIBVqhwTT2ewnKRwtoOLiRsUrTzxhwU3txzXlR.jpegE6bZuaxsHtJ5pSHBsV1OR0wVRNJCRfVYWW9PX8UJ.jpeg

 

GKHpptRFXlRka9tqgSJXBYln76onbfMNEP9Gl1QP.jpegg8drPu5tffGbxAxQXDXm3fmtGPkuoKIYDblzeKMJ.jpegznMyv3r1UNOXYb0CpcUEmZhWLau0IN4ntg1PWxkA.jpegt7k6tdWTosUa1OzVajf54rU9mSVZpV2WtJ9zl4jm.png

小车的底板是4mm厚的亚克力板,是用solidworks2021画的,再给打印出来,比较实惠,可以根据自己需求画出喜欢的形状。要定好孔位用于安装电机和主控板。

zaOwTbrgMdkwCdsSuwimIOTPsFiF4ms04pHCHbtf.jpeg

元器件的焊接比较简单,没有太多引脚密集的芯片,可以轻松焊接好,要注意电机驱动芯片不要焊反。

  1. 程序编写

1.0.96寸OLED显示功能

0.96寸OLED分辨率是128*64,采用IIC协议。通过OLED上面可以显示数字,汉字,字符串,图片等内容,移植了中景园的OLED显示代码。

OLED_Init();            //初始化OLED  

        OLED_Clear();

        OLED_ShowCHinese(0,0,0);//智

        OLED_ShowCHinese(18,0,1);//能

        OLED_ShowCHinese(36,0,2);//小

        OLED_ShowCHinese(54,0,3);//车

        OLED_ShowCHinese(72,0,4);//梁

        OLED_ShowCHinese(90,0,5);//山

        OLED_ShowCHinese(108,0,6);//派

        OLED_ShowString(88,6,".",16);

        OLED_ShowString(112,6,"V",16);

        OLED_ShowString(32,4,"Speed=",16);    //显示运动速度

        OLED_ShowNum(82,4,speed,3,16);

        D= SR04_Get_Distance();               //显示距离

        OLED_ShowString(54,2,"D:",16);

        OLED_ShowNum(72,2,D,4,16);

        OLED_ShowString(108,2,"mm",16);

        voltage=adc_get_val();

        OLED_ShowString(0,6,"Voltage:",16);    //显示电压

        OLED_ShowNum(72,6,((voltage*100/4096)*3.3*5)/100,2,16);

        OLED_ShowNum(96,6,((voltage*100/4096)*3.3*5)/100-1100,2,16);

               

效果演示:

 

ELcRO2fISAPvJjPYbe8ktJIWFGRsAfqsUEiqzCdi.jpeg

 

第一行是汉字智能小车梁山派,其中第二行左边是显示运行状态,0是静止状态,1定距离跟随,2是循迹模式,3是避障模式,4是蓝牙遥控模式。第二行右边是超声波测距的距离,第三行左边是显示小车运行模式,Q表示前进,H表示后退,Z表示左转,Y表示右转,T表示停止等,第三行右边是小车当前速度,第四行是小车的电压。

2.按键,蜂鸣器,LED等代码编写

主要是对各个模块的初始化,蜂鸣器和LED只需要简单的初始化,而按键需要通过一个按键读取函数读取状态。

按键读取函数:

void Key_Init(void)

{

    /* 开启时钟 */

    rcu_periph_clock_enable(BSP_KEYM_RCU);

    rcu_periph_clock_enable(BSP_KEYS_RCU);

    /* 配置为输入模式 上拉模式 */

    gpio_mode_set(BSP_KEYM_PORT,GPIO_MODE_INPUT,GPIO_PUPD_PULLUP,BSP_KEYM_PIN);  // 按键默认状态是高电平,配置为上拉

    gpio_mode_set(BSP_KEYS_PORT,GPIO_MODE_INPUT,GPIO_PUPD_PULLUP,BSP_KEYS_PIN);  // 按键默认状态是高电平,配置为上拉

}

uint8_t Key_Getnum(void)

{

    static uint8_t  KeyNum=0;

    if(gpio_input_bit_get(BSP_KEYM_PORT,BSP_KEYM_PIN) == RESET)

    {

        delay_1ms (10);

        while(gpio_input_bit_get(BSP_KEYM_PORT,BSP_KEYM_PIN) == RESET);

        delay_1ms (10);

        KeyNum +=1;

    }

    if(gpio_input_bit_get(BSP_KEYS_PORT,BSP_KEYS_PIN) == RESET)

    {

        delay_1ms (10);

        while(gpio_input_bit_get(BSP_KEYS_PORT,BSP_KEYS_PIN) == RESET);

        delay_1ms (10);

        KeyNum =0;

    }

    if(KeyNum>4)

    {

        KeyNum=0;

    }

    return  KeyNum;

}

通过按键切换小车运行模式,0是静止模式,默认为静止状态,1是1定距离跟随,2是循迹模式,3是避障模式,4是蓝牙遥控模式。

3.蓝牙模块功能实现

JDY-31 蓝牙基于蓝牙 3.0 SPP 设计,这样可以支持 Windows、 Linux、 android 数据透传,工作频段 2.4GHZ,调制方式 GFSK,最大发射功率 8db,最大发射距离30 米,支持用户通过AT 命令修改设备名、 波特率等指令,方便快捷使用灵活。

可以用蓝牙模块切换不同的运动状态,控制小车运动,控制小车速度,控制车灯的开启与关闭等。

蓝牙软件界面效果:

zTunuAP6LfWarq3a8thmpJygB6BCE7o6hY6omg5Y.jpeg

部分蓝牙代码:

void BSP_UART6_IRQHandler(void)

{

    if(usart_interrupt_flag_get(BSP_UART6,USART_INT_FLAG_RBNE) == SET)   // 接收缓冲区不为空

    {

        g_recv_buff = usart_data_receive(BSP_UART6);      // 把接收到的数据放到缓冲区中

        if(g_recv_buff=='A')  Blue=1;

        if(g_recv_buff=='B')  Blue=2;

        if(g_recv_buff=='C')  Blue=3;

        if(g_recv_buff=='D')  Blue=4;

        if(g_recv_buff=='E')  Blue=0;

        if(g_recv_buff=='F')  Blue=5;

        if(g_recv_buff=='G')  Blue=6;

    }

   

    if(usart_interrupt_flag_get(BSP_UART6,USART_INT_FLAG_IDLE) == SET)   // 检测到帧中断

    {

        usart_data_receive(BSP_UART6);                                     // 必须要读,读出来的值不能要

        g_recv_complete_flag = 1;                                          // 接收完成

    }

   

}

通过软件发送不同的指令控制小车,既可以通过按键控制小车运动模式,也可以通过按键控制小车运行模式。

4.超声波实现定距离跟随

基本工作原理

(1)采用 IO 口 TRIG 触发测距,给最少 10us 的高电平信呈。

(2)模块自动发送 8 个 40khz 的方波,自动检测是否有信号返回;

(3)有信号返回,通过 IO 口 ECHO 输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。测试距离=(高电平时间*声速(340M/S))/2;

超声波代码:

void SR04_Init(void)

{

    /* 使能时钟 */

    rcu_periph_clock_enable(HCSR04_RCU);

    /* 配置为输出模式 浮空模式 */

    gpio_mode_set(PORT_HCSR04,GPIO_MODE_OUTPUT,GPIO_PUPD_NONE,HCSR04_Trig_PIN);

    /* 配置为推挽输出 50MHZ */

    gpio_output_options_set(PORT_HCSR04,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,HCSR04_Trig_PIN);

    /* 配置为输入模式 下拉模式 */

    gpio_mode_set(PORT_HCSR04,GPIO_MODE_INPUT,GPIO_PUPD_PULLDOWN,HCSR04_Echo_PIN);

   

    //PB12初始状态为低电平,看时序图

    PBout(12)=0;    //PB12trig  PB10echo

}

int SR04_Get_Distance(void)

{

    uint32_t t=0;

    int32_t d=0;

    PBout(12)=1;    //PB12高电平

    delay_1us(20);//持续10us以上

    PBout(12)=0;    //PB12低电平

    t=0;

    while(PBin(10)==0)//等待PB10出现高电平

    {

        t++;

        delay_1us(1);

        if(t >= 1000000)

            return -1;  

    }

    t=0;

    while(PBin(10))//测量高电平的时间

    {

        t++;

        delay_1us(9);   //9us == 3mm

       

        if(t >= 1000000)

            return -2;

   

    }

        //由于测量的时间,就是超声波从发射到返回的时间

    t=t/2;

    d = 3*t;

    return d;

}

定距离跟随代码:

if(Mode==1)  //模式1定距离跟随模式

                {

                    //定距离跟随

            if(SR04_Get_Distance()>100)

            {

                car_front(speed);//前进

                delay_1ms(50);

            }

            if(SR04_Get_Distance()<50)

            {

                car_back(speed);//后退

                delay_1ms(50);

            }

            car_stop(1);

                }

5.循迹模块实现循迹

TCRT5000就是一个红外发射和接收器,不断发射和接收红外线。产品用途: 1、电度表脉冲数据采样2、传真机碎纸机纸张检测3、障碍检测4、黑白线检测

循迹原理非常简单,模块上配有一个输出指示灯,部分模块还有电源指示灯,我们主要关注输出指示灯。红外发射器一直发射红外线,红外线经发射后被接收,此时输出低电平,输出指示灯点亮。黑色是不反射红外线的,也就是说循迹模块遇到黑线,模块输出高电平,输出指示灯熄灭。当然除了遇到黑线熄灭,当距离太远红外线反射后检测不到,此时指示灯也会熄灭。那么如果要循迹,模块离地面要近,在没有遇到黑线时确保指示灯长亮,一旦指示灯熄灭就说明遇到黑线了。

注意引脚要设置为下拉输入模式,输入模式不需要配置速度。

 if(Mode==2)  //模式2循迹模式

                {

                    Black_Line_Detection();

                        //红外对管循迹

            if(XJ01== 0 && XJ02 == 1 && XJ03 == 1 && XJ04 == 0)

            {

                car_front(speed);//前进

                delay_1ms(300);

                car_stop(1);

                delay_1ms(5);              

            }

            if(XJ01== 0 && XJ02 == 0 && XJ03 == 0 && XJ04 == 0)

            {      

                car_stop(1);            

            }

            if(XJ01 == 0 && XJ02 == 1 && XJ03 == 0 && XJ04 == 0)

            {

                car_right(speed);//右转

                delay_1ms(150);

            }

                        if(XJ01 == 1 && XJ02 == 0 && XJ03 == 0 && XJ04 == 0)

            {

                car_right(speed);//右转

                delay_1ms(250);

            }

            if(XJ01 == 1 && XJ02 == 1 && XJ03 == 0 && XJ04 == 0)

            {

                car_right(speed);//右转

                delay_1ms(300);

            }

            if(XJ01 == 0 && XJ02 == 0 && XJ03 == 1 && XJ04 == 0)

            {

                car_right(speed);//左转

                delay_1ms(150);

            }

            if(XJ01 == 0 && XJ02 == 0 && XJ03 == 0 && XJ04 == 1)

            {

                car_right(speed);//左转

                delay_1ms(250);

            }

            if(XJ01 == 0 && XJ02 == 0 && XJ03 == 1 && XJ04 == 1)

            {

                car_right(speed);//左转

                delay_1ms(300);

            }

                }

6.超声波和舵机组合实现避障

舵机基本原理:

控制舵机实际上只需要使用定时器输出一束PWM就可以了

*舵机的控制一般需要一个20ms左右的时基脉冲,该脉冲的高电平部分一般为0.5ms-2.5ms范围内的角度控制脉冲部分,总间隔为2ms。以180度角度伺服为例,那么对应的控制关系是这样的:
0.5ms--------------0度;
1.0ms------------45度;
1.5ms------------90度;
2.0ms-----------135度;
2.5ms-----------180度;
舵机的追随特性
假设现在舵机稳定在A点,这时候CPU发出一个PWM信号,舵机全速由A点转向B点,在这个过程中需要一段时间,舵机才能运B点。

舵机代码:

void Servo_Init(uint16_t pre,uint16_t per)

{

    timer_parameter_struct timere_initpara;                 // 定义定时器结构体

    timer_oc_parameter_struct timer_ocintpara;                      //定时器比较输出结构体

   

    rcu_periph_clock_enable(BSP_Servo_RCU);                         //开启GPIO时钟

    rcu_periph_clock_enable(BSP_Servo_TIMER_RCU);                   // 开启定时器时钟

    rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);       // 配置定时器时钟200MHz

   

    /* 配置GPIO的模式 */   //复用功能模式

    gpio_mode_set(BSP_Servo_PORT,GPIO_MODE_AF,GPIO_PUPD_NONE,BSP_Servo_PIN);

    /* 配置GPIO的输出 */

    gpio_output_options_set(BSP_Servo_PORT,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,BSP_Servo_PIN);

    /* 配置GPIO的复用 */

    gpio_af_set(BSP_Servo_PORT,BSP_Servo_AF,BSP_Servo_PIN);

    /* 配置定时器参数 */

    //timer_parameter_struct timere_initpara;                 // 定义定时器结构体

    timer_deinit(BSP_Servo_TIMER);                                                      // 复位定时器

    timere_initpara.prescaler = pre-1;                          // 时钟预分频值   PSC_CLK= 200MHZ / 200 = 1MHZ      

    timere_initpara.alignedmode = TIMER_COUNTER_EDGE;       // 边缘对齐                

    timere_initpara.counterdirection = TIMER_COUNTER_UP;    // 向上计数                        

    timere_initpara.period = per-1;                                           // 周期    T = 10000 * 1MHZ = 10ms  f = 100HZ  

    /* 在输入捕获的时候使用  数字滤波器使用的采样频率之间的分频比例 */  

    timere_initpara.clockdivision = TIMER_CKDIV_DIV1;         // 分频因子

    /* 只有高级定时器才有 配置为x,就重复x+1次进入中断 */

    timere_initpara.repetitioncounter = 0;                  // 重复计数器 0-255  

    timer_init(BSP_Servo_TIMER,&timere_initpara);                           // 初始化定时器

   

    /* 配置输出结构体 */

    //timer_oc_parameter_struct timer_ocintpara;                        //定时器比较输出结构体

    timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;                                                                      // 有效电平的极性

    timer_ocintpara.outputstate = TIMER_CCX_ENABLE;

    // 配置比较输出模式状态 也就是使能PWM输出到端口

   

    /* 配置定时器输出功能 */

    timer_channel_output_config(BSP_Servo_TIMER,BSP_Servo_CHANNEL,&timer_ocintpara);

    timer_channel_output_pulse_value_config(BSP_Servo_TIMER,BSP_Servo_CHANNEL,0);      //配置占空比                              // 配置定时器通道输出脉冲值

    timer_channel_output_mode_config(BSP_Servo_TIMER,BSP_Servo_CHANNEL,TIMER_OC_MODE_PWM0);             // 配置定时器通道输出比较模式

    timer_channel_output_shadow_config(BSP_Servo_TIMER,BSP_Servo_CHANNEL,TIMER_OC_SHADOW_DISABLE);// 配置定时器通道输出影子寄存器

    timer_auto_reload_shadow_enable(BSP_Servo_TIMER);

     /* 使能定时器 */

    timer_enable(BSP_Servo_TIMER);

}

void Angle_Set(int Angle)

{

      timer_channel_output_pulse_value_config(TIMER8 ,TIMER_CH_1 ,Angle/180*2000+500)   ;  

}

避障代码:

if(Mode==3)  //模式3避障模式

                {

                        //超声波避障

                    timer_channel_output_pulse_value_config(TIMER8 ,TIMER_CH_1 ,1500)   ;   //超声波正前

                    delay_1ms(200);

                    if(SR04_Get_Distance()>50)// 前方无障碍物

                    {

                            car_front(speed);//前进

                            delay_1ms(100);

                          car_stop(1);

                            delay_1ms(50);

                        }

                   

                    if(SR04_Get_Distance()<50)  //向前有障碍物

                    {

                timer_channel_output_pulse_value_config(TIMER8 ,TIMER_CH_1 ,500);//向右转90度

                                if(SR04_Get_Distance()>50)//右侧无障碍物判断

                                {

                                        car_right(speed);//右转

                                      delay_1ms(400);

                                      car_stop(1);

                                      delay_1ms(5);

                                        //delay_1ms(700);

                                }

                                else {   //右边有障碍物

                    timer_channel_output_pulse_value_config(TIMER8 ,TIMER_CH_1 ,2500);//向左转90度

                                    delay_1ms(200);

                                        if(SR04_Get_Distance()>50)//左侧无障碍物

                                        {

                                                 car_left(speed);//左转

                                           delay_1ms(400);

                                           car_stop(1);

                                           delay_1ms(5);

                                        }

                                        else{

                                                 car_back(speed);//后退

                                           delay_1ms(200);

                                           car_stop(1);

                                           delay_1ms(5);

                                               

                                                 car_right(speed);//左转

                                           delay_1ms(200);

                                           car_stop(1);

                                           delay_1ms(5);

                  }                                        

             }

       }                  

  }

超声波配合舵机使其能够判断左右是否有障碍。由于小车速度太快,可能反应不过来,只能降低速度。

  1. 实物演示

wsKMhHiDNwXhtpIm2WXb13tbx5Z037M78JPwIre6.jpeg4dz4u84dwJtuvQfXeDj9CWk1iJgsdYRouxPvn7cJ.jpeg

  1. 思考、反思和总结

原理图有一些没检查好,导致了一些错误,在OLED的移植上耗费了太多时间,由于电源电流不够,导致可能会断电,这些还需要改进。代码的编写移植需要一步一步来,一边检查一边改错,最后再组合起来。

设计图

未生成预览图,请在编辑器重新保存一次

BOM

暂无BOM

附件

序号文件名称下载次数
1
智能小车测试版.rar
58
2
mmexport1670769282495.mp4
3
3
video_20221211_174607.mp4
3
4
video_20221211_183107.mp4
3
克隆工程
添加到专辑
0
0
分享
侵权投诉

工程成员

评论

全部评论(1)
按时间排序|按热度排序
粉丝0|获赞0
相关工程
暂无相关工程

底部导航