PWM-Ausgaben in BASCOMWenn es auf genaues Timing ankommt, dann kommen Timer zum Einsatz.
Die meisten Mikrocontroller besitzen gleich mehrere davon.
Der Timer1 des
ATmega328 hat eine Auflösung von 16-bit.
Man kann sich diesen so vorstellen wie einen 16-stufigen Zähler, ähnlich wie der bekannte
CD4040 mit seinen (nur) 12 Stufen.
Was vorne an (Takt-)Impulsen reinkommt, kommt hinten wieder raus, aber entsprechend geteilt, also mit kleinerer Frequenz.
Mit dem 4040 konnte man Zeitgeber oder Frequenzteiler bauen, oder er konnte als Basis für einen binären Impulszähler dienen.
All das kann der Timer1 auch, man muss ihn nur passend initialisieren.
Zusätzlich gibt es übrigens noch zwei
8-bit-Timer (Timer 0 und Timer2). Unter den vielen Betriebsarten des Timers1 ist auch die PWM-Funktion.
Es
können zwei pulsweiten-modulierte Signale erzeugt werden, also
Rechtecksignale, deren Puls/Pausen-Verhältnis man einstellen kann.
So
lassen sich z.B. Helligkeiten steuern; ganz ähnlich wie bei einem
Dimmer am Lichtnetz, der ja auch nichts anderes macht, als ganz schnell
ein- und auszuschalten.
Und genau das soll jetzt auch hier geschehen, der PWM-Ausgang soll die Helligkeit einer LED steuern.
Die PWM-Ausgabe kann eine Einstellbreite von max. 10-bit haben, aber man kann auch 8-bit einstellen.
10-bit bietet sich an, weil es gerade zur Auflösung des AD-Wandlers passt.
Der Zähler zählt dabei jeweils von 0 bis 1023. Man
kann nun programmieren, dass er zum Beispiel bei einem Zählerwert von
511 die Ausgangsspannung abschaltet (dann ergibt sich ein PWM-Signal mit
etwa 50 % Tastverhältnis).
Bild 3. LED als Lichtsensor 140064-11
'------------------------------------
'UNO_LCD3.BAS PWM
'------------------------------------
$regfile = "m328pdef.dat" 'ATmega328p
$crystal = 16000000 '16 MHz
$baud = 9600
S1 Alias Pinc.0
S2 Alias Pinc.1
Dim D As Word
Dim U As Single
Config Adc = Single , Prescaler = 64 ,
Reference = Avcc '5 V
Config Timer1 = Pwm , Prescale = 1 ,
Pwm = 10 , Compare A Pwm = Clear Up ,
Compare B
Pwm = Clear Up
Config Lcdpin = Pin , Db4 = Portd.4 ,
Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
Config Lcd = 16 * 2
Portc.0 = 1 'Pullup
Portc.1 = 1 'Pullup
Config Portb = Output
Cls
Cursor Off
Do
Locate 1 , 1
Lcd "PWMA="
A = Getadc(3)
Pwm1a = A
Lcd A
Lcd " "
If S1 = 0 Then
If B > 0 Then B = B - 1
End If
If S2 = 0 Then
If B < 1023 Then B = B + 1
End If
Pwm1b = B
Locate 2 , 1
Lcd "PWMB="
Lcd B
Lcd " "
Waitms 100
LoopBASCOM Listing 4: PWM-Steuerung.
Bild 4. Zwei LEDs an zwei PWMAusgängen 140064-11Hierfür wird der Zählerwert regelmäßig in einer Compare-Einheit (compare = vergleichen) mit dem programmierten Wert verglichen.
Tatsächlich
gibt es zwei solcher Compare-Einheiten, sodass man mit dem gleichen
Timer zwei unabhängige PWM-Signale erzeugen kann.
PWM1A kommt am Portpin PB1 heraus und PWM1B an PB2.
Da war doch was?
Ach ja, an PB2 liegt die LED 2 über einen
Vorwiderstand von 1k Ohm.
Zufall? Nein, Absicht.
Denn nun kann man die Helligkeit der LED per PWM steuern.
Das Programm in Listing 4 (PWM-Steuerung.) verwendet den PWM-Ausgang A im Zusammenhang mit dem AD-Wandler an ADC3 (Poti).
Der Wert, den man am Poti einstellt, wird als Vergleichswert für das PWM-Signal verwendet.
Stellt man das Poti in die Mitte, kommt ein symmetrisches Rechtecksignal heraus. Alles zwischen 0 und 1023 ist möglich.
Was gerade ausgegeben wird, erscheint auch auf dem LCD.
Wer sich das Signal ansehen will, kann ein Oszilloskop an PB1 (= Arduino-Pin 9) halten.
Welche Frequenz hat eigentlich das PWM-Signal?
Es hängt natürlich davon ab, mit welchem Takt der Timer angesteuert wird.
Das kann die Quarzfrequenz 16 MHz des Arduino sein oder auch ein davon (über einen Vorteiler) abgeleiteter Teil.
In diesem Fall steht in der Initialisierung die Anweisung Prescale = 1, es wird also die volle Taktfrequenz verwendet.
Daraus ergibt sich eine PWM-Frequenz von
16000 kHz / 1024 = 15,625 kHz - denkt man.
Aber tatsächlich ist es nur die halbe Frequenz, also ca. 7,8 kHz.
Das hat damit zu tun, dass
BASCOM die Betriebsart „Phase Correct PWM“ verwendet, im Gegensatz zur „Fast PWM“.
Näheres dazu erfährt man im Datenblatt des Controllers, aber das ist recht umfangreich.
Bascom dagegen spart Entwickler-Zeit, weil für solche Fälle immer schon eine sinnvolle Vorentscheidung getroffen wurde.
BASCOM funktioniert auch, wenn man noch nicht alle Details überblickt. Die LED 2 liegt am zweiten PWM-Ausgang (PB2).
Die Ausgabe wird in unserem Programm über die beiden Tasten S1 und S2 gesteuert.
Damit das Programm gut lesbar ist, wurden die Namen der Tasten mit einem Alias-Befehl den Porteingängen zugeordnet.
Wenn
man im Programm also „If S1 = 0 Then“ schreibt, dann weiß BASCOM, dass
eigentlich „If Pinc.1 = 0“ gemeint ist, also der Zustand des Portpins
PC1 abgefragt werden soll.
Wichtig ist auch noch, dass die Taster gegen GND angeschlossen sind und deshalb einen Pullup benötigen.
Normalerweise liest man dann den Ruhezustand S1 = 1. Nur wenn jemand auf die Taste drückt wird S1 = 0.
Und so wird die Sache ganz einfach.
Mit
einem Druck auf S1 verkleinern Sie die PWM-Ausgabe (aber nur wenn sie
noch größer als 0 ist) und mit S2 vergrößern Sie die Ausgabe (aber nur
wenn sie noch kleiner als 1023 ist).
Die ganze Sache funktioniert in
Einzelschritten (wenn man kurz drückt), aber auch mit laufender
Veränderung (zehn Schritte pro Sekunde) bei einem Dauerdruck.
Auf dem LCD sehen Sie jeweils, was gerade ausgegeben wird.
TastenabfragenDas Programm zeigt ein sehr einfaches Beispiel für die Verwendung von Tasten und entsprechenden Programmverzweigungen.
Doch da gibt es natürlich noch viele andere Möglichkeiten.
Für eine gegebene Aufgabe die optimale Bedienung zu entwickeln, das ist eine spannende Aufgabe.
Mit
zwei Tastern und einem Poti kann man sehr viele unterschiedliche Dinge
einstellen. Mit wenigen Tasten lässt sich viel erreichen.
Das Programm verwendet alles, was das
Elektor-Shield 140009-91 www.elektor-magazine.de/140009 www.lcd-module.de/pdf/doma/dips082.pdf zu bieten hat.
Das
LCD zeigt die beiden aktuellen PWM-Werte an, das Poti steuert den
Ausgang PWM-A, die beiden Taster steuern PWM-B und damit die LED 2.
Wirklich alles? Nein, die LED 1 ist noch arbeitslos.
Also
stecken Sie einen Draht in PB1 (Arduino Pin 9) und ADC2 (Arduino A2),
damit liegt PWMA über 1k Ohm und einen Jumper an der LED 1 (Bild 4).
Nun können Sie über das Poti die Helligkeit der LED steuern.
Zwei
LED-Helligkeiten, die unabhängig voneinander eingestellt werden können,
das ergibt gleich ein kleines Geschicklichkeitsspiel.
Eine Person stellt mit den Tasten irgendeine Helligkeit an der LED 2 ein. Dann wird das LCD abgedeckt.
Die zweite Person muss nun mit dem Poti die gleiche Helligkeit an der LED 1 einstellen.
Das LCD enthüllt dann, wie gut das geklappt hat.
Dann werden die Rollen getauscht. Alle Abweichungen werden notiert.
Wer insgesamt besser eingestellt hat, ist der Sieger und wird zum Meister mit dem unfehlbaren Blick ernannt.
[2] http://b-kainka.de/bastel49.htm