Go Down

Topic: IRRemote library conflicts with tone() function (Read 12315 times) previous topic - next topic

Automative

Hi,

I'm currently working on a project that combines an IR remote and a piezo sounder to play confirmation sounds.

To produce a beep on the sounder I use the command tone();

When I integrated this in my main sketch, when I got the right sounds. Tried to compile it and got the following error:

core.a(Tone.cpp.o): In function `__vector_13':
C:\Users\Vincent\Desktop\ARDUINO\arduino-1.0.1\hardware\arduino\cores\arduino/Tone.cpp:523: multiple definition of `__vector_13'
IRremote\IRremote.cpp.o:C:\Users\Vincent\Desktop\ARDUINO\arduino-1.0.1\libraries\IRremote/IRremote.cpp:311: first defined here
c:/users/vincent/desktop/arduino/arduino-1.0.1/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/bin/ld.exe: Disabling relaxation: it will not work with multiple definitions

The IRremote.cpp files is attached

An example of a tone function I'll be using:

Code: [Select]
void PlayTone1() {
  tone(PiezoSounderPin, 3000, 8);
  delay(10);
  noTone(PiezoSounderPin);
}


Hope someone can help me with this... Thanks in advance

Automative

With a bit more scouting work i figured it out myself.

Apperently the function tone() uses timer 2 wich, by default, the IRremote also uses when using a ATmega2560 chip.

In the file IRremoteInt.h, you can define wich timer to use. Everything works now!

vicvegax



agcastaldin

worked good to me too. i used timer 5 pin 46

Jamsel

Hi Karma
I am having the same trouble as you with the tone() not working with IR remote. Your comments look really useful except I don't know how to change an existing library. Could you please share your adapted library, with another pin (other than pin2) activated for the IR timer? Please that would be most useful.

Otherwise any advice on changing an existing library? When I try to open an .h file it does not allow it. So not able to get into the library to select the correct pin.

nunesdi01

Hi Jamsel, I just solved the problem too.

You need to go on your Arduino folder --> Libraries --> IR folder
then you need to find the IRremoteInt.h file. You can open with wordpad.
Try to find the part that says

"
// Define which timer to use
//
// Uncomment the timer you wish to use on your board.
// If you are using another library which uses timer2, you have options to
//   switch IRremote to use a different timer.

..."

You need to find the line that has your Arduino type, mine is the UNO so I used this one:

// Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, Nano, etc
#else
   //#define IR_USE_TIMER1    //tx = pin 9
   #define IR_USE_TIMER2     tx = pin 3

Now you put the "//" in the second line and remove them from the first line. Will look like that:

// Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, Nano, etc
#else
   #define IR_USE_TIMER1    tx = pin 9
   //#define IR_USE_TIMER2    // tx = pin 3

 Save the changes and your program should work great.

nunesdi01

Automotive thank you so much for your help!

JonRon

Hi,

I'm quite new to Arduino things and tinker occasionally when I have time. Recently I followed a tutorial on using old TV remotes. http://goo.gl/62c1d8 and got as far as getting an LED to dim with the remote.

I thought I would then modify the sketch to include a bleep (using a piezo speaker) each time a button on the remote was pushed using tone(). No luck, got a compiler upload error, found this thread and did the mod to the IRremoteInt.h detailed above by nunesdi01. Uploaded to my Uno OK but then nothing worked including the dimming led.

LED dimming sketch:

Code: [Select]
#include <IRremote.h>
#define irPin 11
IRrecv irrecv(irPin);
decode_results results;

int ledPin = 9;
int brightness = 10;

void setup() {
   Serial.begin(9600);
   irrecv.enableIRIn();

   pinMode(ledPin, OUTPUT);
}

void loop() {
   if (irrecv.decode(&results)) {

       switch (results.value) {
         case 0x1000405:
            if(brightness < 255) {brightness = brightness+5;}
            analogWrite(ledPin, brightness);
            Serial.println(brightness);
            
            break;

         case 0x1008485:
            if(brightness > 0) {brightness = brightness-5;}
            analogWrite(ledPin, brightness);
            Serial.println(brightness);
            
            break;

         case 0x100BCBD:
            Serial.println("OFF");
            analogWrite(ledPin, 0);
            brightness = 20;
            
            break;
         }
   irrecv.resume();
   }
}


LED dimming sketch with tone() added to one button

Code: [Select]
#include <IRremote.h>
#define irPin 11
IRrecv irrecv(irPin);
decode_results results;

int ledPin = 9;
int brightness = 10;
int buzzer = 8;



void setup() {
   Serial.begin(9600);
   irrecv.enableIRIn();

   pinMode(ledPin, OUTPUT);
   pinMode(buzzer, OUTPUT);
  
}

void loop() {
   if (irrecv.decode(&results)) {

       switch (results.value) {
         case 0x1000405:
            if(brightness < 255) {brightness = brightness+5;}
            analogWrite(ledPin, brightness);
            Serial.println(brightness);
            tone(buzzer, 1000); // Send 1KHz sound signal...
            delay(1000);        // ...for 1 sec
            noTone(buzzer);  
                    
            break;

         case 0x1008485:
            if(brightness > 0) {brightness = brightness-5;}
            analogWrite(ledPin, brightness);
            Serial.println(brightness);
            
            break;

         case 0x100BCBD:
            Serial.println("OFF");
            analogWrite(ledPin, 0);
            brightness = 20;
            
            break;
         }
   irrecv.resume();
   }
}


I know I've done something wrong...can someone help me please?

Thanks

Gerri1981

can somen sent a link for the <IRremoteINT.h> please

DangerouslyExplosive

In the newer version of the IRremote library, the timer control is moved to the file boarddefs.h, which deals directly with board-specific functions. You will no longer be able to find the timer pin control in the other files if you have the new version.


kehayles

#12
May 09, 2018, 06:29 am Last Edit: May 09, 2018, 07:05 am by kehayles
Hi, I changed the library as described above, switching to timer 1 rather than 2, but now I am getting a servo error that I wasn't getting before. Previously I was able to control my robot  using the irremote.h library as well as the servo.h library. After changing to timer 1, I now am getting what's below. Can anyone help? I read the servo.h library and there is some instructions about the timers, but I don't understand what I should change. My code follows the error. Thank you!

/tmp/992817512/build/libraries/servo_1_1_2/avr/Servo.cpp.o (symbol from plugin): In function `ServoCount':

(.text+0x0): multiple definition of `__vector_11'

/tmp/992817512/build/libraries/IRremote-2.2.3/IRremote.cpp.o (symbol from plugin):(.text+0x0): first defined here

collect2: error: ld returned 1 exit status

exit status 1



// IRremote-2.2.3 - Version: Latest
#include <ir_Lego_PF_BitStreamEncoder.h>
#include <boarddefs.h>
#include <IRremoteInt.h>
#include <IRremote.h>

/*
 

 The IR sensor's pins are attached to Arduino as so:
 Pin 1 to Vout (pin 2 on Arduino)
 Pin 2 to GND
 Pin 3 to Vcc (+5v from Arduino)

*/

#include <Servo.h>

int IRpin = 4;  // pin for the IR sensor
int buzzerPin = 7; //pin for buzzer
int LED = 13;    // LED pin
int servoLeftpin = 9;
int servoRightpin = 12;
IRrecv irrecv(IRpin);
decode_results results;
Servo servoLeft;          // Define left servo
Servo servoRight;         // Define right servo

boolean LEDon = true; // initializing LEDon as true

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
  pinMode(LED, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
  servoLeft.attach(servoLeftpin);   // Set left servo to digital pin
  servoRight.attach(servoRightpin); // Set right servo to digital pin
}

void loop()
{
   
  if (irrecv.decode(&results))
    {
     
      irrecv.resume();   // Receive the next value
    }
 
  switch(results.value)
 {

  case 144:
  forward();
  reAttach();
  break;
 
  case 2192:
  reverse();
  reAttach();
  break;
 
  case 3216:
  turnLeft();
  reAttach();
  break;
 
  case 1168:
  turnRight();
  reAttach();
  break;
 
  case 656:
  stopRobot();
  break;
 
  case 2064:
  slowForward();
  reAttach();
  break;
 
  case 3088:
  slowTurnLeft();
  reAttach();
  break;
 
  case 2576:
  slowTurnRight();
  reAttach();
  break;
 
  case 3600:
  slowReverse();
  reAttach();
  break;
 
  case 2704:
  stopRobot();
  break;
 
 // case 16:
 // sound();
 // break;
 
  default:
  digitalWrite(LED, LOW);
 
  }
}
  // Motion routines for forward, reverse, turns, and stop
void forward() {
  servoLeft.write(0);
  servoRight.write(180);
}

void reverse() {
  servoLeft.write(180);
  servoRight.write(0);
}

void turnRight() {
  servoLeft.write(180);
  servoRight.write(180);
}

void turnLeft() {
  servoLeft.write(0);
  servoRight.write(0);
}

void stopRobot() {
  servoLeft.detach();
  servoRight.detach();
}

void slowForward() {
  servoLeft.write(80);
  servoRight.write(105);
}

void slowReverse() {
  servoLeft.write(105);
  servoRight.write(80);
}

void slowTurnRight() {
  servoLeft.write(105);
  servoRight.write(105);
}

void slowTurnLeft() {
  servoLeft.write(80);
  servoRight.write(80);
}

void reAttach() {
  if(!servoLeft.attached())
    servoLeft.attach(servoLeftpin);
  if(!servoRight.attached())
    servoRight.attach(servoRightpin);
}   
   
//void sound() {
 // tone(12,330,500);
 // delay(500);
  //tone(12,294,500);
  //delay(500);
  //tone(12,262,500);
  //delay(500);
  //tone(12,294,500);
  //delay(500);
  //tone(12,330,500);
  //delay(500);
  //tone(12,330,500);
  //delay(500);
  //tone(12,330,1000);
  //delay(1500);   
//}



sterretje

You have a problem ;) There are limited resources on a microcontroller. Get an Arduino that has more timers (if you currently use an Uno/Nano/Mini, 32U4 based or a Mega provide extra timers).

Or use something else instead of the tone library; switching a pin on and off at a certain 'rate' gives you a tone. An extremely simple example
Code: [Select]
void loop()
{
  digitalWrite(tonePin, LOW);
  delay(10);
  digitalWrite(tonePin, HIGH);
  delay(10);
}

gives a tone of roughly 50 Hz. There are limitations to this (even if you use a millis / micros based approach) so your mileage will vary ;)
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

kehayles

Thank you so much for your reply. Can you explain why this won't work? How can I tell which timers are being used by the servos? It looks like I can only use Timer 1 or 2 for the Tone function on Uno (which I am using). How many timers are there? Any way to specify the servos use other timers? So this means I cannot have a TV-remote controlled robot that has two servo wheels using the Uno and have it play a little tune using Tone? If I use the Mega, will the timers be allocated appropriately or do I need to alter the library? I'd like to know a little more info because I am leading a group of kids on this and want to explain to them. Don't worry, I am not charging these kids for this  ;) . I will try implementing your other method for playing a tune. How do you create different frequencies with it? Do you think I could play a simple tune ok?
Thanks again.

Go Up