Arduino Uno PWM和IRremote库冲突问题

问题发生环境:

Arduino UNO R3控制板,用两个L298N驱动板驱动4轮小车,然后通过控制4路PWM来控制4个轮子的速度,遥控方式为红外遥控,使用的红外库是IRremote Arduino Library v2.2.3。

问题发生时,4路PWM的控制管脚分别是:PIN5,PIN6和PIN10,PIN11

问题描述:

对于PIN11,除了PWM设置为255,其他任何合法PWM值都不能驱动电机转动,其他3个PIN脚控制的电机工作正常。

定位发现是irrecv.enableIRIn()这个操作导致。也就是说IR库和PWM控制有冲突。

解决方案:

方案一(推荐):将4路PWM的控制管脚改为:PIN5,PIN6和PIN9, PIN10

方案二:根据网上的其他方案,https://www.douban.com/note/542007770/

按照下面修改boarddefs.h,改用Timer1。

// Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, Nano, etc
#else
    #define IR_USE_TIMER1   // tx = pin 9
    //#define IR_USE_TIMER2     // tx = pin 3

这个方案对我的方案没用,因为PIN10也要用来输出PWM:(,另外,和其他库还有编译冲突,就没有沿这条路往下走了。


根因分析:

首先,Arduino PWM控制是需要使用内部timer的,我这个方案用两个timer来控制PWM有点奢侈,其实只用PIN5 PIN6控制小车左右侧轮子的速度就可以了。但是手头的4个电机一致性不好,同样PWM设置下转速不同,只好分别控制,根本原因是穷,买不起4个一致性好的电机。

Arduino主芯片(328P)有3个timer:

Timer0 :8-bit timer, 最大值 255. timer0控制的管脚是PIN5, PIN6,delay() 和millis()也会用到Timer0;

Timer1 :16-bit timer, 最大值 65535 (unsigned 16-bit integer).  timer1控制管脚PIN9,PIN10,Arduino Servo 用这个 timer;

Timer2 : 8-bit timer, timer2控制管脚PIN3和PIN11,Arduino tone()会用到;

每个timer可以有多种用途,但是每个timer只产生一个中断。

以Timer0为例,根据delay()和delay_us()的设定时间产生中断,也被用来在PIN5和PIN6上产生PWM。之所以在没产生冲突是因为PWM不用中断,而是用的比较器。

IRremote库默认使用Timer2,按照上面的说法,既然PWM不使用中断,应该不会出问题的,但是PIN11上确实没有输出。

为什么在PIN11上就出问题了?

分析了一下IR库的代码,在IRremote.cpp中ISR函数开头有以下操作:

ISR (TIMER_INTR_NAME)

{

TIMER_RESET;

从这里看,Timer2每次产生中断,都会重置timer计数,而比较器在等待达到某个计数,但是却永远等不到了:(。这就是PWM在PIN11上无法输出的原因。

至于为什么在255这个值上是可以的,从代码上看:

void analogWrite(uint8_t pin, int val)
{
       // We need to make sure the PWM output is enabled for those pins
       // that support it, as we turn it off when digitally reading or
       // writing with them.  Also, make sure the pin is in output mode
       // for consistenty with Wiring, which doesn't require a pinMode
       // call for the analog output pins.
       pinMode(pin, OUTPUT);
       if (val == 0)
       {
           digitalWrite(pin, LOW);
       }
       else if (val == 255)
       {
           digitalWrite(pin, HIGH);
       }

在设置255时,analogWrite直接忽略PWM和输出比较这些操作,直接设置HIGH :<。

解决这个问题避开11和3就好了,所以这里将PWN管脚改成了PIN10。

Arduino Uno中,可以使用PWM(脉冲宽度调制)波来控制舵机。PWM波通过改变脉冲的宽度来控制设备的输出。在舵机控制中,通常使用的是舵机中的`writeMicroseconds()`函数或`write()`函数。 使用`writeMicroseconds()`函数,可以向舵机写入一个微秒的值来控制舵机的轴。对于标准舵机,参数设置为1000表示完全逆时针方向,2000表示完全顺时针方向,1500表示在中间。通过改变参数值,可以控制舵机的转动角度。 另外,还可以使用`write()`函数来直接控制舵机的轴。对于标准舵机,该函数设置舵机的角度,并将齿轮转到对应的位置。例如,0表示全速向一边,180表示全速向另一边,90附近的值表示停止。 通过调用这两个函数,可以使用PWM波来控制舵机的转动方向和角度,从而实现小车超声波避障功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [arduino 舵机控制与pwm控制小车冲突解决](https://download.csdn.net/download/weixin_38724611/12611998)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Arduino Uno 舵机控制](https://blog.csdn.net/idleAsaPig/article/details/122813115)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值