kramann.info
© Guido Kramann

Login: Passwort:










Mikrocontroller
1 Einfuehrung
..1.1 Entwicklungsgeschichtliches
..1.2 Maschinensprache
..1.3 Assemblerbeispiel
..1.4 Sprachwahl
..1.5 Praxis
....1.5.1 Digital_IO
....1.5.2 Byteoperationen
....1.5.3 AVR_Studio
....1.5.4 Testboard
....1.5.5 Aufgaben
....1.5.6 Do_it_yourself
......1.5.6.1 Ampel
......1.5.6.2 Programmierer
..1.6 Literatur
..1.7 Programmierer
....1.7.1 Bauverlauf
....1.7.2 KurzreferenzLow
....1.7.2 Kurzreferenz_16PU
..1.8 Uebung1
..1.9 BoardAtHome
....1.9.1 Software
....1.9.2 Hardware
....1.9.3 Knoppix
....1.9.4 Aufbau
....1.9.5 LED
2 Oszillator
..2.1 Assembler
..2.2 Interner_RC
..2.3 Quarz
..2.4 Taktgenerator
3 DigitalIO
..3.1 Elektrische_Eigenschaften
..3.2 Pullup_Widerstaende
..3.3 Bitmasken_Eingang
..3.4 Bitmasken_Ausgang
..3.5 Tic_Tac_Toe
....3.5.1 DuoLEDs
....3.5.2 Schaltplan
....3.5.3 Spielfeld
....3.5.4 Anwahl
....3.5.5 Kontrolle
..3.6 Laboruebung2
..3.7 Laboruebung2_alt
4 PWM
..4.1 Prinzip
..4.2 Nutzen
..4.3 Generierung
..4.4 Programmierung
..4.5 Servos
..4.7 Laboruebung3
..4.8 LoesungUE3
..4.9 Uebung6
5 LichtKlangKugeln
..5.1 LED
..5.2 RGB
..5.3 Sensoren
..5.4 lautsprecher
..5.5 tonerzeugung
6 UART
..6.1 Bussysteme
..6.2 UART
..6.3 RS232
..6.4 Hardware
..6.5 Senden
..6.6 Hyperterminal
..6.7 Empfangen
..6.8 Broadcast
..6.9 Uebung4
7 Infrarot
..7.1 schalten
..7.2 seriell
..7.3 Uebung
8 OOP
..8.1 Probleme
..8.2 Konzept
..8.3 Statisch
..8.4 Datentypen
..8.5 RS232
....8.5.1 Prozedural
....8.5.2 Analyse
....8.5.3 Umsetzung
....8.5.4 Vererbung
....8.5.5 Statisch
....8.5.6 Performance
..8.6 Fahrzeug
9 ADW
..9.1 ADW
..9.2 Zaehler
10 Peripherie
..10.1 RS232Menue
..10.2 ASCIIDisplay
..10.3 Tastenmatrix
..10.4 Schrittmotor
..10.5 Zaehler
..10.6 Uebung7
11 SPI
..11.1 Testanordnung
..11.2 Register
..11.3 Test1
..11.4 Test2_Interrupt
..11.5 Test3_2Slaves
..11.6 Laboruebung
12 EEPROM
13 I2C
..13.1 MasterSendByte
..13.2 MasterSend2Bytes
..13.3 MasterReceiveByte
..13.4 MasterReceive2Bytes
14 Anwendungen
..14.1 Mechatroniklabor
....14.1.1 Biegelinie
....14.1.2 Ausbruchsicherung
....14.1.3 Einachser
....14.1.4 AV
....14.1.5 Vierradlenkung
....14.1.6 Kommunikation
..14.2 Sinuserzeugung
....14.2.1 Variante1
....14.2.2 Variante2
....14.2.3 Variante3
....14.2.4 Variante4
..14.3 Laboruebung8
..14.4 Loesung_Ue8
..14.5 SPI_Nachtrag
20 Xubuntu

14.4 Lösung zu Übung 8: Erzeugen eines Sinussignals von 440Hz über einen PWM gepulsten Digitalausgang

Vorüberlegungen

Was soll erreicht werden?

  • Was muß erfüllt sein, damit ein Sinussignal von 440Hz über einen PWM-Ausgang erzeugt werden kann?
  • Bekanntermaßen müssen in einer Periode eine Vielzahl an Pulsen unterschiedlicher Länge geschickt werden, damit ein glatter Verlauf zustande kommt.
  • Angenommen, eine Periode soll in 100 Pulse zergliedert werden.
  • Dann müßte ein PWM-Signal der Frequenz 44000Hz erzeugt werden.
  • Da aber mit jedem Puls auch noch eine andere Pulsbreite geschickt werden soll und das Hauptprogramm diese Pulsbreitenänderung immer mindestens zwischen zwei Pulsen durchführen muß, sollte die PWM-Frequenz noch höher sein.
  • Beispielsweise könnte man sich vorstellen, dass in dem Zeitraum zwischen zwei Pulsbreitenänderungen immer 5 Pulse gesendet werden.
  • Damit wäre eine PWM-Frequenz von 220000Hz notwendig.

Was ist möglich?

  • Der zu verwendende Lautsprecher ist bei Pin27, OC2, PD7 angeschlossen.
  • Das bedeutet, er kann entweder über Bit 7 des digitalen Ports D angesteuert werden, oder über den PWM-Ausgang von Timer 2
  • Ein Blick in das Datenblatt des ATmega32 bei Timer 2 zeigt:
  • Die minimale Vorteilung ist N=1.
  • Bei dem schnellsten PWM-Mode "Fast PWM Mode" errechnet sich die Frequenz des PWM-Signals nach f=fquarz/(2*N*256)
  • Bei 9,216MHz Quarzfrequenz ergibt sich so f=18000Hz.

Versuch einen Kompromiß zu finden

  • Angesichts der Begrenztheit der maximalen PWM-Frequenz soll ein Kompromiß gesucht werden.
  • Eine vielleicht noch ausreichende Teilung der Sinus-Periode könnten 16 Schritte sein.
  • In diesem Fall benötigt man nur noch eine Mindest PWM-Frequenz von 7040Hz.
  • Mit den möglichen 18000Hz würde man in einem der 16 Teilschritten dann 2 bis 3 Pulse schicken können.
  • Nun muß man berücksichtigen, dass bei diesem Vorhaben Schmutzeffekte auftreten können:
  • Ist die Pulsbreitenänderung nicht gut mit der PWM-Frequenz synchronisiert, so können Schwebungen und/oder Knackgeräusche entstehen.
  • Am günstigsten wäre es, wenn die PWM-Frequenz und die Pulsbreiten-Änderungsfrequenz weit im unhörbaren Frequenzbereich lägen.
  • Dann wäre ein zumindest vom Höreindruck sauberes Signal zu erwarten.
  • Bei dem hier angestrebten Kompromiß ist zu erwarten, dass das Signal nicht besonders sauber ist.

Einrichten der PWM-Breiten-Änderung

  • Im Gegensatz zu der PWM-Frequenz muß der Verlauf der PWM-Breitenänderung in jedem Fall genau mit einem ganzen Vielfachen der gewünschten Frequenz von 440Hz erfolgen.
  • In unserem Fall wird eine Frequenz von genau 7040Hz benötigt.
  • Ist dies realisierbar?
  • Es wurde die Technik mit einer Warteschleife am Ende der Endlosschleife erarbeitet.
  • Die Anwendung dieser Technik setzt voraus, dass die restlichen Befehle der Endlosschleife insgesamt weniger Zeit benötigen, als die eingesetzte Wartezeit.
  • Wahrscheinlich scheidet deshalb schon die Methode aus, bei der der Sinuswert zu jedem Teilschritt berechnet wird. Eine Lookup-Tabelle ist sicher nortwendig.
  • Zudem kann mit dieser Methode nicht jede beliebige Frequenz realisiert werden.
  • Timer 1 wurde bereits im 16Bit-Modus eingesetzt und hatte damit eine maximale Oberschranke von hexadezimal 0xFFFF, also dezimal 16383.
  • Als Vorteilung möglich sind hier die Werte 1,8,64,256 und 1024.
  • Mit 9216000/7040 ergibt sich eine gewünschte Teilung von 1309,0909..
  • Bei einer Vorteilung durch 8 verbleibt eine Restteilung von 163,636.
  • Setzt man in die Warteschleife den nächst gelegenen ganzzahligen Wert 164 ein, erreicht man dann eine Sinus-Frequenz von 439,024Hz.
  • Dies entspricht dem Kammerton zur Zeit des Barock und soll uns jetzt einmal von der Genauigkeit genügen.
  • Es gibt auch einen Mode, bei dem der maximale Zählerwert (TOP) durch einen Eintrag in das Register OCR1A bestimmt wird. Dies läßt eine größere Anzahl an Frequenzeinstellungen zu.
  • Alternativ kann auch nach einem Quarz gesucht werden, der bessere Werte liefert.

Umsetzung des Programms

Lösung Übung 8 - 440Hz.zip

Vorausberechnung der Sinuswerte mit einem Scilab-Skript:

x=zeros(16,0);
t=0;
for i=0:1:15
t=(i*2.0*%pi)/16;
x=round( 0.5*(sin(t)+1.0)*255 )
end

Code 14.4-1: Scilab-Skript sinus_berechnen.sce

Mikrocontroller-Programm zur Erzeugung des Sinussignals

#include <avr/io.h>
int main(void)
{
    int i=0;
    //Die 16 im Voraus berechneten  und im Bereich 0..255 skalierten Sinuswerte:
    unsigned char sinus[16] = {128,176,218,245,255,245,218,176,
                               128,79,37,10,0,10,37,79};
    DDRD |= 0b10000000;
    //Konfigurieren des Timers 2 als PWM-Ausgang im Fast-PWM-Mode, OC2 set on compare match,
    //Vorteilung 1:
    TCCR2 = (0<<FOC2) | (1<<WGM20) | (1<<COM21) | (0<<COM20)
          | (1<<WGM21) | (0<<CS22) | (0<<CS21) | (1<<CS20);
    //Konfigurieren des Timers 1 als normaler Zähler,
    //Vorteilung 8:
    TCCR1A = (0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0)
           | (0<<FOC1A) | (0<<FOC1B) | (0<<WGM11) | (0<<WGM10);
    TCCR1B = (0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12)
           | (0<<CS12) | (1<<CS11) | (0<<CS10);
    while(true)
    {
        OCR2 = sinus[i];
        while(TCNT1<164);
        TCNT1 = 0; 
        i++;
        i%=16;
    }
    return 0;
}

Code 14.4-2: Mikrocontroller-Programm, um ein 439Hz Sinussignal zu erzeugen.