Hallo, mir ist aufgefallen, dass in meiner Anwendung, wenn ich über I2C Daten von Sensoren auslesen möchte, eine Interrupt Routine, welche einen Zählerwert speichern soll(captue mode), negativ beeinflusst wird. Vielleicht ein bißchen detallierter: In meiner Anwendung lese ich in der main Funktion in der Endlosschleife unter anderem Werte über I2C von einigen Sensoren. Das läuft alles schön und gut. In einer separaten Interrupt-Routine wird noch die Länge eines externen Signals gemessen. Das läuft über die Capture Funktion einer Timer Einheit, welche einen Interrupt auslöst, wenn eine fallende Flanke am GPIO Pin detektiert wird. In der Interrupt Routine wird der Wert im Capture Register einfach in eine Variable geschrieben. Mir ist nun aufgefallen, dass wenn ausgerechnet gerade die I2C Kommusnikation stattfindet und dann der Interrupt ausgelöst wird, die Timer Werte nicht mehr so sind, wie sie sein sollten. Ich konnte das eingrenzen auf eine gewisse Abfolge von Register Zugriffen, die ich machen muss, um die I2c Kommunikation zu starten. Es scheint also, als ob die I2C Kommunikation die Interrupt Verarbeitung verzögert und ich dadurch falsche Zählerwerte erhalte. Der Mikrocontroller ist ein MKL46Z256 von Freescale. Die Registerzugriffe, welche dieses Problem erzeugen sind folgende: I2C0_BASE_PTR->C1 |= I2C_C1_MST_MASK; // Master Mode I2C0_BASE_PTR->C1 |= I2C_C1_TX_MASK; // TX Mode I2C0_BASE_PTR->D = 0xff; // Zu sendende Daten ins Datenregister schreiben Hat irgendjemand Erfahrung mit diesem Problem oder kann sich das erklären?
Ob es bei dir daran liegt, weiß ich nicht - aber zeitkritische Aufgaben und I2C vertragen sich nicht immer so so richtig. Das tolle I2C gibt's im Gegensatz zum altbackenen RS232 bei AVRs nur im Polling Mode. Die 3 Sachen, die ich bisher mit I2C gemacht habe, ließen sich so lösen, dass ich abwechselnd zeitkritische Sachen gemacht habe und mich dann um I2C kümmern konnte. Sonst kann schon mal was Zeitkritisches (oder der I2C-Bus) sich vernachlässigt fühlen...
Marcel B. schrieb: > die > Timer Werte nicht mehr so sind, wie sie sein sollten. Noch ungenauer hätte man es nicht sagen können. Was erwartest Du, was liest Du stattdessen? Ist irgendeine Regel in der Abweichung (Richtung, Betrag) zu erkennen? Was zählt der Timer, hat er einen Prescaler, erfolgt ein Überlauf, wie wird der Überlauf behandelt? Beim P87C751 wurde ein Timer mit als I2C-Timeout benutzt, d.h. er war nicht mehr unabhängig einsetzbar.
:) Also, es handelt sich bei dem Signal um ein Summensignal von einem RC Empfänger. Ein gesamter Zyklus mit allen 4 Steuerfunktionen ist 20ms Sekunden lang. Eine einzelne Steuerfunktion wird mit einer fallenden Flanke eingeleitet. Es handelt sich um ein PPM Signal. Wenn ich über die Capture Funktion meines Timer eine fallende Flanke registriere, speichere ich den Zählerwert und setze den Zähler wieder auf 0. Der Zählwert, welcher einem Wert länger als 2ms entspricht dient mir zur Synchronisation. Der Zähler ist ein 16 Bit Zähler und wird mit 24 MHz getaktet. Der Prescaler ist auf 16 gestellt. Es durfte also kein Überlauf stattfinden. Also wenn der Zähler einen Wert unter 1499 im Captue Register zu stehen hat, muss irgendetwas schief glaufen sein. Ich messe das Summensignal zur Sicherheit noch mit einem Oszilloskop. Hier mal eine Beispielmessung mit allen 4 Kanälen: Kanal 1 Gas Nullstellung also 1,0ms -> Zählerwert 1500 Kanal 2 Gier Mittelstellung also 1,5ms -> Zählerwert 2254 Kanal 3 Roll Mittelstellung also 1,5ms -> Zählerwert 754 !!!!!! Kanal 4 Pitch Mittelstellung also 1,5ms -> Zählerwert 1491 !!!!!!! In diesem Fall sind die Zählerwerte für Kanal 3 und 4 Fehlmessungen.
Marcel B. schrieb: > Hier mal eine Beispielmessung mit allen 4 Kanälen: > > Kanal 1 Gas Nullstellung also 1,0ms -> Zählerwert 1500 > Kanal 2 Gier Mittelstellung also 1,5ms -> Zählerwert 2254 > Kanal 3 Roll Mittelstellung also 1,5ms -> Zählerwert 754 !!!!!! > Kanal 4 Pitch Mittelstellung also 1,5ms -> Zählerwert 1491 !!!!!!! > > In diesem Fall sind die Zählerwerte für Kanal 3 und 4 Fehlmessungen. Es fällt sofort auf, dass die Fehlmessungen sich im Verhältnis zum Erwartungswert in (näherungsweise) ganzzahligen Verhältnissen (1:2:3) befinden. Wenn das nicht nur in diesem einen Beispiel so ist, sondern generell bei Auftreten des Fehlers, ist das ein sehr wichtiger Hinweis auf die Fehlerursache. Man muss dann einfach nur noch herausfinden, wo das parasitäre Mess-Intervall von ca. 500µs eigentlich her kommt. Da in der Nähe ist dann mit an Sicherheit grenzender Wahrscheinlichkeit auch die Fehlerursache zu suchen...
Vielleicht hast du auch ein schlechtes Eingangssignal, und nach 754 Zählern (0,5ms) ist eigentlich eine steigende Flanke. Wenn die steigende Flanke aber relativ langsam steigt, mit etwas Rauschen überlagert ist, und du keinen Schmitt-Trigger benutzt, kann hier irrtümlich eine zusätzliche fallende Flanke erkannt werden. Nächste Vermutung: deine I2C Leitungen liegen in der Nähe des RC Eingangssignals, und koppeln so ein.
Hier sind noch einige Beispiele für Fehlmessungen: Kanal 1 Gas Nullstellung also 1,0ms -> Zählerwert 1500 Kanal 2 Gier Mittelstellung also 1,5ms -> Zählerwert 2254 Kanal 3 Roll Mittelstellung also 1,5ms -> Zählerwert 2248 Kanal 4 Pitch Mittelstellung also 1,5ms -> Zählerwert 754 !!!!! Kanal 1 Gas Nullstellung also 1,0ms -> Zählerwert 1500 Kanal 2 Gier Mittelstellung also 1,5ms -> Zählerwert 754 !!!!!! Kanal 3 Roll Mittelstellung also 1,5ms -> Zählerwert 1497 !!!!!! Kanal 4 Pitch Mittelstellung also 1,5ms -> Zählerwert 2248 Kanal 1 Gas Nullstellung also 1,0ms -> Zählerwert 743 !!!!!! Kanal 2 Gier Mittelstellung also 1,5ms -> Zählerwert 754 !!!!!! Kanal 3 Roll Mittelstellung also 1,5ms -> Zählerwert 2254 Kanal 4 Pitch Mittelstellung also 1,5ms -> Zählerwert 2248
Mach mal ein paar hochauflösende Bilder von deinem Signal mit einem Oszilloskop. Alles andere ist ja stochern im Nebel.
Marcel B. schrieb: > Hier sind noch einige Beispiele für Fehlmessungen: [...] Die bestätigen die von mir bisher nur vermutete Gesetzmäßigkeit doch schon relativ deutlich. Du darfst dich bei deiner Fehlersuche also auf Sachverhalte konzentrieren, die irgendwie diese 500µs-Intervalle produzieren. Viel Spass...
Ich wette, dass du die falsche Flanke misst. Bei PPM ist ja der positive Puls genau 0.5ms breit. Und wenn du jetzt aus irgend einem Grund bei der steigenden Flanke eine irrtümliche negative Flanke detektierst (wg. Rauschen auf langsam steigender Flanke), hast du genau deine 0.5ms bis zur nächsten tatsächlich fallenden Flanke. Und jetzt guck mal hier: Kanal 1 Gas Nullstellung also 1,0ms -> Zählerwert 1500 Kanal 2 Gier Mittelstellung also 1,5ms -> Zählerwert 754 !!!!!! Kanal 3 Roll Mittelstellung also 1,5ms -> Zählerwert 1497 !!!!!! Kanal 4 Pitch Mittelstellung also 1,5ms -> Zählerwert 2248 Der 2. Messwert ist 0.5ms, und dem 3. Messwert, der eigentlich der 2. sein sollte, fehlen genau die 0.5ms (sollten 1.5ms sein, du misst aber 1ms)... Bestätigt meine Theorie. Mach mal einen Schmitt-Trigger zwischen deinen Signal-Ausgang und den uC. Oder, du machst es ganz schmutzig in Software: wenn der Messwert kleiner als z.B. 0,75ms ist, gehst du von einer Fehlmessung aus, inkrementierst den Kanal-Zähler zunächst nicht, sondern merkst dir diesen Messwert. Beim nächsten Intervall zählst du dann diese (unabsichtlich gemessene High-Phase) zum Messwert dazu... done. Edit: falsch. Der Puls ist ja am Anfang des Kanals. Das heisst also, wenn gleich bei Kanal 1 eine Fehlmessung passiert, ignorierst du diesen Messwert einfach, und nimmst den nächsten für Kanal 1. Für die weiteren Kanäle musst du die Fehlmessungen zum jeweils vorherigen Kanal dazu rechnen.
Du scheinst ausserdem auf steigende Flanken zu reagieren, bzw. ist dein Signal invertiert. Anbei deine 3 Beispiele als Grafik, und die naheliegende Erklärung für deine seltsamen Messwerte.
Joe F. schrieb: > Oder, du machst es ganz schmutzig in Software: Bei manchen MCs kann man für die Eingänge einen Schmit-Trigger enablen. Oder nach jeder Startflanke eine Totzeit von 0,9ms.
Ich hab kann gerade nur ein myRIO als Oszilloskop nutzen, aber ich denke das reicht für diesen Zweck vollkommen aus. Also, sorry erstmal für die Falschaussage. Es handelt sich nicht um ein PPM Signal sondern um ein PWM Signal. Also beim variieren der entsprechenden Kanäle verändert sich die Länge des positiven Impulses. Siehe Anhang. Und ja, du hast Recht, Joe F. Ich hab die Konfiguration vom Timer geändert. Das heißt der Interrupt wird nun bei einer positiven Flanke ausgelöst und speichert in der Routine den entsprechenden Zählerwert. Die Flaschmessungen treten nun nicht mehr auf. Allerdings sollte das eigentlich kein Problem sein. Ob ich nun auf die positive, oder negative Flanke reagiere ist doch egal. Die Pausen zwischen dem duty cycle sind immer 0.5 ms lang. Daher habe ich mich ursprünglich dafür entschieden auf die fallende Flanke zu reagieren. Interessant ist allerdings, dass die "falsche" fallenden Flanke immer durch die I2C Kommuniaktion ausgelöst wurde. "Du scheinst ausserdem auf steigende Flanken zu reagieren, bzw. ist dein Signal invertiert." Nee, das ist nicht invertiert. Also nicht von mir:) Der Empfänger(Graupner GR-16) gibt das genau so aus. Vielen Dank für eure zahlreichen Tipps und Anmerkungen!!!
Marcel B. schrieb: > Also, sorry erstmal für die Falschaussage. Es handelt sich nicht um ein > PPM Signal sondern um ein PWM Signal. Also beim variieren der > entsprechenden Kanäle verändert sich die Länge des positiven Impulses. Es handelt sich also um PPM (Puls-Pausen-Modulation) ;-) https://de.wikipedia.org/wiki/Puls-Pausen-Modulation Marcel B. schrieb: > Allerdings sollte das eigentlich kein Problem sein. Ob ich nun auf die > positive, oder negative Flanke reagiere ist doch egal. ...ausser man möchte die Fehlerkorrektur in Software machen. Marcel B. schrieb: > Ich hab kann gerade nur ein myRIO als Oszilloskop nutzen, aber ich denke > das reicht für diesen Zweck vollkommen aus. Naja, vermutlich eben nicht, da man die Qualität der Flanken so nicht beurteilen kann. Versuche es mal mit einem Schmitt-Trigger, ich bin mir sicher, das hilft.
Achso: Softwarelösung geht noch viel einfacher: In deiner Interrupt-Routine prüfst du, ob der Counter einen plausiblen Wert hat, also > ca. 0.7ms (>1050) ist. Nur dann Timerwert verarbeiten und Timer zurücksetzen. Wenn die gemessene Zeit < 0.7ms ist, lässt du den Timer einfach weiterlaufen und verlässt die Interrupt Routine sofort wieder (das ist dann ein Fehl-Trigger auf der falschen Flanke). Dadurch, dass der Timer weiterläuft, hast du dann bei der nächsten (tatsächlichen) Flanke den korrekten Wert.
Hallo, also ob ich nun auf die positive oder negative Flanke reagiere ist egal. Es werden in beiden Fällen gelegentlich "ungültige Zählerwerte", also Werte welche einer Zeit kleiner 1ms entsprechen, in das Capture Register geschrieben. Ich hab das nun als Workaround so gelöst wie du es beschrieben hast. Ich lass den Zähler weiterlaufen wenn der Wert ungültig ist. Das funktioniert ganz gut.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.