PWM



PWM steht für Pulsweitenmodulation (engl.: pulse width modulation).
Eigentlich ist das bessere deutsche Wort für unsere Anwendung: Pulsbreitensteuerung.

Hier wird erklärt, was es ist und was man damit alles machen kann.



Es gibt zwei verschiedene Wege, PWM mit einem Atmega8 zu machen:

  1. Software-PWM:
    Man schaltet einfach einen digitalen Ausgang, z. B. PB1, wiederholend ein und aus und legt jeweils die High- und die Low-Zeit mit Hilfe von _delay_ms() oder _delay_us() fest.  (Bei _delay_us() steht das us für Mikrosekunden.)
    Diese Variante hat den Nachteil, daß der Atmega8 dann nicht viel anderes mehr machen kann, als sich ununterbrochen um genau diese Aufgabe zu kümmern.

  2. Hardware-PWM:
    Man benutzt die als Hardware vorhandenen drei PWM-Ausgänge des Atmega8.
    Sie heißen: OC1A, OC1B und OC2.
    Diese arbeiten unabhängig davon, womit der Atmega8 sonst gerade beschäftigt ist.
    Man sagt einfach einem (oder 2 oder 3) dieser Ausgänge: "Gib eine PWM von dieser oder jener Form aus!" und der macht das dann unabhängig von anderen Prozessen.
     

Hier eine Schaltung für unser Experimentierboard 1 (oder auch für Steckbrett), die beide PWM-Varianten ermöglicht:





1. Software-PWM realisiert 4 Helligkeitsstufen einer LED

Unsere an Pin 15 des Atmega8  (=Ausgang PB1) angelegte LED leuchtet für 2s nicht, dann schwach, dann halbhell und dann hell.

Hier der Code:

#include <avr/io.h>

#define F_CPU 1000000UL  // 1 MHz
#include <util/delay.h>


int main(void)
{
    int i;
   
    DDRB |= _BV(PB1);
   
   
    while(1){   
   
        //LED aus
        PORTB |=_BV(PB1);
        for(i=0;i<100;i++) {
            _delay_ms(20);
        }
       
        //LED leuchtet schwach
        for(i=0;i<100;i++){
            PORTB &= ~_BV(PB1); _delay_ms(1);
            PORTB |=_BV(PB1); _delay_ms(19);
           
        }
       
        //LED leuchtet etwa halbhell
        for(i=0;i<100;i++){
            PORTB &= ~_BV(PB1); _delay_ms(5);
            PORTB |=_BV(PB1); _delay_ms(15);
           
        }
       
        //LED leuchtet hell
        for(i=0;i<100;i++){
            PORTB &= ~_BV(PB1); _delay_ms(19);
            PORTB |=_BV(PB1); _delay_ms(1);       
        }
       
    }
   
       
    return 0;
}


Hier der Code-Ordner.




2. Hardware-PWM realisiert einen LED-Fader

Unsere an Pin 15 des Atmega8 (=Ausgang OC1A) angelegte LED schalten wir so schnell ein und aus, das wir das eigentliche Schalten nicht bemerken. Unser Programm verschiebt dabei des Verhältnis zwischen ein und aus und läßt somit die LED für uns langsam aufleuchtend und dann langsam dunkel werdend erscheinen. Diesen Lichteffekt nennen manche Leute "faden" und eine solche Schaltung "Fader".

Hier der Code:

#include <avr/io.h>

#define F_CPU 1000000UL  // 1 MHz
#include <util/delay.h>


int main(void)
{
    DDRB |= _BV(PB1);
   
    TCCR1A = (1<<WGM11) | (1<<WGM10) | (1<<COM1A1); // 10bit-Counter, nicht invert. PWM
    TCCR1B = (1<<CS10); // Pre-Scaler = 1, also ohne Teiler
       
    int a = 1023; // höchster Wert = dunkel, wenn LED in den PORT hineinzeigt, wie bei unserem Board
   
    while(1){   
   
        while(a>700){
            OCR1A = a;
            _delay_ms(10);
            a--;
        }   

        while(a<1023){
            OCR1A = a;
            _delay_ms(10);
            a++;
        }
   
    }
   
       
    return 0;
}


Hier der Code-Ordner.




Anmerkungen und Aufgaben:

  • Du kannst (eventuell mit einem zusätzlichen Transistor) auch gewaltige superhelle LEDs oder Lampen sowie Gleichstrommotoren und Servomotoren ansteuern.
    Mit Software-PWM steuern wir in der Mikrocontrollerspielwiese beispielsweise hier einen Servomotor an.

  • Ich geb's zu: Die Harware-PWM-Befehle sind ziemlich unübersichtlich. Wenn Du genau das Benutzen der PWM-Funktionen von Atmega8 erkunden willst, kannst Du das auch alles im Datenblatt nachlesen.

  • PWM-Experimente gibt es auf der Mikrocontrollerspielwiese für den Attiny13 hier.