Forum: Compiler & IDEs schnelle PWM bei 1Mhz


von Dario C. (dario) Benutzerseite


Lesenswert?

Hi Freaks,

nachdem Ihr mir so gut beim letzten Mal geholfen habt,
komme ich mit noch einem Problem.

Das hängt zusammen mit dem Heizkörperthermostat, den ich
neu programmieren will, hier der Artikel dazu in der Wiki:
       Heizungssteuerung mit Honeywell HR20


Eckdaten:
  - ATMega169
  - Frequenz 1 MHz (CKDIV8, CKSEL 0010, SUT=10)
  - Timer 0

Jetzt weiss ich aus der Analyse, des bestehenden Thermostaten,
dass der ein PWM-Signal an PB4/OCOA mit der Frequenz von 15,625 kHz
und den Verhältnissen 44.5us:19.5us und 19.5us:44.5us erzeugt.
Würde der Counter jetzt von 0-255 zählen wäre dass der compare
value von 179 im normalen bzw. im invertierten Betrieb.

Aber dann komme ich nur auf 3,9kHz (1/256 von 1MHz).
Die gemessenen 15,625 kHz sind 1/64 der 1MHz.

Jetzt die Fragen:

1.)
Wie kann ich die 15,625 kHz mit 1MHz erreichen?

2.)
Oder soll ich lieber die Frequenz temporär mit CLKPS3..0 auf 4Mhz
erhöhen wenn ich den Motor anschmeisse und danach wieder auf 1MHz
schalten. Der Motor läuft ja weniger als 0,1% der Zeit.

3.)
Ist das für so einen Mini-Gleichstrommotor sowieso egal,
ob die PWM-Frequenz bei 4kHz oder 16kHz liegt?


In der Hoffnung auf fachkundige Hilfe,

Dario.

von Benedikt K. (benedikt)


Lesenswert?

Dario C. wrote:
> Jetzt die Fragen:
>
> 1.)
> Wie kann ich die 15,625 kHz mit 1MHz erreichen?

1MHz/15,625kHz=64
Demnach muss der Timer nur bis 63 zählen. Das geht bei den meisten AVRs 
auch, indem man einen PWM Modus wählt, bei dem man den TOP Wert vorgeben 
kann.

> 2.)
> Oder soll ich lieber die Frequenz temporär mit CLKPS3..0 auf 4Mhz
> erhöhen wenn ich den Motor anschmeisse und danach wieder auf 1MHz
> schalten. Der Motor läuft ja weniger als 0,1% der Zeit.

Ist auch möglich, aber eigentlich unnötig.

> 3.)
> Ist das für so einen Mini-Gleichstrommotor sowieso egal,
> ob die PWM-Frequenz bei 4kHz oder 16kHz liegt?

Weitestgehend. Die Frage ist, ob die Elektronik dazwischen ausreichend 
schnell ist.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

...und ob dich das Gefietsche stört. ;-)

von Dario C. (dario) Benutzerseite


Lesenswert?

Benedikt K. wrote:

> 1MHz/15,625kHz=64
> Demnach muss der Timer nur bis 63 zählen. Das geht bei den meisten AVRs
> auch, indem man einen PWM Modus wählt, bei dem man den TOP Wert vorgeben
> kann.

Und genau den finde ich nicht bei dem ATMega1169 am Timer0.
Und es muss Timer0 sein, da das ja in der Originalschaltung
verkabelt ab PB4, also OC0A funktioniert.

Im Datenblatt zum Mega169 steht nämlich:

Seite 80
BOTTOM whern it becomes 0x00
MAX whern it becomes 0xFF
TOP ... can be stored in the OCR0A Register

Seite 85
Fast PWM Mode: ... The counter counts from BOTTOM to MAX ...

Seite 86
Phase Correct PWM Mode: ... The counter counts from BOTTOM to MAX ...

Ich sehe nicht, wie ich den Timer0 einen PWM Modus wählen kann,
bei dem ich den TOP != MAX wähle.

Spricht denn generell was dagegen zwischenzeitich über das CLKPR
Register die Clock zu verändern (insbesondere wenn die Echtzeituhr
asynchron über einen 32kHz Quarz gemacht wird)?

Dario

von Benedikt K. (benedikt)


Lesenswert?

Dario C. wrote:

> Und genau den finde ich nicht bei dem ATMega1169 am Timer0.

Der kann das nur bei Timer1 (mittels OCR1A oder ICR1).

> Spricht denn generell was dagegen zwischenzeitich über das CLKPR
> Register die Clock zu verändern (insbesondere wenn die Echtzeituhr
> asynchron über einen 32kHz Quarz gemacht wird)?

Generell nicht. Allerdings musst du schauen was du so alles laufen hast: 
UART, Timer, ADC usw. laufen dann alle schneller. Das sollte man 
berücksichtigen.

von Dario C. (dario) Benutzerseite


Lesenswert?

Würde das dann so gehen?
1
cli();
2
CLKPR=(1<<CLKPCE);  
3
CLKPR=(1<<CLKPS0);
4
sei();

Nicht dass mir da der Compiler was wegoptimoert.

von Benedikt K. (benedikt)


Lesenswert?

Ja, aber pack noch ein asm("nop"); hinter das cli(); denn die Interrupts 
werden erst einen Takt später abgeschaltet.

von Dario C. (dario) Benutzerseite


Lesenswert?

Hi Benedikt

> Ja, aber pack noch ein asm("nop"); hinter das cli();

Danke.

Das cli(); habe ich nur Proforma da hin geschrieben, denn ich habe
mich entschlossen alles auf 4MHz laufen zu lassen (dann kann ich eben 
mehr sleepen)

Die Frequenz stelle ich nach einem Reset ein, wo die Interrups sowieso 
aus sind.

Danke nochmal an alle,


Dario

von Falk B. (falk)


Lesenswert?

@ Benedikt K. (benedikt)

>Ja, aber pack noch ein asm("nop"); hinter das cli(); denn die Interrupts
>werden erst einen Takt später abgeschaltet.

Käse. Nach cli() ist definiv Ruhe. Sonst würde cli() gar nicht 
funktionieren, weil der RETI der ISR das I-Bit wieder anschalten würde.

MFG
Falk

von Benedikt K. (benedikt)


Lesenswert?

Falk Brunner wrote:

> Käse. Nach cli() ist definiv Ruhe.

Irgendwas gabs da doch mit den Interrupts, was einen Takt verzögerung 
hatte, war das dann bei sei ?

von Kai G. (runtimeterror)


Lesenswert?

- Zwischen zwei Interrupts wird immer noch eine Instruktion ausgeführt.
- Laufende Mehrtaktbefehle werden beim Auftreten eines Interrupts zu 
Ende ausgeführt.

Vielleicht hattest du davon einen im Kopf...

Die cli/sei-Klammer wird auch im Datasheet in den Codebeispielen 
verwendet.

von Benedikt K. (benedikt)


Lesenswert?

Ich habs gefunden: Es ist bei sei, aber angeblich nirgends dokumentiert:

Beitrag "Re: Compilerbug bei AVR-GCC ?: Stack Pointer und Interrupts"

von Kai G. (runtimeterror)


Lesenswert?

Na ja... in der Instruction Set-Doku findet sich bei SEI folgender 
Absatz...
1
sei    ; set global interrupt enable
2
sleep  ; enter sleep, waiting for interrupts
3
       ; note: will enter sleep before any pending interrupt(s)

In der Doku zum ATmega16 findet sich darüber:

When using the SEI instruction to enable interrupts, the instruction 
following SEI will be executed before any pending interrupts, as shown 
in this example.

...

Ich würd's schon als dokumentiert bezeichnen ;)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Kai Giebeler wrote:

> When using the SEI instruction to enable interrupts, the instruction
> following SEI will be executed before any pending interrupts, as shown
> in this example.

Das trifft übrigens nur auf das /Zu/schalten der Interrupts zu,
nicht auf das Abschalten.  Daher ist der NOP oben nicht nötig.

> Ich würd's schon als dokumentiert bezeichnen ;)

Dokumentiert ist es für SEI, nicht aber für den (beim GCC genutzten)
impliziten Fall, dass das I-Bit durch das Zurückspeichern des SREG
eingeschaltet wird.

von Kai G. (runtimeterror)


Lesenswert?

>Das trifft übrigens nur auf das /Zu/schalten der Interrupts zu,
>nicht auf das Abschalten.  Daher ist der NOP oben nicht nötig.

Bezog sich ja auch nicht mehr auf das Originalposting sondern auf 
Benedikts Querverweis.

>Dokumentiert ist es für SEI, nicht aber für den (beim GCC genutzten)
>impliziten Fall, dass das I-Bit durch das Zurückspeichern des SREG
>eingeschaltet wird.

Hier noch ein paar Indikatoren, die dafür sprechen:
1
_SEI();    /* set global interrupt enable */
2
_SLEEP();  /* enter sleep, waiting for interrupt */
3
           /* note: will enter sleep before any pending interrupt(s) */
(ohne Anmerkungen zu den Implementierungsdetails von _SEI())

Die Beschreibung zum I-Bit im SREG nennt keinen Unterschied zwischen dem 
Setzen per SREG oder CLI/SEI:

The I-bit can also be set and cleared by the application with the SEI 
and CLI instructions, as described in the instruction set reference.

Das Verhalten beim Setzen des Flags deckt sich mit dem einer 
RETI-Anweisung:

When the AVR exits from an interrupt, it will always return to the main 
program and execute one more instruction before any pending interrupt is 
served.

Last but not least: SEI ist ja nur ein Alias von BSET 7 in dessen 
Doku das Warteverhalten auch Erwähnung finden müsste - steht aber nicht 
drin. Ich gehe also davon aus, dass die Verhaltensbeschreibung von SEI 
irreführender Weise für alle Varianten zum Setzen des I-Bits gelten.

Ich sehe aber den verbleibenden Interpretationsspielraum. Insofern danke 
für die Ergänzung.

von Andreas K. (a-k)


Lesenswert?

Komische Logik. Da habe diverse Leute das Verhalten von SEI im Kopf und 
schliessen daraus auf das Verhalten von CLI. Es wird dazu sogar die Doku 
zu SEI zitiert. Aber auf die Idee direkt bei CLI nachzusehen kommt 
keiner?

"No interrupt will be executed after the CLI instruction, even if if 
occurs simultaneously with the CLI instruction".

von Kai G. (runtimeterror)


Lesenswert?

Danke, das haben wir oben auch schon ein paar mal festgestellt!

Benedikt hatte nur ein verwandtes Thema angesprochen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.