Analoge-Signale‎ > ‎

Analoge Signale ausgeben

http://sites.prenninger.com/arduino-uno-r3/analoge-signale/analoge-signale-ausgeben

http://www.linksammlung.info/

http://www.schaltungen.at/

                                                                                        Wels, am 2015-05-10

BITTE nützen Sie doch rechts OBEN das Suchfeld  [                                                              ] [ Diese Site durchsuchen]

DIN A3 oder DIN A4 quer ausdrucken
**********************************************************************************
DIN A4  ausdrucken
*********************************************************
015_b_PrennIng-a_arduino.uno.r3-analoge.signale-analoge.signale.ausgeben (xx Seiten)_1a.pdf


               Pulsweitenmodulation (PWM)

Pulsdauermodulation (PDM)[1],
                                                   Pulslängenmodulation[2] (PLM),
                                                                                                          Unterschwingungsverfahren oder Pulsbreitenmodulation (PBM);


auf englisch pulse-width modulation (PWM)) ist eine Modulationsart, bei der eine technische Größe (z. B. elektrische Spannung) zwischen zwei Werten wechselt.
Dabei wird bei konstanter Frequenz der Tastgrad eines Rechteckpulses moduliert, also die Breite der ihn bildenden Impulse.


Messtechnik
Pulsweitenmodulation wird oft eingesetzt, um analoge Messwerte von Sensoren über lange Leitungen oder Funk zu übertragen.
Da an langen Leitungen ein Spannungsabfall entsteht, würde bei Übertragung der Information in Form einer Spannungshöhe eine Verfälschung entstehen.
Bei der Übertragung mit Pulsbreitenmodulation reicht es aus, wenn der Empfänger noch die Pegel 1 und 0 unterscheiden kann.
Gleiches gilt auch bei einer Übertragung per Funk, wo die Empfangsintensität durch viele Umweltfaktoren beeinflusst wird.


Sinusförmiger Verlauf (grün) kann durch Vergleich mit einem sägezahnförmigen Signal (blau) in ein unten in rosa dargestelltes PWM-Signal umgewandelt werden:
Für jeden PWM-Puls durchläuft die Sägezahnrampe den ganzen Wertebereich
– auf ausreichend träge Verbraucher wirkt der PWM-Spannungsverlauf wie eine Sinusspannung

                                    
http://de.wikipedia.org/wiki/Pulsweitenmodulation




             Analoge Signale ausgeben mit PWM
                                   um auch ein analoges Mess-Instrument anzusteuern.

ARDUINO-IDE
MENU > Datei > Beispiele > 03 Analog > Fading

Fading
Demonstrates the use of analog output (Pulse Width Modulation (PWM)) to fade an LED.
PWM is a technique for getting an analog-like behavior from a digital output by switching it off and on very fast.

Circuit

An LED connected to digital output pin-9 through a 220R resistor.


/*
 Fading_1a.ino

 This example shows how to fade an LED using the analogWrite() function.  The circuit:  LED attached from digital pin 9 to ground. 30 Aug 2011 By Tom Igoe  http://arduino.cc/en/Tutorial/Fading  This example code is in the public domain.  */ int ledPin = 9; // LED connected to digital pin-9 void setup() {    // nothing happens in setup } void loop() {    // fade in from min to max in increments of 5 points   for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {        analogWrite(ledPin, fadeValue); // sets the value (range from 0 to 255)     delay(30); // wait for 30 milliseconds to see the dimming effect   }    // fade out from max to min in increments of 5 points   for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) {         analogWrite(ledPin, fadeValue); // sets the value (range from 0 to 255)     delay(30); // wait for 30 milliseconds to see the dimming effect   } } Quelle:
http://arduino.cc/en/Tutorial/Fading



*********************************************************
               fritzing / Fading.fzz
Sketch: Sketchbook / Fritzing Creator Kit / Fading

Wir haben nun erfahren, wie man eine LED an- und abschaltet und einen Taster ausliest.
Beides sind digitale Vorgänge, die also nur zwei Zustände kennen.
Nun wollen wir die analoge Ausgabe kennenlernen.
Sie wird verwendet um z.B. LEDs in ihrer Leuchtkraft oder Motoren in der Drehgeschwindigkeit zu beeinflussen.
Ein Arduino-Board kann keine wirkliche analoge Ausgabe realisieren, sondern nutzt dafür einen Trick.
Es schaltet einen Kanal einfach extrem schnell an und aus.
Dieser Vorgang wird PWM (Pulsweiten-Modulation) genannt.
Das Verhältnis zwischen An und Aus steuert dabei z.B. die Leuchtstärke der LED (bzw. wie hell uns die LED erscheint).
Das Arduino-UNO-Board verfügt über sechs PWM-Kanäle.
Sie sind mit einer Wellenlinie gekennzeichnet.
Die Pulsweiten-Modulation kann Werte von 0 (immer aus) bis 255 (dauerhaft an) ausgeben.*
Die Beispielschaltung besteht aus einer LED, die über einen Vorwiderstand mit einem PWM-Kanal verbunden ist.

Das Arduino-Board verfügt über eine 8-bit-PWM-Ausgabe.
Jedes bit kann 0 oder 1 sein und es ergeben sich 2hoch8 = 256 Zustände, also 0 - 255.




int ledPin = 9;

void setup() {
pinMode(ledPin, OUTPUT);

}

void loop(){

/*Durch die for-Schleife wird fadeValue von 0 bis 255 hochgezählt
(leuchtwert++ zählt die Variable jeweils um 1 hoch).
Dieser Wert wird durch den Befehl analogWrite an die LED gesendet.
Sie wird also immer heller.*/

   for (int leuchtwert —0; leuchtwert< =255; leuchtwert++){
     analogWrite(ledPin, leuchtwert);
     delay(2);

   }
/* Die zweite for-Schleife zählt von 255 bis 0 herunter
(leuchtwert -- zählt die Variable jeweils um 1 herunter).
Die LED wird wieder dunkler.*/
   for (int leuchtwert-255; leuchtwert>=0; leuchtwert--){
     analogWrite(ledPin, leuchtwert);
     delay(2);
   }

}


Übung:
1. Mache das Gleiche nur umgekehrt mit einer zweite LED an einem anderen Pin.
Achte darauf, dass es ein PWM-Pin ist.
Lösung:
Sketchbook / Fritzing Creator Kit / fritzing_Uebung6_1a.ino


/*
  Fading  fritzing_Uebung6_1a.ino
  dimmt zwei LEDs langsam an und aus
  
  Dieses Beispiel aus dem Fritzing Creator Kit: www.fritzing.org/creator-kit.
*/

int led1Pin = 9;                                                  // led1 pin-9 wird deklariert
int led2Pin = 10;                                                 // led2 pin-10 wird deklariert

void setup(){ 
  // die analoge Ausgabe muss nicht im Setup initialisiert werdenvoid loop(){ 
  for(int leuchtwert = 0; leuchtwert <= 255; leuchtwert++) {      // fadeValue wird in 5er-Schritten hochgezählt 
    analogWrite(led1Pin, leuchtwert);                             // und als analoger Wert an die LED übertragen 
    analogWrite(led2Pin, 255-leuchtwert);                         // 255 LeuchtWERTe erzeugt genau das umgekehrte Verhalten     
    delay(2);                                                     // mind. 2ms Wartezeit notwendig zur Fehlervermeidung                         
  } 
  for(int leuchtwert = 255; leuchtwert >= 0; leuchtwert--) {      // fadeValue wird in 5er-Schritten runtergezählt 
    analogWrite(led1Pin, leuchtwert);                             // und als analoger Wert an die LED übertragen 
    analogWrite(led2Pin, 255-leuchtwert);                         // 255 Leuchtwerte erzeugt genau das umgekehrte Verhalten    
    delay(2);                                                     // kurze Wartezeit                     
  } 
}


Quelle: 
www.fritzing.org/creator-kit



Ausgabediagramm

Die Spannung steigt bis auf 5V an und fällt danach wieder auf 0V ab.
Wie vorher erwähnt, geschiet dies durch schnelles An- und Ausschalten - PWM.


Quelle:  
x704_b_fritzing-x_CREATOR KIT - K.9 (Einführung in den kreativen Umgang mit Elektronik)135 Seiten_1a.pdf





*********************************************************
                                  PWM


Abb. 4.8: Ausgangssignal des PWM

Analoge Ausgänge
Das Ausgeben einer Spannung an den analogen Ausgängen wird mittels Pulswei-tenmodulation (PWM) realisiert.
Die Grundfrequenz liegt dabei bei ungefähr 490 Hertz.
Der Wert liegt im Bereich von o bis 255, das entspricht 8 Bit.

analogWrite(PortNummer, Wert)
analogWrite(10, 123); // Ausgeben eines analogen Wertes an Port 10


Für die analoge Ausgabe sind folgende Ports möglich:
(3, 5, 6, 9, io, II): Arduino-Standardboards
(2-13): Arduino Mega

Hinweis:
Anwendungsbeispiele und Konfigurationsmöglichkeiten der analogen Ausgabe als PWM sind in ARDUINO Praxiseinstieg Kapitel 4 ausführlicher beschrieben.

Siehe auch ARDUINO Kochbuch
Kapitel 18

http://sites.prenninger.com/arduino-kochbuch/kapitel-18-deutsch


18.6 Ändern einer Timer-PWM-Frequenz
Problem
Sie müssen sich erhöhen oder verringern die Pulsweitenmodulation (PWM) Frequenz verwendet mit analogWrite (siehe Kapitel 7).
Zum Beispiel können Sie mit analogWrite sind mit einer Steuer Motordrehzahl und es gibt ein hörbares Brummen, da die PWM-Frequenz zu hoch ist, oder Sie sind Multiplexing LEDs und das Licht ist uneben, weil PWM-Frequenz zu niedrig ist.

Lösung
Sie können die PWM-Frequenz durch Ändern einer Registerwert einstellen. Die Registerwerte und die damit verbundenen Frequenzen sind in Tabelle 18-2 gezeigt.
Tabelle 18-2. Einstellwerte für PWM
usw.

Quelle:
http://sites.prenninger.com/arduino-kochbuch/kapitel-18-deutsch



*********************************************************
7.0 Analoge Ausgänge

Analog bezieht sich auf die Spannungspegel, die schrittweise bis zum Maximum verändert werden können (denken Sie an Helligkeits- und Lautstärkeregler).
Arduino besitzt die Funktion analogWrite, mit deren Hilfe Sie beispielsweise die Helligkeit einer mit dem Arduino verbundenen LED steuern können.

Die analogWrite Funktion arbeitet in Wahrheit gar nicht analog, auch wenn sie sich so verhält (wie Sie gleich noch sehen werden).
analogWrite
verwendet eine Technik, die man als Pulsweitenmodulation (Pulse Width Modulation, kurz PWM) bezeichnet.
Sie emuliert ein analoges Signal mit Hilfe digitaler Impulse.
PWM verändert dabei die Dauer der An/Aus-Zeiten der Impulse (siehe Abbildung 7-1).
Niedrige Ausgangswerte werde dabei durch Impulse erzeugt, die nur für eine kurze Zeitspanne an sind.
Bei höheren Ausgangswerten werden diese An-Perioden immer länger.
Werden diese Impulse schnell genug wiederholt (beim ARDUINO UNO R3 etwa 500 mal pro Sekunde), können wir Menschen dieses Pulsieren nicht mehr erkennen,
und LEDs sehen so aus, als würde sich ihre Helligkeit sanft verändern, wenn die Impulsbreite verändert wird.

Abbildung 7-1: PWM-Ausgabe für verschiedene analog Write-Werte


Der Arduino besitzt nur eine beschränkte Anzahl von Pins, die für die analoge Ausgabe verwendet werden können.
Bei einem Standard-Board stehen die Pins 3, 5, 6, 9, 10 und 11 zur Verfügung.
Bei einem Arduino Mega können Sie die Pins 2 bis 13 für analoge Ausgaben nutzen.
Viele der nachfolgenden Sketches nutzen Pins, die sowohl digital als auch analog genutzt werden können.
Sie müssen dann nicht alles neu verdrahten, wenn Sie andere Rezepte ausprobieren wollen.
Wenn Sie andere Pins für die analoge Ausgabe wählen, müssen Sie sich für einen der anderen Pins entscheiden, die von analogWrite unterstützt werden (alle anderen Pins erzeugen keinen Ausgabewert).

Quelle:
O'REILLY - ARDUINO Kochbuch Seite 241




7.2 Helligkeit einer LED regeln

Problem
Sie wollen die Helligkeit einer oder mehrerer LEDs aus Ihrem Sketch heraus regeln.
Lösung
Verbinden Sie jede LED mit einem PWM-fähigen Analogausgang. Verwenden Sie die Verschaltung aus Abbildung 7-2.
Der Sketch lässt die LED langsam (über einen Zeitraum von etwa 5 Sekunden) immer heller werden und dann wieder dunkel.

/*
LedBrightness Sketch
Steuert die Helligkeit von LEDs an analogen Ausgangsports
*/

const int firstLed = 3;     // Pins für die LEDs festlegen
const int secondLed = 5;
const int thirdLed = 6;

int brightness = 0;
int increment = 1;

void setup()
{
// Mit analogWrite angesteuerte Pins müssen nicht als Ausgänge deklariert werden
}

void loop()
{
if(brightness > 255)
{
increment = -1; // Beim Erreichen von 255 herunterzählen
}
else if(brightness < 1)
{
increment = 1; // Beim Erreichen von 0 wieder hochzählen
}
brightness = brightness + increment; // Inkrementieren (oder bei negativem Vorzeichen
                                     // dekrementieren)
                                     // Helligkeitswert an die LEDs schreiben
analogWrite(firstLed, brightness);
analogWrite(secondLed, brightness);
analogWrite(thirdLed, brightness );

delay(10); // ioms pro Schritt bedeutet 2,55 Sekunden für auf- und abblenden
}


Diskussion
Wir verwenden die gleiche Verschaltung wie im vorigen Sketch, steuern die Pins aber über analogWrite anstelle von digitalWrite an. analogWrite nutzt PWM, um die Spannung an der LED zu kontrollieren. In der Einführung zu diesem Kapitel erfahren Sie mehr über analoge Ausgänge.
Der Sketch regelt die Helligkeit, indem er den Wert der brightness-Variable bei jedem Schleifendurchlauf erhöht (heller) oder verringert (dunkler).
Dieser Wert wird dann über die analogWrite-Funktion an die drei angeschlossenen LEDs übergeben. Der Minimalwert für analogWrite ist 0 — das entspricht einer Spannung von 0 Volt am Pin.
Der Maximalwert ist 255 und hält die Spannung am Pin bei 5 Volt.
Erreicht die brightness-Variable ihren Maximalwert, wird sie wieder kleiner, weil sich das Vorzeichen von increment von +1 auf —1 ändert (-1 zu einem Wert zu addieren ist das gleiche, wie eine 1 zu subtrahieren).
Siehe auch
Die Einführung zu diesem Kapitel erläutert, wie die Analogausgänge des Arduino funktionieren.

Quelle:
O'REILLY - ARDUINO Kochbuch Seite 248





7.15 Ein analoges Anzeigeinstrument nutzen
Problem
Sie wollen den Zeiger einer Analoganzeige aus dem Sketch heraus steuern.
Schwankende Messwerte lassen sich auf einer Analoganzeige leichter Interpretieren und verleihen Ihrem Projekt einen coolen Retro-Look.
Lösung
Verbinden Sie die Anzeige über einen Vorwiderstand (5kOhm sind für ein 1 mA-Meter üblich) mit einem analogen (PWM) Ausgang
(siehe Abbildung 7-17).

Abbildung 7-17: Eine analoge Anzeige ansteuern


Die Bewegung der Anzeige entspricht der Position eines Potentiometers (variablen Widerstands):

/*
* AnalogMeter Sketch
* Steuert eine Analoganzeige über einen Arduino-PWM-Pin
* Der Pegel der Anzeige wird dabei durch den variablen Widerstand am Analogeingang bestimmt
*/

const int analogInPin = 0;    // Analoger Eingang für Poti
const int analogMeterPin = 9; // Analoger Ausgang für Anzeige

int sensorValue = 0;          // Vom Poti eingelesener Wert
int outputValue = 0;          // PWM-Ausgabewert

void setup()
{
// Hier ist nichts zu tun
}

void loop()
{
sensorValue = analogRead (analogInPin ) ;        // Analogwert einlesen
outputValue = map(sensorValue, 0, 1023, 0, 255); // Für analoge Ausgabe skalieren
analogWrite(analogMeterPin, outputValue);        // Wert an analogen Ausgang schreiben
}


Diskussion
Bei dieser Variante von Rezept 7.2 steuert der Arduino mit analogWrite eine Analoganzeige.
Solche Anzeigen sind üblicherweise viel empfindlicher als LEDs.
Ein Widerstand muss zwischen den Arduino-Ausgang und die Anzeige geschaltet werden, um den Strom entsprechend zu begrenzen.
Der Wert des Vorwiderstands hängt von der Empfindlichkeit der Anzeige ab. 5k Ohm sorgen bei einer 1 mA-Anzeige für einen Vollausschlag.
Sie können einen 4,7k Widerstand verwenden, da sie leichter zu beschaffen sind als 5K, allerdings müssen Sie dann den Maximalwert für analogWrite auf etwa 240 beschränken.
Nachfolgend sehen Sie, wie Sie den Wertebereich der map-Funktion anpassen müssen, wenn Sie einen 4,7k Widerstand für eine 1 mA-Anzeige verwenden:

outputValue = map(sensorValue, 0, 1023, 0, 240); // Auf Anzeigebereich abbilden

Arbeitet Ihre Anzeige nicht mit 1 mA, müssen Sie einen anderen Vorwiderstand verwenden. Die Formel für den Widerstand in Ohm lautet
Widerstand = 5000 / mA
Bei einer 500 Mikroampere-Anzeige (0,5 mA) ist das also 5000 / 0,5, d.h. 10000 (10 K) Ohm.
Eine 10 mA-Anzeige benötigt 500 Ohm, bei 20 mA 250 Ohm.

Bei einigen Anzeigen sind bereits interne Vorwiderstände integriert.
Sie müssen möglicherweise experimentieren, um den korrekten Wert des Vorwiderstands zu ermitteln, achten Sie aber darauf, die Anzeige nicht mit zu viel Strom zu versorgen.
Siehe auch Rezept 7.2  Seite 248 Helligkeit eine LED regeln

Quelle:
O'REILLY - ARDUINO Kochbuch Seite 285




*********************************************************
9.5 Analoge Ausgabe PWM
 
Es stehen beim Arduino-Board sechs PWM-Ausgänge zur Verfügung: Pin 3, 5, 6, 9, 10 und 11, bei den älteren ATmega8-Controllern nur die Pins 9, 10 und 11.
Diese können zur DA-Umsetzung, zur Ansteuerung von Servomotoren oder zur Ausgabe von Tonfrequenzen benutzt werden.
Bei der Puls-Weiten-Modulation (engl.: Pulse Width Modulation) wird ein digitales Ausgangssignal erzeugt, dessen Tastverhältnis moduliert wird.
Das Tastverhältnis gibt das Verhältnis der Länge des eingeschalteten Zustands zur Periodendauer an.
Dabei bleiben die Frequenz und der Pegel des Signals immer gleich.
Es ändert sich nur die Länge von High zu Low.

analogWrite(pin, value)
Dieser Befehl schreibt pseudoanaloge Werte mittels einer hardwarebasierten Pulsweitenmodulation (PWM) an einen Ausgangspin. Der Wert kann als Variable oder Konstante im Bereich von 0-255 festgelegt werden
.
analogWrite(pin, value);    // schreibt value auf den analogen Pin


Ein Wert 0 generiert eine gleichmäßige Spannung von 0 V an einem festgelegten Analog-Pin.
Ein Wert von 255 generiert eine gleichmäßige Spannung von 5 V an einem festgelegten Analog-Pin.
Für Werte zwischen 0 und 255 wechselt der Pin sehr schnell zwischen 0 und 5 V, je höher der Wert, desto länger ist der Pin HIGH (5 V).
Bei einem Wert von 64 ist der Pin zu Dreiviertel der Zeit auf 0 V und zu einem Viertel auf 5 V.
Ein Wert von 128 führt dazu, dass die Ausgangsspannung zur Hälfte der Zeit auf HIGH steht und zur anderen Hälfte auf LOW.
Bei 192 misst die Spannung am Pin zu einem Viertel der Zeit 0 V und zu Dreiviertel die vollen 5 V.
Weil dies eine hardwarebasierte Funktion ist, läuft die konstante Welle unabhängig vom Programm bis zur nächsten Änderung des Zustands per analogWrite (oder einem Aufruf von digitalRead oder digitalWrite am selben Pin).

INFO:
Analoge Pins müssen, im Gegensatz zu digitalen, nicht zuvor als Ein- oder Ausgang deklariert werden.


Dieses Beispiel lässt die LEDs sehr oft blinken.
Die PWM stellt hier die Helligkeit ein.

Beispiel: AnalogWrite.ino

// FRANZIS ARDUINO 
Analog Write

int value;
int LEDgruen=10; // grüne LED mit 470R Vorwiderstand an pin-10
int LEDrot=11;  
// rote LED mit 560R Vorwiderstand an pin-11

void setup()
{
// Diesmal kommt hier nichts herein
}

void loop()

{
for(value=0;value<255;value++)
{
analogWrite(LEDgruen, value);
analogWrite(LEDrot, 255-value);

delay(5);
              // 5ms warten
}

delay(1000);    
// 1Sek. warten
for(value=255;value!=0;value--)

{
analogWrite(LEDgruen, value);
analogWrite(LEDrot, 255-value);
delay(5);

}
delay(1000);

}




Wenn Sie an den Analogausgang nun den kleinen Piezo-Schallwandler anschließen, können Sie die Pulse hörbar machen.
Der Buzzer ist jedoch nicht sonderlich laut.

Mach mal Pause mit delay
In den vorhergehenden Beispielen haben wir bereits mehrmals eine kleine Pause mittels delay() eingebaut.

delay(ms)
pausiert ein Programm für die Dauer der Zeit, angegeben in Millisekunden, wobei 1000 = 1 Sekunde entspricht.
delay (1000 ) ;    // wartet für eine Sekunde


micros()
pausiert ein Programm für die Dauer der Zeit angegeben in Mikrosekunden, wobei 1000 = 1 Millisekunde entspricht.
micros (1000);    // wartet für eine Millisekunde


Quelle:
FRANZIS - ARDUINO Mikrocontroller-Programmierung mit Arduino Seite 122





10.8 DAC mit PWM-Ports  Seite 151
Die meisten in der Natur vorkommenden Signale sind analog.
Daher ist es für eine digital arbeitende Maschine notwendig, die digitalen Werte in analoge Größen umzusetzen, wenn externe Vorgänge beeinflusst werden sollen.
Benötigen wir eine analoge Spannung, muss ein RC-Glied an den Analogausgang angeschlossen werden, das aus dem PWM-Signal eine quasi analoge Spannung formt.
Die meisten Mikrocontroller, wie auch der Arduino-Mikrocontroller, haben keinen echten DA-Wandler integriert.
Allerdings kann man mittels des PWM-Signals auch eine DA-Wandlung vornehmen und Gleichspannung generieren.
Wird ein PWM-Signal über einen Tiefpass gefiltert (geglättet), entsteht eine Gleichspannung mit Wechselanteil, deren Mittelwert dem des PWM-Signals entspricht und deren Wechselanteil von der Beschaltung abhängig ist.


Bild 10.10: Aufbau eines RC-Glieds zur Glättung der PWM




Das RC-Glied zur Glättung berechnet sich wie folgt:


Fg = 1 (2x3,14x10000 x 0,000001) = 15,9 Hz


Fg = Grenzfrequenz des PWM-Signals  z.B. 16 Hz
Pi = 3,14
R = Widerstand in Ohm  z.B. 10k
C = Kondensator in Farad  z.B. 1uF

Der im Beispiel verwendete RC-Tiefpass besteht aus einem 1uF Kondensator und einem 10k   Widerstand und besitzt eine Grenzfrequenz von 16 Hz.

Das RC-Glied darf in diesem Zustand natürlich nicht sonderlich belastet werden, da sich der Kondensator sonst zu schnell entladen würde.
Dadurch würde das RC-Glied überflüssig oder die Welligkeit, auch Rippel genannt, würde sich erhöhen.
Am besten man setzt noch eine Treiberendstufe hinter das RC-Glied, sodass das Signal auf den gewünschten Level angehoben und der erforderliche Strom abgegeben werden kann.
Für unseren Versuch können wir die Spannung über den analogen Eingangs pin-A0 messen.

/* Beispiel: sketch_DAC_1a.ino  Franzis Arduino DAC */
char buffer[18];
int pinPWM = 9;
int raw = 0;
float Volt = 0;

void setup() 
{
  Serial.begin(9600);
  Serial.println("DAC mit PWM-Ausgang");
  Serial.println();
  Serial.println("Geben Sie einen Wert zwischen 0 und 255 ein");
  Serial.flush();
}

void loop() 
{
  if (Serial.available() > 0)
  {
    int index = 0;
    delay(100);    // warten, bis die Zeichen im Puffer sind
    int numChar = Serial.available();
    if (numChar > 15) 
    {
      numChar = 15;
    }
    while (numChar--) 
    {
      buffer[index++] = Serial.read();
    }
    splitString(buffer);
  }
}

void splitString(char* data)
{
  Serial.print("Empfangen wurde der Wert: ");
  Serial.println(data); 
  char* parameter; 
  parameter = strtok (data, " ,");
  while (parameter != NULL)
  {

    setPWM(parameter);
    parameter = strtok (NULL, " ,");
  }
  
  // Puffer wieder löschen
  for (int x=0; x<16; x++)
  {
    buffer[x] = '\0';
  }
  Serial.flush();
}

void setPWM(char* data)
{ 
  int Ans = strtol(data, NULL, 10);
  Ans = constrain(Ans, 0, 255);
  analogWrite(pinPWM, Ans);
  Serial.print("PWM = ");
  Serial.println(Ans);
  delay(100);
  
  raw = analogRead(0);
  float ref = 5.0/1024.0;
  Volt = raw * ref; 
  Serial.print("Die Spannung am ADCO beträgt: ");
  Serial.print(Volt);
  Serial.println(" Volt");
  Serial.println();
  Serial.println("Geben Sie einen Wert zwischen 0 und 255 ein");
}


Das Beispiel erzeugt ein PWM-Signal am Analogausgang pin-9.
Das Signal wird über das RC-Glied geglättet und über den Analogeingang pin-A0 gemessen.
Je kleiner der eingegebene Wert ist, desto kleiner ist die Ausgangsspannung am Filter.
Die Stellzeit von 0 auf 5 V oder von 5 auf 0 V beträgt ca. 40 ms.
Das Beispiel zeigt auch, wie man eine Dateneingabe über die serielle Schnittstelle gestalten kann.

Quelle:
FRANZIS - ARDUINO Mikrocontroller-Programmierung mit Arduino Seite 151





*********************************************************
4.3.2 Analoge Signale ausgeben

Die Ausgabe einer analogen Spannung mittels Pulsweitenmodulation (PWM) erfolgt mit dem Befehl analogWrite()
Das Ausgabesignal ist kein richtiges Analogsignal, sondern ein digitales Rechtecksignal mit veränderbarer HIGH-Phase.
Dabei bleibt die Frequenz unverändert.

Im Beispiel in Abb. 4.8 ist die Frequenz 489 Hz.

Die Syntax für die Ausgabe des Analogwertes lautet:

analogWrite(Pin, Wert)

Der Parameter Pin definiert den Ausgabeport für das PWM-Signal,  der Wert definiert die Länge der HIGH-Phase und liegt zwischen 0 und 255, was 0 bis 100%  entspricht.

Somit gibt es folgende HIGH- und Low-Phasen bei unterschiedlichen Werten:

Wert    HIGH-Phase   Low-Phase
0         0%         100%
127      50%          50%
255     100%           0%

Tabelle 4.1: PWM-Ausgang: HIGH- und Low-Phasen


Auf dem Arduino Uno stehen die pin-3, pin-5, pin-6, pin-9, pin-10 und pin-11 für die Ausgabe eines PWM-Signals zur Verfügung.

In Listing (Sketch) 4.8 wird ein PWM-Signal an pi-10  ausgegeben.
Der Wert für das PWM-Signal ist dabei fix mit 55 angegeben.

// Port für PWM
int PWMPin = 10;
   // PWM pin-10
int PWMWert = 0;
   // PWM Wert

void setup() {
pinMode(PWMPin, OUTPUT); 
// PWM-Port als Ausgang
}

void loop() {
// PWM setzen (0-255) - entweder fix oder als Wert von anderem Programm
int PWMWert = 55;
analogWrite(PWMPin, PWMWert); 
// PWM ausgeben
}


Listing 4.8: Ausgabe PWM-Signal


Bei der Verwendung der Ports mit PWM-Ausgang ist zu beachten, dass die einzelnen PWM-Signale unterschiedliche Frequenzen aufweisen, da sie von drei internen Timern gesteuert werden.

In Tabelle 4.2 sind die PWM-Ports sowie deren Timer und Ausgangsfrequenzen aufgelistet.

Port-Nr.    Frequenz von PWM-Signal   Timer-Register
Port  3     488 Hz                    TCCR2B
Port  5     976 Hz                    TCCR0B
Port  6     976 Hz                    TCCR0B
Port  9     488 Hz                    TCCR1B
Port 10     488 Hz                    TCCR1B
Port 11     488 Hz                    TCCR2B


Tabelle 4.2: Arduino PWM: Zuordnung von Port zum Timer-Register



Um die Frequenz des PWM-Signals zu verändern, muss in der Setup-Routine der Teilungsfaktor für die Frequenz verändert werden.
Das Beispiel in Listing 4.9 zeigt die Veränderung für pin-3 oder pin-11, die durch Timer 2 gesteuert werden.

// PWM pin-3 oder pin-11
int PWMPin = 11;

void setup(){
int pwmfreq = 7;
    //Änderung der Frequenz, Wert 7 ergibt Frequenz von 31 Hertz
TCCR2B = (TCCR2B & OxF8)| pwmfreq;

pinMode(PWMPin, OUTPUT);
   // PWM Port
}

void loop(){
PWMWert = 123;
analogWrite(PWMPin, PWMWert);
   // PWM ausgeben

}

Listing 4.9: PWM-Frequenz verändern


Die Frequenzen und deren Konfigurationswerte für Timer 2 sehen wie folgt aus:

Frequenz    Wert
31372 Hz    1
3921 Hz     2
980 Hz      3
490 Hz      4 (Default)
245 Hz      5
122 Hz      6
31  Hz      7

Tabelle 4.3: PWM-Frequenzen für Pins 3 und ii (Timer 2)


Den Spickzettel aller Timer und der möglichen Frequenzen gibt's für den Praktiker unter:

http://www.arduino.cc/playground/Main/TimerPWMCheatsheet
Einstellen PWM-Frequenzen

Für weitere Kenntnisse über Arduino PWM-Frequenzen beziehen sich auf die ATmega328p  ein vollständiges Datenblatt auf der www. Arduino.cc Seite

"Secrets of Arduino PWM" http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM


Umwandlung PWM in Analogspannung
Eine Schaltung mit Widerstand und Kondensator wie in Abbildung 4.9 kann aus dem digitalen Pulssignal eine analoge Spannung erzeugen.





Abb. 4.9: Analoge Ausgabe - Spannung aus PWM-Signal erzeugen
Wie man eine analoge Spannung ohne PWM-Signal generieren kann, wird in KAPITEL 6 im Projekt SIGNALGEBER beschrieben.

Quelle:
mitp  - ARDUINO Praxiseinstieg Seite 101





*********************************************************
Einstellen PWM-Frequenzen
Für weitere Kenntnisse über Arduino PWM-Frequenzen beziehen sich auf die ATMega Vollständiges Datenblatt und dieser Arduino.cc Seite "Secrets of Arduino PWM"
http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM


In Bezug auf Arduino Mega

Dieser Artikel ist nicht vollständig kompatibel zu Arduino Mega (oder ATmega2560 Mikroprozessor)

For Arduino Mega: (tested on Arduino Mega 2560)
timer 0 (controls pin 13, 4)
timer 1 (controls pin 12, 11)
timer 2 (controls pin 10, 9)
timer 3 (controls pin 5, 3, 2)
timer 4 (controls pin 8, 7, 6)


TCCRnB, where 'n' is the number for the timer.
TCCR2B for timer 2, TCCR3B for timer 3.
Eg:

TCCR2B = TCCR2B & 0b11111000 | 0x01;
//sets Arduino Mega's pin 10 and 9 to frequency 31250.
//code typically inserted in setup()

Thanks to valerio_sperati
http://arduino.cc/forum/index.php/topic,72092.0.html

Wie man am Arduino die PWM-Frequenzen einstellt

by macegr in this forum post http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1235060559/12

Pins 5 and 6: controlled by Timer 0 in fast PWM mode (cycle length = 256)

Setting 	Divisor 	Frequency
0x01 	 	1 	 	62500
0x02  		8 	 	7812.5
0x03  		64 	 	976.5625   <--DEFAULT
0x04 	 	256 	 	244.140625
0x05 	 	1024 	 	61.03515625

TCCR0B = TCCR0B & 0b11111000 | <setting>;

Pins 9 and 10: controlled by timer 1 in phase-correct PWM mode (cycle length = 510)

Setting 	Divisor 	Frequency
0x01 	 	1 	 	31372.55
0x02 	 	8 	 	3921.16
0x03  		64 	 	490.20   <--DEFAULT
0x04  		256 	 	122.55
0x05 	 	1024 	 	30.64

TCCR1B = TCCR1B & 0b11111000 | <setting>;

Pins 11 and 3: controlled by timer 2 in phase-correct PWM mode (cycle length = 510)

Setting 	Divisor 	Frequency
0x01 	 	1  		31372.55
0x02 	 	8 	 	3921.16
0x03  		32  		980.39
0x04 	 	64 	 	490.20   <--DEFAULT
0x05 	 	128  		245.10
0x06  		256  		122.55
0x07 	 	1024  		30.64

TCCR2B = TCCR2B & 0b11111000 | <setting>;

Alle Frequenzen in Hz bei einem 16 MHz Systemtakt.



Fragen aus der Anpassung PWM Frequenzen und Lösungen

from koyaanisqatsi in this forum post http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1235060559/12

Wenn Sie TCCR0B ändern, wirkt sich dies millis () und Delay ().
Sie werden Zeit schneller oder langsamer als normal zu zählen, wenn Sie die TCCR0B Einstellungen zu ändern.
Unten ist der Anpassungsfaktor, um konsistente Verhalten dieser Funktionen zu erhalten:

Default: delay(1000) or 1000 millis() ~ 1 second

0x01: delay(64000) or 64000 millis() ~ 1 second
0x02: delay(8000) or 8000 millis() ~ 1 second
0x03: is the default
0x04: delay(250) or 250 millis() ~ 1 second
0x05: delay(62) or 62 millis() ~ 1 second
(Or 63 if you need to round up. The number is actually 62.5)

Also, the default settings for the other timers are:
TCCR1B: 0x03
TCCR2B: 0x04

Jeder Gedanke auf dem Arduino Mega?

PWM frequencies on Timer 0, pins 5 and 6, Arduino Uno

by yanngg, 02-15-2012

Timer 0 verwendet eine Prescale Faktor, der zu 64 voreingestellt
So legen Sie den Prescale Faktor verwenden Sie diese Zeile in der Setup-Funktion
Setting                          Prescale_factor
TCCR0B = _BV(CS00);              1
TCCR0B = _BV(CS01);              8
TCCR0B = _BV(CS00) | _BV(CS01);  64
TCCR0B = _BV(CS02);              256
TCCR0B = _BV(CS00) | _BV(CS02);  1024


Fast PWM Timer 0 zu verwenden
Schreiben Sie die folgende Zeile in der Setup-Funktion
TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM01) | _BV(WGM00);
Und die PWM-Frequenz zu berechnen verwenden
Fast_PWM_frequency = (16 000 000)/(Prescale_factor*256);

Phase-PWM auf korrekte Timer 0 zu verwenden (die Hälfte der Frequenz von Fast PWM)
Schreiben Sie die folgende Zeile in der Setup-Funktion
TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00);
Und die PWM-Frequenz zu berechnen verwenden
Phase_correct_PWM_frequency = (16 000 000)/(Prescale_factor*510);

Ändern des Prescale Faktor auf Timer0 wird Funktionen beeinflussen
millis () micros (), Delay (), ...

So passen millis () micros (), Delay (), ... dementsprechend
Sie können eine Zeile in der wiring.c Funktion in den Programmdateien Arduino ändern
hardware\arduino\cores\arduino\wiring.c

Zu Beginn des wiring.c finden Sie:
// Der Vorteiler ist so eingestellt, dass Timer0 Zecken alle 64 Taktzyklen, und die
// Der Überlauf-Handler wird alle 256 Ticks genannt.
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))

Sie müssen die Prescale Faktor in dieser Funktion auf die entsprechende Zeile ändern

Für die schnelle PWM (default):
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(PRESCALE_FACTOR* 256))
Für phasenrichtige PWM:
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(PRESCALE_FACTOR * 510))

Example: DC motor drive on the Arduino UNO, pin-5 and pin-6

Für schnelle PWM von 62,500 kHz (Prescale Faktor 1)
Verwenden Sie diese zwei Zeilen in der Setup-Funktion:

TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM01) | _BV(WGM00);
TCCR0B = _BV(CS00);


Und ändern Sie die Zeile in der wiring.c Funktion in den Programmdateien Arduino
Hardware \ arduino \ Kerne \ arduino \ wiring.c:
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(1 * 256))

Für Phase-korrekte PWM von 31,250 kHz (Prescale Faktor 1)
Verwenden Sie diese zwei Zeilen in der Setup-Funktion:

TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00);
TCCR0B = _BV(CS00);


Und ändern Sie die Zeile in der wiring.c Funktion in den Programmdateien Arduino
Hardware \ arduino \ Kerne \ arduino \ wiring.c:
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(1 * 510))


Quelle:
http://www.arduino.cc/playground/Main/TimerPWMCheatsheet




*********************************************************
Der fortgeschrittene Anwender findet zum Thema PWM Secrets weitere Informationen, wie man die Timer verändern kann, unter folgender Adresse:


http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM
Geheimnisse der Arduino PWM

von Ken Shirriff
mit weiteren Bearbeitung von Paul Badger
das Originaldokument

Pulsbreitenmodulation (PWM) auf der Arduino auf verschiedene Weise implementiert werden.
Dieser Artikel erklärt, einfache PWM-Techniken, als auch, wie man die PWM-Register direkt für mehr Kontrolle über das Tastverhältnis und Frequenz verwenden.

Dieser Artikel konzentriert sich auf die Arduino Duemilanove Diecimila und Modellen, welche die ATmega168 oder ATmega328 zu verwenden.

Falls Sie nicht mit Pulsweitenmodulation sind, finden Sie in der Anleitung.
Kurz gesagt wird ein PWM-Signal eine digitale Rechteckwelle, bei der die Frequenz konstant ist, aber der Anteil an der Zeit, das Signal eingeschaltet ist (das Tastverhältnis) zwischen 0 und 100% variiert werden.




PWM-Beispiele

PWM hat mehrere Einsatzmöglichkeiten:

    
Dimmen eine LED
    
Bereitstellen eines analogen Ausgangssignals; wenn das digitale Ausgangssignal wird gefiltert,
    
es wird eine Analogspannung zwischen 0% und 100% bereitzustellen.
    
Erzeugen von Audiosignalen.
    
Bereitstellung von Drehzahlregelung für Motoren.
    
Erzeugen eines modulierten Signals, beispielsweise um eine Infrarot-LED für eine Fernbedienung zu fahren.

Einfache Pulsweitenmodulation mit analogWrite

Programmiersprache Die Arduino macht PWM einfach zu bedienen; rufen analogWrite (pin, Tastverhältnis), wobei Tastverhältnis ein Wert von 0 bis 255 und Pin ist eine der PWM Stifte (3, 5, 6, 9, 10 oder 11).
Die analogWrite Funktion bietet eine einfache Schnittstelle zur Hardware PWM, aber keine Kontrolle über die Frequenz bereitzustellen.

(Man beachte, daß trotz der Funktionsname, der ein digitales Signal, das oft als eine Rechteckwelle bezeichnet).

Wahrscheinlich 99% der Leser kann hier aufhören, und verwenden Sie nur analogWrite, aber es gibt andere Optionen, die mehr Flexibilität bieten.

Bit-banging PulsWeitenModulation (PWM)

Sie können "von Hand" zu implementieren PWM auf jedem Stift durch wiederholtes Ein- und Ausschalten die PIN für die gewünschte Zeit. z.B.

void setup()
{
  pinMode(13, OUTPUT);
}

void loop()
{
  digitalWrite(13, HIGH);
  delayMicroseconds(100);     //
Etwa 10% Einschaltdauer bei 1kHz
  digitalWrite(13, LOW);
  delayMicroseconds(1000 - 100);
}



Diese Technik hat den Vorteil, dass es keine digitalen Ausgangsstift zu verwenden.
Darüber hinaus haben Sie die volle Kontrolle das Tastverhältnis und Frequenz.

Ein großer Nachteil ist, dass alle Interrupts wird das Timing, die erhebliche Jitter verursachen kann, es sei denn, Sie deaktivieren Interrupts beeinflussen.

Ein zweiter Nachteil ist, können Sie nicht aus dem Ausgabelauf, während der Prozessor tut etwas anderes.

Schließlich ist es schwierig, die entsprechenden Konstanten für einen bestimmten Arbeitszyklus und die Frequenz bestimmen, es sei denn, man entweder sorgfältig zählen Zyklen oder zwicken die Werte, während Sie ein Oszilloskop.

Ein aufwendiger Beispiel manuell PWMing alle Pins finden Sie hier.


Verwenden des ATmega PWM-Register direkt

Die ATmega168p / ATmega328P Chip hat drei PWM-Timer, Steuerung 6 PWM-Ausgänge.
Durch die direkte Manipulation von Zeitgeberregister des Chips, können Sie mehr Kontrolle als die analogWrite Funktion liefert zu erhalten.

Der AVR ATmega328p Datenblatt enthält eine detaillierte Beschreibung der PWM-Timer, aber das Datenblatt kann schwer zu verstehen, aufgrund der vielen unterschiedlichen Steuer- und Ausgabearten der Timer.

Ein Wort über die Beziehung zwischen dem Arduino Sprache und dem Datenblatt kann, um hier zu sein.

Die ATmega168 
ATmega328 Timer.

Die ATmega328p hat drei Timer als Timer 0, Timer 1 und Timer 2.
Jeder Timer hat zwei Ausgangsregister, die die PWM Breite für zwei Ausgänge des Timers zu steuern vergleichen bekannt: wenn der Timer die Vergleichsregister Wert erreicht, wird der entsprechende Ausgang umgeschaltet.

Die beiden Ausgänge für jeden Zeitgeber wird in der Regel die gleiche Frequenz, jedoch unterschiedliche Tastverhältnisse haben (abhängig von der jeweiligen Ausgangsvergleichs-Register).

Jeder der Zeitgeber hat einen Vorteiler, der die Zeitschaltuhr erzeugt durch Teilen des Systemtakts durch einen Skalierwert Faktor, wie 1, 8, 64, 256 oder 1024.
Die Arduino hat einen Systemtakt von 16 MHz und die Timer-Taktfrequenz wird das
Systemtaktfrequenz geteilt durch den Faktor Skalierwert.
Beachten Sie, dass Timer 2 hat einen anderen Satz von Prescale Werte von den anderen Timern.

Die Timer werden von mehreren verschiedenen Modi kompliziert.
Die Haupt-PWM-Modi "Fast PWM" und "Phase-PWM korrekte", die nachfolgend beschrieben werden.

Der Zeitgeber kann entweder ausgeführt 0-255 oder von 0 auf einen festen Wert ein.

(Der 16-Bit-Zeitgeber 1 weist zusätzliche Modi unterstützt Timerwerte bis zu 16 Bit).
Jeder Ausgang kann auch invertiert werden.

Die Timer-Interrupts können auch bei Überlauf und / oder Spiel gegen beiden Ausgangsvergleichs-Register zu generieren, aber das ist über den Rahmen dieses Artikels sprengen.
Timer-Register Mehrere Register werden verwendet, um jeden Timer steuern.
Der Zeitgeber / Zähler Kontrollregister TCCRnA und TCCRnB halten die Haupt Kontrollbits für den Timer.
(Beachten Sie, dass TCCRnA und TCCRnB nicht an die Ausgänge A und B entsprechen)
Diese Register enthalten mehrere Bitgruppen:

    
Wellenform-Generierungsmodus-Bits (WGM): Sie steuern den Gesamtbetrieb des Timers.
    
(Diese Bits werden zwischen TCCRnA und TCCRnB aufgeteilt.)
    
Clock Select Bit (CS): Diese steuern die Takt Vorteiler
    
Vergleichen Spiel Output A Mode-Bits (COMnA): Sie aktivieren / deaktivieren / Invert-Ausgang A
    
Vergleichen Spiel Output B-Modus-Bits (COMnB): Sie aktivieren / deaktivieren / Invert-Ausgang B

Die Ausgangsvergleichsregister OCRnA und OCRnB setzen Sie die Ebenen, auf denen Ausgänge A und B betroffen sein werden.
Wenn der Zeitgeberwert den Registerwert übereinstimmt, wird das entsprechende Ausgangs modifiziert werden, wie durch den Modus spezifiziert.

Die Bits sind etwas anders für jeden Timer, so konsultieren Sie das Datenblatt für Details.
Timer 1 ist ein 16-Bit-Timer und zusätzliche Modi.
Timer 2 unterschiedliche Werte Vorteiler.

Schnelle PWM

Im einfachsten PWM-Modus, der Timer zählt wiederholt von 0 bis 255.
Der Ausgang wird eingeschaltet, wenn der Timer auf 0 ist, und erlischt, wenn der Zeitgeber entspricht der Ausgangsvergleichsregister.

Je höher der Wert in dem Ausgangsvergleichs-Register, je höher das Tastverhältnis.

Dieser Modus wird als Fast PWM-Modus bekannt.

Das folgende Diagramm zeigt die Ausgänge für zwei bestimmte Werte OCRnA und OCRnB.

Man beachte, daß beide Ausgänge den gleichen Frequenzverhältnisses, Anpassung der Frequenz eines kompletten Zeitgeberzyklus.

Schnelle PWM-Modus

Das folgende Codefragment richtet schnelle PWM auf den Pins 3 und 11 (Timer 2).
In das Register Einstellungen zusammenfassen, die Einstellung der Wellenform-Erzeugungsmodus-Bits WGM zu 011 wählt schnelle PWM.

Einstellen der COM2A Bits und COM2B Bits bis 10 bietet nicht invertierten PWM für die Ausgänge A und B.
Einstellung der CS Bits auf 100 Sätze der Vorteiler, um die Uhr nach 64 teilen
(Da die Bits für die verschiedenen Timer sind, konsultieren Sie das Datenblatt
für die richtigen Werte.)
Die Ausgangsvergleichsregister werden willkürlich auf 180 und 50 eingestellt, um die PWM-Tastverhältnis von Ausgängen A und B zu steuern
(Natürlich können Sie die Register direkt anstatt pinMode ändern, aber Sie brauchen nicht zu setzen
die Stifte bis zur Ausgabe.)


  pinMode(3, OUTPUT);
  pinMode(11, OUTPUT);
  TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
  TCCR2B = _BV(CS22);
  OCR2A = 180;
  OCR2B = 50;


Auf der Arduino Duemilanove, ergeben diese Werte:

    
Ausgang A Frequenz: 16 MHz / 64/256 = 976.5625Hz
    
Ausgang A Einschaltdauer: (180 + 1) / 256 = 70,7%

    
Ausgang B Frequenz: 16 MHz / 64/256 = 976.5625Hz
    
Ausgang B Einschaltdauer: (50 + 1) / 256 = 19,9%

Die Ausgangsfrequenz ist 16 MHz Systemtaktfrequenz geteilt durch den Prescaler-Wert (64), geteilt durch die 256 Zyklen, die für den Timer zyklisch durchlaufen.
Beachten Sie, dass schnelle PWM hält den Ausgang hoch ein Zyklus länger als das Vergleichsregister Wert.


Phasenrichtige PWM

Die zweite PWM-Modus wird als phasenrichtige PWM. In diesem Modus wird der Timer zählt von 0 bis 255 und dann wieder auf 0.
Der Ausgang schaltet sich aus, wie der Countdown der Ausgangsvergleichsregister Wert auf dem Weg nach oben und dreht sich wieder auf, wie der Countdown der Ausgangsvergleichsregister Wert auf
nach unten.
Das Ergebnis ist ein symmetrischer Ausgang.

Die Ausgangsfrequenz wird etwa die Hälfte des Wertes für die schnelle PWM-Modus, weil die Zeit abgelaufen ist nach oben und unten.

Phasenrichtige PWM Beispiel

Das folgende Codefragment richtet phasenrichtige PWM auf den Pins 3 und 11 (Timer 2).
Die Wellenform-Erzeugungsmodus-Bits WGM sind zu 001 für phasenrichtige PWM gesetzt.

Die anderen Bits sind die gleichen wie für schnelle PWM.


  pinMode(3, OUTPUT);
  pinMode(11, OUTPUT);
  TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM20);
  TCCR2B = _BV(CS22);
  OCR2A = 180;
  OCR2B = 50;


Auf der Arduino Duemilanove, ergeben diese Werte:

    
Ausgang A Frequenz: 16 MHz / 64/255/2 = 490.196Hz
    
Ausgang A Einschaltdauer: 180/255 = 70,6%

    
Ausgang B Frequenz: 16 MHz / 64/255/2 = 490.196Hz
    
Ausgang B Einschaltdauer: 50/255 = 19,6%

Phasenrichtige PWM teilt die Frequenz durch zwei gegenüber schnellen PWM, da der Timer nach oben und unten.
Etwas überraschend ist die Frequenz von 255 statt 256 geteilt, und das Tastverhältnis Berechnungen nicht ein wie für die schnelle PWM hinzuzufügen.

Siehe Erklärung unten unter "Off-by-one".

Variieren der Timer oben Grenze: schnelle PWM

Sowohl schnelle PWM und Phase korrekt PWM haben einen zusätzlichen Modus, der die Kontrolle über die Ausgangsfrequenz gibt. In diesem Modus zählt der Timer 0 bis OCRA (der Wert des Ausgabevergleichsregister A) anstelle von 0 bis 255.
Dies gibt viel mehr Kontrolle über die Ausgangsfrequenz als die vorherigen Modi.
(Noch mehr Frequenzsteuerung, verwenden Sie die 16-Bit-Timer 1.)

Man beachte, dass in diesem Modus ist nur der Ausgang B für die PWM verwendet werden; OCRA können nicht beide als Top-Wert verwendet werden, und die PWM-Vergleichswert.
Es besteht jedoch eine Sonderfallmodus "Toggle Očná auf Vergleichen Match", die am Ende jedes Zyklus umschalten ausgegeben A, Erzeugen eines festen Tastverhältnis von 50% und halber Frequenz in diesem Fall.

Die Beispiele werden diesen Modus verwenden.

Im folgenden Diagramm ist, setzt der Zeitgeber, wenn sie übereinstimmt OCRnA, wodurch eine schnellere Ausgangsfrequenz OCNB als in den vorhergehenden Diagrammen.
Beachten Sie, wie Ocna schaltet einmal für jeden Zeitgeber zurückgesetzt.

Schnelle PWM-Modus mit OCRA top

Das folgende Codefragment richtet schnelle PWM auf den Pins 3 und 11 (Timer 2), mit OCR2A als Top-Wert für den Timer.
Die Wellenform-Erzeugungsmodus-Bits WGM sind zu 111 für schnelle PWM mit OCRA Steuerung der oberen Grenze gesetzt.

Die OCR2A Obergrenze willkürlich auf 180 gesetzt und der OCR2B Vergleichsregister wird willkürlich festgelegt, um Modus 50 OCR2A ist, indem Sie die COM2A Bits 01 bis "Toggle on Vergleichen Spiel" gesetzt.

  pinMode(3, OUTPUT);
  pinMode(11, OUTPUT);
  TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
  TCCR2B = _BV(WGM22) | _BV(CS22);
  OCR2A = 180;
  OCR2B = 50;


Auf der Arduino Duemilanove, ergeben diese Werte:

    
Ein Ausgangsfrequenz: 16 MHz / 64 / (180 + 1) / 2 = 690.6Hz
    
Ausgang A Einschaltdauer: 50%

    
Ausgang B Frequenz: 16 MHz / 64 / (180 + 1) = 1381.2Hz
    
Ausgang B Einschaltdauer: (50 + 1) / (180 + 1) = 28,2%

Beachten Sie, dass in diesem Beispiel geht der Timer von 0 bis 180, die 181 Taktzyklen dauert, so wird die Ausgangsfrequenz durch 181 geteilt Output A hat die Hälfte der Frequenz des Ausgangs B, weil das Umschalten auf die Vergleichsliste Spiel-Modus schaltet Ausgang A je einmal Abschluß-Timer-Zyklus.

Variieren der Timer oben Grenze: phasenrichtige PWM

In ähnlicher Weise kann der Zeitgeber in phasenrichtige PWM-Modus konfiguriert ist, zurückzusetzen, wenn es OCRnA erreicht werden.
Phasenrichtige PWM mit OCRA top Das folgende Codefragment richtet phasenrichtige PWM auf den Pins 3 und 11 (Timer 2), mit OCR2A als Top-Wert für den Timer.

Die Wellenform-Erzeugungsmodus-Bits WGM sind zu 101 für phasenrichtige PWM mit OCRA Steuerung der oberen Grenze gesetzt.

Die OCR2A Obergrenze willkürlich auf 180 gesetzt und der OCR2B Vergleichsregister wird willkürlich festgelegt, um Modus 50 OCR2A ist, indem Sie die COM2A Bits 01 bis "Toggle on Vergleichen Spiel" gesetzt.

  pinMode(3, OUTPUT);
  pinMode(11, OUTPUT);
  TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM20);
  TCCR2B = _BV(WGM22) | _BV(CS22);
  OCR2A = 180;
  OCR2B = 50;


Auf der Arduino Duemilanove, ergeben diese Werte:

    
Ausgang A Frequenz: 16 MHz / 64/180/2/2 = 347.2Hz
    
Ausgang A Einschaltdauer: 50%

    
Ausgang B Frequenz: 16 MHz / 64/180/2 = 694.4Hz
    
Ausgang B Einschaltdauer: 50/180 = 27,8%

Man beachte, dass in diesem Beispiel geht die Steuerung 0-180 und zurück auf 0, was 360 Taktzyklen dauert.
So ist alles, was um 180 bzw. 360 unterteilt, anders als die schnelle PWM-Fall, der alles durch 181 geteilt;

Details siehe unten.
Off-by-one Sie haben vielleicht bemerkt, dass schnelle PWM und phasenrichtige PWM scheinen off-by-one in Bezug zueinander stehen, dividiert durch 256 gegenüber 255 und das Hinzufügen einer an verschiedenen Orten.
Die Dokumentation ist hier ein wenig undurchsichtig, also werde ich in ein wenig näher erläutern.

Nehmen wir an, der Zeitgeber auf schnelle PWM-Modus eingestellt ist und soll zu zählen bis zu einem Wert von OCRnA 3.
Der Timer wird auf die Werte 012301230123 nehmen ... Beachten Sie, dass es 4 Taktzyklen in jedem Timer-Zyklus.

Somit wird die Frequenz durch 4 geteilt werden kann, wird nicht 3.
Der Arbeitszyklus ein Vielfaches von 25% sein, da der Ausgang hoch für 0, 1, 2, 3 oder 4 Zyklen aus dem vier sein.

Ebenso, wenn der Zeitgeber zählt bis zu 255 ist, wird es 256 Taktzyklen in jedem Zeitgeberzyklus, und der Arbeitszyklus ist ein Vielfaches von 1/256 sein.

Um zusammenzufassen, teilt schnelle PWM durch N + 1, wobei N die maximale Zeitgeberwert (entweder OCRnA oder 255).

Betrachten wir nun phasenrichtig PWM-Modus mit der Timer zu zählen bis zu einem Wert von OCRnA 3.
Die Timer-Werte wird 012321012321 sein ...
Es gibt 6 Taktzyklen in jedem Timer-Zyklus (012.321).

Somit wird die Frequenz von 6. Der Arbeitszyklus aufgeteilt wird ein Vielfaches von 33%, da der Ausgang hoch für 0, 2, 4 oder 6 der 6 Zyklen.

Ebenso, wenn der Zeitgeber zählt bis zu 255 und zurück nach unten, wird es 510 Taktzyklen in jedem Zeitgeberzyklus, und der Arbeitszyklus wird ein Vielfaches von 1/255 sein.

Um zusammenzufassen, phasenrichtige PWM teilt durch 2N, wobei N die maximale Zeitgeberwert.

Der zweite wichtige Timing Unterschied ist, dass schnelle PWM hält den Ausgang hoch für einen Zyklus länger als das Ausgangsvergleichs-Register-Wert.
Die Motivation dafür ist, dass für die schnelle PWM Zählen bis 255, kann der Arbeitszyklus von 0 bis 256 Zyklen, aber die Ausgangsvergleichs-Register können nur einen Wert von 0 bis 255 zu halten
Was passiert mit dem fehlenden Wert?

Die schnelle PWM-Modus hält die Ausgangshoch für N + 1 Zyklen, wenn der Ausgangsvergleichsregister wird auf N gesetzt, ein Ausgangsvergleichsregister Wert von 255 ist 100% ED, sondern ein Ausgangsvergleichs-Register-Wert von 0 ist nicht Tastverhältnis von 0%
aber 1/256 Tastverhältnis.
Dies ist anders als phasenrichtige PWM, wo ein Registerwert von 255 ist 100% Einschaltdauer und ein Wert von 0 ist ein Tastverhältnis von 0%.

Zeitgeber und die Arduino Arduino unterstützt PWM auf einer Teilmenge der Ausgangs-Pins.

Es kann nicht sofort ersichtlich, welche Timer steuert die ausgegeben werden, aber der folgenden Tabelle wird die Situation zu klären.

Es gibt für jeden Timer-Ausgang auf der Arduino der Ausgangspin (dh dem Siebdruck Aufkleber auf der Platine), auf dem ATmega Chip den Stift und den Namen und die Bit des Ausgangs-Port.

z.B.  Timer 0 Ausgangs OC0A ist mit dem Arduino Ausgang Pin 6 verbunden ist;
es nutzt Chip Stift 12, der auch als PD6 ist bekannt.
Timer-Ausgang Arduino Ausgangs Chip Pin Pin Name OC0A 6 12 PD6 OC0B 5 11 PD5 OC1A 9 15 10 16 OC1B PB1 PB2 OC2A 11 17 PB3 OC2B 3 5 PD3

Das Arduino führt einige Initialisierung der Timer.
Das Arduino initialisiert den Vorteiler auf allen drei Zeitgeber, um die Uhr nach 64 Timer 0 zu teilen ist mit Schnell-PWM-initialisiert, während Timer 1 und Timer 2 wird initialisiert, um korrekte PWM-Phase.

Siehe die Arduino-Quelldatei wiring.c für Details.

Arduino verwendet Timer 0 intern für die Millis () und Verzögerung () -Funktionen so gewarnt, dass die Änderung der Frequenz des Zeitgebers bewirkt, dass die Funktionen, als fehlerhaft angesehen werden.
Unter Verwendung der PWM-Ausgänge ist sicher, wenn Sie nicht die Frequenz zu ändern, wenn.

Die Funktion analogWrite (pin, duty_cycle) setzt das entsprechende Pin auf PWM und setzt das entsprechende Ausgangsvergleichsregister zu duty_cycle (mit dem Sonderfall für Arbeitszyklus von 0 auf Timer 0).
Die Funktion digital () schaltet sich aus PWM-Ausgang, wenn auf einem Timer Pin genannt.

Der entsprechende Code ist wiring_analog.c und wiring_digital.c.

Wenn Sie analogWrite verwenden (5, 0) Sie ein Tastverhältnis von 0% erhalten, auch wenn Pin 5 der Zeitgeber (Timer 0) ist über schnelle PWM.
Wie kann das sein, wenn eine schnelle PWM-Wert von 0 ergibt ein Tastverhältnis von 1/256, wie oben erklärt?

Die Antwort ist, dass analogWrite "betrügt";
es Sonderfall Code explizit schalten Sie den Stift auf, wenn Timer 0 genannt mit einem Tastverhältnis von 0.
Als consequency, ist das Tastverhältnis von 1/256 nicht verfügbar, wenn Sie auf analogWrite Timer0 nutzen, und es gibt einen Sprung in
das tatsächliche Tastverhältnis zwischen Werten von 0 und 1.

Einige andere Modelle verwenden Arduino different AVR-Prozessoren mit ähnlicher Timer.
Der ARDUINO Mega verwendet die ATmega1280 (Datenblatt), die vier 16-bit Timer mit 3 Ausgängen und zwei 8-bit Timer mit 2 Ausgängen verfügt.
Nur 14 der PWM-Ausgänge werden von der Arduino Wiring-Bibliothek unterstützt, jedoch.
Einige ältere Arduino-Modelle nutzen die ATMEL ATmega8 (Datenblatt), die drei Zeitgeber hat aber nur 3 PWM-Ausgänge:
Timer 0 keine PWM, Timer 1 ist 16 Bit und hat zwei PWM-Ausgänge und Timer 2 8 Bit und hat einen PWM-Ausgang.
Fehlerbehebung
Es kann schwierig zu bekommen, die PWM-Ausgänge, um zu arbeiten.


Einige Tipps:
    
Sie müssen sich mit beiden Verfahren können Sie den Stift für die Ausgabe und aktivieren Sie die PWM-Modus auf dem Stift um jede Ausgabe zu erhalten.
    
Das heißt Sie brauchen, um pinMode (do) und legen Sie die COM-Bits.
    
Die verschiedenen Timer benutzen Sie die Steuer-Bits und Vorteiler anders;
    
Sie in der Dokumentation für das entsprechende Zeitgeber.
    
Einige Kombinationen von Bits, die Sie vielleicht erwarten, arbeiten, sind vorbehalten, was bedeutet, wenn Sie versuchen, sie zu nutzen, werden sie nicht.
    
Zum Beispiel bedeutet Toggle-Modus nicht mit schnellen PWM arbeiten bis 255, oder mit Ausgangs B.
    
Stellen Sie sicher, die Bits, wie Sie denken gesetzt. Bit-Operationen kann tückisch sein, so drucken Sie die Registerwerte mit dem binären (BIN) Formatierer und sicherzustellen, dass sie, was Sie erwarten.
    
Stellen Sie sicher, dass Sie mit den richtigen Ausgangs-Pins sind. Siehe die Tabelle oben.
    
Sie werden wahrscheinlich wollen ein Entkopplungskondensator, um Spitzen auf dem Ausgabe vermeiden.

Ein Oszilloskop ist sehr praktisch für die Fehlersuche bei der PWM
Wenn Sie noch kein Osci haben, empfehle ich, mit Ihrer Soundkarte und ein Programm wie xoscope

xoscope: digital oscilloscope
1MHz AC/DC Xoscope Sound Card oscilloscope

http://sourceforge.net/projects/xoscope/
http://xoscope.sourceforge.net/

http://xoscope-digital-oscilloscope.soft112.com/



xoscope Nachbau
http://www.mikrocontroller.net/topic/125504


Quelle:
http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM





*********************************************************
Kapitel 11:    Die analogen Ausgänge

Du hast vor kurzem schon selbst erkannt, dass das Mikrocontroller-Board keine analogen Ausgänge besitzt.
Ob das ein Fehler ist und sie einfach vergessen wurden?
Hm, ich glaube nicht! Ich kann an dieser Stelle bereits sagen, dass es keine dedizierten, also eigens für analoge Signale erforderlichen Ausgänge gibt.
Da aber trotzdem analoge Ausgänge für uns zur Verfügung stehen, so wirbt jedenfalls die Beschreibung des Arduino-Boards, muss es eine andere Lösung geben.
Doch welche?
Da sind wir auch schon beim Thema PWM.
Drei Buchstaben und keine Ahnung, was sie bedeuten, was dann auch schon die Überleitung zum nächsten Abschnitt ist.
Was bedeutet PWM?
Du würdest es vielleicht auf Anhieb nicht vermuten, doch die vermeintlich fehlenden analogen Ausgänge befinden sich auf einigen digitalen Pins.
Bei genauerer Betrachtung des Arduino-Boards erkennst du unterhalb einiger dieser Pins ein merkwürdiges Zeichen, das an eine Schlangenlinie erinnert.
Dieses Zeichen wird Tilde genannt und kennzeichnet die analogen Ausgänge.

DIGITAL PWM an pin-3  pin-5  pin-6  pin-9  pin-10  pin-11

PWM ist die Abkürzung für Pulse Width Modulation und bedeutet übersetzt Pulsweitenmodulation.
Jetzt bist du sicherlich genau so schlau wie vorher.
Doch schau her: Bei einem PWM-Signal handelt es sich um ein digitales Signal mit konstanter Frequenz und Spannung.
Das einzige, was variiert, ist der Tastgrad. Was das ist, wirst du gleich sehen.


Abbildung 11-8
Impulsdauer und Periodendauer im zeitlichen Verlauf (t variiert beim PWM; T ist konstant)


Je breiter der Impuls, desto mehr Energie wird an den Verbraucher geschickt.
                   t
Tastgrad =  ----
                  T
Wir können auch sagen, dass die Fläche des Impulses ein Maß für die abgegebene Energie ist. Ich habe einmal vier Oszillogramme bei einem Tastgrad von 25 %, 50%, 75 % und 100% aufgenommen.


Abbildung 11-9
Der Tastgrad liegt bei 25%


Wenn wir eine LED an den PWM-Ausgang anschlössen, erhielte sie nur 1/4 der möglichen Energie zum Leuchten.
Bevor sie richtig aufleuchten kann, wird sie auch schon wieder ausgeschaltet. Das bedeutet, dass sie nur recht schwach leuchtet.

Abbildung 11-10 ► Der Tastgrad liegt bei 50%


Bei einem Tastgrad von 50 % ist die An-Zeit gleich der Aus-Zeit pro Periodendauer. Die LED leuchtet auf jeden Fall heller als bei 25 %, da ihr pro Zeiteinheit mehr Energie zugeführt wird.


Abbildung 11-11 ► Der Tastgrad liegt bei 75%


Bei einem Tastgrad von 75 % fällt das Verhältnis von An-Zeit zu Aus-Zeit eindeutig zugunsten der An-Zeit aus, was bedeutet, dass die LED wiederum heller leuchtet als bei 25 % bzw. 50 %.


Abbildung 11-12 ► Der Tastgrad liegt bei 100%


Bei 100 % Tastgrad leuchtet die LED ständig, denn der Pegel ist durchgehend auf 5V und sie ist somit auch am hellsten.
Bei der Verwendung von analogen Ausgängen liegt eines auf der Hand:

DieAnzahl der verwendeten analogen Ausgänge geht natürlich zu Lasten der zur Verfügung stehenden digitalen Pins.
Wenn ich den analogen Ausgang nutzen möchte, der sich aber auf einem digitalen Pin befindet, wie spreche ich ihn dann an?
Verwende ich den digitalWrite-Befehl mit vielleicht einem weiteren Parameter?
Die Frage ist absolut berechtigt, Ardus!
Für die analoge Ausgabe über ein PWM-Signal verwendest du den analogWrite-Befehl, der die Angabe des Pins und die des Wertes erfordert.
Wir kommen zu gegebener Zeit noch genauer darauf zu sprechen.
Der übergebene Wert kann sich zwischen 0 und 255 bewegen.
In der folgenden Tabelle habe ich einige markante Werte dargestellt.


Abbildung 11-13
Der Befehl analogWrite mit einigen Beispielwerten


In diesem Beispiel wird PWM-Pin Nummer 5 angesprochen und über den PWM-Wert 64 ein Tastgrad von 25 % erreicht.
Über die folgende Formel kannst du dir unter Verwendung des gewünschten Prozentwertes den erforderlichen PWM-Wert berechnen.

                             gewünschter Tastgrad [%] • 255
PWM — Wert =   ---------------------------------------------------
                                            100%

Das könnte wichtig für dich sein

Um einen analogen Ausgang zu nutzen, ist es nicht notwendig, den erforderlichen Pin mit dem pinMode-Befehl als Ausgang (OUTPUT) zu programmieren.

Dieses Thema abschließend, muss ich natürlich betonen, dass es sich bei einem PWM-Signal nicht um ein wirkliches analoges Signal im eigentlichen Sinne handelt.
Wenn jedoch ein solches benötigt wird, kannst du ein RC-Glied an den Ausgang schalten, was einen Tiefpass darstellt, wobei die Ausgangsspannung geglättet wird.

Nähere Informationen dazu findest du im Internet oder auf meiner Internetseite.
Das könnte wichtig für dich sein
Ein paar Begriffe für die Suchmaschine, die dir weitere interessante Informationen liefern:
•    PWM-Signal
•    Pulsweitenmodulation

Quelle:
O'REILLY - Die elekronische Welt mit ARDUINO entdecken Seite 302





*********************************************************
10.3 Schnelle PWM macht's möglich: nicht nur Töne sondern auch Klänge

Die einfachste Möglichkeit zur Erzeugung von echten Klängen, besteht in der Verwendung der schnellen Pulsweiten-Modulation.
Hier stellt sich natürlich zunächst die Frage nach dem Unterschied zwischen Tönen und Klängen.
Töne können im Wesentlichen durch eine einzige physikalische Größe, nämlich ihre Frequenz beschrieben werden.
So hat der Kammerton A auf allen Musikinstrumenten die gleiche Frequenz von 440 Hz.
Wieso aber klingt ein „A" auf einer Posaune ganz anders als auf einem Piano?
Dies liegt daran, dass ein Klang durch wesentlich mehr Parameter beschrieben werden muss, als nur durch seine Frequenz.
Es kommen noch weitere Eigenschaften hinzu, beispielsweise wird die Klangfarbe durch den Anteil an Obertönen definiert.
Aber auch der zeitliche Verlauf der Lautstärke eines Tons, die sogenannte Hüllkurve ist von entscheidender Bedeutung.
Bei Verwendung der Funktion tone() hat man keinerlei Einfluss auf diese Größen.
Es wird einfach eine feste Rechteckfrequenz für eine bestimmte Zeitdauer ausgegeben.
Da Rechtecksignale sehr obertonhaltig sind, klingen sie hart und technisch.
Für einen weicheren Klangeindruck muss die Anzahl der Oberwellen reduziert werden.
Für einen weichen und harmonischen Klang sind reine Sinuswellen erforderlich.
Diese können nicht durch digitales Ein- und Ausschalten eines Ports erzeugt werden.
Einen Ausweg bietet die Methode der Pulsweiten-Modulation.
Bei diesem Verfahren wird eine Rechteckspan-nung erzeugt, deren Grundfrequenz weit über dem Hörbereich bei beispielsweise 62,5 kHz liegt.
Die Frequenz dieser Schwingung bleibt konstant, allerdings wird das Taktverhältnis, also die Zeitdauer von Ein- und Ausschaltzustand variiert.
Dadurch kann, nach entsprechender Filterung, ein nahezu kontinuierlich veränderliches Signal erzeugt werden.
Damit steht also ein Quasi-Analogausgang zur Verfügung und es können prinzipiell alle Signalformen ausgegeben werden.

Das folgende Programm erzeugt einen sinusförmigen Signalverlauf.



Listing 10-3: Schnelle PWM: Sinussignal (pde)

// audio sine using fast PWM
int audioPin = 9;    // audio output for fast PWM
void analogOut(byte val)    OCR1A = (val);}
byte value[] =
128,131,134,137,141,144,147,150,153,156,159,162,165,168,171,174, 177,180,183,186,189,191,194,197,199,202,205,207,209,212,214,217, 219,221,223,225,227,229,231,233,235,236,238,240,241,243,244,245, 246,247,248,249,250,251,252,253,253,254,254,255,255,255,255,255, 255,255,255,255,255,254,254,254,253,253,252,251,250,249,248,247, 246,245,243,242,240,239,237,236,234,232,230,228,226,224,222,220, 218,215,213,211,208,206,203,201,198,195,193,190,187,184,181,179, 176,173,170,167,164,161,158,155,152,148,145,142,139,136,133,130, 126,123,120,117,114,111,108,104,101,98,95,92,89,86,83,80, 77,75,72,69,66,63,61,58,55,53,50,48,45,43,41,38, 36,34,32,30,28,26,24,22,20,19,1746,14,13,11,10, 9,8,7,6,5,4,3,3,2,2,1,1,0,0,0,0,
0,0,0,1,1,1,2,2,3,4,4,5,6,7,8,10,
11,12,13,15,16,18,20,21,23,25,27,29,31,33,35,37,
39,42,44,47,49,51,54,57,59,62,65,67,70,73,76,79,
82,85,88,91,94,97,101,103,106,109,112,115,119,122,125,
};
void setup()
{
pinMode(audioPin, OUTPUT);
TCCR1A = Ob10000001;
TCCR1B = Ob00001001;
}
void loop()
{ for (unsigned int j = 0; j < 256; j++)
analogOut(value[j]);
delayMicroseconds(10);
}
}


Um eine möglichst hohe Verarbeitungsgeschwindigkeit zu erreichen, wurden die Werte der Sinusfunktion extern berechnet und als Array an die Variable „value" übergeben.
In der Hauptschleife werden dann einfach die einzelnen Amplitudenwerte über die schnelle PWM-Funktion ausgegeben.

Die Zeilen
TCCR1A = Ob10000001;
TCCR1B = Ob00001001;


schalten die PWM-Frequenz auf die gewünschten 62,5 kHz um.
Dazu werden die erforderlichen Werte direkt in die Timer und Counter Control Register (TCCR) des Prozessors geschrieben.
Eine detaillierte Beschreibung dieses Vorgehens würde den Rahmen dieses Buches sprengen.
Für weitere Einzelheiten hierzu muss an dieser Stelle auf das Datenblatt des ATmeg168/328, Kapitel Timer, Counter und PWM oder auf weiterführende Literatur zum Thema Mikrocontroller verwiesen werden.

Hier zeigt sich aber wieder der Vorteil der Verwendung von Arduino-Prozessing als Programmier-Umgebung.
Da von Anfang an der AVR-GCC Compiler im Hintergrund arbeitet, ist es nun problemlos möglich, auch fortgeschrittenere Techniken zu integrieren.
Bei Verwendung spezieller Programmiersprachen für Einsteiger, würde man hier auf unüberwindbare Probleme stoßen.

Erweiterungen und Übungen:
•    Laden Sie die beiden Sketche Fast PWM_sine.pde und Alarm_Sound.pde abwechselnd auf den Arduino und vergleichen Sie die akustischen Eindrücke.
Der folgende Sketch ermöglicht den direkten akustischen Vergleich der verschiedenen Signalformen.
Dazu wird ein Rechtecksignal ausgegeben, dann ein Sägezahnsignal und schließlich die Sinusschwingung. Abschließend werden noch Sinussignale verschiedener Lautstärken erzeugt.
Damit wird demonstriert, dass man nun nicht nur Frequenzen und Oberwellen steuern kann, sondern auch die Signalamplituden.



Listing 10-4: Audiosinale mit schneller PWM (.pde)

// audio sounds using fast PWM
int audioPin = 9;    // audio output for fast PWM
void analogOut(byte val) { OCR1A = (val);}
Byte value[] =
{    128,131,134,137,141,144,147,150,153,156,159,162,165,168,171,174, 177,180,183,186,189,191,194,197,199,202,205,207,209,212,214,217, 219,221,223,225,227,229,231,233,235,236,238,240,241,243,244,245, 246,247,248,249,250,251,252,253,253,254,254,255,255,255,255,255, 255,255,255,255,255,254,254,254,253,253,252,251,250,249,248,247, 246,245,243,242,240,239,237,236,234,232,230,228,226,224,222,220, 218,215,213,211,208,206,203,201,198,195,193,190,187,184,181,179, 176,173,170,167,164,161,158,155,152,148,145,142,139,136,133,130, 126,123,120,117,114,111,108,104,101,98,95,92,89,86,83,80, 77,75,72,69,66,63,61,58,55,53,50,48,45,43,41,38, 36,34,32,30,28,26,24,22,20,19,17,16,14,13,11,10, 9,8,7,6,5,4,3,3,2,2,1,1,0,0,0,0,
0,0,0,1,1,1,2,2,3,4,4,5,6,7,8,10,
11,12,13,15,16,18,20,21,23,25,27,29,31,33,35,37,
39,42,44,47,49,51,54,57,59,62,65,67,70,73,76,79,
82,85,88,91,94,97,101,103,106,109,112,115,119,122,125,
};
void setup()
{ pinMode(audioPin, OUTPUT);
TCCR1A = Ob10000001;
TCCR1B = Ob00001001;
}
void loop()
{ // square
for (unsigned int d = 0; d < 3; d++)
{ for (unsigned int j = 0; j < 100; j++)
{ analogOut(0);
delayMicroseconds(3000);
analogOut(255);
delayMicroseconds(3000);
}
}
delay(1000);
// sawtooth
for (unsigned int d = 0; d < 500; d++)

{ for (unsigned int j = 0; j < 255; j++)
{ analogOut(j);

delayMicroseconds(10);
}
}
delay(1000);
// sinus
for (unsigned int d = 0; d < 1000; d++)
{ for (unsigned int j = 0; j < 256; j++)
{ analogOut(value[j]);
delayMicroseconds(10);
}
}
delay(1000);
// volume variation
for (int ampl = 1; ampl < 10; ampl++)
{ for (unsigned int d = 0; d < 100; d++)
{ for (unsigned int j = 0; j < 256; j++)
{ analogOut(value[j]/10*ampl);
delayMicroseconds(10);
}
}
}
for (int ampl = 10; ampl >=0 ; ampl--)
{ for (unsigned int d = 0; d < 100; d++)
{ for (unsigned int j = 0; j < 256; j++)
{ analogOut(value[j]/10*ampl);
delayMicroseconds(10);
}
}
}
delay(1000);
}



Im nächsten Sketch werden glockenähnliche Klänge erzeugt.
Ein entsprechender akustischer Eindruck entsteht, wenn eine Sinusschwingung langsam abklingt.
Dies wird durch eine doppelte Schleife realisiert.
Die jeweils innere Schleife erzeugt die Grundschwingung, die äußere Schleife lässt die Schwingungsamplitude langsam auf Null absinken.
Vermutlich kommen Ihnen entsprechende Klänge bereits bekannt vor.
Sie sind bei vielen Gelegenheiten in Automobilen, Flugzeugen oder öffentlichen Verkehrsmitteln zu hören, wenn auf bestimme Ereignisse hingewiesen werden soll.
Ein typisches Beispiel ist das Warnsignal bei nicht angelegtem Sicherheitsgurt oder ein Hinweis, für den Fall, dass die Außentemperatur auf unter 3 °C gefallen ist und mit Glatteisgefahr gerechnet werden muss.


Listing 10-5: Fast PWM_Bell.pde
// bell like sounds using fast PWM
int audioPin = 9;    // audio output for fast PWM
void analogOut(byte val) { OCR1A = (val);}
byte valuen =
{    128,131,134,137,141,144,147,150,153,156,159,162,165,168,171,174,
177,180,183,186,189,191,194,197,199,202,205,207,209,212,214,217,
•    219,221,223,225,227,229,231,233,235,236,238,240,241,243,244,245, 246,247,248,249,250,251,252,253,253,254,254,255,255,255,255,255, 255,255,255,255,255,254,254,254,253,253,252,251,250,249,248,247, 246,245,243,242,240,239,237,236,234,232,230,228,226,224,222,220, 218,215,213,211,208,206,203,201,198,195,193,190,187,184,181,179, 176,173,170,167,164,161,158,155,152,148,145,142,139,136,133,130, 126,123,120,117,114,111,108,104,101,98,95,92,89,86,83,80, 77,75,72,69,66,63,61,58,55,53,50,48,45,43,41,38, 36,34,32,30,28,26,24,22,20,19,17,16,14,13,11,10, 9,8,7,6,5,4,3,3,2,2,1,1,0,0,0,0,
0,0,0,1,1,1,2,2,3,4,4,5,6,7,8,10,
11,12,13,15,16,18,20,21,23,25,27,29,31,33,35,37,
39,42,44,47,49,51,54,57,59,62,65,67,70,73,76,79,
82,85,88,91,94,97,101,103,106,109,112,115,119,122,125,
};
void setup()
{ pinMode(audioPin, OUTPUT);
TCCR1A = Ob10000001;
TCCR1B = 0b00001001;
}
void loop()
{ for (int ampl = 10; ampl >=0 ;
{ for (unsigned int d = 0; d < 40; d++)
{ for (unsigned int j = 0; j < 256; j++)
{ analogOut(value[j]/10*ampl); delayMicroseconds(5);
}
}
}
delay(100);
for (int ampl = 10; ampl >=0 ; ampl--)
{ for (unsigned int d = 0; d < 40; d++)
{ for (unsigned int j = 0; j < 256; j++)
{ analogOut(value[j]/10*ampl); delayMicroseconds(5);
}
}

}
delay(100);
for (int ampl = 10; ampl >=0 ; ampl--)
{ for (unsigned int d = 0; d < 20; d++)
{ for (unsigned int j = 0; j < 256; j++)
analogOut(value[j]/10*ampl); delayMicroseconds(10);
}
}
}
delay(300);
}



Erweiterungen und Übungen:

•    Bei realen Percussion-Instrumenten wie Glocken, Triangeln aber auch Trommeln und Becken klingt die Schwingung nicht linear ab, sondern exponentiell.
Schaffen Sie es, diese Klänge weitgehend naturgetreu nachzuahmen?


Quelle:
elektor - ARDUINO Schaltungsprojekte für Profis  Seite 197




*********************************************************
    3.3 Dimmen einer LED mittels PWM (Pulsweitenmodulation)
Eine LED lässt sich im Gegensatz zu einer herkömmlichen Glühbirne nicht dimmen, sondern lediglich ein- oder ausschalten.
Wird eine LED jedoch sehr schnell abwechselnd ein- und wieder ausgeschaltet, so nehmen wir Menschen eine geringere Helligkeit wahr.

Beachte: Nur die mit der "~" gekennzeichneten Ports können für die PWM genutzt werden.
Aufgaben:
1. Schließe eine LED mit passendem Vorwiderstand an Port11 an und lasse Sie blinken. Verändere die Dauer der Pause nun so, dass die LED dunkler leuchtet.
Ab wie vielen Millisekunden Pausendauer nimmt dein Auge ein Blinken wahr?
2. Wie musst du die PWM anpassen, damit das Signal im Mittel 3 V beträgt?
3. Die PWM kannst du auch mittels analogWrite() am digitalen (sic!) PWM-Port erzeugen.
4. Für Schnelle: Siehe dir das Beispiel "Fade" an und benutze es, um eine LED kontinuierlich heller und wieder dunkler werden zu lassen.
Achtung:
analogWrite() hat nichts mit analogen Ports zu tun. Du benutzt die (digitalen) mit ~ als PWM-Ports markierten Ports und brauchst sie vorher nicht einmal mittels pinMode() als Ausgang deklarieren.

Quelle:
704_d_ARDUINO-x_Arduino - Eine Einführung – Popovic (63 Seiten)_2a.pdf




*********************************************************
Kapitel 6  
PWM (PulsWeitenModulation)

Bauelemente: -
Befehle: analogWrite(ledPin, Helligkeit);
Eine LED soll mit einem LDR gedimmt werden.

Aufgabe 6.1:
•    Baue die Schaltung wie in der Abbildung auf.
•    Öffne und starte den Sketch „A061_LDR_Dimmen.ino“
•    Verändere die Stellung des Potentiometers und beobachte dabei die LED.
     Notiere deine Beobachtungen.



/* A061_LDR_Dimmen.ino  */

int ledPin = 6;                     // pin-6 is a "PWM-Pin"
void setup() {
   Serial.begin(9600);              //
Initialisierung der seriellen Kommunikation auf 9500 Bits pro Sekunde:
   pinMode(ledPin, OUTPUT)
}

void loop()  {
                                    //
lesen Sie den Eingang auf Analog-pin 0:
int sensorValue = analogRead(0);    //
Der Wert ist betueen 0 und 1023                                   
Serial.println (sensor Value);      
//  Drucken Sie den Wert, den Sie gelesen:
brightness = sensorValue/4;
analogWrite(ledPin, brightness);    //
Helligkeit zwischen 0 ein 255
delay(1);                           //
mind. 1mS Verzögerung dazwischen für die Stabilität
}



INFO: PWM (PulsWeitenModulation)
Ein digitaler Pin kennt die beiden Zustände HIGH und LOW.
Dann liegen an diesem Pin entweder 0V oder 5V an.
Einige der digitalen Pins auf dem Arduino-Board sind mit „PWM“ (oder „~“) gekennzeichnet.
Mit dem Befehl analogWrite(pin, value) kann man an diesen Pins eine pseudo-analoge Spannung erzeugen:
Der Befehl analogWrite(11, 0) generiert eine gleichmäßige Spannung von 0 Volt an Pin11, der Befehl analogWrite(11, 255) generiert eine gleichmäßige Spannung von 5 Volt an Pin11.
Für Werte zwischen 0 und 255 wechselt der Pin sehr schnell zwischen 0 und 5 Volt - je höher der Wert, desto länger ist der Pin HIGH (5 Volt).
Der Befehl analogWrite(11, 127) führt dazu, dass die Ausgangsspannung zur Hälfte der Zeit auf HIGH steht und zur anderen Hälfte auf LOW.
Bei analogWrite(11, 192) 192 misst die Spannung am Pin zu einer Viertel der Zeit 0 Volt und zu Dreivierteln die vollen 5 Volt.
Weil dies eine hardwarebasierte Funktion ist, läuft die konstante Welle unabhängig vom Programm bis zur nächsten Änderung des Zustandes per analogWrite
(bzw. einem Aufruf von digitalRead oder digitalWrite am selben Pin).



Aufgabe 6.2:
•    Ersetze in der Schaltung das Potentiometer durch einen Spannungsteiler aus einem 10 kΩ Widerstand und einem LDR. (Siehe Praktikum 5)
•    Starte den Sketch.
•    Öffne den seriellen Monitor.
•    Dunkle den LDR mit der Hand ab und beobachte die LED.
•    Notiere deine Beobachtungen.
•    Zeichne den Schaltplan.


Quelle: 

704_d_ARDUINO-x_ARDUINO Duemilanove - Kurzanleitung für Einsteiger (48 Seiten)_1a.pdf





*********************************************************
5 Steuerung von Licht mittels PWM

Abbildung 5-4:  LED am PWM-pin-9

Mit den bisher erworbenen Kenntnissen könnten Sie eine interaktive Lampe bauen — und zwar eine, die nicht nur über einen langweiligen Ein/Aus-Schalter verfügt, sondern vielleicht mit eleganteren Features aufwartet.
Eine der Beschränkungen unserer Beispiele mit einer blinkenden LED war die, dass das Licht nur ein- oder ausgeschaltet werden konnte.
Eine schicke Lampe muss aber auch dimmbar sein.
Hierzu können wir uns eines Phänomens bedienen, das viele solcher Dinge wie Fernsehen oder Kino erst ermöglicht: die Trägheit des Auges.
Nach dem ersten Beispiel in Kapitel 4 wurde schon angedeutet, dass, wenn Sie die Angaben für die Verzögerungen im Code so ändern, dass Sie kein Blinken der LED mehr wahrnehmen können, das von den LEDs abgegebene Licht gegenüber ihrer normalen Helligkeit um 50 % reduziert erscheint.
Ändern Sie nun die Angaben so, dass die LED ein Viertel der Zeit ausgeschaltet ist.
Wenn Sie den Sketch ausführen, werden Sie sehen, dass die Helligkeit noch etwa 25% beträgt.
Diese Technik heißt Pulsweitenmodulation (PWM), eine hübsche Bezeichnung dafür, dass wenn Sie die LED nur schnell genug blinken lassen, Sie das Blinken nicht mehr wahrnehmen, aber die Helligkeit ändern können, indem Sie das Verhältnis von Ein- und Ausphasen entsprechend anpassen.
In Abbildung 5-3 ist dargestellt, wie dies funktioniert.

Diese Technik funktioniert auch bei anderen Bauteilen als LEDs. Die Schnelligkeit eines Motors lässt sich auf dieselbe Weise ändern.
Wenn Sie herumexperimentieren, werden Sie bemerken, dass das Erzeugen von Blinkverhalten bei einer LED durch Einfügen von Verzögerungen im Code recht ungünstig sein kann, weil, sobald Sie einen Sensor auslesen oder Daten an den seriellen Anschluss schicken möchten, die LED zu flackern beginnt, während sie darauf wartet, dass das Auslesen des Sensors beendet wird.
Glücklicherweise verfügt der Pozessor, der bei Arduino verwendet wird, über eine spezielle Hardware, die recht effizient drei LEDs blinken lassen kann, während der Sketch etwas anderes tut. Diese Hardware ist in den Pins 9, 10 und 11 implementiert, die wiederum über die Anweisung analogWrite(Pin, Helligkeit) gesteuert werden können.


Abbildung 5-3.   PWM in Aktion

Wenn Sie zum Beispiel analogWrite(9,128)schreiben, wird die Helligkeit der LED, die an pin-9 angeschlossen ist, auf 50% gedimmt.
Warum 128? analog Write() erwartet als Argument eine Zahl zwischen 0 und 255, wobei 255 volle Helligkeit bedeutet und bei 0 die LED ausgeschaltet ist.


Hinweis:
Es ist eine feine Sache, dass Ihnen drei Kanäle zur Verfügung stehen, weil Sie so rote, grüne und blaue LEDs kaufen und das Licht dann nach Belieben mischen können!


Das wollen wir nun einmal ausprobieren.
Bauen Sie den Schaltkreis, der in Abbildung 5-4 abgebildet ist.
Beachten Sie, dass die LEDs gepolt sind:
Der lange Pin (positiv) sollte nach rechts zeigen, der kurze Pin (negativ) nach links.
Außerdem ist bei den meisten Widerständen die negative Seite abgeflacht, wie in der Abbildung zu sehen ist.
Verwenden Sie einen 270 Ohm Widerstand (rot-violett-braun).

Erzeugen Sie dann in Arduino einen neuen Sketch und verwenden Sie Beispiel 5-1
die Codebeispiele können auch unter
http://www.makezine.com/getstartedarduino
heruntergeladen werden


// Beispiel 5-1: Fade an LED in and out
const int LED = 9; // the pin for the LED
int i = 0;         // We'll use this to count up and down

void setup() {
pinMode(LED, OUTPUT); // tell Arduino LED is an output
}

void loop(){
for (i = 0; i < 255; i++) { // loop from 0 to 254 (fade in)
analogWrite(LED, i);    // set the LED brightness
delay(10); // Wait 10ms because analogWrite
// is instantaneous and we would
// not see any change
}

for (i = 255; i > 0; i--) { // loop from 255 to 1 (fade out)
analogWrite(LED, 1); // set the LED brightness
delay(10);    // Wait lOms
}



Sie haben nun ein nettes Laptop-Feature nachgebildet
 (vielleicht ist es auch ein wenig verschwenderisch, Arduino für so eine simple Angelegenheit zu nutzen).
Wir wollen nun dieses Wissen einsetzen, um unsere Lampe zu verbessern.

Fügen Sie auf der Steckplatine die Schaltung hinzu, die wir verwendet haben, um den Drucktaster auszulesen (siehe weiter vorne in Kapitel 4).
Versuchen Sie dabei, nicht auf die nächste Seite zu schauen, weil ich möchte, dass Sie damit anfangen, jeden hier gezeigten Basisschaltkreis als Baustein zu sehen, mit denen sich immer größere Projekte realisieren lassen.

Wenn Sie doch nachschauen müssen, macht das nichts;
wichtig ist, dass Sie sich vorher ein paar Gedanken darüber gemacht haben, wie das Ganze aussehen könnte.

Um den gewünschten Schaltkreis zu bauen, müssen Sie die Schaltung, die Sie gerade gebaut haben (die aus Abbildung 5-4), mit der Drucktasterschaltung, die in Abbildung 4-6 dargestellt ist, kombinieren.
Wenn Sie möchten, können Sie die beiden Schaltkreise auf verschiedene Bereiche der Platine bauen; es gibt hier viel Platz.
Einer der Vorteile der Steckplatine (siehe Anhang A) besteht in den beiden Leiterbahnen, die horizontal über dem oberen und dem unteren Bereich verlaufen, eine ist rot (positiv) und die andere blau oder schwarz (Masse) gekennzeichnet.

Diese Leiterbahnen dienen dazu, Energie und Masse so zu verteilen, wie sie benötigt werden.
Bei dem hier zu bauenden Schaltkreis müssen zwei Komponenten (beide sind Widerstände) mit dem Masse-(GND-)Pin des Arduino-Boards verbunden werden.
Da Arduino über drei GND-Pins verfügt, können Sie die beiden Schaltkreise einfach auf die in jeder der beiden Abbildungen dargestellte Weise verbinden.

Schließen Sie einfach beide an das Arduino-Board an.
Sie können auch einen der Drähte der Masseleiterbahn der Steckplatine an einen der GND-Pins auf dem Arduio-Board anschließen und die Drähte, die in den Abbildungen an die GND-Pins angeschlossen sind, stattdessen mit der Masseleiterbahn auf der Steckplatine verbinden.

Wenn Sie noch nicht so weit sind, dies auszuprobieren, ist das nicht weiter schlimm:
Verdrahten Sie einfach beide Schaltkreise mit dem Arduino-Board, wie es in den Abbildungen 4-6 und 5-4 dargestellt ist.
Ein Beispiel, bei dem Masse und positive Leiterbahnen der Steckplatine genutzt werden, finden Sie im Kapitel 6.


Fahren wir nun mit unserem nächsten Beispiel fort.

Abbildung 5-5:  Taster am pin-7

Wenn wir nur einen Drucktaster haben, wie können wir dann die Helligkeit der Lampe an pin-13  steuern?

An dieser Stelle werden wir nun eine weitere Technik aus dem Interactive Design kennenlernen:
das Ermitteln, wie lange ein Taster gedrückt wurde.
Hierzu müssen wir ein Upgrade zu Beispiel 4-5 aus dem Kapitel 4 durchführen, um einen Dimm-Effekt einzubauen.
Die Idee besteht darin, eine Schnittstelle herzustellen,
über die mittels Drücken- bzw. Freigabe-Aktionen das Licht ein- oder ausgeschaltet
und per Drücken- und Halten-Aktionen die Helligkeit geändert wird
.

Schauen wir uns den entsprechenden Sketch an:


// Beispiel 5-2: Turn on LED when the button is pressed
const int LED = 13;    // the pin for the LED
const int BUTTON = 7; // input pin of the pushbutton

int val = 0;          // stores the state of the Input pin

int old_val = 0;      // stores the previous value of "val"
int state = 0;         // 0 = LED off while 1 = LED on

int brightness = 128;    // Stores the brightness value
unsigned long startTime . 0; // when did we begin pressing?


void setup() {
pinMode(LED, OUTPUT);      // teil Arduino LED is an output
pinMode(BUTTON, INPUT);     // and BUTTON is an input
}

void loop() {
val = digitalRead(BUTTON); // read input value and store it
// yum, fresh

// check if there was a transition
if ((val == HIGH) && (old_val == LOW)) {

state = 1 - state;    // change the state from off to on
                       // or vice-versa

startTime = millis(); // millis() is the Arduino clock
                      // it returns how mang milliseconds
                      // have passed since the board has // been reset.

// (this line remembers when the button
// was last pressed)
delay(10);

}

// check whether the button is being held down
if ((val == HIGH) && (old_val == HIGH)) {

// If the button is held for more than 500ms.
if (state == 1 && (millis() - startTime) > 500) {

brightness++; // increment brightness by 1
delay(10);    // delay to avoid brightness going
              // up too fast

if (brightness > 255) { // 255 is the max brightness

brightness = 8; // if we go over 255
                // let's go back to 0
}
}

}

old_val = val;                // val is now old, let's store it

if (state == 1) {
analogWrite(LED, brightness); // turn LED ON at the
                              // current brightness level
} eise {
analogWrite(LED, 0);          // turn LED OFF
}

}


Das wollen wir nun einmal ausprobieren.
Wie Sie sehen, nimmt unser Interaktionsmodell Formen an.
Wenn Sie den Taster drücken und sofort wieder loslassen, schalten Sie die Lampe ein bzw. aus.
Wenn Sie den Taster gedrückt halten, ändert sich die Helligkeit.
Nehmen Sie einfach den Finger vom Taster, wenn die gewünschte Helligkeit erreicht ist.
Als Nächstes wollen wir uns ein wenig näher mit der Verwendung einiger interessanter Sensoren beschäftigen.


Quelle:
OREILLY - ARDUINO für Einsteiger Seite 54





*********************************************************
7.2    PWM versus D/A-Wandler

Bild 7.3: Mit dem Potentiometer wird die Helligkeit der LED eingestellt.

Oft müssen in der Elektronik nicht nur analoge Signale gemessen, sondern auch erzeugt werden.
Leider fehlt bei vielen MCUs (wie auch beim AVR) der dazu notwendige D/A-Wandler.
Wieso stellt die Arduino-API dann eine Funktion mit der Bezeichnung analogWrite zur Verfügung?
Weil hier ein Trick ins Spiel kommt.
Dieser Trick heißt Pulsbreitenmodulation (Pulse Width Modulation = PWM) und ist bei MCU-Herstellern sehr verbreitet.
Um herauszufinden, warum dies so ist, habe ich einige Mikrocontroller-Hersteller befragt, und die einhellige Antwort war, dass D/A-Wandler einfach viel mehr Platz auf dem Chip verbrauchen würden - Platz, der sehr teuer ist und daher lieber für Mehrkanal-PWM-Einheiten genutzt wird.
Solche Schaltungen sind eng verwand mit Zählern und Timern.
Aus diesem Grunde wird die PWM-Funktionalität oft von bereits vorhandenen, peripheren Hybrid-Zählern bzw. -Timern übernommen.
Mit einem Tiefpass-Filter kann ein PWM-Signal recht einfach in ein analoges Signal verwandelt werden (siehe auch Abschnitt 3.2.7, Seite 29).
Selbst dies ist in einigen Fällen nicht notwendig, da sich das System selbst wie ein Filter verhält.
Dies ist zum Beispiel bei einem Motor mit seiner mechanischen Trägheit der Fall.
Ein anderes Beispiel ist die Leuchtdiode, deren Helligkeit sich ebenfalls gut über ein PWM-Signal steuern lässt.
Im Gegensatz zu einem Motor ist eine LED jedoch überhaupt nicht träge:
Unser Sehvermögen kann lediglich dem schnellen Wechsel von hell und dunkel nicht folgen und nimmt die LED daher als gleichmäßig leuchtend wahr.
In diesem Falle funktioniert der Mensch selbst als Tiefpassfilter (mit niedriger Eckfrequenz).
Ein wichtiger Grund für die Verwendung von PWM-Signalen besteht in der Einsparung von Energie.
Ein durch ein PWM-Signal angesteuerter Transistor kennt nur zwei Zustände:
Sperrend und leitend.
In beiden Fällen sind die Verluste nur sehr gering.
Die Zustände zwischen den beiden Extremen, in denen die Verlustleistung hoch ist, sind nur sehr kurz.
Der Energieverbrauch des Transistors ist daher sehr niedrig, wenn sich der Transistor möglichst oft in diesen beiden Extremzuständen befindet.
Die Arduino-Funktion analogWrite ( ) erzeugt daher ein PWM-Signal an Stelle eines analogen Signals, und es hängt von der Art der Anwendung ab, ob sie überhaupt in ein richtiges Analogsignal umgewandelt werden muss.
Der Duty Cycle des Signals wird durch sein 8-bit Argument in Prozentwerten festgelegt.
Die Zahl 0 bedeutet „Null Prozent Pulsbreite", was einer dauerhaften Spannung von 0 V entspricht.
Ein dauerhafter Pegel auf dem Niveau der Versorgungsspannung entspricht einem Wert von 100% bzw. der Zahl 255.
Da das PWM-Signal von den Zählern der MCU erzeugt wird, funktioniert die analogWrite-Funktion nur mit den Pins, die intern mit den Zählern verbunden sind.
Die Anzahl der für PWM-Zwecke verfügbaren Pins hängt von der jeweiligen MCU ab.
Der Uno besitzt sechs solcher Anschlüsse (3, 5, 6, 9, 10 und 11, die auf dem Board mit dem Tilde-Zeichen „—" markiert sind).
Beim Mega stehen 15 solcher Anschlüsse zur Verfügung (die ganze Reihe 2 bis 13 und die nicht markierten Pins 44 bis 46)
Hier ein Sketch, der die Helligkeit einer mit Pin 11 verbundenen LED über eine am Analog-Eingang A0 anliegende Spannung steuert.
Hierbei handelt es sich nicht um die On-Board-LED die ist an pin-13 angeschlossen.

/*
dimmer
*/

int led = 11;
void setup(void)
{
}

void loop(void)
{
analogWrite(led,analogRead(A0)/4);
}


Der von analogWrite ( ) zur Verfügung gestellte Wert wird durch 4 geteilt, damit er nicht größer als 255 werden kann - der Maximalwert für die Pulsbreite.

Quelle:
elektor - Mikrocontroller verstehen und anwenden (mit Elektor-Shield 129009-11)  Seite 134




9.5.1 Zwei Arten von PWM

Die Qualität der von analogWrite ( )  erzeugten PWM-Signale ist bei allen Ausgängen fast gleich.
Der Ausgang des Timer/counter 0 (Pin 5 und 6) arbeitet mit etwa 977 Hz (16 MHz / 64 / 256) - die anderen erzeugen eine Frequenz von knapp über 490 Hz (16 MHz / 64 / 255 / 2).
Die Signale an pin-5 und 6 (pin-4 und 13 beim Mega) sind zwar schneller, aber weniger genau in ihrer Symmetrie als diejenigen an den anderen Pins, bei einen eine MCU-Option mit Namen Phase Correct PWM verwendet wird.
Timer/counter 0 dagegen arbeitet im schnellen PWM-Betrieb.
Dies ist darauf zurückzuführen, dass timer/counter 0 auch als Millisekunden-Zähler verwendet wird.
Wird timer/counter 0 im phasentreuen PWM-Modus verwendet (was ebenfalls möglich ist), so arbeitet der Millisekunden-Zähler nicht mehr genau.
Die von den Funktionen millis und micros gelieferten Werte sind dann falsch und die Funktion delay wird zu langsam.

Zur Erzeugung eines PWM-Signals wird der Zähler mit einem Schwellenwert verglichen.
Ist der Zähler unterhalb der Schwelle, ist das PWM-Signal low, ist der Zähler oberhalb der Schwelle, so ändert sich das PWM-Signal in high.
Im schnellen PWM-Modus zählt der Zähler von 0 bis 255 und beginnt dann von vorn, da 255 + 1 in der 8-bit Registerarithmetik gleich 0 ist.
Der Zählertakt wird daher durch 256 geteilt.
Die vom Zähler erzeugte Wellenform ist ein Sägezahn, und die Pulse des PWM-Signals sind immer nach links vom maximalen Zählerwert aus betrachtet ausgerichtet.
Im Gegensatz dazu beginnt der Zähler im phasentreuen PWM-Modus nach Erreichen des Maximums nicht bei 0, sondern ändert stattdessen seine Richtung und zählt rückwärts (255, 254, 253 usw.).


In diesem Falle wird vom Zähler ein Dreiecksignal erzeugt.
Daraus folgt, dass der Zähler die Schwelle zweimal überquert; einmal beim Aufwärts- und einmal beim Abwärtszählen.
Dies hat wiederum zur Folge, dass die Pulse des PWM-Signals symmetrisch zum Maximalwert des Dreiecksignals ausgerichtet wind.
Die Frequenz dieses Signals ist sichtlich höher als die Hälfte der Frequenz des schnellen PWM-Signals, da der Takt in diesem Falle durch 255 x 2 geteilt wird.
Um den Unterschied zwischen den beiden PWM-Methoden zu veranschaulichen, kann man die beiden Ausgänge desselben timer/counter-Moduls mit einem Oszilloskop vergleichen, während sie zwei verschiedene Duty Cycle erzeugen.

Bild 9.4: Unterschied zwischen fast PWM (oben) und phasentreuem PWM (unten)


Quelle:
elektor - Mikrocontroller verstehen und anwenden (mit Elektor-Shield 129009-11)  Seite 255





DIN A4 ausdrucken
*********************************************************

Impressum: Fritz Prenninger, Haidestr. 11A, A-4600 Wels, Ober-Österreich, mailto:schaltungen@schaltungen.at
ENDE







Comments