¿Puedes tocar acordes en Arduino con un solo altavoz piezoeléctrico?

Necesito poder reproducir dos tonos a la vez y tengo el arduino uni con un pequeño altavoz piezoeléctrico de 8 ohmios. ¿Es posible hacerlo?

Código de muestra

#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);
    }
}

Respuestas (2)

Debería ser factible. Tener una tabla de búsqueda de senos. Calcule la diferencia de fase entre muestras sucesivas para ambas señales a la frecuencia de muestra utilizada. Tras un tic del temporizador (a su frecuencia de muestreo), agregue esas fases a los acumuladores de dos fases, busque sus valores en la tabla de senos, agréguelos y configure una salida PWM a ese valor.
Use un filtro de paso bajo para filtrar un voltaje analógico del PWM.

Por ejemplo, suponga que desea una señal de 2 kHz con una señal de 3 kHz y su frecuencia de muestreo es de 10 kHz. Tu tabla de senos tiene un valor para cada grado. Su señal de 2kHz avanzará 72° por muestra, su señal de 3kHz 108°. Entonces, para la primera señal, lee 72 valores más en la tabla de senos, para la otra, avanza 108 valores más en cada muestra.

Esto también funciona para mezclar más de dos señales.

Las principales diferencias con la solución de Telaclavo son que sus señales son ondas cuadradas, mientras que las mías son sinusoidales, lo que prefieras. Mi solución requiere más CPU, mientras que la suya usa más E/S y componentes externos (sumador de voltaje).

¿Conoces algún enlace o algún lugar donde pueda aprender a escribir el código para esto? Es muy confuso para mí.
@Henry: lo siento si es confuso, trato de ser claro. Su código no funciona porque ambas señales hacen exactamente lo mismo: entre dos escrituras cambian 180 ° en fase. Lo que hace mi solución es cambiar este 180 ° a un valor más pequeño, dependiendo de la relación entre la frecuencia de la señal de sonido y la frecuencia de muestra. Si la frecuencia de muestra es diez veces mayor que la de su señal, entonces hay 10 muestras para cada período. Entonces, en cada muestra, se mueve 36 ° (360 °/10) en su onda sinusoidal.
¿Hay alguna posibilidad de que pueda mostrar una muestra para dos frecuencias cualesquiera? :)
Vale la pena señalar que muchos transductores piezoeléctricos suenan realmente horribles cuando se manejan a un volumen casi completo con más de un tono simultáneamente. Incluso la distorsión severa a menudo no es objetable cuando todas las frecuencias son armónicos de un solo tono, porque todas las frecuencias sumadas y diferenciadas también serán armónicos de ese tono. Sin embargo, si uno intenta generar, por ejemplo, 440 Hz y 554 Hz simultáneamente, la distorsión puede producir todo tipo de otras frecuencias extrañas como 114 Hz, 326 Hz, etc.

Si la cantidad máxima de tonos que necesita reproducir simultáneamente es solo dos (o incluso tres o cuatro), usaría dos pines de salida, configurados para entregar PWM, y agregaría sus contribuciones externamente, ya sea con dos resistencias (si no t necesita mucho volumen), o con un amplificador operacional como sumador.

Si usa una sola señal PWM para recrear la suma de los dos tonos, necesitará la atención de la CPU para cada muestra de su señal total. El ATmega328 no tiene DMA.

Con los dos pines, no acaparas la CPU. De hecho, durante los intervalos de tiempo en los que ninguna de las dos frecuencias cambia, la CPU no necesitará hacer nada.

Otra ventaja es que puedes cambiar cualquiera de las frecuencias, en tiempo real. No necesita una tabla de búsqueda para cada combinación de frecuencias posibles.

¿Sería algo como el código que puse? (Excepto que la frecuencia para cada uno sería diferente)
¿Podría dar un ejemplo de pseudo código y un pseudo esquema para demostrarlo? Estoy realmente interesado.