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)