Go Down

Topic: Can't use "tone" and SoftPWM at the same time (Read 587 times) previous topic - next topic

schmidtbag

So I'm trying to use a code (on a mega1280) that utilizes "tone" and the SoftPWM library simultaneously.  Both work just fine, but I can't include both tone and SoftPWM in the same code at the same time.  If I do both I get an error like this:
Code: [Select]
core.a(Tone.cpp.o): In function `__vector_13': multiple definition of `__vector_13' SoftPWM/SoftPWM.cpp.o:/arduino/libraries/SoftPWM/SoftPWM.cpp:212: first defined here collect2: ld returned 1 exit status

Any suggestions?  I have a feeling this has something to do with the MC's limited amount of timers but I'm not sure what to do about it.  Currently I have a script that manually plays the tone using delayMicroseconds, but this drastically slows down the entire program - I'd like to be able to run other commands at the same time.  I don't need a tone to play in more than 1 pin at a time (although that would be nice).

Nick Gammon

It's possible to generate pulses without using interrupts.

I have example code on my interrupts page:

http://www.gammon.com.au/interrupts

For example (for the Atmega328):

Code: [Select]
const byte LED = 9;

void setup() {
  pinMode (LED, OUTPUT);
 
  // set up Timer 1
  TCCR1A = _BV (COM1A0);  // toggle OC1A on Compare Match
  TCCR1B = _BV(WGM12) | _BV(CS10) | _BV (CS12);   // CTC, scale to clock / 1024
  OCR1A =  4999;       // compare A register value (5000 * clock speed / 1024)
}  // end of setup

void loop() { }


That actually pulses pin 9 purely in hardware. Choosing a suitable counter and prescaler and you could get into audio frequencies. To play a tune (if that is what you want) you would need to reconfigure the counter from time to time, but you can still have it doing its stuff in the background.

BTW "__vector_13" is a reference to the interrupt used by the Tone library.
http://www.gammon.com.au/electronics

schmidtbag

So, if I put a piezo buzzer on that, it would create a tone of 5000Hz?

Quote
Choosing a suitable counter and prescaler and you could get into audio frequencies. To play a tune (if that is what you want) you would need to reconfigure the counter from time to time, but you can still have it doing its stuff in the background.


Are you saying that I would have to change values like TCCR1A and OCR1A to change the frequency from like 500Hz to 10KHz?  How am I supposed to know what to change them to?  What causes the need to change? What causes the LED to pulse when there is nothing that sets it to a LOW value?  And what do _BV and WGM12 and all that stuff mean?

I think you did a good job writing your reference but it doesn't explain everything.  It states a feature, gives an example scenario, and shows a code on how that scenario could be performed (which is great, that's how it should be done) but it doesn't explain why everything is the way it is and why certain values are used, and it isn't clear what's a constant and whats a variable.  For many people on these forums, they don't care - they just want to copy a code and make sure it works.  But I don't like taking something unless I actually understand it.  Your guide is overall informative and an easy read, but I'm going to need some extra assitance.

Nick Gammon


So, if I put a piezo buzzer on that, it would create a tone of 5000Hz?


Er, no. About 1.56 Hz because of the prescaler (and because it takes two toggles per period).


Are you saying that I would have to change values like TCCR1A and OCR1A to change the frequency from like 500Hz to 10KHz?


You change OCR1A which is the amount it counts up to.

Quote
How am I supposed to know what to change them to?


Ah, with a calculator? The maths is well-defined and described in the datasheet. The raw input to the timer is the processor clock, which clocks every 62.5 nS for a 16 MHz clock. A prescaler of 1024 (if you choose to use that) will give you a count every 64 uS. Then if you count up to 5000 before toggling you are now up to 320 mS.  Since it takes two toggles to give a period (one on, one off) your period is 640 mS. The frequency is the inverse of that: 1.5625 Hz.

Quote
What causes the need to change?


Only if you want different frequencies. Like, play a tune. If you don't want different frequencies you don't need to change it.

Quote
What causes the LED to pulse when there is nothing that sets it to a LOW value?


It toggles. On/off.

Quote
And what do _BV and WGM12 and all that stuff mean?


_BV is a macro: 1 << x. So _BV (4) is 1 << 4, effectively bit 4 (if you count from zero).

WGM12 and all that stuff: as described in the datasheet.

Quote
I think you did a good job writing your reference ...


Thank you.

Quote
... but it doesn't explain everything.  It states a feature, gives an example scenario, and shows a code on how that scenario could be performed (which is great, that's how it should be done) but it doesn't explain why everything is the way it is and why certain values are used, and it isn't clear what's a constant and whats a variable.  For many people on these forums, they don't care - they just want to copy a code and make sure it works.  But I don't like taking something unless I actually understand it.  Your guide is overall informative and an easy read, but I'm going to need some extra assitance.


The page was really about interrupts, not timers. I have another page about timers:

http://www.gammon.com.au/forum/?id=11504

Ultimately you need to read the datasheet.

http://atmel.com/dyn/resources/prod_documents/8271S.pdf

(That's for the 328). I don't have the link to hand for the 1280 but it will be on the Atmel web site.

There are also quite a few good other resources about Atmega328 timers, and how to use them. Calculators to work out exactly what values to choose, I dare say.
http://www.gammon.com.au/electronics

Go Up