PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Led dimmen mit PWM



H3llGhost
23.08.2008, 15:25
Hallo Leute,

ich habe mal eine Frage:
Ich habe eine LED, die an einem ATmega168 mit einem Vorwiderstand angeschlossen ist und möchte diese von 100 % Leistung runterdimmen.
Dazu habe ich hier schon die Suchfunktion benutzt aber nicht wirklich was gefunden.
Dann habe ich bei mikrocontroller.net gesucht und einen Artikel für Assembler gefunden, aber der ist für den ATmega8 geschrieben:



.include "m8def.inc"

.def temp = r16

.def PWMCount = r17

.def ocr_1 = r18 ; Helligkeitswert Led1: 0 .. 127
.def ocr_2 = r19 ; Helligkeitswert Led2: 0 .. 127
.def ocr_3 = r20 ; Helligkeitswert Led3: 0 .. 127
.def ocr_4 = r21 ; Helligkeitswert Led4: 0 .. 127
.def ocr_5 = r22 ; Helligkeitswert Led5: 0 .. 127
.def ocr_6 = r23 ; Helligkeitswert Led6: 0 .. 127

.org 0x0000
rjmp main ; Reset Handler
.org OVF0addr
rjmp timer0_overflow ; Timer Overflow Handler

main:
ldi temp, LOW(RAMEND) ; Stackpointer initialisieren
out SPL, temp
ldi temp, HIGH(RAMEND)
out SPH, temp

ldi temp, 0xFF ; Port B auf Ausgang
out DDRB, temp

ldi ocr_1, 0
ldi ocr_2, 1
ldi ocr_3, 10
ldi ocr_4, 20
ldi ocr_5, 80
ldi ocr_6, 127

ldi temp, 0b00000001 ; CS00 setzen: Teiler 1
out TCCR0, temp

ldi temp, 0b00000001 ; TOIE0: Interrupt bei Timer Overflow
out TIMSK, temp

sei

loop: rjmp loop

timer0_overflow: ; Timer 0 Overflow Handler
inc PWMCount ; den PWM Zähler von 0 bis
cpi PWMCount, 128 ; 127 zählen lassen
brne WorkPWM
clr PWMCount

WorkPWM:
ldi temp, 0b11000000 ; 0 .. Led an, 1 .. Led aus

cp PWMCount, ocr_1 ; Ist der Grenzwert für Led 1 erreicht
brlt OneOn
ori temp, $01

OneOn: cp PWMCount, ocr_2 ; Ist der Grenzwert für Led 2 erreicht
brlt TwoOn
ori temp, $02

TwoOn: cp PWMCount, ocr_3 ; Ist der Grenzwert für Led 3 erreicht
brlt ThreeOn
ori temp, $04

ThreeOn:cp PWMCount, ocr_4 ; Ist der Grenzwert für Led 4 erreicht
brlt FourOn
ori temp, $08

FourOn: cp PWMCount, ocr_5 ; Ist der Grenzwert für Led 5 erreicht
brlt FiveOn
ori temp, $10

FiveOn: cp PWMCount, ocr_6 ; Ist der Grenzwert für Led 6 erreicht
brlt SetBits
ori temp, $20

SetBits: ; Die neue Bitbelegung am Port ausgeben
out PORTB, temp

reti


(Quelle: http://www.mikrocontroller.net/articles/AVR-Tutorial:_PWM)

Da ich aber mit C arbeiten möchte hilft mir der Code nicht wahrlich weiter.
Ich würde mich freuen, wenn ihr mir Tipps geben könntet, die mir bei der Umsetzung helfen würden.
Danke im Voraus!

McJenso
23.08.2008, 17:58
Hallo,

schnapp dir das Datenblatt und diesen Artikel (https://www.roboternetz.de/wissen/index.php/Timer/Counter_%28Avr%29#PWM) aus dem Wissenbereich.
Achte halt drauf, das die LED am richtigen PIN sitzt und der PIN als Ausgang definiert ist. Wenn's dann nicht klappt, haben wir eine Grundlage mit der wir arbeiten können.

Gruß

Jens

H3llGhost
23.08.2008, 18:16
Hallo Jens,

danke für die Infos.
Ich werde mich dann mal gleich zu Hause dransetzen und testen.
Wenn das nicht klappt werde ich mich mal melden ... ;)
Bzw. wenn es geklappt hat ... :)

H3llGhost
23.08.2008, 21:19
So hier ist nun mein Programm:



#include <avr/io.h>
#include <util/delay.h> //Warteschleife für die Demo-Ausgabe. Für die eigentliche PWM nicht benötigt!

int main()
{

// PWM-Beispiel für Mega168 mit dem Timer2

// 1. Den Prescaler einstellen, der die Frequenz festlegt
TCCR2B |= (1<<CS22); //Prescaler 256

// 2. Den Timer in den Fast PWM Mode, 8 Bit schalten
TCCR2A |= (1<<WGM20);
TCCR2A |= (1<<WGM21);

// 3. Compare Output mode einstellen: Pin geht auf high bei Compare match, auf low bei Überlauf. Ergibt nichtinvertierte PWM.
TCCR2A |= (1<<COM2B1);

// In diesen Registern wird der gwünschte PWM-Wert abgelegt. Erlaubter Bereich: 0 bis 255.
OCR2B = 255;

// 4. Zuletzt den Pin als Ausgang konfigurieren. Erst jetzt liegt das PWM-Signal an dem Pin an!
DDRD |= (1<<PD3);

/*Nun ist der PWM-Modus aktiv! Der Ausgangswert kann nun über das Register OCR2B vorgegeben werden.
Man könnte ihnen per define noch einen Zweitnamen verpassen, zb */
#define LED OCR2B

LED = 0;



/*PWM-Demo: Die PWM-Werte werden erst bis zum Maximalwert erhöht und dann wieder verringert.
Eine angeschlossene LED wird langsam heller und wird dann wieder verdunkelt*/
uint8_t wert;
while(1)
{
for (wert=0; wert<255; wert++)
{
OCR2B = wert;
_delay_ms(20);
}

for (wert=255; wert>0; wert--)
{
OCR2B = wert;
_delay_ms(20);
}
}
}


Das Programm läuft erstmal so wie ich es möchte.

EDIT: Kommentare aus dem Code überarbeitet

oberallgeier
24.08.2008, 11:56
So hier ist nun mein Programm:....
Das Programm läuft erstmal so wie ich es möchte.Es läuft so, wie Du möchtst? Das wundert mich schon ein bisschen. Du bist wohl ein kleiner Scherzkeks ! ? ! ?


... LED ... ATmega168 ... runterdimmen ... ... PWM-Beispiel für Mega16/32 ...Na ja, ok, man kann natürlich statt mit em m168 auch mit m32/16 dimmen - wie Du es ja wohl tust.


... Timer1 ... 8 Bit ...Dein code ist aber doch für den Timer 2 ! ? Ist wegen der 8 Bit auch sinnvoller.


... Timer1 im Fast PWM Mode, 8 Bit ...Fast PWM ? Wieso? Wo ist die Parameterisierung?


... Beispiel für Mega16/32 ... TCCR2A |= (1<<COM2B1); ...In meinem ATmega32-doc2503 und im mega16-doc2466 gibts weder ein TCCR2A noch ein COM2B1. Ist das ein neuartiger mega16/32 ? ? Und die WGM20/~21 stehen im TCCR2 - das ist der ohne "A". ... und so weiter, etliche Ungereimtheiten.

Also doch ein mega168. Scheint eine Denksportaufgabe zu sein.


... DDRD |= (1<<PD3); ...Jaaa, hier ist ja (noch) ein Hinweis auf den m168.


... Fast PWM Mode ...Da Du Dich nicht um die COM0x* nicht kümmerst, weiss ich nicht ob das stimmt. Oder liegt hier eine weitere Denksportaufgabe?


... Das Programm läuft erstmal so wie ich es möchte.Dann ist´s ja gut.

H3llGhost
24.08.2008, 15:55
Ich hätte vielleicht die alten Kommentare entfernen können ... :D
Das ist der Code für einen ATmega168.



... Fast PWM Mode ...Da Du Dich nicht um die COM0x* nicht kümmerst, weiss ich nicht ob das stimmt. Oder liegt hier eine weitere Denksportaufgabe?

Warum sollte ich denn das Register COM0x* einstellen?!
Ich benutze doch den Timer2 und dann benutze ich doch das Register COM2B1.

oberallgeier
24.08.2008, 17:42
... Warum sollte ich denn das Register COM0x* einstellen?! ...Tut mir leid, war mein Fehler.


Ich hätte vielleicht die alten Kommentare entfernen können ...Stimmt, am Besten vorm Fragen. Nix ist so alt, wie der Kommentar vom letzten (abgeänderten) Code.

H3llGhost
25.08.2008, 08:39
Stimmt, am Besten vorm Fragen. [...]

Ich habe doch keine Frage gestellt oder?
Ich habe einfach nur mein Ergebnis mit komischen Kommentaren gepostet oder? :-P