Wie erzeuge ich mit Atmeaga32 avr mcu ein PWM-Signal, das mindestens 20 Mal zwischen 0 und 5 V variiert?

Ich mache ein Photovoltaik-Datenlogger-Projekt (PV), in dem ein Leistungs-MOSFET (IRFZ34N) als Last verwendet werden kann. Ich möchte also die Gate-Spannung mit einem PWM-Signal (0-5-V-Bereich) der MCU variieren und brauche mindestens 2o variierende Punkte. Ich bin also verwirrt, wenn ich einen 'C'-Code schreibe, um ein PWM-Signal zu erzeugen. wie 1. Was sollte der Zeitraum von PWM sein? 2. Wie kann ich das PWM-Tastverhältnis in verschiedenen Schritten variieren? und ETC..

Und bitte helfen Sie mir, wenn ich noch etwas tun muss, um mein Projekt erfolgreich zu machen. Ich wäre sehr dankbar, wenn mir irgendjemand mit Antworten weiterhelfen würde.

Antworten (2)

Sie können dies in Software tun und das gesamte erforderliche Timing selbst verfolgen, aber die meisten Mikrocontroller verfügen über Hardware, die PWM nach der Initialisierung autonom erzeugen kann. Die grundlegenden Dinge sind ein Timer/Zähler und ein Output Compare Register (OCR):

Geben Sie hier die Bildbeschreibung ein

Der Zähler erhöht sich kontinuierlich, dargestellt durch die Steigung, und wird mit der OCR verglichen. Der PWM-Ausgang geht auf Low, wenn der Zähler die OCR überschreitet, und geht wieder auf High, wenn er zurückgesetzt wird. Die benötigte Auflösung von 5 % (20 Stufen) ist kein Problem; ein 16-Bit-Timer kann PWM mit einer Auflösung von besser als 0,002 % erzeugen, und sogar ein 8-Bit-Timer kann 0,4 % erreichen.

Sie müssen lediglich einen neuen Wert in der OCR programmieren. Je niedriger der Wert, desto kleiner die Impulsbreite. Die folgende Animation stammt von dieser Seite :

Geben Sie hier die Bildbeschreibung ein

Weiterführende Literatur
Using the AVR's High-speed PWM , ein Anwendungshinweis von Atmel.
ATMega32 Datenblatt beschreibt auf Seite 69 ff. wie man Timer0 für den PWM-Betrieb verwendet.

Bewegte Bilder im Internet? Das zählt für mindestens 10.000 hübsche Stimmen.
@Kortuk - 10.000 pro Standbild, hoffe ich! :-) Ich habe gehört, es gibt eine völlig neue Erfindung, mit der man noch schneller bewegte Bilder machen kann, ich glaube, sie nennen es Kinematografie oder so ähnlich. Ich weiß nicht, ob es auch Ton gibt, vielleicht in der Zukunft. ;-)

Angenommen, Ihr Mikrocontroller verfügt über ein PWM-Modul, dann ist es ganz einfach. Sie müssen das Datenblatt lesen und Ihr Modul entsprechend einrichten und dann die entsprechenden Werte in das Register für den Arbeitszyklus (normalerweise "Vergleichen") laden. Hier ist ein grobes Beispiel: Sie richten einen Timer für Ihre gewünschte (feste) PWM-Frequenz ein und ändern dann ein Register, um die EIN / AUS-Zeit in diesem Zeitraum zu ändern.
Angenommen, Sie haben ein 10-Bit-PWM-Modul. 10 Bit = 2 ^ 10 = 1024. Für 50 % Arbeitszyklus müssen Sie also 512 in das Register laden, für 25 % 256 und so weiter (der spezifische Betrieb Ihres PWM-Moduls kann etwas anders sein).
Dann fügen Sie ein Low hinzu Passfilter (ein einfacher RC-Filter reicht normalerweise aus) vor der PWM, um die PWM zu mitteln und eine variierende Gleichspannung zu erzeugen:

PWM-Filter

RC-Filter

Für den Filter müssen Sie sicherstellen, dass die PWM-Frequenz stark gedämpft wird und die niedrigeren Frequenzen übrig bleiben. Da Sie sagen, dass Sie nur Gleichstrom benötigen, reicht etwas wie R = 10 k C = 0,1 uF aus. Dies erzeugt eine Grenzfrequenz von 1 / (2pi * 10k * 0,1uF) = 159Hz. Wählen Sie eine PWM-Frequenz deutlich darüber (z. B. 10 kHz)

Mir ist das AVR-Tag aufgefallen - ich verwende AVR nicht (daher kann ich nicht persönlich für die folgenden Informationen bürgen), aber ich habe gegoogelt und ein paar ziemlich gute Tutorials gefunden:
Aquaticus PWM-Anleitung
AVR Freaks PWM-Anleitung
PWM-Sinuswellenbeispiel

Falls Sie das PWM-Modul nicht verwenden möchten (oder PWM an einem bestimmten Pin benötigen), hier ein "weicher" PWM-Code:

 // The following two ISRs are doing "poor man's PWM" 
//  but this allows it to be on a pin of my choice 
ISR(TIMER0_COMP_vect) { 
        // clear the output pin on OCR0 match 
   PORTC &= ~(1<<PC0); 
} 
ISR(TIMER0_OVF_vect) { 
        // set the output pin at timer overflow 
   PORTC |= (1<<PC0); 
} 

int main(void) { 

   // going to use PORTC.0 to PWM the contrast voltage 
   DDRC = (1<<DDC0); 
   TIMSK |= ((1<<OCIE0) | (1<<TOIE0)); // use both interrupts
   OCR0 = 10; // 10 out of 256 means very short on period (low voltage) 
   TCCR0 = (1<<CS00); // timer on - nice high PWM frequency 

   // Might later consider PWMing the backlight voltage too 
   // so it would also be adjustable ... 
   sei();