毕业设计| STM32坡道行驶巡线小车制作教程

发布者:shiwanyongbing最新更新时间:2023-04-26 来源: zhihu关键字:STM32 手机看文章 扫描二维码
随时随地手机看文章

1)主控芯片STM32F103C8T6

2)编码电机

型号MG513 p30 12v;转动一圈390个脉冲;减速比1比30。通过获取每100毫秒的脉冲个数,就可以计算出速度的大小

3)7针0.96寸oled显示屏

4)舵机:看着挺高级的,马力大,不过控制代码与那种两块钱的一样,模拟控制,PWM控制,用来控制方向


5)红外传感器模块:4个红外对管,一块模拟转数字模块

6)电源18650+电池座:经济实惠

7)锂电池充电器:一个模块加一个电池座,加起来不到2块钱

8)旋转编码器,用来调节时间的,按下小车就可以跑了



8)小车底盘

购买链接:m.tb.cn/h.4MEu0RC?

其实编码电机与舵机小车上面都有,直接买一个小车车身。买来是散装的,装了好久装好:


02

原理图设计

首先就是要进行硬件设计,连接好了硬件,软件就好办了。

然后开始连接硬件。

连接好了硬件,写程序就可以调试了…

硬件与程序调试用了两天时间总算搞定了接下来开始测量数据。


03

数据测量

1)功耗测量:

设置全程1.5m走的时间:


2)OLED速度监测

显示屏数据说明:

V1、V2左右轮实时速度

PIDOUT:输出PWM值

time:定时间

speed:通过设定时间计算得到的速度,因为路程固定

running/stop运行状态


可以看到PID算法起到了良好的效果,很好的把速度恒定在指定范围之内

平地测量场景:

记录数据:



04

程序设计

1)主程序设计

主函数是执行了整个程序的入口点。

首先初始设置定时器参数,设置TIM1 16位定时器递增计数,设置定时器时间10MS,主要用来在定时器中断测量小车速度与PID算法调用。


配置TIM4为PWM模式,设置周期为30ms,298能够反应过来,周期太大小车会有抖动,通过脉宽来调节小车速度,脉宽越大,小车运动越快,设置计数器为1000向上计数,也就是重装载值设置1000小车最快,设置重装载值0小车不运动。


配置TIM3为PWM模式,根据舵机的特性,配置周期为30MS,向上计数模式,计数器设置为3000,当脉宽长度为28MS时,舵机刚好再0度位置,所以初始化重装载寄存器为2800,上电默认向前方向。


配置红外传感器4个输入引脚为输入模式,来检测输入的电平情况


配置旋钮编码器为3个引脚输入模式,用来检测是否旋转与按下


配置LED引脚为推挽输出模式,来驱动LED闪烁


配置串口与滴答定时器延时,串口主要用来调试,延时用来消耗某些时刻需要消耗的时间


循环:循环检测旋钮状态,如果旋转了就根据旋转的方向与角度设定时间的大小,如果旋钮按键按下,那么前进状态变成1

//主函数

int main(void)

{

  u8 state;

  int ang,i;

  

  uart_init(9600);//蓝牙串口初始化

  delay_init(); //延时初始化

  SteerinMotor_Init(); //舵机初始化

  EncodeMotor_Init();//编码电机初始化

  OLED_Init();//oled初始化

  LED_Init();//led初始化

  TIM1_Int_Init(100,7200);//定时器初始化10ms

  Encodeing_Init();//旋钮编码器初始化

  //测试

  printf(" this is Ramp patorl trolley  by HUAZUOCHEN! ^_^ rn");

  while (1) {

  OLED_update();//更新OLED显示

  encodeing_scan();//编码器扫描

  //获取红外线传感器传回的数据

  state = Get_Infrared_Sensor();

  ang = 0;

  switch (state)//循迹转弯设置

  {

      case 0x00:ang = 0;

        break;

      case 0x01:ang = -55;

        break;

      case 0x03:ang = -45;

        break;

      case 0x02:ang = -10;

        break;

      case 0x06:set_steerMotor_ang(0);//设置舵机角度 0

        break;

      case 0x04:ang = 10;

        break;

      case 0x0c:ang = 45;

        break;

      case 0x08:ang = 55;

        break;

      case 0x0f:  //识别到杂乱信号角度设置为0

      case 0x09:

      case 0x05:

      case 0x0a:

      case 0x0e:

      case 0x0b:

        run_flag = 0;//停止  

        break;

      default:ang = 0;

        break;

    }

    if(ang != 0)

    {

      set_steerMotor_ang(ang);//设置舵机角度

      delay_ms(100);

    }

    state = 0;

    }

}


定时器1中断,10ms调用一次,调用时计数10次调用,也就是100ms进行一次速度测量,V = X/t ,速度等于位移处以时间,位移等一编码个数乘以编码单位长度,小车轮的直径为6.4厘米,周长为20.12cm,得到一个脉冲计数,大约是0.258毫米,得出左轮速度V_left = pause_cnt_left2.58;右轮速度V_right = pause_cnt_right2.58;当按下旋转编码器的按键run_flag = 1;使得PID算法开始运行,小车开始按照计算好的速度与当前测量到的速度做比较,进行闭环PID调节。


u16 time_cnt,run_cnt;

//100ms计算一次速度

void TIM1_UP_IRQHandler(void)

{

  if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 

  {

    TIM_ClearITPendingBit(TIM1, TIM_IT_Update);  //清除TIMx的中断待处理位:TIM 中断源 

    time_cnt ++;

    if(time_cnt >= 10)

    {

      V_left = pause_cnt_left*2.58;

      V_right = pause_cnt_right*2.58;

      pause_cnt_left=0;

      pause_cnt_right=0;

      time_cnt =0;

      LED = !LED;

    }

    

    if(run_flag)

    {

      speed = 1200/time;  //总路程/时间

      Set_Temp1 = Set_Temp = speed;

      set_pid_speed();

      run_cnt++;

      if(run_cnt == time*200)

      {

        run_flag = 0;

        run_cnt = 0;

      }

    }

    else 

    {

      PID_OUT = 0;

      PID_OUT1= 0;

      //run_cnt = 0;

      car_go_forward(0,0);//停止

    }

  }

}


霍尔编码器脉冲获取采用中断方式,中断设置上升沿下降沿都触发,电机传动轴与编码器相连,编码器感应论上有13个感应线条,从而使得编码器齿轮转动一圈,或编码器能识别到13个脉冲。


减速箱使得小车轮子转动一圈,电机轴转动30圈,使得编码器齿轮也转动30圈,得到,小车轮子转动一圈,编码器输出13×30,等于390个脉冲,又因为一个脉冲有一个上升,沿有一个下降沿,单片机通过检测上升沿和下降沿,可以得到有780个计数。


double V_left,V_right;//定时器计算

u16 pause_cnt_left,pause_cnt_right;//脉冲计数


//外部中断2服务程序

void EXTI2_IRQHandler(void)

{

  pause_cnt_left++;

  EXTI_ClearITPendingBit(EXTI_Line2);  //清除LINE2上的中断标志位  

}

//外部中断3服务程序

void EXTI3_IRQHandler(void)

{

  

  pause_cnt_right++;

  EXTI_ClearITPendingBit(EXTI_Line3);  //清除LINE3上的中断标志位  

}

速度平衡算法,给定一个速度,听过与编码电机反馈的速度进行比对,然后输出一个算出来的PWM值返回给电机调速,达成闭环速度调节。


void PID_calc(float V_1, float V_2) //PID算法

{

    /***********************左轮**************************/

    float Rate;//误差变化率

    float Rate1;//误差变化率

    Current_Error = Set_Temp - V_1;//当前误差

    Sum_Error += Current_Error; //误差积分

    Prev_Error = Last_Error;//存储误差积分

    Last_Error = Current_Error;//存储误差分析

    Rate = Current_Error - Last_Error; //变化速率计算



    if (Rate > 10) //不让ta大于5也不让ta小于5

        Rate = 10;

    if (Rate < -10)

        Rate = -10;


    P_OUT = P * Gain * Current_Error; //比列项

    I_OUT = I * Gain * Sum_Error; //积分项


    //积分限幅处理

    if (I_OUT > PID_I_MAX)  I_OUT = PID_I_MAX; //不能超过最大值不能低于最小值

    if (I_OUT < PID_I_MIN)  I_OUT = PID_I_MIN;


    //微分输出处理

    D_OUT = D * Gain * Rate;

    PID_OUT =  P_OUT  +  I_OUT  +  D_OUT ;

    if (PID_OUT >= V_DATA_MAX)  PID_OUT = V_DATA_MAX;

    if (PID_OUT <= V_DATA_MIN)  PID_OUT = V_DATA_MIN;


    /***********************右轮********************************/


    Current_Error1 = Set_Temp1 - V_2;//当前误差

    Sum_Error1 += Current_Error1; //误差积分

    Prev_Error1 = Last_Error1;//存储误差积分

    Last_Error1 = Current_Error1;//存储误差分析

    Rate1 = Current_Error1 - Last_Error1; //变化速率计算



    if (Rate1 > 10) //不让ta大于5也不让ta小于5

        Rate1 = 10;

    if (Rate1 < -10)

        Rate1 = -10;


    P_OUT1 = P * Gain1 * Current_Error1; //比列项

    I_OUT1 = I * Gain1 * Sum_Error1; //积分项


    //积分限幅处理

    if (I_OUT1 > PID_I_MAX1)  I_OUT1 = PID_I_MAX1; //不能超过最大值不能低于最小值

    if (I_OUT1 < PID_I_MIN1)  I_OUT1 = PID_I_MIN1;


    //微分输出处理

    D_OUT1 = D * Gain * Rate1;

    PID_OUT1 =  P_OUT1  +  I_OUT1  +  D_OUT1 ;

    if (PID_OUT1 >= V_DATA_MAX1)  PID_OUT1 = V_DATA_MAX1;

    if (PID_OUT1 <= V_DATA_MIN1)  PID_OUT1 = V_DATA_MIN1;

    /*******************************************************/

}


获取红外传感器值,红外对管用一个发射管与一个接收管组成,红外发射管发射出去的红外线遇到白色物体会反射回红外接收管,使之导通,反之遇到黑色物体不反射,使之截止。接收到的红外线越强,导通电流越大,输出电压越大,输出的电压经过逻辑电路转换为数字信号传回到单片机进行识别处理。单片机引出4个引脚对应接收电平状态,4个引脚配置为输入模式,循环检测电平的变化,电平为1则对应红外对管识别到黑色,电平0对应红外对管识别到白色。


//获取传感器状态

u8 Get_Infrared_Sensor(void)

{

  u8 state=0;

  if(PBin(4) == 1)     

    state |= 0x08;  //IN4

  if(PBin(5) == 1)

    state |= 0x04;   //IN3

  if(PBin(6) == 1)

    state |= 0x02;   //IN2

  if(PBin(7) == 1)

    state |= 0x01;   //IN1

  

  return state;

}


关键字:STM32 引用地址:毕业设计| STM32坡道行驶巡线小车制作教程

上一篇:毕业设计| 不超过100元的简易防疲劳驾驶检测
下一篇:毕业设计| STM32+TI BQ76940设计48V BMS方案

推荐阅读最新更新时间:2024-11-08 16:44

STM32单片机使用ST-LINK调试程序时不能设断点
我使用的是STM32单片机,昨天使用ST-LINK调试程序时,发现有些语句不能设断点。程序编译时OK的,没有错误,将程序烧录入单片机后程序看着也能正常运行,但是点击keil中debug按钮后程序进入调试状态,程序并没有停留在main函数的第一条语句,而是停留在别处。main函数第一条语句不能设置断点。 经过在网上查阅资料,发现可能是由于keil软件代码优化的问题。经过测试,发现果然是代码优化的问题。关于以上问题的解决方法:点击keil中“options for target”- 点击 C/C++ ,修改其中的 Optimization 一栏,选择“Level 0”即可。重新按keil中debug按钮进入调试状态,语
[单片机]
STM32(6) STM32时钟系统精讲(正点原子)
讲解内容: 时钟系统框图 时钟配置相关函数 参考资料 《STM32F4开发指南库函数版本》4.3小节STM32F4时钟系统 《STM32F4中文参考手册》第六章 复位和时钟系统 先看开发指南4.3小节的时钟树 时钟框图在中文参考手册的6.2小节,STM32的时钟系统还是很复杂的,为什么ARM的时钟系统要做的这么复杂,采用 多时钟源, 时钟频率越高功耗 越高。 F4与F1类似也有5个时钟来源 1 LSIRC 低速 的内部时钟 2 LSEOSC 低速的外部时钟 3 HSIRC 高速的内部时钟 4 PLLCLK 锁相环时钟输出 5 HSEOSC 也是一个很重要的时钟源,也是我们最常用的
[单片机]
<font color='red'>STM32</font>(6) <font color='red'>STM32</font>时钟系统精讲(正点原子)
STM32出现HardFault_Handler故障
STM32出现HardFault_Handler故障的原因主要有两个方面: 1、内存溢出或者访问越界。这个需要自己写程序的时候规范代码,遇到了需要慢慢排查。 2、堆栈溢出。增加堆栈的大小。 出现问题时排查的方法: 发生异常之后可首先查看LR寄存器中的值,确定当前使用堆栈为MSP或PSP,然后找到相应堆栈的指针,并在内存中查看相应堆栈里的内容。由于异常发生时,内核将R0~R3、R12、LR、PC、XPRS 寄存器依次入栈,其中LR即为发生异常前PC将要执行的下一条指令地址。 注意:寄存器均是32位,且STM32是小端模式。(参考Cortex-M3权威) 编写问题代码如下: void StackFlow(void) {
[单片机]
<font color='red'>STM32</font>出现HardFault_Handler故障
GPIO的描述和配置
首先介绍stm32的GPIO,这是入门的起点,也是最容易上手的部分。 一、GPIO的综合描述 stm32每一个GPIO端口拥有2个32bits的configuration寄存器(GPIOx_CRL,GPIOx_CRH),2个32bits的数据寄存器(GPIOx_IDR,GPIOx_ODR),1个32bits的set/reset寄存器(GPIOx_BSRR),1个16bits的reset寄存器(GPIOx_BRR)和1个32bits的Lock寄存器(GPIOx_LCKR)。 (一)每一个IO引脚都可以使用软件配置为以下几种模式: 1. 浮空输入 2. 带上拉输入 3. 带下拉输入 4. 模拟输入 5. 开漏输出——
[单片机]
STM32各种头文件No such file or directory的解决方法
初学STM32经常学习会网上找的例程,或是买的开发板带的例程等等,经常在编译的时候遇到 ..Userstm32f10x_it.c(26): error: #5: cannot open source input file stm32_eval_sdio_sd.h : No such file or directory 等等,打不到某个头文件的编译错误。而网上大多数都会提到是工程设置的问题,路径设置不正确,无法找到文件等等。因为这个小问题也折腾了些时间,现在头脑还算清醒,记录下来。 1.首先,一定要清晰的了解工程设置路径的含义,为什么要设置这个路径而不是别的?出于什么原因设置的?答:工程设置的路径是在搜索*.h文件。
[单片机]
<font color='red'>STM32</font>各种头文件No such file or directory的解决方法
个人对STM32 SysTick的总结(寄存器操作)
一、概述: SysTick是一个简单的递减24位计数器。如果你不需要再应用程序中嵌入操作系统,SysTick可以作为简单的延时和产生周期性的中断。 状态控制寄存器的第0位可以使能计数器,当前值寄存器随着时钟一直递减,当他减到0的时候,重装载寄存器就会重新装载这只的值,计数器继续从这个值递减。 二、相关寄存器: 2.1SysTick- CTRL 状态和控制寄存器 位16:当前值寄存器递减到0,位16置1 位2:时钟源选择位,0:使用外部参考时钟;1:使用内核时钟 位1:使能SysTick中断,当前值寄存器递减到0时产生中断 位0:SysTick时钟使能 2.2SysTick- LOAD 重装载值寄存器 当前值寄存器为
[单片机]
个人对<font color='red'>STM32</font> SysTick的总结(寄存器操作)
STM32】HAL库-系统滴答定时器SysTick
SysTick定时器被捆绑在NVIC中,是一个简单的定时器,对于CM3、CM4内核芯片,都有Systick定时器。Systick定时器常用来做延时,或者实时系统的心跳时钟。这样可以节省MCU资源,不用浪费一个定时器。 Systick定时器就是系统滴答定时器,一个24 位的倒计数定时器,计到0 时,将从RELOAD 寄存器中自动重装载定时初值。 系统滴答定时器有4个寄存器 时钟源 该定时器的时钟源可以是 内部时钟(FCLK,CM3上的自由运行时钟) 外部时钟( CM3处理器上的STCLK信号) 通过SysTick控制及状态寄存器的第2位来确定 STM32的时钟树 RCC通过AHB时钟(HCLK)8分频或者不分
[单片机]
【<font color='red'>STM32</font>】HAL库-系统滴答定时器SysTick
STM32串口usart发送数据
主函数请直接关注41行到47行代码!! 1 #include stm32f10x.h // 相当于51单片机中的 #include reg51.h 2 #include stm32f10x_gpio.h 3 #include stm32f10x_usart.h 4 #include led.h 5 #include key.h 6 #include key interrupt.h 7 #include delay.h 8 #include usart1.h 9 #include stdio.h 10 #include usart.h 11 12 int main() 13 { 14 /* 15
[单片机]
热门资源推荐
热门放大器推荐
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved