MSP430F5529循迹小车 2022电赛 C题

这篇具有很好参考价值的文章主要介绍了MSP430F5529循迹小车 2022电赛 C题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

编辑时间2022/8/21

方案

选用材料:主控MSP430F5529、直流减速电机(带光电编码器)、TB6612电机驱动、超声波测距、灰度传感器、无线透传、OLED屏显示。

使用灰度传感器巡线,超声波检测前后车距作为位置环反馈,通过位置环调节前后车距离。

关键词:MSP430   循迹    无线串口透传通信   PID算法    陀螺仪

一、题目

msp430寻迹小车,c语言,开发语言

msp430寻迹小车,c语言,开发语言 

 

二、控制方案

题目难点在于小车路过“y”路口时的判断,以及小车停车时需保证20cm的间距。我们最初的想法是通过陀螺仪直线矫正通过“y”路口,实际测试发现小车直线稳定性良好,但是陀螺仪数据反馈会有跳变,经过PID直线矫正后可能会导致小车偏离赛道。经过讨论后我们决定采用检测灰度传感器数字量判断小车位置,当小车行驶“y”路口时关闭靠左一路灰度值的传入,通过路口后重新开启,该方案实际测试没有发现较大误差。

题目中均要求一车停止后二车需立即停止并保证20cm间距,所以控制方案尤为重要,我们的想法是二车使用位置环-速度环串级PID控制,这样在一车保证速度的同时,二车会紧跟一车,在一车停止后,二车会立即停止。

问题一分析

问题一较为简单,一车二车设置一样的速度后跑一圈停止即可.

问题二分析

问题二要求二车在E路径上跑两圈后追上 一车,该问中需使用位置环-速度环控制二车,一车速度调到问题二要求的速度即可。

问题三分析

问题三要求小车行驶一圈检测“等停指示”后两辆车需同时停止,与第一问差别不大,唯一区别就是速度,在保证速度的同时又要考虑行车循迹的稳定性才是关键。

问题四分析

问题四需要对小车进行路径规划,一车二车之间需要将自身的编码器里程发送接收,通过里程判断是否需要加减速。

msp430寻迹小车,c语言,开发语言

 电赛准备的TB6612电机驱动板,画了两板,可直接连接电机。模块自带16-5V降压msp430寻迹小车,c语言,开发语言

msp430寻迹小车,c语言,开发语言

链接; TB6612FNG编码电机控制 - 嘉立创EDA开源硬件平台 (oshwhub.com)

 三、代码讲解

1、小车PID代码讲解 

void PID_Position_Calc( PID *pp,  float  CurrentPoint,  float NextPoint ) //位置环 
{   
	pp->Error =  NextPoint -  CurrentPoint;          
	pp->SumError += pp->Error;                      
	pp->DError = pp->Error - pp->LastError;

	pp->output =  pp->Proportion * pp->Error +   \
								abs_limit(pp->Integral * pp->SumError, pp->Integralmax ) +   \
								pp->Derivative * pp->DError ;  

	if(pp->output > pp->outputmax )  pp->output = pp->outputmax;
	if(pp->output < - pp->outputmax )  pp->output = -pp->outputmax;
//	pp->PrevError = pp->LastError;  
	pp->LastError = pp->Error;
}

void PID_Incremental_Calc( PID *pp,  float  CurrentPoint,  float NextPoint )  //速度环
{  
	pp->Error =  NextPoint -  CurrentPoint;          
	pp->SumError += pp->Error;                      
	pp->DError = pp->Error - pp->LastError;

	pp->output +=  pp->Proportion * ( pp->Error - pp->LastError )+   \
								 abs_limit(pp->Integral * pp->Error, pp->Integralmax ) +   \
								 pp->Derivative * ( pp->Error +  pp->PrevError - 2*pp->LastError);  

	if(pp->output > pp->outputmax )  pp->output = pp->outputmax;
	if(pp->output < - pp->outputmax )  pp->output = -pp->outputmax;
	pp->PrevError = pp->LastError;  
	pp->LastError = pp->Error;
}

void PIDInit(PID *pp, float Kp , float Ki , float Kd ,  float outputmax, float Integralmax)    //PID初始化  
{  
	pp->Integralmax = Integralmax;
	pp->outputmax  = outputmax;
	pp->Proportion = Kp;
	pp->Integral   = Ki;
	pp->Derivative = Kd;
	pp->DError = pp->Error = pp->output = pp->LastError = pp->PrevError = 0; 
} 
void navigation_execute(float angle_z,int16_t left_sp,int16_t right_sp)//正反馈 陀螺仪直线矫正
{
//    uint8_t angle_dev = 2;
//    if(mpu_angle>(angle_z-3))
//        moto_set_speed(gpt_cnt.set_speed_a+angle_dev,gpt_cnt.set_speed_b-angle_dev);
//    else if(mpu_angle<(angle_z+3))
//        moto_set_speed(gpt_cnt.set_speed_a-angle_dev,gpt_cnt.set_speed_b+angle_dev);
//    else
//        moto_set_speed(gpt_cnt.set_speed_a,gpt_cnt.set_speed_b);
    PID_Position_Calc(&ANGLE,Mpu_angle.angle_z+180.0f,angle_z/1.0f);//直线矫正
    gpt_cnt.set_speed_a=left_sp - ANGLE.output;
    gpt_cnt.set_speed_b=right_sp + ANGLE.output;
}

void car_follow(float now_distance,float next_distance)//小车位置-速度环  next_distance = 20
{
    PID_Position_Calc(&distance,now_distance/1.0f,next_distance/1.0f);//位置环计算行驶距离误差
    PID_Incremental_Calc(&MOTOR_Spid[0], gpt_cnt.speed_a, distance.output);//速度环输出
    PID_Incremental_Calc(&MOTOR_Spid[1], gpt_cnt.speed_b, distance.output);

    moto_set_speed(MOTOR_Spid[0].output, MOTOR_Spid[1].output);//速度环输出项发送电机
}

void car_remove(float now_speed[2],float set_speed[2])//小车速度环
{
    PID_Incremental_Calc(&MOTOR_Spid[0],now_speed[0], set_speed[0]);//速度环输出
    PID_Incremental_Calc(&MOTOR_Spid[1],now_speed[1], set_speed[1]);

    moto_set_speed(MOTOR_Spid[0].output, -MOTOR_Spid[1].output);//速度环输出项发送电机
}

二、路径规划

1.编码器获取

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=PORT2_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(PORT2_VECTOR)))
#endif
void Port_2 (void)//编码器采用外部中断获取
{
    if(GPIO_getInterruptStatus(GPIO_PORT_P2,GPIO_PIN4) == GPIO_PIN4)
    {
        if(GPIO_getInputPinValue(GPIO_PORT_P2,GPIO_PIN4) == GPIO_INPUT_PIN_HIGH)//上升沿
        {
            if(GPIO_getInputPinValue(GPIO_PORT_P2,GPIO_PIN0) == GPIO_INPUT_PIN_LOW)//正转
            {
                gpt_cnt.count_a --;
            }
            else//反转
            {
                gpt_cnt.count_a ++;
            }
        }

        GPIO_clearInterrupt(GPIO_PORT_P2,GPIO_PIN4);
    }
}

2.小车任务三 

void car_control_fort3(void) //任务三
{
   run_distance = ((gpt_cnt.count_a+gpt_cnt.count_b)/2.0f)/Encoder_cnt*2.0f*3.14f*3.25f;//行驶距离 = 小车行驶总脉冲 / 1圈的脉冲值 * 2 * pi * 轮子半径
   switch(run_dis)
   {
        case 0:
//            navigation_execute(179.0f,set_sp,set_sp);//直线矫正
            sensor_checking(30,0,0);//开启循迹 
            if(run_distance>=stright_dis+15.0f)//通过第一路口
            {
                gpt_cnt.set_speed_a = gpt_cnt.set_speed_b = 0;
                run_dis = 1;
            }
        break;
        case 1:
            car_follow(rec_distance-run_distance,200);//位置环控制小车
            sensor_checking(set_sp,min_sp,max_sp);//开启循迹
            if(run_distance >= cross_third)//判断位置到达第三路口
            {
                if(sensor_reading[1]&&sensor_reading[2]&&sensor_reading[3])//检测停止标志
                {
                    DL20_AgreementDirectives(0x05,USCI_A1_BASE);//发送停车指令
                    gpt_cnt.set_speed_a = gpt_cnt.set_speed_b = 0;
                    if(systick_delay.count_1s != systick_delay.last_count_1s)//1ms
                    {
                        if(++delay_tim>=6)//1ms*6
                        {
                            DL20_AgreementDirectives(0x06,USCI_A1_BASE);//发送中途启动指令
                            DL20_AgreementDirectives(0x06,USCI_A1_BASE);//发送中途启动指令
                            run_dis = 2;
                        }
                        systick_delay.last_count_1s = systick_delay.count_1s;
                    }
                }
                else
                {
                    delay_tim = 0;
                }
            }
        break;
        case 2:
            sensor_checking(30,min_sp,max_sp);//开启循迹
            if(run_distance >= 580.0f)//一圈总距离584.8cm
            {
                if((sensor_reading[1]&&sensor_reading[2])||(sensor_reading[2]&&sensor_reading[3]))
                {
                    gpt_cnt.set_speed_a = 0;
                    gpt_cnt.set_speed_b = 0;
                    DL20_AgreementDirectives(0x02,USCI_A1_BASE);//发送停车指令
                    beep_on;
                    run_flag = 0;
                }
            }
        break;
    }
}

 

四、工程获取

代码及设计报告还在整理中,开学后会公布文章来源地址https://www.toymoban.com/news/detail-600980.html

到了这里,关于MSP430F5529循迹小车 2022电赛 C题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MSP430F5529——中断理解

    认识低功耗模式; MSP430的中断,需要两个部分,一部分是打开中断,另外一部分是编写中断服务函数 首先我们得知道__bis_SR_register和_BIS_SR是一个玩意。查看宏定义可知  _BIS_SR()可传入的参数 然后我们查看x的值,发现里面有八个可以传入的值 我们这里只需要关系GIE就可以

    2024年02月16日
    浏览(43)
  • MSP430F5529库函数学习——串口

    波特率计算网站;导入MSP430Ware,查看例程;原理图和中文开发手册获取 目录 GPIO_setAsPeripheralModuleFunctionInputPin()和GPIO_setAsPeripheralModuleFunctionOutputPin 函数声明  作用 参数 selectedPort selectedPins 使用 USCI_A_UART_init() 函数声明  作用 参数 baseAddress param  USCI_A_UART_enable() 函数

    2024年02月16日
    浏览(56)
  • 05:OLED模块【MSP430F5529】

    目录 实物图 字模取字         字模软件         取模步骤         1.设置软件         2.取模         3.输出数据  代码 type.h oledfont.h oled.h oled.c main.c 下面图片中,可以看到OLED模块的四个接口:GND,VCC,SCL,SDA GND VCC SCL SDA 接地 接电源3.3V/5V 接P3.5 接P3.6       

    2024年02月16日
    浏览(36)
  • MSP430F5529学习笔记(6)——导入MSP430Ware,查看例程

    MSP430WARE下载; 目录 在线版本 下载MSP430Ware 查看例程 导入例程  离线版本 下载MSP430Ware  查看例程 导入例程 MSP430Ware里面有很多例程和库函数使用手册,我们可以查看学习。非常重要 (1) 打开CCS——view——Resource Explorer  之后我们会进入如下界面 (2)  点击MSP430——Embe

    2024年02月13日
    浏览(44)
  • MSP430F5529库函数GPIO学习

    导入MSP430Ware,查看例程;数据手册以及原理图获取 建议不是很了解寄存器的看完我的MSP430F5529学习笔记  目录 GPIO_setAsOutputPin() 函数声明 作用 参数 selectedPort selectedPins 修改的寄存器 使用 与GPIO_setAsOutputPin()参数一致的函数  GPIO_setOutputHighOnPin() GPIO_setOutputLowOnPin()

    2024年02月15日
    浏览(54)
  • msp430f5529学习笔记(2)时钟系统

    写在前~本章将会详细的讲解msp430f5529单片机的时钟系统及其使用方法。如有不妥的地方欢迎各位大佬斧正!!! 目录 什么是时钟系统和时钟源 MSP430f5529时钟源和时钟系统介绍 产生时钟信号的时钟源: 时钟配置        在单片机中,单片机每开始一个周期的工作就需要一个节

    2024年02月17日
    浏览(35)
  • 06:PWM与电机驱动【MSP430F5529】

    电机型号: 工作方式: 原理图以及接线: 根据官方例程,主要代码为drive.c drive.h main.c (后面好像使用的时候会有什么冲突导致1或者2通道无法正常运行,不太记得了,可以到实物上实验一下子) 下面是智能送药小车使用PWM驱动电机相关代码与注释(在实物中,均能正常运行)

    2024年02月15日
    浏览(42)
  • MSP430F5529学习笔记(五)——串口|UART

            我们在使用MSP430的时候大家会发现插上usb线后电脑上有两个端口标识,那么在进行串口通信时选择哪个呢。其实如图所示,上面的端口是用来进行串口通信的,下面的则是用来进行程序的下载,大家在使用的时候多加分辨即可。          当然熟悉单片机操作的

    2024年02月16日
    浏览(33)
  • MSP430F5529单片机入门学习笔记1

    本笔记整理自B站教程 MSP430F5529单片机学习视频汇总 右边部分写错了,看的时候注意 注意#include“driverlib.h”头文件时要注意: 添加MSP430F5xx_6xx文件夹到当前工程下 MSP430F5xx_6xx文件夹是在导入的msp430ware_3_80_13_03包中找 把上述MSP430F5xx_6xx文件夹的路径包含进来 有三个系统时钟可

    2024年02月06日
    浏览(35)
  • MSP430F5529库函数定时器A——捕获实验

    需提前学习:MSP430F5529库函数学习——串口;MSP430F5529库函数定时器A——硬件PWM 目录 引脚手册获取 实验目的 代码 代码解析 串口数据发送部分 数据捕获部分 定时器部分可选参数 设置定时器部分 捕获部分可选参数 设置捕获引脚部分 中断处理 TA2IV_TACCR2解析 TA2IV_TAIFG解析 主函

    2024年02月13日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包