TransWikia.com

Unable to use IR receiver and motor shield together

Electrical Engineering Asked on November 14, 2021

#include <IRremote.h>
#include <AFMotor.h>
AF_DCMotor motor(1);


int RECV_PIN = 14;//The definition of the infrared receiver pin 11
IRrecv irrecv(RECV_PIN);
decode_results results;

void setup()
{
  Serial.begin(9600); //Open serial 
  irrecv.enableIRIn(); // Initialization infrared receiver
  motor.setSpeed(255);
  motor.run(RELEASE);
  Serial.println("start");
  motor.run(FORWARD);
  delay(1000);
} 

void loop() 
{
  if (irrecv.decode(&results)) {
    if(results.value==0x3D9AE3F7)
    {

      motor.run(FORWARD);
      delay(2000);    
    }
    else if(results.value==0x1BC0157B)
    {
      motor.run(RELEASE);
      motor.run(BACKWARD);    
    }
    Serial.println(results.value, HEX);//Wrap output in hex receive code
    Serial.println();//For ease of viewing the output to add a blank line
    irrecv.resume(); //Receiving the next value
  }
}

The motor shield is not working when I use an IR receiver.

I tried connecting the IR receiver to different analog pins but it didn’t work. I guess it’s due to some error in my code but I am unable to figure it out.

2 Answers

If you use the AFmotor library (adafruit shield) with IRremote, there is a conflict on TIMER2 (pin 3). If you do not use pin 9 for PWM issues in AFmotor, you can modify IRremoteInt.h in IRremote library by uncommenting the TIMER1 line instead of TIMER2 like below

... 
// Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, etc
#else   
#define IR_USE_TIMER1   // tx = pin 9  <--  uncomment
//#define IR_USE_TIMER2     // tx = pin 3 <-- comment
...

On my arduino UNO R3 it works well. With TIMER2, motors 1 and 2 where inactive. With TIMER1 all motors work.

Hope its helpfull for someone else

Answered by PhilFr94 on November 14, 2021

Is this the infrared receiver library you are using?

Compare the following code snippet from the IR receiver example they give with your code. Perhaps that's the issue?

#include <IRremote.h>

#if defined(ESP32)
int IR_RECEIVE_PIN = 15;
#else
int IR_RECEIVE_PIN = 11;
#endif
IRrecv irrecv(IR_RECEIVE_PIN);

And is this the motor library you are using?

README.txt

This library is old and deprecated - and the hardware disconinued years ago. V2 of the shield uses i2c only and works with anything that has I2C support (e.g. all arduinos) without endless incompatibilities and porting requirements! :)
-> https://www.adafruit.com/products/1438

From the motor example they give, the motor is gradually slowed down before reversing it; rather than trying to instantly reverse at full speed.

Modified Controller

I've modified the controller a little:

  1. to slow down the motor before changing direction.
  2. to only command a new direction when the command changes the direction, i.e. it will ignore successive FORWARD commands or successive BACKWARD commands.
  3. to give more feedback about what it's doing.
#include <IRremote.h>
#include <AFMotor.h>
AF_DCMotor motor(1);


int RECV_PIN = 14;//The definition of the infrared receiver pin 11
IRrecv irrecv(RECV_PIN);
decode_results results;
decode_results old_results;        // ADDED to compare with previous results.

void setup()
{
  Serial.begin(9600); //Open serial
  irrecv.enableIRIn(); // Initialization infrared receiver
  motor.setSpeed(255);
  motor.run(RELEASE);
  Serial.println("Idle");                   // CHANGED to Idle.
  delay(1000);
}

void loop()
{
  if (irrecv.decode(&results))
  {
    if (results.value != old_results.value) // ADDED to test for change of command.
    {
      if(results.value==0x3D9AE3F7)
      {
        old_results = results;              // ADDED to remember the command for next time.
        Serial.println("Slowing");          // ADDED to give feedback.
        motor.run(RELEASE);                 // ADDED to remove power from motor.
        delay(2000);                        // ADDED to let motor slow down before changing direction.
        Serial.println("Forward");          // ADDED to give feedback.
        motor.run(FORWARD);
      }
      else if(results.value==0x1BC0157B)
      {
        old_results = results;              // ADDED to remember the command for next time.
        Serial.println("Slowing");          // ADDED to give feedback.
        motor.run(RELEASE);                 // ADDED to remove power from motor.
        delay(2000);                        // ADDED to let motor slow down before changing direction.
        Serial.println("Backward");         // ADDED to give feedback.
        motor.run(FORWARD);
      }
    }
    Serial.println(results.value, HEX);//Wrap output in hex receive code
    Serial.println();//For ease of viewing the output to add a blank line
    irrecv.resume(); //Receiving the next value
  }
}

Possible Timer1 and Timer2 Conflict

I've been digging through the source code of the libraries and found that they both use Timer1 and Timer2 for some Arduinos. It may not be possible to use both libraries together with your Arduino. Perhaps you could modify the libary source code so that the IR Receiver and the motor use separate timers.

esp32.cpp

void IRrecv::enableIRIn() {
// Interrupt Service Routine - Fires every 50uS
    // ESP32 has a proper API to setup timers, no weird chip macros needed
    // simply call the readable API versions :)
    // 3 timers, choose #1, 80 divider nanosecond precision, 1 to count up
    timer = timerBegin(1, 80, 1);
    timerAttachInterrupt(timer, &IRTimer, 1);
    // every 50ns, autoreload = true
    timerAlarmWrite(timer, 50, true);
    timerAlarmEnable(timer);

irRecv.cpp

void IRrecv::enableIRIn() {
// Interrupt Service Routine - Fires every 50uS
    cli();
    // Setup pulse clock timer interrupt
    // Prescale /8 (16M/8 = 0.5 microseconds per tick)
    // Therefore, the timer interval can range from 0.5 to 128 microseconds
    // Depending on the reset value (255 to 0)
    TIMER_CONFIG_NORMAL();

    // Timer2 Overflow Interrupt Enable
    TIMER_ENABLE_INTR;

    TIMER_RESET;

    sei();

AFMotor.cpp

#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    // on arduino mega, pin 11 is now PB5 (OC1A)
    OCR1A = s;

Answered by tim on November 14, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP