Arduino Uno PWM引脚冲突

时间:2013-09-09 19:18:37

标签: timer arduino avr atmega pwm

我基于L298N芯片构建了this motor shield来控制坦克的两个电机。它将引脚5和6用于一个电机,而引脚10和11用于另一个电机。

在尝试添加TSOP 4838以便使用IR遥控器控制油箱时,我注意到在10/11引脚上反向移动电机只能以全速运行 - 即HIGH(255)引脚11上的值。低于该值的任何值都不会在引脚11上输出任何内容(这些引脚上的测量电压为0 V)。

对于遥控器我使用this libraryIR接收器连接在引脚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

  • 引脚5和6:由Timer0控制
  • 引脚9和10:由Timer1控制
  • 引脚11和3:由Timer2控制

所以我的问题是:

  1. 为什么指示屏中的屏蔽使用引脚10和11进行PWM?它们对应于2个不同的计时器。为什么不9和10?

  2. 为了将IR与电机屏蔽一起使用,我应该使用哪个定时器来配置IR库?

  3. 如果答案为2,则应在IRremoteInt.h中取消注释一行。我猜Uno将在第68行采用else分支,尽管只有timer1和timer2存在。我想知道为什么timer0不能用于Uno。

  4. 虽然我想留下切割痕迹和重新焊接作为最后一种选择,但另一种可能性是改变屏蔽使用的引脚,但是哪个?而且我猜这也可以配置在其他引脚上配置定时器而不是默认值,但是我对定时器/中断一无所知,而且我对Arduino和C的了解有限。

    我提出了一个很长的问题,因为我想学习的不仅仅是解决问题,所以请自由解释所提出的问题。

    在查找解决方案时,我还发现在使用{{3}}或计时器时要记住其他冲突:

    • Timer0 是一个8位定时器,它可以保存最大值255.它由delay()millis()使用,因此在使用时会产生影响它
    • Timer1 是一个16位定时器,最多可以保存65535(无符号16位整数)。 Arduino Servo库使用此计时器
    • Timer2 是Arduino tone()函数使用的8位定时器

    当然, IRremote 库使用TIMER_RESET,因此根据它使用的计时器,它可能与相关的引脚冲突。

3 个答案:

答案 0 :(得分:14)

  1. 并非所有硬件都以最佳方式设计。使用10和11确实是浪费,因为它需要两个计时器。
  2. 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遥控器控制我的机器人。