mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Software PWM mit Bascom


Autor: Dennis Brenzel (danrulz81)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Kluchscheißernder Nixwisser (kluchscheisser)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Dennis Brenzel (danrulz81)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> - bei Erreichen des Tastgrades (PWM-Wertes) wird der Portpin wieder
>   ausgeschaltet

Das hab ich irgendwie nicht ganz verstanden. Der PWM - Zähler zählt 
dabei nochmals auf den eingestellten Wert hoch und schaltet dann wieder 
zurück, oder was ist mit Tastgrad gemeint.

Autor: Dennis Brenzel (danrulz81)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Kluchscheißernder Nixwisser (kluchscheisser)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Dennis Brenzel (danrulz81)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Kluchscheißernder Nixwisser (kluchscheisser)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Kluchscheißernder Nixwisser (kluchscheisser)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Dennis Brenzel (danrulz81)
Datum:

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

Config Timer0 = Timer , Prescale = 64

On Timer0 Timer0_isr

Config Portc = Output
Portc = 255
B = 120
A = 0
Enable Timer0
Enable Interrupts
Portc.1 = 0

Do
Loop

Timer0_isr:
Incr A                                                      'A eins hoch zählen
If A = 200 Then
Portc.0 = 0                                                 'Wenn A 200 ist dann portc.0 ein
A = 0
End If                                                      'A wieder nullen
If A = B Then                                               'Wenn A 120 ist dann
Portc.0 = 1                                                 'Portc.0 aus
A = 0                                                       'A wieder nullen
endif
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?

Autor: AVRuser (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Dennis Brenzel (danrulz81)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: r-u (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Dennis Brenzel (danrulz81)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> PS: Das Speichern der Register beim ISR-Aufruf wird hier (prescaler 64)
> kaum eine Rolle spielen, man kann es aber mit Parameter NOSAVE
> verhindern.

Wo trag ich den ein?

Autor: Weingut Pfalz (weinbauer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gibt aber auch nen Befehl der u.U. dafür passen würde ...

SERVO

Autor: Dennis Brenzel (danrulz81)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vor allem fällt mir ein, dass ich dass dann ja für jedes Register 
explizit machen muss, welches ich nicht speichern möchte, oder hab ich 
das falsch verstanden?

Autor: r-u (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Handbuch lesen hilft - beides steht in der Hilfe zu "ON INTERRUPT"

Autor: Dennis Brenzel (danrulz81)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also werden alle nicht gespeichert, so hab ich es verstanden:
When you specify NOSAVE, no registers are saved and restored in 
the interrupt routine. So when you use this option make sure to save 
and restore all used registers.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Kluchscheißernder Nixwisser (kluchscheisser)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Dennis Brenzel (danrulz81)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Kluchscheißernder Nixwisser (kluchscheisser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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.

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

MfG

Autor: Paul Baumann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht hilft Dir das:
Beitrag "Software PWM Bascom"

MfG Paul

Autor: Dennis Brenzel (danrulz81)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.