Forum: Mikrocontroller und Digitale Elektronik Timer stören sich gegenseitig


von Björn (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich will zwei verschiedene Signale mit Timer0 und Timer2 bei einem
Atmega48 in C erzeugen. Die Signale sollen jeweils 9 unterschiedliche
Impulslängen besitzen.

Die Signale hab ich hinbekommen und Sie funktionieren einzeln
wunderbar. Nur wenn ich beide Timer in einem Programm laufen lasse
besitzt das Signal von Timer0 einen Fehler! Genauer gesagt, der dritte
Impuls des Signals spinnt rum, schaltet immer zwischen Low- und
Highpegel hin und her.

Kann es sein dass sich die Timer irgendwie gegenseitig beeinflussen,
bzw. stören?

Hab das Programm mal angehangen....

von Läubi (Gast)


Lesenswert?

Ich vermute deine Timer ISR ist zu lang!

von Läubi (Gast)


Lesenswert?

Mist zu früh abgeschickt.
Wollte schreiben:
Setz mal in der Timer ISR nur ein Flag und mach die Aktion im
Hauptprogramm (zumindest bei dem Timer wo du soviel rumrechnest!)

von Björn (Gast)


Lesenswert?

Aber ich rechne doch in beiden Timern gleich viel.

Bei Timer2 funktioniert es ja auch, nur bei Timer0 hat das signal einen
Fehler.

Wenn ich Timer0 mal alleine in dem Programm laufen lasse, ist das
Signal völlig in Ordnung.

Nur wenn beide Timer gleichzeitig laufen, taucht das Problem auf.

von Läubi (Gast)


Lesenswert?

Ich wollte sagen: wenn du in einer ISR viel rechnest mußt dus ins
Hauptprogramm verlagern.

Sosnt kannst du das Problem haben:
T0 kriegt interupt rechnet rechnet rechnet
T1 erzeugt Interupt, da T0 aber noch nicht fertig ist wird erstmal
gewartet auf T0, jezt ist T0 fertig, T1 darf rechnen aber inzwischen
sind schon wieder interupts für T1/T0 aufgelaufen...
Da aber immer nur ein Interupt abgearbeitet wird kannst du interupts
verlieren.

Ein anderes Problem könnte sein das Variablen die in einer ISR
verwendet werden mit voiltaile deklariert werden müssen, das sit jezt
aber nur "gelesenes Wissen" da ich selber in ASM programmiere.

von johnny.m (Gast)


Lesenswert?

@Läubi:
Variablen müssen im Prinzip nur dann volatile deklariert werden, wenn
sie im Hauptprogramm verwendet werden, aber auch in ISRs verändert
werden können.

Ansonsten stimme ich zu: Mach die ISR so kurz wie möglich. Ich weiß
jetzt nicht, wie groß die Wahrscheinlichkeit ist, dass beide Interrupts
gleichzeitig auftreten (oder dass während der Ausführung einer ISR beide
Interrupts erneut auftreten), aber wenn das der Fall sein sollte, wird
die Timer2-ISR bevorzugt ausgeführt, da Timer2 die höhere "Priorität"
besitzt. Da kann es durchaus vorkommen, dass Timer 0 ins Hintertreffen
gerät.

von Björn (Gast)


Lesenswert?

Ist es nicht irgendwie möglich, während der eine Interrupt läuft den
anderen auszuschalten und danach wieder einzuschalten?

Hab gerade mal versucht, es ohne ISR zu machen, also in der main().
Nur das klappt gar nicht.

von inoffizieller WM-Rahul (Gast)


Lesenswert?

>Ist es nicht irgendwie möglich, während der eine Interrupt läuft den
>anderen auszuschalten und danach wieder einzuschalten?

Das passiert sowieso grundsätzlich beim AVR.
Wäre dein Programm etwas besser kommentiert, könnte man vielleicht
sogar einen Vorschlag machen, wie man es verbessern könnte.
Was soll das Ding überhaupt machen?

von Björn (Gast)


Angehängte Dateien:

Lesenswert?

Hey,

hab das Programm mal neu kommentiert und beschrieben. Befindet sich im
Anhang.

Wäre super wenn einer mal schauen könnte und vielleicht ne Idde hat wie
man das Problem lösen kann, komm nämlich echt nicht weiter.

von inoffizieller WM-Rahul (Gast)


Lesenswert?

erste Verbesserung:

statt
if(NrOverflow_Servo2 % 2 == 0)

geht auch
if (!(NrOverflow_Servo2 & 1))

Wenn NrOverflow_Servo2 nicht ungerade ist, wird Port ausgeschaltet,
sonst eingeschaltet.

Wenn man die Anweisung aus den Entscheidungszweigen vertauscht müsste
auch

if (NrOverflow_Servo2 & 1)

gehen.

Wegen der Timer habe ich noch eine Idee, die aber noch nicht ganz
ausgeklügelt ist...(es hat mit dem fast PWM-Mode zutun...)

von Björn (Gast)


Lesenswert?

Danke erst ein mal für die Tips!

Wäre super wenn einer noch ne Idee für den Timer hätte, bin schon echt
verzweifelt! Häng nun schon seid 6 Stunden davor und kries einfach
nicht hin.

von inoffizieller WM-Rahul (Gast)


Lesenswert?

Der Unterschied zwischen dem CTC- und dem fPWM-Mode ist, dass der
fPWM-Mode gepuffert ist. Das bedeutet, dass man dem Timer schon einen
neuen TOP-Wert übergeben kann, ohne dass ihn dieser in dem Moment
interessiert. Beim CTC wird TOP sofort überschrieben.
Damit könnte man die ISR vereinfachen, in dem dort nur noch ein Zähler
hocgezählt wird, und der Portpin umgeschaltet wird (und setzt ein
Flag).
In der Hauptschleife vergleicht man entweder einfach den aktuellen
Feldindex mit dem letzten, und schreibt den neuen Wert ins OCR, oder
reagiert ebenso auf das gesetzte Flag.
In der Schleife kann man dann auch noch einen Feldindex-Überlauf
überwachen.
Könnte so funktionieren...

von Björn (Gast)


Lesenswert?

Hi Rahul,

leider haut es so bei mir auch nicht hin. Brauch jetzt erst mal ne
Pause, seh schon gar nichts mehr.

Werd es dann gleich noch mal versuchen.

Gibt es denn noch irgend ne andere Möglichkeit?

von Björn (Gast)


Lesenswert?

>Der Unterschied zwischen dem CTC- und dem fPWM-Mode ist, dass der
>fPWM-Mode gepuffert ist. Das bedeutet, dass man dem Timer schon >einen
neuen TOP-Wert übergeben kann, ohne dass ihn dieser in dem
>Momentinteressiert. Beim CTC wird TOP sofort überschrieben.
>Damit könnte man die ISR vereinfachen, in dem dort nur noch ein
>Zähler hocgezählt wird, und der Portpin umgeschaltet wird (und >setzt
ein Flag).
>In der Hauptschleife vergleicht man entweder einfach den aktuellen
>Feldindex mit dem letzten, und schreibt den neuen Wert ins OCR, oder
>reagiert ebenso auf das gesetzte Flag.
>In der Schleife kann man dann auch noch einen Feldindex-Überlauf
>überwachen.

Kapier ich nicht, bzw. ich krieg es nicht hin!

Kannst du mir das noch mal etwas genauer erklären?

von inoffizieller WM-Rahul (Gast)


Lesenswert?

Noch genauer?
Was denn genau?

Wenn man im CTC-Mode das Register ändert, das für den TOP-Wert
verantwortlich ist, dann kann es passieren, dass der neue Wert kleiner
als der aktuelle Zählerwert ist. Das führt dazu, dass der Timer
komplett bis 0xFFFF durchläuft und dann erst wieder Chance hat, den
Vergleichswert zu erreichen. Es ist kein "Timer >= TOP?"-, sondern
ein "Timer == TOP?"-Vergleich.
Bei fPWM-Mode (fast PWM) wird der TOP-Wert erst aktualisiert, wenn der
zuvor gewählte erreicht wurde. Man kann also während der Timer sein
"Programm" (zähle bis TOP) abarbeitet, ihm den nächsten
"Programmpunkt" (neues TOP) mitteilen.

Zu meiner ISR-Methode:
Muß ich noch mal genauer drüber nachdenken (und es mir vielleicht auch
noch aufmalen...)

von Björn (Gast)


Lesenswert?

Ist es denn nicht möglich, die Signale hintereinander zu erzeugen. Also
dass der eine Interrupt erst startet wenn der andere mit der Erzeugung
des Signals fertig ist.

Der hat dann solange Pause bis der andere fertig ist und dann immer hin
und her.

Irgendeine Idee in diese Richtung...?

von inoffizieller WM-Rahul (Gast)


Lesenswert?

Willst du Signale für zwei Servos erzeugen?
Du kannst es natürlich so machen, dass der zweite Timer erst losläuft,
wenn der erste seine komplette Sequenz abgearbeitet hat (und
andersherum).
Dann könnte man das aber auch mit nur einem Timer realisieren.

von Björn (Gast)


Lesenswert?

Das hab ich mir jetzt auch gerade gedacht. Eigentlich kann ich doch
beide Signale in einer ISR hintereinander erzeugen.....

Mal ausprobieren!

von Björn (Gast)


Lesenswert?

Würde gerne ne doppelte Bedingung in die if-Anweisung einbauen?

Etwas wie if(Count <= 17 & >=34) ?

Wie kann ich das schreiben?

von inoffizieller WM-Rahul (Gast)


Lesenswert?

if((Count <= 17) && (Count>=34))

von Björn (Gast)


Angehängte Dateien:

Lesenswert?

Danke!

Hab es jetzt soweit hinbekommen. Die Signale sehen ganz gut aus.

Nur im zweiten Signal läuft irgendwie noch mal ein Impuls durch. Kann
es da sein, dass es irgendwie noch Teile vom ersten Signal bekommt?

Hab den Code noch mal angehangen. Wäre super wenn du ihn dir noch mal
anschauen könntest

von Björn (Gast)


Lesenswert?

Hab den Fehler schon!

Hätte <=35 nicht <=34 heißen müssen!

von Hannes L. (hannes)


Lesenswert?

Machen Deine Servos denn jetzt auch das, was sie sollen?

...

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.