mikrocontroller.net

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


Autor: Björn (Gast)
Datum:
Angehängte Dateien:

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

Autor: Läubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich vermute deine Timer ISR ist zu lang!

Autor: Läubi (Gast)
Datum:

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

Autor: Björn (Gast)
Datum:

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

Autor: Läubi (Gast)
Datum:

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

Autor: johnny.m (Gast)
Datum:

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

Autor: Björn (Gast)
Datum:

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

Autor: inoffizieller WM-Rahul (Gast)
Datum:

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

Autor: Björn (Gast)
Datum:
Angehängte Dateien:

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

Autor: inoffizieller WM-Rahul (Gast)
Datum:

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

Autor: Björn (Gast)
Datum:

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

Autor: inoffizieller WM-Rahul (Gast)
Datum:

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

Autor: Björn (Gast)
Datum:

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

Autor: Björn (Gast)
Datum:

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

Autor: inoffizieller WM-Rahul (Gast)
Datum:

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

Autor: Björn (Gast)
Datum:

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

Autor: inoffizieller WM-Rahul (Gast)
Datum:

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

Autor: Björn (Gast)
Datum:

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

Mal ausprobieren!

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Würde gerne ne doppelte Bedingung in die if-Anweisung einbauen?

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

Wie kann ich das schreiben?

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
if((Count <= 17) && (Count>=34))

Autor: Björn (Gast)
Datum:
Angehängte Dateien:

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

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab den Fehler schon!

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

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Machen Deine Servos denn jetzt auch das, was sie sollen?

...

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.