Servo.h conflicting with Tone.h

Hi,

I am using an AtMega328PU with two piezo modules to create some sounds and a servo.
So far I did not use the piezos with the main project, only the servo and some inputs.
Everything worked fine.
And I did the programing of the piezo modules and tested it in a different project.
Now I am trying to merge the two projects together, but I get an error message:

libraries/Tone/Tone.cpp.o: In function __vector_11': /home/agoston/Arduino/libraries/Tone/Tone.cpp:422: multiple definition of __vector_11'
libraries/Servo/avr/Servo.cpp.o:/opt/arduino-1.6.8/libraries/Servo/src/avr/Servo.cpp:81: first defined here
collect2: error: ld returned 1 exit status
exit status 1
Error compiling for board Arduino/Genuino Uno.

I have an idea that it is because of the timers.
I know that the Atmega 328 has three timers, one for the micros() and two "free" to use. (Or am I wrong?)
And the Tone library uses as much timers as much Tone objects I create, in my case two.
And the Servo library also uses one, and the Timer0 for the micros.
As I saw in the Tone lib, it can use also Timer0, but I am not sure if it may cause any problems...
So I would need 4 timers at all.
But I never use the Servo and the tone at the same time,

I use them like this:

I attach the servo
I send a position to servo
I detach the servo (to prevent clicking)

Then I play some music

Then I attach the servo
I send a position to servo
I detach the servo.

So at the same time I never use all timers.
I wonder If there is a way to modify the libraries to get it all working.

Thanks in advance for any help.

You may want to try the ServoTimer2 library - my guess is that the Tone library and the Servo library are both trying to use Timer1

...R

If you don’t want to change library here is a quick and dirty hack if you do not plan to do anything at all while you play music: you could just create the sound yourself manually triggering the pins at approximately the right frequency

for (unsigned long i = 0; i < toneDuration * 1000UL; i += tonePeriod) {
    digitalWrite(tonePin, HIGH);
    delayMicroseconds(toneHalfPeriod); // toneHalfPeriod is tonePeriod / 2
    digitalWrite(tonePin, LOW);
    delayMicroseconds(toneHalfPeriod);
}

Hi,
Thanks for the answers.
The Tone library uses in this case both TImer1 and Timer2, because I use two Tone objects to create two tones at the same time.

J-M-L: I like your solution, but not everything is clear for me. What is tonePeriod in your code? Is that the frequency?
And what is 1000UL?
And I am afraid this solution is not gonna work for me, because I need to produce two notes with different frequencies at the same time.
So I am afraid I have to modify one of the libraries.

Does anyone have any idea that could help me? :slight_smile:
Thanks in advance :slight_smile:

dagoston93:
Hi,
Thanks for the answers.
The Tone library uses in this case both TImer1 and Timer2, because I use two Tone objects to create two tones at the same time.

J-M-L: I like your solution, but not everything is clear for me. What is tonePeriod in your code? Is that the frequency?
And what is 1000UL?
And I am afraid this solution is not gonna work for me, because I need to produce two notes with different frequencies at the same time.
So I am afraid I have to modify one of the libraries.

Does anyone have any idea that could help me? :slight_smile:
Thanks in advance :slight_smile:

tonePeriod is the period of the tone, so the inverse of the frequency. If frequency is 500 Hz (i.e. 500 times per second) then period is 1 / 500 = 2 ms

1000UL means the number 1000 as an Unsigned Long. this is to tell the compiler "please don't use signed int but really unsigned long in the multiplication (basic integer math would overflow very quickly)".

And I am afraid this solution is not gonna work for me, because I need to produce two notes with different frequencies at the same time.
So I am afraid I have to modify one of the libraries.

Well you can just have a while loop and be smart about what you do in terms of on off for the PINs. What are the 2 frequencies you have in mind?

dagoston93:
The Tone library uses in this case both TImer1 and Timer2,

I believe the Mega has more Hardware Timers

...R

Hi,
J-M-L,
I am using frequencies between 96Hz, to 4kHz, to create some music.
So any combination between this range can be used in my case.
I need to use two different tones at a time, but for the same length.

So I am thinking to write a function which first
check micros, when the note has started to play
then saves when it should end
then a while loop repeats until the micros is smaller than the time it should end.
within the loop, I can check the modulus of (startTime+micros) / period.
If the modulus is smaller than the half of the period the pin should be HIGH else LOW.
And the same with the other note.

Do I get it good, or I misunderstood someting?

Robin2: I cannot use an Arduino Mega in this project becuase I need to use the existing hardware I already have..,

Hi,
I found a library, called TimerFreeTone, available at this link:

TimerFreeTone

It uses a method very much like you described me yesterday.

I did some modifications the way I described in the above reply.
But it is only half success.
This way the voice gets ‘unclear’, noisy.
Like if the speaker was blocked or I dont know how to describe, but its not clean as it was before, or with the Tone library.
Maybe my timing is not good enough?

The modified TimerFreeTone.h;

#ifndef TimerFreeTone_h
	#define TimerFreeTone_h

  	#if defined(ARDUINO) && ARDUINO >= 100
    	#include <Arduino.h>
  	#else
    	#include <WProgram.h>
		#include <pins_arduino.h>
	#endif
  
	void TimerFreeTone(uint8_t pin1, uint8_t pin2, unsigned long frequency1, unsigned long frequency2, unsigned int duration, uint8_t volume = 10);
#endif

And the .cpp file:

#include "TimerFreeTone2.h"




void TimerFreeTone(uint8_t pin1, uint8_t pin2,unsigned long frequency1, unsigned long frequency2, unsigned int duration, uint8_t volume) {
	if (frequency1 == 0 || frequency2 == 0 || volume == 0) return; // If frequency or volume are zero, quit to avoid divide by zero error.
	frequency1 = 1000000 / frequency1;
	frequency2 = 1000000 / frequency2;                                // Calculate the square wave length (in microseconds).
	uint32_t duty1 = frequency1 / 2; 				// Calculate the duty cycle.
	uint32_t duty2 = frequency2 / 2;  
	uint32_t noteEnd = millis() + duration;                       // Calculate when the note will end.
	
	bool pin1CurrentState = false;					//To save the current state of each pin
	bool pin2CurrentState = false;

	uint32_t noteStart = micros();

#ifdef __AVR__
	uint8_t pinBit1 = digitalPinToBitMask(pin1);
	uint8_t pinBit2 = digitalPinToBitMask(pin2);                                  // Get the bitmask for the pin.
	uint8_t *pinOutput1 = (uint8_t *) portOutputRegister(digitalPinToPort(pin1));
	uint8_t *pinOutput2 = (uint8_t *) portOutputRegister(digitalPinToPort(pin2)); // Get the port register for the pin.
	uint8_t *portMode1 = (uint8_t *) portModeRegister(digitalPinToPort(pin1));    // Get the port mode register for the pin.
	uint8_t *portMode2 = (uint8_t *) portModeRegister(digitalPinToPort(pin2));    // Get the port mode register for the pin.	
	*portMode1 |= pinBit1;
	*portMode2 |= pinBit2;                                                        // Set pin to output mode.
#else
	pinMode(pin1, OUTPUT);  
	pinMode(pin2, OUTPUT);                                                     // Set pin to output mode.
#endif

	while(millis() <= noteEnd) { // Loop for the duration.
		if( ((noteStart + micros()) % frequency1) <= duty1 && !pin1CurrentState)
		{
			if(!pin1CurrentState)
			{
				#ifdef __AVR__
				*pinOutput1 |= pinBit1;    // Set pin high.
				#else
				digitalWrite(pin1,HIGH);
				#endif

				pin1CurrentState = true; //Save the state of the pin
			}
			
			
		}else{
			if(pin1CurrentState)
			{
				#ifdef __AVR__
				*pinOutput1 &= ~pinBit1;
				#else
				digitalWrite(pin1,LOW);
				#endif
					
				pin1CurrentState = false;

			}
		}

		if( ((noteStart + micros()) % frequency2) <= duty2 && !pin2CurrentState)
		{
			if(!pin2CurrentState)
			{
				#ifdef __AVR__
				*pinOutput2 |= pinBit2;    // Set pin high.
				#else
				digitalWrite(pin2,HIGH);
				#endif

				pin2CurrentState = true; //Save the state of the pin
			}
			
			
		}else{
			if(pin2CurrentState)
			{
				#ifdef __AVR__
				*pinOutput2 &= ~pinBit1;
				#else
				digitalWrite(pin2,LOW);
				#endif
					
				pin2CurrentState = false;

			}
		}

	}
}

Tanks in advance for any help.

You should probably read micros () only once instead of calling it for frequency1 and 2, because micos() will be different so you will have pins a bit out of phase which is also further delayed by all the computation between toggling pin1 and getting to toggle pin2...

Not sure this can be heard or not though. Do you have an oscilloscope? Would be interesting to check how badly the signal gets out of sync between the 2 pins? I can't try this out now.

If this is the pb one way to deal with it and get the pins to change in closer range would be to record what to do for the pins and do it all without complex math at then end of the while with a switch case (nothing, set pin1 don't touch pin2, set pin2 don't touch pin1, set pin1 and set pin2, set pin1 clear pin2, clear pin1 set pin2, clear pin 1 and clear pin2, clear pin1 don't touch pin2, clear pin2 don't touch pin1) this way the port operations are really close and alignment to timing would be better, assuming of course that all the math is compatible with the half period your try to get for the highest frequency of the 2.