Forum: Mikrocontroller und Digitale Elektronik PWM mit Interrupts


von thomas (Gast)


Lesenswert?

Guten Tag,

ich versuche eine Software-PWM zu implementieren:
1
TIMSK |= ((1 << OCIE0) | (1 << TOIE0));
2
OCR0 = 10;
3
TCCR0 = (1 << CS00);
4
sei();
5
// ...
6
7
// in einer Endlosschleife dann:
8
if(pwm_duty != i2cdata[1]) {
9
    pwm_duty = i2cdata[1];
10
    cli();
11
    OCR0 = pwm_duty;
12
    sei();
13
}
14
15
// .. 
16
17
ISR(TIMER0_COMP_vect) {
18
  PORTA &= ~(1 << PA7); 
19
}
20
21
ISR(TIMER0_OVF_vect) {
22
  PORTA |= (1 << PA7); 
23
}

Irgendwie aber ändert sich, unabhängig davon ob OCR0 nun 0x00 oder 0xFF 
ist, die Helligkeit der angeschlossenen LED kaum.

Sieht jemand einen Fehler im Code?

von spess53 (Gast)


Lesenswert?

Hi

>Sieht jemand einen Fehler im Code?

Du hast weder den PWM-Mode noch die COM-Bits (beides in TCCR0A) 
eingestellt.

MfG Spess

von spess53 (Gast)


Lesenswert?

Hi

>(beides in TCCR0A)

Das Register hängt natürlich von deinem ungenannten AVR ab.

MfG Spess

von Einer K. (Gast)


Lesenswert?

spess53 schrieb:
> Du hast weder den PWM-Mode noch die COM-Bits (beides in TCCR0A)
> eingestellt.
Ihm will ja auch kein PWM Modus.

Und die COM Bits sind hier flüssiger als Wasser.
Denn es soll in der ISR mit einem anderen(?) Pin gewackelt werden.
(warum auch immer)


thomas schrieb:
> Sieht jemand einen Fehler im Code?
Und du hast den Code bis zur Untestbarkeit verstümmelt.
Auch der µC ist (warum auch immer) geheim.

von thomas (Gast)


Angehängte Dateien:

Lesenswert?

Stimmt. Das war natürlich dumm von mir. Ich habe einen ATMega16.

Im Anhang befindet sich lauffähiger Code, der sich schon nicht so 
verhält wie erwartet.

In der Zeile:
OCR0 = 0xFF;

Egal ob dort 0x00 oder 0xFF steht, die Helligkeit ändert sich kaum.

von Einer K. (Gast)


Lesenswert?

Versuchs mal mit:
OCR0 = 0x01;
Statt
OCR0 = 0x00;

Und du wirst sehen!

Übrigens:
Bei einem Teiler von 1, gehen ca 12% der Takte für die ISR drauf.
Diese 12% fehlen dir dann an beiden Enden des Einstellbereiches.

von thomas (Gast)


Angehängte Dateien:

Lesenswert?

Da ist noch irgendwo ein dicker Schnitzer drin :S

Sowohl bei 0xFE wie auch bei 0x01 sieht das Signal jeweils gleich aus.

von thomas (Gast)


Lesenswert?

Im Prinzip enthält mein Code auch das selbe wie hier:

https://www.avrfreaks.net/comment/518563#comment-518563

von Einer K. (Gast)


Lesenswert?

thomas schrieb:
> Sowohl bei 0xFE wie auch bei 0x01 sieht das Signal jeweils gleich aus.
Das kann ich nicht bestätigen.

Teste allerdings mit einem Mega328P

von S. Landolt (Gast)


Lesenswert?

Also bei mir läuft das auf einem ATmega16 - der Fehler muss an anderer 
Stelle liegen.

von c-hater (Gast)


Lesenswert?

S. Landolt schrieb:

> Also bei mir läuft das auf einem ATmega16

Das glaube ich nicht. Ganz sicher jedenfalls nicht über den gesamten 
Wertebereich. Es ist zwar im Detail noch etwas komplizierter, als von 
"Arduino Fanboy D." dargestellt, aber seine Grundaussage ist absolut 
zutreffend: die Laufzeit der ISRs schränkt den mit dieser naiven 
PWM-Methode tatsächlich abbildbaren Wertebereich ein, bei Prescaler 1 
sogar in einem recht dramatischen Umfang.

Ich würde mal darauf tippen, dass du deine Testmethode nicht richtig 
durchdacht hast...

Das vom TO gezeigte Oszillogramm ist jedenfalls absolut realistisch, 
hier spielt eben noch ein Detail mit, was der Fanboy nicht bedacht hat: 
1*100/256 = 0,4% und: 0,4% << 12%. Er wollte wohl primär die 
Singularität bei gleichzeitiger Auslösung der beiden Interrupts 
darstellen, die es obendrein auch noch gibt...

von Einer K. (Gast)


Lesenswert?

c-hater schrieb:
> Das glaube ich nicht.

Ist der Timer des Mega16 denn so vom Timer des Mega328P verschieden?
Klar, etwas andere Register und ihre Bezeichnungen...
Aber die Grundfunktion?



c-hater schrieb:
> Das vom TO gezeigte Oszillogramm ist jedenfalls absolut realistisch,
Ja?
Denn ich sehe bei mir dort einen großen Unterschied zwischen 0x01 und 
0xFE

von c-hater (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:

> Ist der Timer des Mega16 denn so vom Timer des Mega328P verschieden?
> Klar, etwas andere Register und ihre Bezeichnungen...
> Aber die Grundfunktion?

Naja, man könnte sagen, der Timer0 des M16 ist eine stark vereinfachte 
Variante dessen, was du vom M328 kennst. Kann nicht alle Modi, hat nur 
einen PWM-Kanal. Aber die Grundfunktionaltät ist dieselbe.

Wie übrigens bei den meisten AVR8-Timern. Solange nicht Asynchronität 
zur MCU in's Spiel kommt ist das alles ziemlich die gleiche Soße, mit 
nur geringen Variationen.

von Einer K. (Gast)


Lesenswert?

c-hater schrieb:
> Aber die Grundfunktionaltät ist dieselbe.
Also ist der Test auf einem Mega328P aussagekräftig.

c-hater schrieb:
> 1*100/256 = 0,4% und: 0,4% << 12%. Er wollte wohl primär die
> Singularität bei gleichzeitiger Auslösung der beiden Interrupts
> darstellen, die es obendrein auch noch gibt...
Was das heißen soll, ist mir ein Rätsel.

Mit Pin wird in der ISR gewackelt.
Also geht die ISR Laufzeit voll ein

von c-hater (Gast)


Lesenswert?

c-hater schrieb:

> Naja, man könnte sagen, der Timer0 des M16 ist eine stark vereinfachte
> Variante dessen, was du vom M328 kennst. Kann nicht alle Modi, hat nur
> einen PWM-Kanal. Aber die Grundfunktionaltät ist dieselbe.

Ergänzung: Das Problem der Singularität hängt vom Timer-Modus ab. Mal 
liegt sie bei 0, mal bei 1. Das könnte der entscheidende Unterschied 
sein.

Besser wäre also, die Testpunkte auf 2 und 0xFE zu legen. Dann sollte 
sich in jedem Fall ein invertiertes Oszillogramm für die beiden 
Testpunkte ergeben, allerdings in beiden Fällen mit viel zu langem Puls. 
Das ist dann die Laufzeit der ISRs.

von Einer K. (Gast)


Lesenswert?

> die Testpunkte auf 2 und 0xFE
Wenn der compare match auf 2 erfolgt ist die Overflow ISR noch lange 
nicht fertig.

Erst bei OCR0 Werten von über 0x20 zeigt sich eine Verlängerung des High 
Pulses.
Vergleichbares gilt für hohe Werte, nur dass dann eben die Overflow ISR 
verzögert wird.
Der konkrete Wert ist sicherlich auch von der 
Optimierungsstufe/Kompilerversion abhängig.

von c-hater (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:

> Erst bei OCR0 Werten von über 0x20 zeigt sich eine Verlängerung des High
> Pulses.
> Vergleichbares gilt für hohe Werte, nur dass dann eben die Overflow ISR
> verzögert wird.

So isses.

> Der konkrete Wert ist sicherlich auch von der
> Optimierungsstufe/Kompilerversion abhängig.

Nicht, wenn man in Assembler programmiert. Dann kann man ganz genau 
vorhersagen, wie sich die Scheisse verhalten wird und ist nicht auf 
Raterunden angewiesen.

Wenn man das tut, fallen einem allerdings auch diverse Tricks ein, das 
Verhalten zu verbessern. Der allerbeste davon lautet allerdings: man 
benutzt dieses naive PWM-Schema erst garnicht...

Es gibt ja schließlich reichlich bessere Lösungen für Soft-PWM. Sogar 
etliche in C...

von Codix (Gast)


Lesenswert?

In diesen Forum findet man massig funktionierende
Codebeispiele.
Warum sind viele nicht in der Lage diese als Grundlage für ihre eigenen 
Ideen zu nutzen.
Alleine schon der Lerneffekt ist nicht zu verachten.
Daneben sollte man nicht im Nebel herum stochern, sondern das Dateblatt 
vollständig lesen.
Koofschüttel...

von PittyJ (Gast)


Lesenswert?

Manchmal frage ich mich, muss das wirklich sein?
Es gibt genug günstige Prozessoren, die haben eine Hardware PWM-Einheit. 
Da werden ein halbes Dutzend Register gesetzt, und der Rest geht 
automatisch.
Alternativ gibt es bei Reichelt I2C Dacs für 76 Cent. Da brauche ich 
mich auch nicht um die Glättung zu kümmern.

Warum muss immer die billigste CPU genommen werden, und dann verkrampft 
eine SW von Anfängern entworfen werden?

Nur einen Euro mehr, und man hätte keine Probleme.

von Einer K. (Gast)


Lesenswert?

c-hater schrieb:
> man benutzt dieses naive PWM-Schema erst garnicht...
Da hat man schon so eine schöne Hardware PWM, und dann wird sie so 
sträflich ignoriert.
Das auch mir schon ein wenig weh.

c-hater schrieb:
> Nicht, wenn man in Assembler programmiert.
Ja, man kann das Problem mit Assembler etwas optimieren.
So wie man aus jedem Problem das Maximum raus holen kann.
Aber schöner wirds dadurch auch nicht.

von c-hater (Gast)


Lesenswert?

PittyJ schrieb:

> Manchmal frage ich mich, muss das wirklich sein?
> Es gibt genug günstige Prozessoren, die haben eine Hardware PWM-Einheit.

Natürlich muß das nicht sein, haben die AVR8 ja auch. Und nicht nur 
eine, sondern mehrere, manche sogar ganz schön viele.

Bloß wollte der TO die halt aus unerfindlichen Gründen nicht benutzen...

von Johann J. (johannjohanson)


Lesenswert?

thomas schrieb:
> ich versuche eine Software-PWM zu implementieren

Warum?

von Johann J. (johannjohanson)


Lesenswert?

thomas schrieb:
> Im Anhang befindet sich lauffähiger Code, der sich schon nicht so
> verhält wie erwartet.

Dann Google mal nach AVR Prolog und Epilog.

von Stefan F. (Gast)


Lesenswert?

thomas schrieb:
> cli();
> OCR0 = pwm_duty;
> sei();

Zugriffe auf 8bit Register sind immer atomar. Die Kommandos cli() und 
sei() bewirken hier nichts hilfreiches.

Das wird allerdings nicht die Ursache deines Problems sein.

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.