Programmieren Sie einen ATtiny13 als Audio-Oszillator mit variabler Frequenz und Impulsbreite


8

Ich möchte einen einfachen Rechteckwellenoszillator erstellen, der dem eines 555 ähnelt, aber ich möchte die Interrupt-basierte PWM-Unterstützung verwenden, um die Impulsbreite und -frequenz zu steuern.

Ich habe das Datenblatt, die AVR-APIs und alle PWM-Beispiele, die ich finden kann, studiert, aber ich konnte nicht alles zusammenstellen.

Ist es möglich, einen solchen Oszillator mit der eingebauten AVR PWM-Funktionalität zu erstellen, und wenn ja, wie? Ein Freund von mir hat etwas Ähnliches mit einem 8-Pin-PIC gemacht.

Meine Argumentation ist, dass ich interessante Klänge bekomme, wenn ich die Pulsbreite und damit die Wellenform bei einer bestimmten Frequenz ändere. Ähnlich wie die Atari Punk-Konsole funktioniert, aber hoffentlich stabiler, dh die Pulsbreite ändert, aber die Frequenz konstant bleibt oder umgekehrt.


2
Könnten Sie bitte klarstellen, was Ihre Frage ist?
Jason S

Ich bin mir nicht sicher, wie interessant sie sein werden, aber es ist einfach zu versuchen und man kann beurteilen. Wenn sich der Impuls verengt, nehmen die Amplituden der Harmonischen zu. Verengen Sie den Puls weiter und Sie erhalten weißes Rauschen. Ich denke, Sie hätten interessantere Optionen für einen numerisch gesteuerten Oszillator. Sie können die in den Wavetable geladenen Wellenformen ändern.
Jluciani

Antworten:


5

Diese sollten Sie ziemlich weit bringen und den Rest können Sie mit dem Datenblatt tun. Beginnen Sie Stück für Stück mit dem Aufbau, von blinkend über Wellenform zu Wellenform, die sich im Laufe der Zeit in Töne ändert. Einige Quellen können beim Filtern und Ansteuern von Audioausgängen hilfreich sein (aktiver LPF kann beides problemlos erledigen).

Ich schlage vor, mit spezifischeren Fragen zurückzukommen.


4

Die Dauer der PWM wird durch die Überlaufrate Ihres Timers bestimmt. Im Abschnitt Betriebsmodi gibt es viele Einstellungen, über die Sie nachdenken müssen. Wenn Sie lediglich eine Rechteckwelle mit konstanter Periode und variablem Arbeitszyklus erzeugen möchten, sollten Sie den CTC-Modus (Clear Timer on Compare Match) verwenden. Die Grundidee besteht darin, OCR0A auf die Anzahl der Timer-Ticks einzustellen, bis der Pin als nächstes umgeschaltet werden soll, und den Interrupt "Vergleich vergleichen" zu verwenden, um diesen Wert für das nächste Mal zu ändern. In avr-gcc würde es also ungefähr so ​​aussehen:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>

// global variables defining number of ticks on and off
uint8_t on_time_ticks, off_time_ticks, csxx_bits=0; 


void setup_timer(double p_ms, double duty){
  TCCR0A = _BV(COM0A0) // toggle OC0A on Compare Match
  TCCR0B = _BV(WGM02); // set CTC mode WGM0[2,1,0] = 0b100

  // ... do some stuff based on your CPU frequency
  // to define the csxx_bits of TCCR0B when the timer is running
  // and consequently, to set on_time_ticks and off_time_ticks
  OCR0A = on_time_ticks;
  TCCR0B |= your_settings_here;
}


void start_timer(){
  //start the timer running at the desired rate
  TCCR0B |= csxx_bits; 
}


int main(int argc, char **argv){
  double period_ms, duty_cycle;
  setup_timer(period_ms, duty cycle);
  start_timer();  
  for(;;){
    //spin or sleep or whatever
  }
}


ISR(TIM0_COMPA_vect){
  if(OCR0A == on_time_ticks){
    OCR0A = off_time_ticks;
  }
  else{
    OCR0A = on_time_ticks;
  }
}

Achtung, dies ist ungetesteter Code, aber ich denke, die Idee ist richtig. Dies ist keineswegs der einzige Weg, dies zu tun.

Es gibt übrigens eine Sache, die Sie über den ATTiny13 wissen sollten. Es wird garantiert, dass der interne RC-Oszillator nur bis zu 10% von der Fabrik entfernt ist. Es gibt einen Benutzerkalibrierungsprozess, den Sie durchlaufen können (beschrieben durch eine atmel- Appnote ), der Sie auf eine Genauigkeit von 2% für den ATTiny13 bringt. Wenn Sie es besser machen wollen, müssen Sie wahrscheinlich einen Chip verwenden, der einen externen Kristall aufnehmen kann ...


1
Ihre Antwort hat dazu beigetragen, etwas Ähnliches zu klären, mit dem ich Probleme hatte - danke. Nur ein Punkt (für alle, die dies lange nach dem ursprünglichen Thread lesen): Ihre Wahl von 0b100 für WGM0 [2,1,0] setzt den CTC-Modus nicht. (Tatsächlich wird ein von Atmel reservierter Modus festgelegt.) Das Datenblatt ATtiny13 besagt, dass der CTC-Modus den Wert 2 benötigt. Sie haben ihm stattdessen versehentlich die Bitnummer 2 gegeben (dh den Wert 4). Aus diesem Grund ist es auch notwendig, WGM02 in TCCR0B nicht nur zu ändern (dh zu löschen), sondern auch die Bits WGM01 und WGM00 auf 1 bzw. 0 zu setzen. Diese Bits befinden sich in TCCR0A, daher reicht es nicht aus, TCCR

3

Keine direkte Antwort auf Ihre Frage, aber dies kann naheliegend sein und einige Hinweise geben -

Ich habe gerade einen numerisch gesteuerten Oszillator (NCO) mit einem ATmega uC und einem DAC erstellt. Ein Array von ganzen Zahlen wird verwendet, um einen Zyklus einer Wellenform (Wavetable) zu speichern. Ein Phasenakkumulator (long int) wird verwendet, um die Adresse der Ausgangsdaten im Wavetable zu bestimmen. Jeder Timer-Interrupt erhöht den Phasenakkumulator um einen festen Wert. Das Phaseninkrement bestimmt die Frequenz.

In meiner Anwendung habe ich eine 64-Byte-Wavetable verwendet, die einen Sinuszyklus enthielt. Es ist einfach, den Wavetable zu erweitern und den Samples mehr Auflösung hinzuzufügen. Mein Anwendungshinweis befindet sich unter http://wiblocks.com/docs/app-notes/nb1a-nco.html


1

Grundsätzlich ändert eine PWM die Frequenz nicht. PWM werden meistens verwendet, um die "Intensität" eines Signals zu steuern.

Um einen Interrupt für verschiedene Frequenzen zu erzeugen, würde ich empfehlen, den Timer im CTC-Modus zu verwenden.

Es wird zu Ihrem Vergleichswert ausgeführt, ein Interrupt umgeschaltet, gelöscht und neu gestartet - bis es wieder zu Ihrem Vergleichswert läuft ...

Bei jedem Interrupt können Sie einen oder mehrere Ports wechseln und den Rest der Zeit (der Timer läuft immer noch automatisch) können Sie Ihre Eingaben jeglicher Art beobachten ...

Sie können Ihre Rechteckwelle weiterhin mit einer PWM "modulieren", um die "Verstärkung" zu steuern. Aber einer von ihnen muss "von Hand" gemacht werden, weil der ATtiny13 nur einen Hardware-Timer hat ...


1
Bei den meisten Hardware-PWM-Peripheriegeräten können Sie die Frequenz auswählen. Wenn Sie das Tastverhältnis konstant halten, kann PWM Ihnen weiterhin eine variable Frequenzsteuerung geben
Jason S

1
Durch Ändern der Impulsbreite wird die Grundfrequenz nicht geändert, aber die Harmonischen.
Jluciani
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.