问题 Arduino Uno PWM引脚冲突


我建造了 这个电机护罩 基于L298N芯片控制一个油箱的两个电机。它将引脚5和6用于一个电机,而引脚10和11用于另一个电机。

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

对于我使用的遥控器 这个图书馆。该 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);
}

现在,我找到了 这里 定时器使用的引脚 Arduino Uno 是:

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

所以我的问题是:

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

  2. 为了使用IR和电机屏蔽,我应该使用什么定时器配置IR库?

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

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

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

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

  • 定时器0 是一个8位定时器,它可以保持最大值255.它被使用 delay() 和 millis(),所以当弄乱它时会有后果
  • 定时器1 是一个16位定时器,它最多可以保存65535(无符号16位整数)。 Arduino Servo库使用此计时器
  • 定时器2 是Arduino使用的8位定时器 tone() 功能

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


2517
2017-09-09 19:18


起源

+1。示例问题。 - Peter Mortensen


答案:


  1. 并非所有硬件都以最佳方式设计。使用10和11确实是浪费,因为它需要两个定时器。

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库并尝试使其工作而不重置计数。


13
2017-09-09 20:11



很好的答案,谢谢!我将进行重新布线路线并将引脚10移至9并将引脚11移至10(仅保持逻辑顺序)。所以这只会使用 Timer1。 - talereader
我也看到了代码 analogWrite() 但当时我没有怀疑定时器可能是问题所在。现在看着它,我也看到了 pinMode(pin, OUTPUT); 在 setup 是多余的,如 analogWrite 已经这样做了。 - talereader
@talereader是的,你会注意到Arduino函数中内置了许多冗余的膨胀代码。记住这些是个好主意,所以如果你需要更高的速度,你可以直接使用较低级别的C命令。 (例如,代替digitalWrite,您可以使用更快的DDRB | = 0x01,它的可读性更低但速度更快)。 - user2461391


注意使用的主板,如果你使用Arduino Uno,那么负责的代码将是:// Arduino Duemilanove,Diecimila,LilyPad,Mini,Fio等 其他   //定义IR_USE_TIMER1 // tx =引脚9   定义IR_USE_TIMER2 // tx =引脚3 万一


1
2018-03-25 20:31



你是对的,我现在正在研究的项目是Mega 2560,我看错了代码。因此,库中的评论警告我关于9号引脚,但是当时并不知道TX部分是什么。 - talereader
只是为了澄清将来读这篇文章的人,你的回答是我在下面的评论中提出的问题,而不是直接发布的问题。 - talereader


我有一个预建的同样的问题 L298 V2 电机屏蔽。

盾牌上的针脚标记如下:

电机1:引脚3和5 电机2:引脚6和9

我使用PIN10而不是3并使用一个小的解决方法:我在SHIELD上放了PIN10到PIN3的电线。 我的项目是使用SAMSUNG TV遥控器控制我的机器人。


0
2018-03-15 14:31



欢迎来到罗马尼亚同胞! RoboFun很有趣,但建立自己的更有趣:)我的目的是学习,这就是为什么我更喜欢DIY构建。但这也让我有些头疼。无论如何,由于坦克项目我现在已经转移到另一个项目,使用2个步进器和IR控制。我修改了一下IRremote库以适应我的目的。但是我对这个库仍有一个问题:你有没有理解这些评论 IRremoteInt.h 是指定时器使用定义的那些?例如, #define IR_USE_TIMER1 // tx = pin 11。引脚11与什么有关 TIMER1? - talereader
另外,我遇​​到了这个问题:我需要实时控制步进器,在按下IR按钮的同时保持步进器移动。但是,我目前的遥控器(sparkfun.com/products/retired/10280)以3种不同的格式发送相同的信号,这需要时间并产生延迟问题(导致步进器停止)。这就是为什么我要转向这个: sparkfun.com/products/11759。刚订购,尚未到货。但是,一个IR命令仍有8个字节,需要一些时间才能被IR接收器发送和完全读取。三星电视遥控器的表现如何? - talereader
你肯定会讨厌它。它有间歇性的红外光束。不适合精细电机控制。 - sky10