I built this motor shield based on the L298N chip to control two motors of a tank. It uses pins 5 and 6 for one motor, and pins 10 and 11 for the other.
While trying to add a TSOP 4838 in order to control the tank with an IR remote I noticed that moving the motor on pins 10/11 in reverse only works at full speed - that is, a HIGH (255) value on pin 11. Anything below that value doesn't output anything on pin 11 (measured voltage on those pins is 0 V).
For the remote I use this library. The IR receiver is connected on pin 2 (but the pin doesn't matter). The problem is the library code itself. The line that enables IR listening irrecv.enableIRIn();
is what is causing the problem. I learned that there is a conflict of internal Arduino timers and the pins used for PWM by the shield.
This is the code to power the motor in reverse:
#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);
}
Now, I found here that the pins used by the timers on Arduino Uno are:
- Pins 5 and 6: controlled by Timer0
- Pins 9 and 10: controlled by Timer1
- Pins 11 and 3: controlled by Timer2
So my questions are:
Why does the shield in the instructable use pins 10 and 11 for PWM ? They correspond to 2 different timers. Why not 9 and 10?
In order to use the IR along with the motor shield, what timer should I configure the IR library to use?
If the answer is 2, a line should be uncommented in
IRremoteInt.h
. I am guessing the Uno would take theelse
branch at line 68, although only timer1 and timer2 are there. I wonder why timer0 couldn't be used for the Uno.
Although I'd like to leave cutting traces and resoldering as a last option, another possibility would be to change the pins used by the shield, but which? And I am guessing this would also be paired with configuring the timers to PWM on other pins than default, but I don't know anything about timers/interrupts and my knowledge of Arduino and C is limited.
I made this a long question, because I want to learn not just solve the problem, so feel free to explain more than what is asked.
While looking up for a solution I also found other conflicts to keep in mind when using PWM or timers:
- Timer0 is an 8-bit timer, it can hold a maximum value of 255. It is used by
delay()
andmillis()
, so there are consequences when messing with it - Timer1 is a 16-bit timer, it can hold a maximum of 65535 (an unsigned 16-bit integer). The Arduino Servo library uses this timer
- Timer2 is an 8-bit timer used by the Arduino
tone()
function
And, of course, the IRremote library uses TIMER_RESET
, so depending on which timer it uses it can conflict with the associated pins.