PWM pin left at non-zero or non-255 value disturbes IRRemote library.

I am relatively new at Arduino but I have basic skills in programming and electronics from before. I am also relatively good at googling. I have read up quite a bit on this problem but still found no suggestion of a solution.

I am trying to control an RGB-LED with an remote control and an IR-receiver connected to an Arduino R3. The ultimate goal is to produce a "magic staff with a glowing crystal". The remote has 17 buttons and I can decode them without problem, using Shariffs IRremote library.

Some of the functions I want the staff/LED to do is:

For any or all colors: dim to 0, dim up to max, dim down a bit, dim up a bit. Also for all colors: Immediate White/off.

IRreciever is on pin 11. LED is on pins 9, 10 and 6 (NOT 11, since timer2 is used by the library - I am aware of this) (Putting the receiver on pin 2 makes no difference, as it shouldn't).

It now turns out that all actions that leave the PWM pins at 0 or 255 works just fine. However, as soon as any of the upabit() or downabit() are used which leave the pins at levels not equal to 0 or 255, the next IR signal cannot be properly decoded. In fact, all key presses on the remote after that crucial function call decode simply as random codes.

In other words, "floating" or "active" PWM pins seems to disturb the IRRemote library, or at least the resume() method.

It seems to be some sort of interference with timing/timers, but according to what I know, only timer2 is used which only affects pins 3 and 11. Other pins are not affected in theory, and in practice, they work too. Its just that they somehow affect the library functions back.

Is there any way to get around or solve this problem? Or am I just incredibly stupid and have missed something obvious? Has anyone else managed to do what I am doing?

Code follows.

#include "IRremote.h"

#define RECV_PIN 11
IRrecv irrecv(RECV_PIN);
decode_results results;

//Codes for small Arduino remote
const unsigned int ONE =   0x1817725F;
const unsigned int TWO =   0xB3B02336;
const unsigned int THREE = 0xC8BFDD51;
const unsigned int FOUR =  0x6785E38A;
const unsigned int FIVE =  0x823E3FB6;
const unsigned int SIX =   0xBDF598EE;
const unsigned int SEVEN = 0x783D9008;
const unsigned int EIGHT = 0xEF0BED8A;
const unsigned int NINE =  0xDAF6040A;
const unsigned int STAR =  0x5F0B42EE;
const unsigned int ZERO =  0x34D6A5EA;
const unsigned int HASH =  0x967033A2;
const unsigned int UP =    0xD78D4FA0;
const unsigned int DOWN =  0x88C35FEC;
const unsigned int LEFT =  0x2F8CEC34;
const unsigned int RIGHT = 0x24FBAE9C;
const unsigned int RIGHT2= 0x36433321;
const unsigned int OK =    0xCACD90A9;

const int ledPIN[3] = {9, 10, 6};       // Pin 11 seems to not work. Most likely library uses timers attached to it.

const int RED = 0;
const int GREEN = 1;
const int BLUE = 2;

float increment = 20;  //How many percent to increase/decrease light in one step for upabit() and downabit()
int timestep = 10;    //How much to delay in loop when changing color

//Variables to keep track of stuff
float downfactor = 1 - increment/100;
float upfactor = 1 + increment/100;

//current intensities
int ledvalue[3] = {0, 0, 0};

void setup()
{
  // Start serial debug output
  while (!Serial);
  Serial.begin(115200);
  Serial.println(F("Startup"));
  Serial.print("Upfactor = ");
  Serial.println(upfactor);
  Serial.print("Downfactor = ");
  Serial.println(downfactor);

  //Set output for RGB LED
  pinMode(ledPIN[0], OUTPUT);
  pinMode(ledPIN[1], OUTPUT);
  pinMode(ledPIN[2], OUTPUT);

  irrecv.enableIRIn(); // Start the receiver
}
// Main loop somehow does not likw PWM output. If LedPINs are not 0 or 255 then scrambling occurs. 
void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    switch(results.value) {
      case 0x1817725F: Serial.println("ONE");   break;
      case 0xB3B02336: Serial.println("TWO");   break;
      case 0xC8BFDD51: Serial.println("THREE"); break;
      case 0x6785E38A: Serial.println("FOUR");  break;
      case 0x823E3FB6: Serial.println("FIVE");  break;
      case 0xBDF598EE: Serial.println("SIX");   break;
      case 0x783D9008: Serial.println("SEVEN"); break;
      case 0xEF0BED8A: Serial.println("EIGHT"); break;
      case 0xDAF6040A: Serial.println("NINE");  break;
      case 0x5F0B42EE: Serial.println("STAR");  break;
      case 0x34D6A5EA: Serial.println("ZERO");  break;
      case 0x967033A2: Serial.println("HASH");  break;
      case 0xD78D4FA0: Serial.println("UP");    break;
      case 0x88C35FEC: Serial.println("DOWN");  break;
      case 0x2F8CEC34: Serial.println("LEFT");  break;
      case 0x24FBAE9C: Serial.println("RIGHT"); break;
      case 0x36433321: Serial.println("R2");    break;
      case 0xCACD90A9: Serial.println("OK");    break;
    }
    handleAction(results.value);
//    results.value = 0;   //desperately trying to get things to work 
//    delay(50); // if you keep receiving "button kept" response
    irrecv.resume(); // Receive the next value
  }
}

void handleAction(unsigned int cmd) {
    switch (cmd)  {
      case ONE:    up(RED);        break;
      case TWO:    up(GREEN);      break;
      case THREE:  up(BLUE);       break;
      case FOUR:   upabit(RED);    break;
      case FIVE:   upabit(GREEN);  break;
      case SIX:    upabit(BLUE);   break;
      case SEVEN:  downabit(RED);  break;
      case EIGHT:  downabit(GREEN);break;
      case NINE:   downabit(BLUE); break;
      case STAR:   down(RED);      break;
      case ZERO:   down(GREEN);    break;
      case HASH:   down(BLUE);     break;
      case OK:     flash();        break;
      case LEFT:   dark();         break;
      case RIGHT:  shine();        break;
      case RIGHT2: shine();        break;
      case UP:     allup();        break;
      case DOWN:   alldown();      break;        
    }
    printCV();
}

//up() and down() are exponential and they work!

void up(int color) {
  int cur = ledvalue[color];
  for(int i = cur; i < 255; i = min(255, int(i*upfactor) + 1)){
    analogWrite(ledPIN[color], i);
    delay(10*timestep);
  }
  analogWrite(ledPIN[color], 255);
  ledvalue[color] = 255; 
}

void upabit(int color) {
  int cur = ledvalue[color];
  int loops = 0;
  for(int i = cur; loops <= 3; i = min(255, int(i*upfactor) + 1)){
    loops++;
    analogWrite(ledPIN[color], i);
    ledvalue[color] = i;     
    delay(10*timestep);
  }
}

void down(int color) {
  int cur = ledvalue[color];
  for(int i = cur; i > 0; i = max(0, int(i*downfactor)) ){
    analogWrite(ledPIN[color], i);
    delay(10*timestep);
  }
  analogWrite(ledPIN[color], 0);
  ledvalue[color] = 0; 
}

void downabit(int color) {
  int cur = ledvalue[color];
  int loops = 0;
  for(int i = cur; loops <= 3; i = max(0, int(i*downfactor)) ){
    loops++;
    analogWrite(ledPIN[color], i);
    ledvalue[color] = i; 
    delay(10*timestep);
  }
  analogWrite(ledPIN[color], 0);
  ledvalue[color] = 0; 
}

// upabit() and downabit() are exponentioal and do NOT work. They work once and then scramble the input...
// ...once the if-statement is entered.  
/*
void upabit(int color) {
  int cur = ledvalue[color];
  if (cur < 255) {
    int newValue = int(cur*upfactor) + 1;
    newValue = min(255, newValue);
    analogWrite(ledPIN[color], newValue);
    ledvalue[color] = newValue; 
    delay(250);
  }
}

void downabit(int color) {
  int cur = ledvalue[color];
  if (cur > 0) {
    int newValue = max(0, int(cur*downfactor) - 1);
    analogWrite(ledPIN[color], newValue);
    ledvalue[color] = newValue; 
  }
}
*/


// allup() and alldown() are linear and work

void allup() {
  int minrg = min(ledvalue[RED], ledvalue[GREEN]);
  int minrgb = min(minrg, ledvalue[BLUE]);
  for(int i = minrgb; i <= 255; i++){
    for(int color = RED; color <= BLUE; color++){
      if (ledvalue[color] < i) {
        analogWrite(ledPIN[color], i);
        delay(timestep);
      }
    }
  }
  for(int color = RED; color <= BLUE; color++) {
    ledvalue[color] = 255; 
  }
}

void alldown() {
  int maxrg = max(ledvalue[RED], ledvalue[GREEN]);
  int maxrgb = max(maxrg, ledvalue[BLUE]);
  for(int i = maxrgb; i >= 0; i--){
    for(int color = RED; color <= BLUE; color++){
      if (ledvalue[color] > i) {
        analogWrite(ledPIN[color], i);
        delay(timestep);
      }
    }
  }
  for(int color = RED; color <= BLUE; color++) {
    ledvalue[color] = 0; 
  }
}

void shine() {
    for(int color = RED; color <= BLUE; color++){
        analogWrite(ledPIN[color], 255);
        ledvalue[color] = 255; 
    }
}

void dark() {
    for(int color = RED; color <= BLUE; color++){
        analogWrite(ledPIN[color], 0);
        ledvalue[color] = 0; 
    }
}

void flash() {
    if (ledvalue[RED] + ledvalue[GREEN] + ledvalue[BLUE] == 765) {
      dark();
    }
    else {
      shine();
    }
}

void printCV() {
  Serial.print("R=");
  Serial.print(ledvalue[RED]);
  Serial.print(" G=");
  Serial.print(ledvalue[GREEN]);
  Serial.print(" B=");
  Serial.println(ledvalue[BLUE]);
//  Serial.println(" ");
}

If you do nothing else but remove the rgb LED, does the problem disappear? Perhaps optical interference is causing it. Worth eliminating that from your enquiries.

What do you mean by "RGB receiver"? Please post link.

Sorry. I meant IR-receiver of course. Edited original post. Will try your suggestion and come back.

Sorry, no improvement if RGB LED removed or if room lighting switched off. Behaviour remains.

What I suggest is:

Upload up the example sketch File-->Examples-->IRremote-->IRrecvDemo. Check you can receive all the codes you want to use. Then edit the example sketch and put an analogWrite(9, 128); into setup(). Upload the modified sketch and test again. If your theory is correct, the modified sketch should receive only garbled codes. But if it does still work, then the problem is in your sketch (which is good news, because it should be fixable).

Something else to check: what model of ir receiver are you using and how is it connected? The one I have needs 2 external resistors and a capacitor to work correctly, for example.