Hallo,
stehe gerade mit der PWM Funktion (phase correct PWM, Mode 5) der Timer
0 und 2 bei meinem ATmega168PA auf Kriegsfuss. An den Ausgangspins
passiert einfach nichts, d.h. die wechseln nie von 0 auf 1. Die Timer
zählen/laufen brav, der Wert für TOP ist gesetzt und die vier OCxx Bits
sind auch gesetzt.
Was habe ich an der Stelle vergessen, bzw. mache ich falsch?
Gruß, Hans
Hallo Stefan,
Bootloader nutze ich nicht, beim (neu-)programmieren des AVRs wird der
AVR gelöscht und dann neu beschrieben.
Habe es aber auch einmal mit "=" probiert: keine Änderung. Die Pins
wackeln nicht.
Nehme ich die Initialisierung des Timers 0 raus und packe ein
1
PORTD|=(1<<PD5)|(1<<PD6);
2
_delay_ms(10);
3
PORTD&=~(1<<PD5)&~(1<<PD6);
4
_delay_ms(10);
in die while Schleife, so lässt das die beiden Pins vom Timer 0 schön
wackeln.
Bin so langsam echt ratlos...
@Landolt & mmmhh: so wie ich die PWM Funktion des Timers bis jetzt
verstanden habe, ist es doch wie folgt: der Zähler des Timers (TCNTx)
zählt von Null bis TOP, von dort wieder runter auf Null, wieder hoch auf
TOP usw. Wenn ich nun das TOP per OCRxA oder OCRxB auf einen Wert
kleiner (oder auch größer) als den aktuellen Zählerstand ändere (da TOP
eben genau diesen Werten entspricht), so läuft der Zähler des Timers
(TCNTx) über/bis zum max. möglichen Wert (hier: 2^8 da 8-Bit Zähler).
Den Zähler selbst stört das aber nicht, er zählt dann wieder ganz normal
von null an wieder weiter nach dem Überlauf (oder von 0xFF eben runter
Richtung null). Somit hätte ich einmalig ein einziges "unsauberes" PWM
weil eben nicht bis zu OCRxA gezählt wird, sondern bis 2^8. Sofern OCRxA
aber konstant bleibt, ist das eine einmalige Sache und im Anschluss
läuft der Zähler des Timers zw. Null und OCRxA=TOP (bzw. OCRxB). Oder
habe ich das völlig falsch verstanden?
mmmhh schrieb:> Schon mal OCR0B bzw OCR2B etwas kleiner als OCR0A bzw OCR2A angegeben?
OCR0B soltle im Mode 5 komplett außen vor sein, als TOP wird immer OCRxA
genommen, oder?
> OCR0B soltle im Mode 5 komplett außen vor sein
?
Einfach mal ausprobieren wie von mmmhh vorgeschlagen, also z.B.
OCR0B=$A0. Dann blinkt das nämlich bei mir an OC0B, während OC0A
konstant bleibt.
Was auch immer das Datenblatt unter
https://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48_88_168_megaAVR-Data-Sheet-40002074.pdf
sagt, entweder ist da ein Fehler drin, oder ich kapiere es gar nicht.
Habe mich schon gewundert, dass z.B. in der Tabelle Table 15-8 immer
OCRA genannt ist (und nicht OCRnA) und auch an anderer Stelle kleinere
Ungereimtheiten sind. Auf jeden Fall hat OCRnB einen entscheidenden
Einfluss auf das Verhalten! Meine Vermutung ist, dass der eine OCR Werte
der Vergleichswert ist, während der andere TOP festlegt. Sind beide
ungleich, dann gibt es auch einen PWM am Ausgangspin.
@Landolt: danke für deine Hartnäckigkeit, das war der entscheidende
Tipp!!!
@all: nutze nun den fast PWM mode und bin glücklich damit. Funktioniert
alles wie es soll, auch wenn die Phase nun bei Änderungen nicht sauber
ist. Aber die wird eh nur alle ~2min in kleinen Schritten geändert.
> Sind beide ungleich, dann gibt es auch einen PWM am Ausgangspin.
Nicht ganz - OCRnB, welches den Tastgrad der PWM festlegt, muss kleiner
als der TOP-Wert, d.h. OCRnA, sein, Letzteres bestimmt die Frequenz.
... im Modus 5, natürlich.
Und falls Sie eine, mit OCRnA festgelegte Frequenz mit Tastgrad 0.5
möchten, einfach (1 << COM0A0) (statt (1 << COM0A1)) setzen.
ja, der Code ist recht gut dokumentiert... Sollte man oben ja sehen und
die Info hängt mit dran ;-) Aber solche Dinge werde ich auch in zehn
Jahren noch wissen, denn ich habe schon locker 36h gegrübelt und zig
Werte per LEDs und seriell ausgegeben weil ich verzweifelte. Das bleibt
hängen
In meinem Datenblatt steht in der Fußnote zur Tabelle:
"A special case occurs when OCR0B equals TOP and COM0B1 is set. In this
case, the Compare Match is ignored, but the set or clear is done at
TOP."
Heisst das nicht, dass das Vorhaben des TO von Anfang an hätte
funktionieren müssen?
@Stefan: das steht bei mir auch da drin und hatte ich auch so
verstanden, deswegen hatte ich ja auch noch meine Begründung/Erklärung
30.12.2020 18:07 geschrieben. Das Silizium ist aber anders gestrickt...
Wenn nur der zweite Compare Ausgang nicht funktioniert hätte, wäre ich
ja vielleicht noch experimentiell drauf gekommen. Aber dass der erste
Ausgang auch ausfällt wenn OCRnA=OCRnB, das ist schon sehr fies.
Ich werde mir das mal als Textdatei neben das Datenblatt legen. Denn
irgendwann in den nächsten 10 Jahren wird es bestimmt auch mir passieren
und dann erinnere ich mich nicht mehr an diesen Thread.
> Der OCRnA Ausgang kann in diesem Modus kein PWM Signal erzeugen.
Ist das nicht eine reine Definitions- oder Ansichtssache? Da OCRA=TOP
wäre das "PWM Signal" doch allenfalls ein Nadelimpuls, wenn überhaupt,
oder?
S. Landolt schrieb:> Ist das nicht eine reine Definitions- oder Ansichtssache? Da OCRA=TOP> wäre das "PWM Signal" doch allenfalls ein Nadelimpuls, wenn überhaupt,> oder?
Man würde einen symmetrisches PWM Signal mit 50/50 Tastverhältnis
erwarten, denn es geht im den Phase Correct Mode.
Der Zähler zählt immer abwechselnd hoch und runter. Bei Erreichen von
TOP (OCRnA) geht der Ausgang auf LOW, bei Erreichen vom BOTTOM (0) geht
der Ausgang auf HIGH.
Im Datenblatt steht:
"the Output Compare (OC1x) is cleared on the compare match between TCNT1
and OCR1x while upcounting, and set on the compare match while
downcounting."
Tatsächlich passiert folgendes:
OCnA geht einmal auf HIGH und bleibt dann so.
OCnB verhält sich wie beschrieben, aber nur wenn OCRnB >0 und <TOP ist.
Das war mein Code:
Hallo,
lässt sich hier jemand verunsichern? :-)
Auf welche Timereinstellung bezieht sich denn der angebliche Fehler im
Manual? Der TO hat nämlich eine völlig konfuse Timereinstellung.
Die Timer sollen laut TO im Phase Correct Mode arbeiten. In welchen
denn?
Da schau ich mir seine WGM Bits an und stelle fest in dem mit
einstellbaren TOP Wert in OCRxA. Danach sehe ich in seinem Code das er
jeweils den Compare Wert für Channel A und B gleich gesetzt hat. Da kann
nichts toggeln. Welche Pulsweite soll sich ändern?
A bestimmt die Periodendauer und B die Pulsweite. Wenn beide gleich sind
pulst nichts, es liegt Ub an.
Das entspricht 100% Duty Cycle. Genauso muss das auch sein. Alles andere
wäre ein Fehler.
Wenn B = 0, liegt dauerhaft Masse an, 0% Duty Cycle.
Wenn B = TOP, liegt dauerhaft Ub an, 100% Duty Cycle.
Irgendwas dazwischen erzeugt eine Pulsweite.
50% Duty erhält man nur mit OCRnB = OCRnA / 2.
Der TO hat 2 Möglichkeiten.
a) In diesem Timermode kann er nur einen Ausgang nutzen, nämlich OCRnB
und kann damit die Frequenz und Pulsweite selbst einstellen.
b) Man nimmt den anderen Phase Correct Mode mit TOP = 255. Dann kann man
die Frequenz nur noch mittels Prescaler einstellen und beide Ausgänge
OCRnA und OCRnB für PWM nutzen.
Bsp. nach Möglichkeit a) für einen ATmega328PB, sollte ohne weitere
Überprüfung zum 168 kompatibel sein. Die Pinbelegung könnte vielleicht
etwas abweichen.
Veit D. schrieb:> 50% Duty erhält man nur mit OCRnB = OCRnA / 2.
Passt. Ich habe da wohl etwas missverstanden.
> cWenn B = TOP, liegt dauerhaft Ub an, 100% Duty Cycle.
Genau das ist eben nicht der Fall. Wenn OCRnB=TOP ist bleibt der Ausgang
permanent auf LOW.
Kapitel 2.9.5 Phase Correct PWM sagt
"The extreme values for the OCRnx Register represents special cases when
generating a PWM waveform output in the phase correct PWM mode. If the
OCRnx is set equal to BOTTOM the output will be continuously low"
[x] check
"and if set equal to TOP the output will be set to high for non-inverted
PWM mode."
[ ] nope, funktioniert nicht, wenn OCRnA den TOP Wert bestimmt.
Stefan ⛄ F. schrieb:>> cWenn B = TOP, liegt dauerhaft Ub an, 100% Duty Cycle.>> Genau das ist eben nicht der Fall. Wenn OCRnB=TOP ist bleibt der Ausgang> permanent auf LOW.
Zeige mir einmal deinen kompletten Code, auf das Wesentliche reduziert,
aber komplett.
Veit D. schrieb:> Zeige mir einmal deinen kompletten Code, auf das Wesentliche reduziert,> aber komplett.
Und jetzt bitte als Datei-Anhang damit hier nicht so ein
Chaos entsteht.
Ich habe die Arduino IDE verwendet und genau das in die setup() Funktion
geschrieben. loop() ist leer. Wenn ich bei OCR1B den gleichen Wert
verwende wie bei OCR1A, dann bleibt der OC1B (PB2) Ausgang auf LOW.
S. Landolt schrieb:> Mangels eines ATmega168PA verwende ich einen ATmega328P, und bei dem> geht PB2 auf high; in Assembler:>
1
> puti TCCR1A,(1<<WGM11)+(1<<WGM10)+(1<<COM1B1)
2
> puti TCCR1B,(1<<WGM13)+(1<<CS11)
3
> putiw OCR1A,$8000
4
> putiw OCR1B,$8000
5
> sbi DDRB,2
6
>
Also, wenn du schon in Beispielcode eigene Macros verwendest, solltest
du aber auch die passenden Includes dazu posten, damit es
nachvollziehbar wird.
Natürlich ist hier klar, was die Intention ist und es ist auch
kinderleicht, sich selber die passenden Macros zu bauen. Aber vermutlich
nicht für jeden...
Hallo,
ich habe das auch nochmal nachvollzogen und die Ausgänge gehen auf High,
also 100% Duty Cycle.
Ich weiß aber wo das Problem liegt. "Arduino IDE" ist die entscheidende
Information. In der Arduino IDE muss man die Timerkonfiguration anders
angehen. Alle Timer sind für PWM (analogWrite) vorbelegt. Wenn man mit
setup() und loop() programmiert ist das alles im Hintergrund
vorbereitet. Hier muss man vorher alle Timerregister nullen, also auch
TIMSK1 usw.. Kannst ja mal vor deiner Änderung alle Timerregister
auslesen.
Oder man programmiert in der Arduino IDE klassisch mit
c-hater schrieb:> S. Landolt schrieb:>>> Mangels eines ATmega168PA verwende ich einen ATmega328P, und bei dem>> geht PB2 auf high; in Assembler:>>
1
>> puti TCCR1A,(1<<WGM11)+(1<<WGM10)+(1<<COM1B1)
2
>> puti TCCR1B,(1<<WGM13)+(1<<CS11)
3
>> putiw OCR1A,$8000
4
>> putiw OCR1B,$8000
5
>> sbi DDRB,2
6
>>
>> Also, wenn du schon in Beispielcode eigene Macros verwendest, solltest> du aber auch die passenden Includes dazu posten, damit es> nachvollziehbar wird.
Mit Verlaub, die stehen alle im Headerfile des Controllers. Das sollte
auch jedem Assembler Programmierer bewusst bzw. bekannt sein. Warum soll
man Standard defines nochmal neu in eigene Makros gießen? Zudem sich
genau diese Benennung im Manual wieder findet. Einfach gehts nicht
fremden Code zu lesen.
Nein, c-hater meinte die Makros puti und putiw; er wollte aber wohl
nur mal wieder meckern.
Ihnen, Veit Devil, wünsche ich einen guten Rutsch ins Neue Jahr!
Hallo S.Landolt,
ach'so, alles klar. Dachte das sind Standard Assemblerbefehle. Naja
egal. Habs verstanden. Ebenfalls guten und gesunden Rutsch ins neue
Jahr!
S. Landolt schrieb:> Nein, c-hater meinte die Makros puti und /putiw/
Genau.
> er wollte aber wohl> nur mal wieder meckern.
Nein. Überleg' dir doch einfach mal, was passiert, wenn jemand ohne
Assemblerkenntnisse versucht, deinen Beispielcode zu verwenden...
Er wird zu der Erkenntnis kommen, dass Assembler Scheiße und unbenutzbar
ist, weil nix funktioniert.
Ist es das, was du willst?
an c-hater:
> Er wird zu der Erkenntnis kommen, dass Assembler Scheiße> und unbenutzbar ist, weil nix funktioniert.
Mit einer solchen Einstellung und Befähigung wäre der hypothetisch
Interessierte für Assembler ohnehin verloren.
> Ist es das, was du willst?
Mir doch egal - ich bin kein Assembler-Priester.
Und nun: Da sprach der Prinz von Pakistan ...
S. Landolt schrieb:> Mit einer solchen Einstellung und Befähigung wäre der hypothetisch> Interessierte für Assembler ohnehin verloren.
Verloren, bevor er es überhaupt jemals ernsthaft benutzt hat.
>> Ist es das, was du willst?> Mir doch egal - ich bin kein Assembler-Priester.
Meinetwegen.
Aber, wenn das Ziel war, kryptische, in ihrer Wirkung im Detail nur noch
sehr schwer nachvollziehbare Makros zu verwenden, kannst du aber auch
gleich C-Code schreiben. Denn das genau ist ja, was C tut...
Hallo,
@ c-hater, dass ist einem Streit doch gar nicht würdig. Das Forum ist
voller Code Beispiele mit Funktionsaufrufen wo die Funktionsdefinitionen
fehlen. Dafür aber brauchbare Namen verwendet wurden, sodass jeder
halbwegs im Saft stehende weiß was gemeint ist und kann es
nachprogrammieren. Notfalls fragt man nach. Oft ist es auch das Ziel nur
einen Hinweis zu geben und nicht alles gleich offen für copy paste zu
legen. Du legst doch auch nicht alles offen was du programmierst. Lasse
das Jahr bitte ruhig ausklingen. Ich bitte darum. Im nächsten Jahr den
Puls nicht gleich wieder hochfahren. :-)
Noch ein Bsp. wie das bei mir in der Arduino IDE aussehen würde. Ich
verwende hierfür allerdings einen ATmega2560. In diesem Bsp. ist ICR1
für TOP zuständig. Atomic Block kann man sicherlich weglassen, habe ich
mir allerdings so angewöhnt, weil sei() im Hintergrund aktiviert wird.
S. Landolt schrieb:> Mangels eines ATmega168PA verwende ich einen ATmega328P, und bei dem> geht PB2 auf high;
Ich hatte auch einen ATmega368P verwendet, auf einem Arduino Nano Klon.
Veit D. schrieb:> Alle Timer sind für PWM (analogWrite) vorbelegt.> Hier muss man vorher alle Timerregister nullen
Interessant, das wusste ich nicht. Ich dachte, Arduino reserviert nur
den Timer 0. Probiere ich gleich mal aus....
Ich das Problem nun nicht mehr reproduzieren. Bei dem angehängten Sketch
gehen alle 6 Ausgänge auf High. Ich komme mir blöd vor. Trotzdem Danke
Veit.
Hans,
ich habe gerade dein Programm ausprobiert (ohne serielle Ausgabe) und
bei mir gehen alle 4 Timer Ausgänge auf High. Also kann ich auch dein
Problem nicht reproduzieren.
Ich habe einen ATmega328P auf einem Arduino Nano Klon verwendet, sowie
avr-gcc 5.4.0 unter Debian Linux (dieses mal ohne Arduino Software).
Ich kann mir nur vorstellen, dass in deiner config.h irgend etwas
relevantes drin steht. Die hast du uns leider nicht gezeigt.
Hans Schmidt schrieb:> Wie gesagt: bin mittlerweile auch glücklich
Was heißt das, funktionieren deine Ausgänge jetzt? Wenn ja: Warum? Was
hast du geändert?
@Stefan:
Hans Schmidt schrieb:> @all: nutze nun den fast PWM mode und bin glücklich damit. Funktioniert> alles wie es soll, auch wenn die Phase nun bei Änderungen nicht sauber> ist. Aber die wird eh nur alle ~2min in kleinen Schritten geändert.
@all: nach euren Hilfen, Hinweisen und verständlichen Erklärungen bin
ich nun doch wieder beim phasenkorrekten PWM gelandet. Ich finde es nur
"fies", das es im Datenblatt nich schöner erklärt ist/wird. Egal, Leben
ist kein Ponyhof.
Danke euch 2021 kann nur besser werden.
Hans
Hans Schmidt schrieb:> bin ich nun doch wieder beim phasenkorrekten PWM gelandet
Und es klappt auch dieses mal, nehme ich an. Aber warum? Was hast du
korrigiert?
Donnerwetter - da hat jemand aber einen besonders eifrigen Fan, um nicht
zu sagen Claqueur; jeder noch so banale Beitrag wird beklatscht.
Wirklich ganz erstaunlich.
Falls Ihnen doch noch ein Licht aufgeht, trösten Sie sich: ich hatte
eben auch einen Moment gestutzt, bevor ich Ihren Beitrag begriff.
Da ich aber nun schon mal hier bin: ich wünsche allen hier ein gutes
Neues Jahr (den meisten von Herzen, einigen mit (virtuellem)
Handschlag), möge es zumindest nicht schlechter werden als 2020.
S. Landolt schrieb:> Da ich aber nun schon mal hier bin: ich wünsche allen hier ein gutes> Neues Jahr (den meisten von Herzen, einigen mit (virtuellem)> Handschlag), möge es zumindest nicht schlechter werden als 2020.
Naja, das wäre ja nun kaum mehr möglich. Abgesehen vom (idiotischerweise
leider immer noch real möglichen weltweiten nuklearen Schlagabtausch)
fällt mir da nichts mehr ein, was es noch mieser machen könnte, als 2020
war.
Möge also dein Wunsch in Erfüllung gehen, die Chancen dafür sind relativ
gut...
Stefan ⛄ F. schrieb:> Hans Schmidt schrieb:>> bin ich nun doch wieder beim phasenkorrekten PWM gelandet>> Und es klappt auch dieses mal, nehme ich an. Aber warum? Was hast du> korrigiert?
Eine Bedingung/Prüfung in den Code eingebaut die bei jeder Änderung der
OCR Register zum Zuge kommt und dadurch sichergestellt ist, dass in
allen Fällen OCRnA > OCRnB ist.
Hans Schmidt schrieb:> Eine Bedingung/Prüfung in den Code eingebaut die bei jeder Änderung der> OCR Register zum Zuge kommt und dadurch sichergestellt ist, dass in> allen Fällen OCRnA > OCRnB ist.
Aber OCRnA muss doch gar nicht > OCRnB sein!
Kommt drauf an wie du es siehst, bzw. ich habe es ggf. immer noch nicht
verstanden... Technisch hast du Recht und B dürfte auch größer als A
sein. Aber was bringt das?
Der Zähler läuft von Null rauf auf TOP und wieder runter auf Null. Und
TOP wird an der Stelle mit durch A festgelegt. Wenn ich also B größer
als A setze, wird dieser Wert (vom Zähler) nie erreicht und ist somit
wirkungslos.
Hans Schmidt schrieb:> Der Zähler läuft von Null rauf auf TOP und wieder runter auf Null. Und> TOP wird an der Stelle mit durch A festgelegt. Wenn ich also B größer> als A setze, wird dieser Wert (vom Zähler) nie erreicht und ist somit> wirkungslos.
Das ist richtig. So weit sollst du auch gar nicht gehen, sondern nur bis
B gleich TOP. Solange du um 1 darunter bleibst kommst du nie auf die
maximal mögliche Pulsbreite von 100%.
Hallo,
ebenfalls gesundes Neues in die lustige Runde.
Ansonsten, blickt hier noch einer durch welchen Code der TO aktuell hat?
Ich nicht. Deswegen nur ganz pauschal formuliert für den TO.
Es kommt darauf an welchen Timermode du verwendest.
Dabei hast du im Phase Correct Modus nur 5 Möglichkeiten - mit Timer 1
erklärt. TOP ist fest auf 0xFF oder 0x01FF oder 0x03FF festgenagelt.
Damit kannste du die Pins OCnA und OCnB für PWM verwenden. Bedingung,
die PWM Werte dürfen TOP nicht überschreiten.
Oder du nimmst den Mode mit ICRn als TOP.
Dann haste auch beide Pins OCnA und OCnB frei.
Bedingung, die PWM Werte dürfen TOP (ICR1) nicht überschreiten.
Oder du nimmst den Mode mit OCRnA als TOP.
Dann haste den Pins OCnB für PWM frei.
Bedingung, der PWM Wert darf TOP (OCRnA) nicht überschreiten.
Beim Update von OCRnA und OCRnB sind diese gepuffert. Das heißt die
Änderung erfolgt immer zum richtigen Zeitpunkt. ICRn ist nicht
gepuffert. Falls du Letzteres zur Laufzeit änderst kann es kurz zucken.
Falls du die Frequenz ändern möchtest.
Und lass dich von der auf/ab Zählweise in diesem Mode nicht
durcheinanderbringen. Für deine Einstellerei ist das unbedeutend. Das
dient "nur" der richtigen Phasenlage. Sieht man schön wenn man beide
Ausgänge am Oszi betrachtet.
Alles weitere nur mit entsprechenden Code.
und wieder schrieb im Beitrag #6536073:
> @Veit>> DAS ist mal eine vernünftige Erklärung. DU solltest die Datenblätter> schreiben!
Ich nehme es dankend zur Kenntnis.