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);
}
}
Best Answer
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).