Können Sie mit einem einzelnen Piezo-Lautsprecher Akkorde auf Arduino spielen?

Ich muss in der Lage sein, zwei Töne gleichzeitig zu spielen, und ich habe das Arduino Uni mit einem kleinen 8-Ohm-Piezo-Lautsprecher. Ist das möglich?

Beispielcode

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

Antworten (2)

Sollte machbar sein. Haben Sie eine Sinus-Nachschlagetabelle. Berechnen Sie die Phasendifferenz zwischen aufeinanderfolgenden Abtastwerten für beide Signale bei der verwendeten Abtastfrequenz. Fügen Sie bei einem Timer-Tick (bei Ihrer Abtastfrequenz) diese Phasen zu Zweiphasen-Akkumulatoren hinzu, suchen Sie ihre Werte in der Sinustabelle, addieren Sie sie und stellen Sie einen PWM-Ausgang auf diesen Wert ein.
Verwenden Sie einen Tiefpassfilter, um eine analoge Spannung aus der PWM zu filtern.

Angenommen, Sie möchten ein 2-kHz-Signal mit einem 3-kHz-Signal und Ihre Abtastfrequenz beträgt 10 kHz. Ihre Sinustabelle hat für jedes Grad einen Wert. Ihr 2-kHz-Signal wird pro Abtastung um 72° schreiten, Ihr 3-kHz-Signal um 108°. Für das erste Signal lesen Sie also 72 Werte weiter in der Sinustabelle, für das andere gehen Sie bei jedem Sample 108 Werte weiter.

Dies funktioniert auch beim Mischen von mehr als zwei Signalen.

Die Hauptunterschiede zu Telaclavos Lösung bestehen darin, dass seine Signale Rechteckwellen sind, während meine Sinuswellen sind, je nachdem, was Sie bevorzugen. Meine Lösung ist CPU-intensiver, während seine mehr E / A und externe Komponenten (Spannungsaddierer) verwendet.

Kennen Sie irgendwelche Links oder irgendwo kann ich lernen, wie man den Code dafür schreibt? Es ist sehr verwirrend für mich.
@Henry - Entschuldigung, wenn es verwirrend ist, ich versuche, klar zu sein. Ihr Code funktioniert nicht, weil Ihre beiden Signale genau dasselbe tun: Zwischen zwei Schreibvorgängen ändern sie die Phase um 180 °. Meine Lösung ändert diese 180 ° auf einen kleineren Wert, abhängig vom Verhältnis zwischen der Frequenz Ihres Tonsignals und der Abtastfrequenz. Wenn die Abtastfrequenz das Zehnfache Ihres Signals beträgt, gibt es 10 Abtastungen für jede Periode. Sie bewegen sich also bei jedem Sample um 36° (360°/10) auf Ihrer Sinuswelle.
Besteht die Möglichkeit, dass Sie ein Beispiel für zwei beliebige Frequenzen zeigen können? :)
Es ist erwähnenswert, dass viele Piezo-Wandler wirklich schrecklich klingen, wenn sie mit mehr als einem Ton gleichzeitig mit annähernd voller Lautstärke betrieben werden. Selbst starke Verzerrungen sind oft nicht zu beanstanden, wenn alle Frequenzen Harmonische eines einzelnen Tons sind, da alle Summen- und Differenzfrequenzen ebenfalls Harmonische dieses Tons sind. Wenn man jedoch versucht, z. B. 440 Hz und 554 Hz gleichzeitig zu erzeugen, kann die Verzerrung alle möglichen anderen seltsamen Frequenzen wie 114 Hz, 326 Hz usw. erzeugen.

Wenn die maximale Anzahl von Tönen, die Sie gleichzeitig spielen müssen, nur zwei (oder sogar drei oder vier) beträgt, würde ich zwei Ausgangspins verwenden, die für die Lieferung von PWM konfiguriert sind, und ihre Beiträge extern hinzufügen, entweder mit zwei Widerständen (falls Sie dies nicht tun) braucht nicht viel Lautstärke) oder mit einem Operationsverstärker als Addierer.

Wenn Sie ein einzelnes PWM-Signal verwenden, um die Summe der beiden Töne nachzubilden, benötigen Sie CPU-Aufmerksamkeit für jedes Sample Ihres Gesamtsignals. Der ATmega328 hat kein DMA.

Mit den zwei Pins belasten Sie die CPU nicht. Tatsächlich braucht die CPU während der Zeitintervalle, in denen sich keine der beiden Frequenzen ändert, nichts zu tun.

Ein weiterer Vorteil ist, dass Sie jede der Frequenzen in Echtzeit ändern können. Sie brauchen keine Nachschlagetabelle für jede Kombination möglicher Frequenzen.

Wäre es so etwas wie der Code, den ich eingegeben habe? (Außer die Frequenz für jeden wäre anders)
Könnten Sie ein Pseudo-Codebeispiel und ein Pseudo-Schema geben, um dies zu demonstrieren? Ich bin wirklich interessiert.