Software PWM mit Bascom

OP #1720933
Lesenswert?

Hallo zusammen,

ich überlege gerade, wie ich ne Software PWM für meinen mega8515L mit 
BASCOM realisiere. Klingt das so geschickt:

Wenn Timerwert = 100 dann die LED einschalten, ansonsten aus

Oder sollte ich lieber den Timer bei sagen wir 155 starten lassen, und 
beim Interrupt die LED einschalten, und wenn der Interrupt wieder weg 
ist, ausschalten?
#1721162
Lesenswert?

Dennis Brenzel schrieb:
> Hallo zusammen,
>
> ich überlege gerade, wie ich ne Software PWM für meinen mega8515L mit
> BASCOM realisiere. Klingt das so geschickt:
>
> Wenn Timerwert = 100 dann die LED einschalten, ansonsten aus

Nö, denn dann kannst Du auf den Interrupt verzichten und den Port direkt 
von der Compare-Einheit des Timers schalten lassen, also Hardware-PWM.

>
> Oder sollte ich lieber den Timer bei sagen wir 155 starten lassen, und
> beim Interrupt die LED einschalten, und wenn der Interrupt wieder weg
> ist, ausschalten?

Auch das ist es nicht...

Es gibt verschiedene Varianten der Soft-PWM, eine (die leicht 
verständlichere) funktioniert so:

Ein Timer generiert in regelmäßigen Zeitabständen Interrupts. In diesem 
Interrupt wird:

- ein PWM-Zähler hochgezählt
- bei Erreichen des PWM-Zählumfangs wird der PWM-Zähler auf 0 gesetzt 
und
  der Portpin eingeschaltet
- bei Erreichen des Tastgrades (PWM-Wertes) wird der Portpin wieder
  ausgeschaltet
- Dies kann für mehrere PWM-Kanäle mit eigenen PWM-Werten und Portpins
  quasi gleichzeitig erfolgen.

In Bascom hast Du allerdings eine schwerwiegende Einschränkung: Bei 
jedem Interrupt werden alle 32 Register auf Stack gesichert, was 128 
CPU-Takte zusätzlich kostet. Dies reduziert die erreichbare 
Interruptfrequenz drastisch und begrenzt die erreichbare PWM-Frequenz. 
So richtig flimmerfrei wird die PWM also kaum werden.
OP #1721199
Lesenswert?

Ah, jetzt hab ich es glaube ich verstanden. Der Timer löst sagen wir bei 
200 einen Interrupt aus, zählt aber weiter bis 255. Bei diesem Interrupt 
schaltet er eine LED ein. Hat der Timer 255 zählt er wieder zurück auf 
0. Wenn er die 200 unterschreitet, löst er wieder einen Interrupt aus, 
der die LED dann ausschaltet. Wobei ich beim nächsten Problem wäre:
Wie lass ich nen Timer rückwärts laufen, und wie sag ich dem Timer dann, 
welchen Interrupt er auslösen soll?
#1721211
Lesenswert?

Der PWM-Zähler zählt von 0 bis zum PWM-Zählumfang, und zwar bei jedem 
Timer-Interrupt nur einen Schritt.

Bei Erreichen des Zählumfangs wird er wieder auf 0 gesetzt. Gleichzeitig 
werden alle PWM-Kanäle auf H-Pegel gesetzt (eingeschaltet).

In jedem Timer-Interrupt wird der PWM-Zähler mit den PWM-Werten 
(Sollwert Tastgrad) aller Kanäle verglichen und bei Gleichstand der 
entsprechende PWM-Kanal ausgeschaltet.

Bei dieser Art der Software-PWM beginnen alle Kanäle zum gleichen 
Zeitpunkt mit dem Impuls, was eine impulsförmige Gesamtbelastung der 
Stromversorgung bewirkt. Es gibt aber auch eine andere Art der 
Software-PWM, die diesen Nachteil nicht hat. Sie braucht dafür aber für 
jeden Kanal einen eigenen PWM-Zähler. Diese Methode ist auch hier 
irgendwo im Forum beschrieben.
<such...> Hier geht's weiter:
Beitrag "Re: Software PWM auf 8 Kanälen"

Unter Tastgrad verstehe ich das Verhältnis Impulsdauer zu Periode in 
Prozent oder als Bruch.
OP #1721215
Lesenswert?

Das Problem wird für mich sein, das ganze auf BASCOM zu portieren, wie 
du ja schon beschrieben hast. Und wenns dann noch in C geschrieben ist, 
verstehe ich leider nur Bahnhof. Assembler versteh ich noch 
einigermaßen, wobei das auch schon wieder 8 Jahre her ist, und das war 
noch auf Siemens µC's. Ich danke dir auf jedenfall, ich werde versuchen 
mich da durch zu kauen.
#1721216
Lesenswert?

Dennis Brenzel schrieb:
> Ah, jetzt hab ich es glaube ich verstanden. Der Timer löst sagen wir bei
> 200 einen Interrupt aus, zählt aber weiter bis 255. Bei diesem Interrupt
> schaltet er eine LED ein. Hat der Timer 255 zählt er wieder zurück auf
> 0. Wenn er die 200 unterschreitet, löst er wieder einen Interrupt aus,
> der die LED dann ausschaltet.

Nein, das Wäre Hardware-PWM im Phase-correct-Mode....

> Wobei ich beim nächsten Problem wäre:
> Wie lass ich nen Timer rückwärts laufen,

Gar nicht, das geht nur bei Hardware-PWM im Phase-correct-Mode.

> und wie sag ich dem Timer dann,
> welchen Interrupt er auslösen soll?

Die Frage erübrigt sich im speziellen Fall, war sie allgemein gemeint, 
so verweise ich auf das Kapitel Timer im Datenblatt des verwendeten 
AVRs. Auch das Benutzen von Bascom befreit nicht vom Lesen des 
Datenblattes. ;-)

Software-PWM wird durch einen Software-Timer (eine stinknormale 
Zählvariable) gesteuert. Der Timer mit seinem Interrupt sorgt nur dafür, 
dass diese Zählvariable in exakt gleichen Zeitabständen hochgezählt 
wird. Welchen Timer-Interrupt und Timer-Modus man nutzt, kommt darauf 
an, was der Timer sonst noch erledigen soll. Soll er nichts weiter als 
Software-PWM erledigen, nimmt man den Compare-Interrupt im CTC-Modus, 
denn der erübrigt Preload oder Aufaddieren des Intervalls auf das 
Compare-Register.
#1721223
Lesenswert?

Dennis Brenzel schrieb:
> Das Problem wird für mich sein, das ganze auf BASCOM zu portieren, wie
> du ja schon beschrieben hast.

Bascom ist für schnelle Folge von Interrupts absolut ungeeignet, weil es 
durch die Sicherung aller (also auch der unbenutzten) Register auf Stack 
zuviel wertvolle Rechenzeit vertrödelt. Es lohnt sich also nicht, Zeit 
dafür zu investieren. In der Zeit, bis Du merkst, dass es zu langsam 
wird, bist Du in ASM zehnmal fertig.

> Und wenns dann noch in C geschrieben ist,
> verstehe ich leider nur Bahnhof.

Das geht mir nicht besser.

> Assembler versteh ich noch
> einigermaßen, wobei das auch schon wieder 8 Jahre her ist, und das war
> noch auf Siemens µC's.

Naja, jede Architektur hat ihren eigenen Assembler, abstrahiert gesehen 
ist zwar alles ähnlich, die details unterscheiden sich aber erheblich. 
Es lohnt sich aber, mit Hilfe von ASM die Architektur des Controllers 
kennen zu lernen.

> Ich danke dir auf jedenfall, ich werde versuchen
> mich da durch zu kauen.

Viel Erfolg
OP #1730819
Lesenswert?

So, ich hab bis heute versucht, was Gescheites hinzubekommen, aber wie 
ihr seht, komm ich nicht weiter. Hier mein Code:
1
$regfile = "m8515.dat"
2
$crystal = 8390000
3
Dim A As Integer
4
Dim B As Integer
5

6
Config Timer0 = Timer , Prescale = 64
7

8
On Timer0 Timer0_isr
9

10
Config Portc = Output
11
Portc = 255
12
B = 120
13
A = 0
14
Enable Timer0
15
Enable Interrupts
16
Portc.1 = 0
17

18
Do
19
Loop
20

21
Timer0_isr:
22
Incr A                                                      'A eins hoch zählen
23
If A = 200 Then
24
Portc.0 = 0                                                 'Wenn A 200 ist dann portc.0 ein
25
A = 0
26
End If                                                      'A wieder nullen
27
If A = B Then                                               'Wenn A 120 ist dann
28
Portc.0 = 1                                                 'Portc.0 aus
29
A = 0                                                       'A wieder nullen
30
endif
31
Return

Ich weiß, das A nie die 200 erreichen wird, da sie vorher von den 120 
abgefangen wird, aber irgendwie steh ich momentan aufm Schlauch. Könnte 
mir jemand einen Wink mit der Blockhütte geben?
Gast #1730883
Lesenswert?

Hallo,

> If A = B Then                                               'Wenn A 120 ist
> Portc.0 = 1                                                 'Portc.0 aus
>> A = 0                                                      'A wieder 0
>>endif
>Return

In diesem Fall darf A NICHT auf Null gesetzt werden. Dann ist es soweit 
korrekt.

Den Befehl "endif" gibt es in BASCOM nicht ...

Wenn ich richtig gerechnet habe, wird die Timer-ISR alle 1,9ms 
aufgerufen.

> $crystal = 8390000

Was ist das für eine komische Frequenz?
OP #1731199
Lesenswert?

AVRuser schrieb:

> Den Befehl "endif" gibt es in BASCOM nicht ...

Ohne bekomm ich einen Fehler.

> Wenn ich richtig gerechnet habe, wird die Timer-ISR alle 1,9ms
> aufgerufen.
>
>> $crystal = 8390000
>
> Was ist das für eine komische Frequenz?

Die hab ich mit nem Frequenzzähler ermittelt. Pin toggeln in ASM und die 
Befehle umgerechnet. ist aber auch nur ungefähr.
Gast #1731304
Lesenswert?

wenn Du aus A und B Bytes machst statt Interger, kannst Du Deine ISR 
extrem vereinfachen, indem Du Dir den "Überlauf" zunutze machst 
(255+1=0):

Timer0_isr:
   Incr A
   if A > B then PortC.0=0 else PortC.0=1 'oder auch andersrum
return

PS: Das Speichern der Register beim ISR-Aufruf wird hier (prescaler 64) 
kaum eine Rolle spielen, man kann es aber mit Parameter NOSAVE 
verhindern.
#1731871
Lesenswert?

Dennis Brenzel schrieb:
> Also werden alle nicht gespeichert,

Etwas unglücklich ausgedrückt.

no registers                         kein Register, kein einziges

are saved                            wird gesichert

and restored                         und wieder hergestellt

....                                 daher

when you use                         wenn sie das benutzen

make sure                            müssen sie sicherstellen

to save and restore                  alle benutzten Register selbst
all used registers                   zu sichern und wieder herzustellen



Wenn dir das jetzt erst mal nichts sagt, dann ist es besser du benutzt 
diese Möglichkeit erst mal nicht. Und nein, mit Registern sind keine 
Variablen gemeint, sondern die echten CPU-Register. Man muss also den 
Assembler Output studieren um festzustellen, welche davon vom Compiler 
in der ISR benutzt werden.
#1732009
Lesenswert?

> Man muss also den
> Assembler Output studieren um festzustellen, welche davon vom Compiler
> in der ISR benutzt werden.

Man benutzt aber Bascom, um genau das (sich mit Assembler befassen) zu 
vermeiden.

Und man hat auch kein Interesse daran, mal selbst die Nase in eine Doku 
(Bascom-Hilfe, Controller-Datenblatt) zu stecken, es ist ja viel 
bequemer, sich alles zusammenzufragen und hinterher doch nicht 
selbstständig denken zu können.

Ohne Verständnis der Architektur ist es (auch in einer Hochsprache) 
nicht möglich, halbwegs effiziente Programme zu schreiben. Und 
Software-PWM (auf mehreren Kanälen, denn sonst könnte man ja 
Hardware-PWM nutzen) verlangt nunmal halbwegs effiziente Programmierung, 
sonst wird es einfach zu langsam.
OP #1732024
Lesenswert?

> Also werden alle nicht gespeichert
Damit meinte ich kein Register, das mit den Variablen war mir klar.

> Und man hat auch kein Interesse daran, mal selbst die Nase in eine Doku
> (Bascom-Hilfe, Controller-Datenblatt) zu stecken, es ist ja viel
> bequemer, sich alles zusammenzufragen und hinterher doch nicht
> selbstständig denken zu können

Das ist deine Meinung. Nur wenn ich auf Arbeit bin (Die im Übrigen 
nichts mit µC's zu tun hat), kann ich schlecht die Bascom Hilfe bemühen, 
geschweige denn ein Datenblatt lesen.
OP #1732099
Lesenswert?

Kluchscheißender Consulter schrieb:

> Dann solltest Du Dich auch besser um Deine Arbeit kümmern und nicht dem
> Chef Deine Arbeitszeit stehlen... ;-)

:P

Paul Baumann (Gast) schrieb:
> Vielleicht hilft Dir das:
> Beitrag "Software PWM Bascom"

Den hatte ich auch schon entdeckt, nur irgendwie war das für den Anfang 
doch etwas verwirrend und hatte leider nicht weiter geholfen. Danke 
trotzdem. Jetzt muss ich das nur noch auf die anderen LEDs konvertieren, 
damit ich mein "fadendes" Lauflicht habe.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren