我基于L298N芯片构建了this motor shield来控制坦克的两个电机。它将引脚5和6用于一个电机,而引脚10和11用于另一个电机。
在尝试添加TSOP 4838以便使用IR遥控器控制油箱时,我注意到在10/11引脚上反向移动电机只能以全速运行 - 即HIGH(255)引脚11上的值。低于该值的任何值都不会在引脚11上输出任何内容(这些引脚上的测量电压为0 V)。
对于遥控器我使用this library。 IR接收器连接在引脚2上(但引脚无关紧要)。问题是库代码本身。启用IR侦听irrecv.enableIRIn();
的行是导致问题的原因。我了解到内部Arduino定时器和屏蔽用于PWM的引脚存在冲突。
这是反向驱动电机的代码:
#include <IRremote.h>
// IR receiver configuration
const int irPin = 2;
IRrecv irrecv(irPin);
// Motors configuration
const int mLeftPin1 = 10;
const int mLeftPin2 = 11;
const int mRightPin1 = 5;
const int mRightPin2 = 6;
void setup()
{
// Start IR
irrecv.enableIRIn();
// Setup motors
pinMode(mLeftPin1, OUTPUT);
pinMode(mLeftPin2, OUTPUT);
pinMode(mRightPin1, OUTPUT);
pinMode(mRightPin2, OUTPUT);
// Move left motor in reverse, slower speed
analogWrite(mLeftPin2, 100); // This works only with 255 instead of 100
digitalWrite(mLeftPin1, LOW);
}
现在,我发现here Arduino Uno上的定时器使用的引脚是PWM:
所以我的问题是:
为什么指示屏中的屏蔽使用引脚10和11进行PWM?它们对应于2个不同的计时器。为什么不9和10?
为了将IR与电机屏蔽一起使用,我应该使用哪个定时器来配置IR库?
如果答案为2,则应在IRremoteInt.h
中取消注释一行。我猜Uno将在第68行采用else
分支,尽管只有timer1和timer2存在。我想知道为什么timer0不能用于Uno。
虽然我想留下切割痕迹和重新焊接作为最后一种选择,但另一种可能性是改变屏蔽使用的引脚,但是哪个?而且我猜这也可以配置在其他引脚上配置定时器而不是默认值,但是我对定时器/中断一无所知,而且我对Arduino和C的了解有限。
我提出了一个很长的问题,因为我想学习的不仅仅是解决问题,所以请自由解释所提出的问题。
在查找解决方案时,我还发现在使用{{3}}或计时器时要记住其他冲突:
delay()
和millis()
使用,因此在使用时会产生影响它tone()
函数使用的8位定时器当然, IRremote 库使用TIMER_RESET
,因此根据它使用的计时器,它可能与相关的引脚冲突。
答案 0 :(得分:14)
2/3。理想情况下,您将使用不是Timer0的计时器。以下是有关定时器/中断的更多详细信息:
Arduino芯片(328P)有三个定时器。每个定时器都可以用于多种用途,但重要的是要注意每个定时器只能启用一个定时器中断。
以Timer0为例。它会中断,以便为delay()和delay_us()方法生成适当的延迟。它还用于引脚5和6上的PWM输出。这可能是因为PWM输出不使用定时器中断,它们使用单独的输出比较模块。
现在专门研究你的问题,它应该工作正常,即使你有一个使用timer2的PWM输出,PWM也不会在timer2上中断,所以IR库可以免费使用那个中断。但是,查看IR库代码,我们看到了这段代码:
ISR(TIMER_INTR_NAME)
{
TIMER_RESET;
每次中断时,它都会重置计时器计数。这可能是您的PWM输出无法正常工作的原因。输出比较模块正在等待某个滴答计数,它永远不会达到。
至于为什么它以某种方式工作在255,我们可以看一下analogWrite代码:
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和输出比较,只需将引脚写入高电平。
最后,至于解决你的问题,我个人会采用不使用引脚11和3(timer2)的路线。是的,它需要一个小的重新布线,但这样你可以释放timer2供IR库使用。
或者,您可以浏览IR库并尝试使其工作而不重置计数。
答案 1 :(得分:1)
注意使用的主板,如果使用Arduino Uno,则负责的代码为:// Arduino Duemilanove,Diecimila,LilyPad,Mini,Fio等 其他 //定义IR_USE_TIMER1 // tx =引脚9 定义IR_USE_TIMER2 // tx =引脚3 ENDIF
答案 2 :(得分:0)
我对预制的L298 V2电机护罩有同样的问题。
盾牌上的针脚标记如下:
电机1:引脚3和5 电机2:引脚6和9
我使用PIN10而不是3并使用一个小的解决方法:我在SHIELD上放置了PIN10到PIN3的电线。 我的项目是使用SAMSUNG TV遥控器控制我的机器人。