循迹原理 - PWM讲解

循迹原理

循迹小车为何会像是长了眼睛一样,紧紧跟着黑线走呢?到底是什么束缚着它不脱轨呢?

小车底部有一个循迹传感器,在传感器两侧各有一对发射和接收的探头。当小车沿着白色地毯上的黑线行走的时候,刚好两侧探头处于黑线两侧,也就是处于白色背景之上。

image-20231231140825714

从工作原理上看,循迹的传感器有红外传感器和灰度传感器两类,以下进行详细介绍。

红外传感器

• 红外传感器的发射二极管会不断发射红外线。

• 当发射出的红外线没有被反射回来或被反射回来但强度不够大时,红外接收管一直处于关断状态,此时模块的输出端为高电平,指示二极管一直处于熄灭状态。

• 被检测物体出现在检测范围内时,红外线被反射回来且足够强大,红外接收管饱和,此时模块的输出端为低电平,指示二极管被点亮。

灰度传感器

• 灰度传感器是模拟传感器,它由一个发光二极管和一个光敏电阻组成并安装在同一平面。

• 工作时二极管会发光,地面会反射二极管的光从而被光敏电阻感知。由于不同颜色的检测面对光的反射程度的不同,灰度传感器的光敏电阻对不同检测面返回光所激发的电阻值也不同,由此进行**灰度值(不同颜色的深浅)**的检测。

• 灰度的工作电压范围比较宽,当电源电压波动比较大的时候也可以正常工作。它输出的是连续的模拟信号,所以很容易通过A/D转换器或者简单的比较器实现对物体反射率的判断。

循迹原理

当安装循迹模块的小车在黑线轨道时,两边的传感器位于黑线两侧。此时定义两只传感器检测到地面为白色的时候,小车两侧轮子都同样转速向前。

image-20231231140854966

对于小车,主要会有以下几种状态:

• 两只轮子同速向前——前进

• 两只轮子同速向后——后退

• 左边轮子转速大于右边轮子转速——右转

• 右边轮子转速大于左边轮子转速——左转

• 转速为0——停止

根据传感器返回值调整小车状态

因此,当我们任意一个传感器检测到地面为黑色的时候(此时说明小车传感器来到黑线上方,即将偏离黑线轨道),根据循迹传感器返回值,小车被控制进行左/右转。

如何实现左右转?

上面已经提到,当两只轮子转速不同步的时候可以实现左右转。

我们循迹小车用的是直流电机作为动力,因此可以通过控制电机的电压从而控制电机的速度,从而让小车左右轮子产生速度差,实现左右转弯。

image-20231231140932979

如何控制直流电机电压呢?

我们引出新的知识——PWM(脉冲宽度调制)

由于Arduino的I/O口标准输出为5V,我们可以控制周期内占空比来实现输出不同的电压。

PWM讲解

脉冲宽度调制(PWM)

PWM是英文 “Pulse Width Modulation” 的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。

PWM是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的。通的时候即是直流供电被加到负载上的时候,断的时候即是供电被断开的时候。只要带宽足够,任何模拟值都可以使用PWM进行编码。

​ ——摘自百度百科

PWM的单位是:Hz,可看出PWM表示的是频率

T(周期) = 1/f(频率)

f = 1/T

对于Arduino的IO口输出,信号从高电平到低电平再到高电平的时间为一个周期 T ,可知 PWM 的频率 f 表示的就是一秒钟内PWM有多少个周期。

占空比

• 占空比是一个脉冲周期内,高电平的时间占整个周期时间的比例。

简单理解:占空比可以理解为在1个周期 T 的输出中,高电平的状态占整个周期 T 的比例。

• 当一个周期内IO口仅输出高电平时,那么我们的占空比就为100%。因为一个周期的时间发生的变化是人眼无法观察到的,所以我们可以当作一个周期内,我们输出的电压是5V(Arduino IO口高电平状态下的标准输出电压为5V)。

• 当输出高电平的时间为1/2T时,我们的占空比就为50%,此时我们输出的电压就可以当作2.5V。

PWM占空比正式版

PWM控制循迹小车转弯

之前的文章中提到控制循迹小车转弯是利用左右轮子转速不同

对于直流电机,转速和电压相关,因此我们可以控制输入给电机的电压从而控制左右轮子的转速。

已知Arduino的IO口输出的是数字信号,并且IO口只能输出高电平或者低电平。

假设高电平为5V,低电平则为0V,那么我们完全可以通过PWM模拟输出任意大于0V小于等于5V的电压。这个时候我们就需要用到Arduino开发板上的模拟输出引脚以及analogWrite (pin,value) 语法来控制该引脚的PWM信号。

具体实现:

  1. 假设一个周期为 T ,高电平状态输出为5V,低电平状态输出为0V。
  2. 通过改变IO口输出的方波的占空比,我们可以将数字信号改变为模拟电压信号,并且理论上我们可以模拟出任意范围在0V(低电平)到5V(高电平)之间的电压。
  3. 我们在1个脉冲周期内输出高电平的时间占总周期的1/2,那么我们输出的电压就是2.5V了。
  4. 1个脉冲周期内输出高电平的时间占总周期的 75%,那么我们输出的电压就是3.75V了。
  5. 以上例子中的 1/2、75% 就是占空比。此时我们就很轻松通过PWM技术,也就是改变高电平的占空比来控制输入到直流电机的电压,从而使不同电机的运转产生速度差,完成差速转弯。

Arduino Uno的PWM引脚

在Arduino Uno的众多数字引脚中,只有数字前带 ~ 符号的引脚支持PWM,这个大家一定要注意。

image-20231231141122104

学习资料

关于PWM具体详细解释、Arduio编程中如何使用……在此附上部分优质教程网址,大家自主学习。

  • 郭天祥老师讲PWM视频(哔哩哔哩)
https://www.bilibili.com/video/BV1Fp4y1s7Qr/?spm_id_from=333.337.search-card.all.click&vd_source=6a1fcd351fb9b00796e2e41ad793d678

Arduino官网讲解PWM

https://create.arduino.cc/projecthub/muhammad-aqib/arduino-pwm-tutorial-ae9d71
  • PWM原理及Arduino使用PWM详解 (CSDN)
https://blog.csdn.net/m0_46336441/article/details/120962470?ops_request_misc=%257B%2522request%25
  • 33
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
#include #include "qudong.h" #include "duankou.h" #include "lcd1602.h" #include "celv.h" #define uchar unsigned char #define uint unsigned int #define CPU_F ((double)8000000) #define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0)) #define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0)) //****************************************************************************** //全局变量 //****************************************************************************** float voltage=6.0; //实际电压值 int RS1=100; int LS1=100; int RS0=100; int LS0=100; char heixian=0x03; //不等于0x03表示检测到信号,等于0x03表示没检测到信号 char ji_shu=0; //表示第几次检测到黑线 char youxinhao=0; //=1表示检测到信号,=0表示没有检测到信号 uint total_time_count=0;//时间相关变量 uint start_low_speed=0; uint end_low_speed=0; uint end_all=0; uint start_all=0; uint LM_cap_new=0; //测速相关变量 uint LM_cap_old=0; uint LM_cap_count=0; uint LM_mai_kuai=0; float real_LM_speed=0.0; float top_speed=0; float average_speed=0; uint RM_cap_new=0; uint RM_cap_old=0; uint RM_cap_count=0; uint RM_mai_kuai=0; float real_RM_speed=0.0; float total_distance=0; //测量值转化为实际值相关变量 float dis1=0; float dis0=0; uint low_speed_time=0; uint total_time=0; //****************************************************************************** //系统时钟初始化,aclk=32768k,mclk=XT2,SMCLK = XT2。 //****************************************************************************** void Init_clock(void) { DCOCTL = DCO0 + DCO1 + DCO2; // Max DCO数字晶振最高频率 BCSCTL1 = RSEL0 + RSEL1 + RSEL2; // XT2on, max RSEL选择高速晶振最高频率 BCSCTL2 |=SELM_2+SELS; //MCLK=8M,SMCLK = XT2,系统主时钟选择高速晶振 do //清除振荡器失效标志,等振荡器稳定。 { IFG1&=~OFIFG; for(unsigned int i=0XFF;i>0;i--); } while((IFG1&OFIFG)!=0); } #pragma vector=ADC_VECTOR //ADC12 interrupt service routine __interrupt void ADC12_ISR (void) { if(ADC12MEM0<2816)P6OUT&=~BIT3; //欠压指示灯亮 else P6OUT|=BIT3; } //*************************

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

土豆小蜡笔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值