Forum: Mikrocontroller und Digitale Elektronik I2C Datentransfer beeinflusst Zähler im capture Modus


von Marcel B. (cable545)


Lesenswert?

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?

von Jakob (Gast)


Lesenswert?

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...

von Peter D. (peda)


Lesenswert?

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.

von Marcel B. (cable545)


Lesenswert?

:) 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.

von c-hater (Gast)


Lesenswert?

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...

von Joe F. (easylife)


Lesenswert?

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.

von Marcel B. (cable545)


Lesenswert?

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

von Joe F. (easylife)


Lesenswert?

Mach mal ein paar hochauflösende Bilder von deinem Signal mit einem 
Oszilloskop.
Alles andere ist ja stochern im Nebel.

von c-hater (Gast)


Lesenswert?

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...

von Joe F. (easylife)


Lesenswert?

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.

von Joe F. (easylife)


Angehängte Dateien:

Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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.

von Marcel B. (cable545)


Angehängte Dateien:

Lesenswert?

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!!!

von Joe F. (easylife)


Lesenswert?

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.

von Joe F. (easylife)


Lesenswert?

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.

von Joe F. (easylife)


Lesenswert?

Und? Läuft so?

von Marcel B. (cable545)


Lesenswert?

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
Noch kein Account? Hier anmelden.