Conflict between pin timers?

I’m excited to get my first Arduino project running (I just used the stepper motor mounted in a wooden box to rotate a plant, using a remote control). I’ve been testing combining elements from my kit (the Elegoo UNO R3 board with a bunch of little sensors and motors) and ran into a mysterious problem.

I am trying to combine some remote control functionality with the RGB light. However, as soon as I add the line of code ‘EnableIRIn’ function in setup() (I removed lines of code until the problem went away, and this one seems to create it), the PWM #3 seems to lose delay functionality. Looking on stack overflow, I’ve read about different pin sets having different timers, and suspect that there is a conflict in the remote library and the delay function for this pin.

Specifically, the problem is that the RGB light is supposed to fade smoothly between R, G, and B, in that order. (When I use only the RGB light fading code, it works like a dream.) When I add the Remote code, especially the aforementioned function, the blue light on pin 3 does not fade in, but only briefly flashes on at the end of the sequence before the red flashes on in full force and begins the fading loop over. Notably, red fades perfectly to green, the problem is only with blue. Removing the IR function above solves the problem.

Any suggestions how to have a remote and a beautiful blue fade, too?

Here’s the code (some disabled as I was testing for the issue).

//www.elegoo.com
//2016.12.12

#include "Stepper.h"
#include "IRremote.h"

/*----- Variables, Pins -----*/
#define BLUE 3
#define GREEN 5
#define RED 6
//#define STEPS  32   // Number of steps per revolution of Internal shaft
//int  Steps2Take;  // 2048 = 1 Revolution
int receiver = 7; // Signal Pin of IR receiver to Arduino Digital Pin 6

/*-----( Declare objects )-----*/
// Setup of proper sequencing for Motor Driver Pins
// In1, In2, In3, In4 in the sequence 1-3-2-4

//Stepper small_stepper(STEPS, 8, 10, 9, 11);
IRrecv irrecv(receiver);    // create instance of 'irrecv'
//decode_results results;     // create instance of 'decode_results'

void setup()
{ 
  pinMode(RED, OUTPUT);
  pinMode(GREEN, OUTPUT);
  pinMode(BLUE, OUTPUT);
  digitalWrite(RED, HIGH);
  digitalWrite(GREEN, LOW);
  digitalWrite(BLUE, LOW);
  irrecv.enableIRIn(); // Start the receiver
}

int redValue;
int greenValue;
int blueValue;

/*void loop()
{
  RunLight();
if (irrecv.decode(&results)) // have we received an IR signal?

  {
    switch(results.value)

    {

      case 0xFFA857: // VOL+ button pressed
                      small_stepper.setSpeed(100); //Max seems to be 500
                      Steps2Take  =  2048;  // Rotate CW 2048
                      small_stepper.step(Steps2Take);
                      //delay(2000); 
                      break;

      case 0xFF629D: // VOL- button pressed
                      small_stepper.setSpeed(500);
                      //Steps2Take  =  -2048;  // Rotate CCW 2048
                      small_stepper.step(Steps2Take);
                      //delay(2000); 
                      break;
                
    }
    
      irrecv.resume(); // receive the next value
                 digitalWrite(8, LOW);
                 digitalWrite(9, LOW);
                 digitalWrite(10, LOW);
                 digitalWrite(11, LOW);       
  }  


}--end main loop -- */

void loop()
{
#define delayTime 10 // fading time between colors

  redValue = 255; // choose a value between 1 and 255 to change the color.
  greenValue = 0;
  blueValue = 0;

  // this is unnecessary as we've either turned on RED in SETUP
  // or in the previous loop ... regardless, this turns RED off
  // analogWrite(RED, 0);
  // delay(1000);

  for (int i = 0; i < 255; i += 1) // fades out red bring green full when i=255
  {
    redValue -= 1;
    greenValue += 1;
    // The following was reversed, counting in the wrong directions
    // analogWrite(RED, 255 - redValue);
    // analogWrite(GREEN, 255 - greenValue);
    analogWrite(RED, redValue);
    analogWrite(GREEN, greenValue);
    delay(delayTime);
  }

  redValue = 0;
  greenValue = 255;
  blueValue = 0;

  for (int i = 0; i < 255; i += 1) // fades out green bring blue full when i=255
  {
    greenValue -= 1;
    blueValue += 1;
    // The following was reversed, counting in the wrong directions
    // analogWrite(GREEN, 255 - greenValue);
    // analogWrite(BLUE, 255 - blueValue);
    analogWrite(GREEN, greenValue);
    analogWrite(BLUE, blueValue);
    delay(delayTime);
  }

  redValue = 0;
  greenValue = 0;
  blueValue = 255;

  for (int i = 0; i < 255; i += 1) // fades out blue bring red full when i=255
  {
    // The following code has been rearranged to match the other two similar sections
    blueValue -= 1;
    redValue += 1;
    // The following was reversed, counting in the wrong directions
    // analogWrite(BLUE, 255 - blueValue);
    // analogWrite(RED, 255 - redValue);
    analogWrite(BLUE, blueValue);
    analogWrite(RED, redValue);
    delay(delayTime);
  }
}

The FAQ states

  • The default IR timer on AVR’s is timer 2. Since the Arduino Tone library as well as analogWrite() for pin 3 and pin 11 requires timer 2, this functionality cannot be used simultaneously. You can use tone() but after the tone has stopped, you must call IrReceiver.start() or better IrReceiver.start(<microsecondsOfToneDuration>) to restore the timer settings for receive. Or you change the timer to timer 1 in private/IRTimer.cpp.h.
    If you can live with the NEC protocol, you can try the MinimalReceiver example, it requires no timer.
1 Like

PWM outputs are based on timers. The Uno has 3 timers with timer 0 being used for timing (delay, millis…). Each timer has 2 PWM outputs, consult the pin mapping which timer controls which output OCx. Using the timer0 PWM outputs OC0A/B is safe, for more outputs find a timer not used by your library functions.

Pin 5/6 are controlled by timer 0, pin 3 by timer 2 OC2B. Then timer 1 should work, i.e. pin 9/10 for OC1A/B.

1 Like

Thank you! Very straightforward. I will try this. Does the timer issue exist with most boards? I am hoping, in addition to the RGB and remote to use a stepper motor on the other PWM pins, so may have reached the capacity for the UNO.

The Mega has 5 timers with 3 PWM outputs each.

1 Like