Tell me more ×
Electrical Engineering Stack Exchange is a question and answer site for electronics and electrical engineering professionals, students, and enthusiasts. It's 100% free, no registration required.

I need to be able to play two tones at once and i have the arduino uni with a small 8ohm piezo speaker. Is it possible to do so?

Sample Code

#define  c     3830    // 261 Hz 

int tone1 = 10; // digital pin10
int tone2 = 9 // digital pin9
void setup() {
    pinMode(tone1, OUTPUT);    // pin as output
    pinMode(tone2, OUTPUT);    // pin as output
} 

void loop() {
   playTone(1000,500,700)
} 

void playTone(long duration, int freq, int freq2) {
    duration *= 1000;
    int period = (1.0 / freq) * 1000000;
    long elapsed_time = 0;
    while (elapsed_time < duration) {
        digitalWrite(tone1,HIGH);
        digitalWrite(tone2,HIGH);
        delayMicroseconds(period / 2);
        digitalWrite(tone1,LOW);
        digitalWrite(tone2,LOW);
        delayMicroseconds(period / 2);
        elapsed_time += (period);
    }
}
share|improve this question

2 Answers

Should be doable. Have a sine lookup table. Calculate the phase difference between successive samples for both signals at the used sample frequency. Upon a timer tick (at your sample frequency) add those phases to two phase accumulators, look up their values in the sine table, add them and set a PWM output to that value.
Use a low-pass filter to filter an analog voltage from the PWM.

For example, suppose you want a 2kHz signal with a 3kHz signal, and your sample frequency is 10kHz. Your sine table has a value for every degree. Your 2kHz signal will step 72° per sample, your 3kHz signal 108°. So for the first signal you read 72 values further in the sine table, for the other you go 108 values further at each sample.

This also works for mixing more than two signals.

The main differences with Telaclavo's solution are that his signals are square waves, whereas mine are sines, whichever you prefer. My solution is more CPU-intensive, while his uses more I/O and external components (voltage adder).

share|improve this answer
Do you know any links or anywhere i can learn how to write the code for this? Its very confusing for me. – h00j May 6 '12 at 14:23
@Henry - Sorry if it's confusing, I try to be clear. Your code doesn't work because both your signals do exactly the same: between two writes they change 180° in phase. What my solution does is change this 180° to a smaller value, depending on the ratio between your sound signal's frequency and the sample frequency. If the sample frequency is ten times your signal's, then there are 10 samples for every period. So on each sample you move 36° (360°/10) on your sine wave. – stevenvh May 6 '12 at 14:49
Is there any chance you can show a sample for any two frequencies? :) – h00j May 6 '12 at 15:12

If the maximum number of tones that you need to play simultaneously is only two (or even three or four), I would use two output pins, configured to deliver PWM, and add their contributions externally, either with two resistors (if you don't need much volume), or with an opamp as an adder.

If you use a single PWM signal to recreate the sum of the two tones, you will need CPU attention for each sample of your total signal. The ATmega328 does not have DMA.

With the two pins, you don't hog the CPU. In fact, during the time intervals when none of the two frequencies change, the CPU will not need to do anything.

Another advantage is that you can change any of the frequencies, in real time. You don't need a lookup table for each combination of possible frequencies.

share|improve this answer
Would it be something like the code i put? (Except the frequency for each would be different) – h00j May 6 '12 at 14:23
Could you give a pseudo code example and a pseudo schematic to demonstrate that? I am really interested. – abdullah kahraman May 6 '12 at 17:42

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.