PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : SOFTWARE-PWM



Exodus
08.06.2006, 08:44
Hallo leute

Mal ne frage!
Hab schon ein paar sachen gelesen über software PWM, aber komm da nicht so ganz mit! Ich meine ab welcher frezuenz ist die led hell und ab welcher frequenz ist die led gedimmt, also dass man halt nicht dass flimmern sieht??


Bitte um Rückantwort wWIE ICH DASS AM BESTEN ANSTELLE in ASSEMBLER!
Also einen vorschlag hätte ich, mit TIMER?
NAJA BITTE UM HILFE

MFG
Michael

trickTronic
08.06.2006, 08:58
Hallo,

ich kann dir nur einen c-code (winavr) zur Verfügung stellen:



#include <avr\io.h>
#include <avr\interrupt.h>

void PwmInit(void) {
gTimerCounter0 = 0;
sPwmMode = pwmMode;

/* Timer/Counter 0 initialization
* Clock source: System Clock / 1024
* Clock Mode: Fast PWM
* Clock value:
* 5,46ms, 12MHz -> prescale 256 (Frequenz ca. 183Hz)
* duty cycle 50% -> OCR0 127
*/
TCCR0 = 0
| BIT_WGM00 | BIT_WGM01 /* Fast PWM */
| BIT_COM00 | BIT_COM01 /* Set OC0 on Compare Match, Clear OC 0 at Top */
| BIT_CS02; /* N = 256 */

TIMSK |= (0
| BIT_TOIE0 /* Output Compare Interrupt Enable */
| BIT_OCIE0); /* Overflow Interrupt Enable */

OCR0 = 0x7f; /* 50% */
TCNT0 = 0;
}

ISR(TIMER0_COMP_vect) {
/* todo: Ausgänge ausschalten */
}

ISR(TIMER0_OVF_vect) {
/* todo: Ausgänge setzen */
}

void BrightnessSet(unsigned char brightness) {
OCR0 = brightness;
}



Der Prescaler für den Timer wurde mit 12MHz (für den Atmega16) bestimmt.
Ich habe damit eine Frequenz von ca. 183Hz, das reicht um die LEDs durchgängig leuchten zu sehen.
Die Helligkeit kann in 256 Schritten eingestellt werden, defaultmäßig liegt sie in diesem Beispiel bei 50%.

LG,
Alex

Exodus
08.06.2006, 09:09
Brauche es aber für ATMEGA8535 mit 4MHZ!
Bitte nicht in C sondern in assembler!

danke
michael

trickTronic
08.06.2006, 09:24
tja.
ich wollt dir nur einen Anhaltspunkt geben...
Lt. Datenblatt des atmega8535 funktioniierts genau gleich.
Die Frequenz berechnet sich so:
f(pwm) = f(io)/(256*N) = 4000000/(256*N) =

Exodus
08.06.2006, 09:26
aber habe keine ahnung wie ich dass anstellen soll? Soll ich mit interrupt arbeiten im Timer??

MFG
Michael

trickTronic
08.06.2006, 09:27
sorry, falschen button erwischt...

15625/N

Wenn du eine Frequenz um die 150Hz haben willst ->
N = 15625/150 = 104.
Da du als N nur 1,8,64,256,1024 auswählen kannst nimm z.B. einfach (wie in meinem Code) 256 und es kommen 61Hz raus. Bei 64 ist es das 4-fache!
MFG, Alex

trickTronic
08.06.2006, 09:28
Mein Beispiel benutzt den Interrupt.
Aber assemblieren tu ich den code nicht.... warum willst du keinen c-compiler benutzen? ist doch viel einfacher...

Exodus
08.06.2006, 09:54
Kann ich dass so machen??


.include <m8535def.inc>

.org 0x0000
rjmp Start

.org OVF0addr
rjmp ein


Start:
ldi R16, High(RAMEND)
out SPH, R16
ldi R16, LOW(RAMEND)
out SPL, R16
ldi R16, 0b00000001
out TCCR0, R16
out TIMSK, R16
sei
aus:
;Code für ausschalten
rjmp loop

ein:
;Code für ausschalten
reti

bitte um rückantowrt

MFg
Michi

Exodus
08.06.2006, 12:39
Ich kapier dass noch immer nicht mit den Timer eine PWM hinzubekommen!

BITTE HELFEN!!

MFG
Michael

trickTronic
08.06.2006, 13:58
TCCR0:

Fast PWM: WGM01=1, WGM00=1
Set OC01 on Compare Match, Clear OC0 at top: COM01=1, COM00=1
Clock(IO)/64(from Prescaler). CS02=0; CS01=1, CS00=1
FOC0: inactive at fast-pwm-mode

Ergibt:
TCCR0 = Bit 6 5 4 3 1 0 = 0x7b;

TIMSK:
Interrupt enable: Output Compare und Overflow Flag, Bits 0 und 1
TIMSK |= 0x03; (| nur wenn andere Timer auch verwendet werden)

TCNT = 0; -> TimerCoutner auf 0 setzen.
OCR0 -> bestimmt Helligkeit.

Anhand des Datenblatts (Abschnitt 8-Bit-Timer-Counter0 with PWM, Figure32. Timing Diagram) zählt der Counter mit dem Prescaler immer hoch. Wenn der Wert in OCR erreicht ist wird der OCR-Interrupt(output compare) ausgelöst, kommt der Zähler oben an wird der TOV-Interrupt (Timer overflow) ausgelöst und der Zähler beginnt wieder bei 0.
Die Perioden des Timers zum Überlauf sind immer gleich lang, die Dauer zwischen Overflow und OCR beträgt somit [t(ges)*256/OCR].

Das sollte genug sein. Noch Fragen?
Alex

Exodus
08.06.2006, 14:27
Hab jetzt mal dass geschrieben!

.include <m8535def.inc>

.org 0x0000
rjmp Reset

.org OVF0addr
rjmp michi

.org OC0addr
rjmp PWM


Reset:

ldi R26, 0b00000000

ldi R16, HIGH(RAMEND)
out SPH, R16

ldi R16, LOW(RAMEND)
out SPL, R16

ldi R16, 0b00000001
out TCCR0, R16

ldi R16, 0b00000011
out TIMSK, R16

ldi R17, 1
out OCR0, R17

sei



loop1:
ldi R27, 0b00000001
out DDRA, R27
ldi R16, 0b00000010
out DDRA, R16
rjmp loop1
loop2:
ldi R27, 0b00000001
out DDRA, R27
ldi R16, 0b00000000
out DDRA, R16
rjmp loop2

PWM:

out TCNT0, R26
out OCR0, R17
sei
sbis DDRA, 1
rcall loop1
rcall loop2

michi:
reti

mfg
Michael

trickTronic
08.06.2006, 15:53
Ich habs zwar nicht getestet aber so müsste theoretisch pin1 von Port a pwm-mäßg bei 50% toggeln.



.include <m8535def.inc>

.org 0x0000
rjmp init

.org OVF0addr
rjmp ovf

.org OC0addr
rjmp ocr

init:
ldi R26, 0b00000000

ldi R16, HIGH(RAMEND)
out SPH, R16

ldi R16, LOW(RAMEND)
out SPL, R16

ldi R16, 0x7b
out TCCR0, R16

ldi R16, 0x03
out TIMSK, R16

ldi R17, 0x7f
out OCR0, R17

ldi DDRA, 0x01

sei

mainloop:
rjmp mainloop

ovf:
ldi r16, 0x01
out PORTA, r16
reti

ocr:
ldi r16, 0x00
out PORTA, r16
reti


MFG,
Alex

Hanni
08.06.2006, 19:31
Hmm ... leicht umständlicher Code.

BTW: Mal als Tip: Benutz mal die Suchfunktion !!!

Rauskommen könnte da z.B. dieses als Ergebniss: klick mich !! (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=18866&highlight=software+pwm)

Dieses sollte als Denkansatz durchaus ausreichen, zumal ich mich weigere jemandem den kompletten Code zu schreiben.

Grüße,

da Hanni.

Exodus
08.06.2006, 21:59
neinnein brauchst nicht den code schreiben. Will eh selber rausbekommen.
Brauche nur anhaltspunkte!

mfg
Michael