IRRemote conflict with analogueWrite

Hi all,

My IR reciever works well until I call one of the "analogWrite" commands with anything less than 255, after that the IR code nolonger works and all commands come through as protocol UNKNOWN.

I used the SimpleReciever code from the IRRemote library, and used an L298N motor controller with an external 12v power supply. I'll try and find out how to show a cuircit diagram, but I am reasonably comfortable the power is correct and there's a shared earth. The Arduino Uno R3 is powered by USB.

If I comment out the analogueWrite commands, the code continues to receive and process good IR commands. If I introduce the analogueWrite commands and call one with say analogueWrite(235), following that all the IR commands just come through as protocol UNKNOWN.

Any guidence is greatly received. Code is below.


#define DECODE_NEC          // Includes Apple and Onkyo

#include <Arduino.h>
#include <IRremote.hpp>

#define enA 11
#define in1 12
#define in2 13
#define enB 6
#define in3 7
#define in4 8
#define irPin 9

int wheelPower = 255;
int wheelDuration = 200;
int turnDuration = 20;

void setup() {
    Serial.begin(9600);
    // Just to know which program is running on my Arduino
    Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));

    // Start the receiver and if not 3. parameter specified, take LED_BUILTIN pin from the internal boards definition as default feedback LED
    IrReceiver.begin(irPin, ENABLE_LED_FEEDBACK);

    Serial.print(F("Ready to receive IR signals of protocols: "));
    printActiveIRProtocols(&Serial);
    pinMode(enA, OUTPUT);
    pinMode(enB, OUTPUT);
    pinMode(in1, OUTPUT);
    pinMode(in2, OUTPUT);
    pinMode(in3, OUTPUT);
    pinMode(in4, OUTPUT);
    setDirection(0); //default to forward
}

// Set the pins for direction
// 0=forward, 1=backwards
void setDirection(int direction){
  if(direction == 0){
    //forward
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
    digitalWrite(in3, LOW);
    digitalWrite(in4, HIGH);
  }else{
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);
    digitalWrite(in3, HIGH);
    digitalWrite(in4, LOW);
  }
}

void loop() {

    if (IrReceiver.decode()) {

        // Print a short summary of received data
        //IrReceiver.printIRResultShort(&Serial);
        //IrReceiver.printIRSendUsage(&Serial);
        if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
            Serial.println(F("Received noise or an unknown (or not yet enabled) protocol"));
            // We have an unknown protocol here, print more info
            IrReceiver.printIRResultRawFormatted(&Serial, true);
        }
        //Serial.println();

        /*
         * !!!Important!!! Enable receiving of the next value,
         * since receiving has stopped after the end of the current received data packet.
         */
        IrReceiver.resume(); // Enable receiving of the next value

        irCommand = IrReceiver.decodedIRData.command;
        /*
         * Finally, check the received data and perform actions according to the received command
         */
        if (irCommand == 0x46) {
          //Serial.println("received vol+");
          Serial.println("Drive Forward");
          setDirection(0);
          analogWrite(enA, wheelPower);
          analogWrite(enB, wheelPower);
          delay(300);
          analogWrite(enA, 0);
          analogWrite(enB, 0); 
          
      } else if (irCommand == 0x15) {
          //Serial.println("received vol-");
          Serial.println("Drive Backward");
          setDirection(1);
          analogWrite(enA, wheelPower);
          analogWrite(enB, wheelPower);
          delay(300);
          analogWrite(enA, 0);
          analogWrite(enB, 0); 
        
      }else if (irCommand == 0x44) {
          //Serial.println("received L");
          Serial.println("Drive LEFT");
          analogWrite(enA, 0);
          analogWrite(enB, 0); 
      }else if (irCommand == 0x43) {
          //Serial.println("received R");
          Serial.println("Drive RIGHT");          
      }else if (irCommand == 0x18) {
          Serial.println("received 2");
          wheelPower -=10;
          if(wheelPower < 3){
             wheelPower = 3;
          }
          Serial.print("Power");
          Serial.println(wheelPower);
      }else if (irCommand == 0x5E) {
          Serial.println("received 3");
          wheelPower +=10;
          if(wheelPower > 255){
            wheelPower=255;
          }
          Serial.print("Power");
          Serial.println(wheelPower);
      }
    }
}

You most likely have interference when using PWM that prevents the IR receiver from working properly.

Both the PWM and IR receiver use timers and act like they own them. You need to figure out if there is some combination where they play nice together.

Thank you, that makes sense.
I can remove delay () by moving to a state machine (which is what the original code was). Which could help. I'm not sure how else to proceed though :frowning:
I'd have thought this was a pretty common combination for newbies.

Try

The ENA and ENB on pins 9 and 10 or 5 and 6.



// Start the receiver and if not 3. parameter specified, take LED_BUILTIN pin from the internal boards definition as default feedback LED
    IrReceiver.begin(irPin, ENABLE_LED_FEEDBACK);

You are using D13 already.

Thank you, I'll give them a go. I'm confident I've had a crack at trying all the different pwm pins over the last few days, but can't be certain so I'll try again.

I've seen references to avoid a handful of pins (3 due to the interrupts, 9 and 10 get taken by the servo lib I use elsewhere)

ENABLE_LED_FEEDBACK

Pin 13 is being use here as IR signal feedback.

But you have #define in2 13 :woozy_face:

Ahh thank you @LarryD I missed that in your prior message. I've moved all the pins so many times now. I'll give that a go.

Many thanks to @oldcurmudgeon, @flashko and @LarryD my problem is now solved.

I believe it was most likely down to a timeer clash, but the problem with pin 13 wasn't helping.

I added more debug and saw that the IR output said it was swapping protocols when I called the analogueWrite with something lower than 255.

I change the IR library to use the "TinyIRReceiver.hpp" instead. I used the Arduino IDE to give me the example code then tailored it for my needs. This library uses a callback "handleReceivedTinyIRData" to manage the IR processing.

I've pasted the working test code below for reference.

#include <Arduino.h>
#define IR_INPUT_PIN 2
#include "TinyIRReceiver.hpp"

#define enA 11
#define in1 12
#define in2 8
#define enB 6
#define in3 7
#define in4 4

/*
 * Helper macro for getting a macro definition as string
 */
#if !defined(STR_HELPER)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif

int wheelPower = 255;
int wheelDuration = 200;
int turnDuration = 20;

volatile struct TinyIRReceiverCallbackDataStruct sCallbackData;

void setup() {
  Serial.begin(9600);
  Serial.println(F("START " __FILE__ " from " __DATE__));
  if(!initPCIInterruptForTinyReceiver()){
      Serial.println(F("No interrupt available for pin " STR(IR_INPUT_PIN))); // optimized out by the compiler, if not required :-)
      
  }
  Serial.println(F("Ready to receive NEC IR signals at pin " STR(IR_INPUT_PIN)));
  
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  setDirection(0); //default to forward
}

// Set the pins for direction
// 0=forward, 1=backwards
void setDirection(int direction){
  if(direction == 0){
    //forward
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
    digitalWrite(in3, LOW);
    digitalWrite(in4, HIGH);
  }else{
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);
    digitalWrite(in3, HIGH);
    digitalWrite(in4, LOW);
  }
}

void loop() {
   //main IR code is running from an intterupt below
}

/*
 * This is the function is called if a complete command was received
 * It runs in an ISR context with interrupts enabled, so functions like delay() etc. are working here
 */
void handleReceivedTinyIRData(uint16_t aAddress, uint8_t aCommand, bool isRepeat){
  Serial.print(F("A=0x"));
  Serial.print(aAddress, HEX);
  Serial.print(F(" C=0x"));
  Serial.print(aCommand, HEX);
  Serial.print(F(" R="));
  Serial.print(isRepeat);
  Serial.println();

  uint16_t irCommand = aCommand;
  if (irCommand == 0x46) {
        //Serial.println("received vol+");
        Serial.println("Drive Forward");
        setDirection(0);
        analogWrite(enA, wheelPower);
        analogWrite(enB, wheelPower);
        delay(wheelDuration);
        analogWrite(enA, 0);
        analogWrite(enB, 0);  
    } else if (irCommand == 0x15) {
        //Serial.println("received vol-");
        Serial.println("Drive Backward");
        setDirection(1);
        analogWrite(enA, wheelPower);
        analogWrite(enB, wheelPower);
        delay(wheelPower);
        analogWrite(enA, 0);
        analogWrite(enB, 0);  
    }else if (irCommand == 0x44) {
        //Serial.println("received L");
        Serial.println("Drive LEFT");
        analogWrite(enA, 0);
        analogWrite(enB, 0); 
    }else if (irCommand == 0x43) {
        //Serial.println("received R");
        Serial.println("Drive RIGHT");          
    }else if (irCommand == 0x18) {
        Serial.println("received 2");
        wheelPower -=10;
        if(wheelPower < 3){
           wheelPower = 3;
        }
        Serial.print("Power");
        Serial.println(wheelPower);
    }else if (irCommand == 0x5E) {
        Serial.println("received 3");
        wheelPower +=10;
        if(wheelPower > 255){
          wheelPower=255;
        }
        Serial.print("Power");
        Serial.println(wheelPower);
    }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.