PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : I²C mit Bitrate > 100 kHz - nur mit Treiber ?



oberallgeier
01.10.2012, 10:08
Zusammenfassung vom 03. Dez. 2012, 09:20.
Die Aufgabe ist für mich gelöst, die durch Intitialisierung vorgegebene Übertragungsrate beträgt deutlich mehr als 400 kHz: TWBR=5 läuft fehlerfrei, mit TWBR=17 erhalte ich laut Rechnung mit dem 20MHz auf Master und Slave 400 kHz.
In diesem Posting (klick) (https://www.roboternetz.de/community/threads/59388-I²C-mit-Bitrate-100-kHz-nur-mit-Treiber?p=560562&viewfull=1#post560562) ist das verdächtige Codeteil zu sehen nach "i2cdmy = i2c_start(SLAVE_MoCo+I2C_READ); // <<<### Lesen beginnen".
In diesem Posting (klick) (https://www.roboternetz.de/community/threads/59388-I²C-mit-Bitrate-100-kHz-nur-mit-Treiber?p=565338&viewfull=1#post565338) wird über den letzten, sehr gut funktionierenden Stand berichtet.

- - - - - Es folgt der ursprüngliche Beitrag - - - - -

Hallo Alle, bitte um Ratschläge.

Aufgabe:
o Eine Platine als Master, derzeit mit mega1284/20 MHz, I²C mit je 1x10kΩ, soll mehrere Slaves - weniger als zehn - treiben, die verschiedene Aufgaben erledigen.
o Derzeit hängt an einem Flachbandkabel 55cm EIN einziger Slave mit mega328/20MHz, I²C mit je 1x10kΩ.
o Auf Master und Slave wird zum I²C-Betrieb die Fleurylib benutzt.

Die Kommunikation läuft in dieser Konfiguration nur dann störungsfrei, wenn ich sie mit gemächlichen 100 kHz betreibe. Tests mit 200 gehen öfters schief, ein Test mit 400 funktioniert gleich garnicht. Diese 100 kHz sind mir eigentlich schon bei diesem 1-Slave-Aufbau zu wenig, da der Slave als Motorsteuerung arbeitet und zukünftig recht viel Rechenarbeit schon zu Regelung und Fahrplanung haben wird.

Nun möchte ich ja später mehrere Slaves dranhängen - da fürchte ich, dass dann der Master (und der Bus) recht viel zu tun bekommen. Ne ganz grobe Milchmädchenrechnung (Daumenlutschen) lässt vermuten, dass ich mit der geplanten Kommunikation bei der derzeitigen Datenrate das spätere, ganze System recht ausbremsen würde.

MUSS ich für höhere Bitraten unbedingt einen Treiber verwenden - z.B. den PCA9600? Da ich fertige Platinen verwende (~n möchte) käme mir ein aufge"klebter" Bustreiber garnicht gelegen . . .

Danke für Eure Hilfe.



PS: GAAAANZ grosses Manko im Forum: die Suche mit dem Suchbegriff "I2C" wird abgelehnt:

Die folgenden Probleme traten bei deiner Suche auf:


Die folgenden Wörter sind sehr allgemein, zu kurz oder zu lang und wurden daher in der Suchanfrage ignoriert:
i2c

djdune
01.10.2012, 10:53
Schon mal einen kleineren Pull-up versucht? Je höher der Takt, desto niedriger der Pull-up. Ich nehme für 400kHz (mit PIC) 4k7 und hatte noch nie Probleme

PICture
01.10.2012, 10:53
Hallo!

Bei jedem Bus wird die Bandbreite per Tiefpass aus "pull up's" und Kapazitäten des Kabels bestimmt. Daher glaube ich, dass bei gleichem Kabel eine Senkung von "pull up's", die durch alle I2C Teilnehmer noch auf "low" gezogen werden können, helfen wird. ;)

Crazy Harry
01.10.2012, 12:29
Hab ich das richtig verstanden ?

Eine Platine als Master, derzeit mit mega1284/20 MHz, I²C mit je 1x10kΩ, soll mehrere Slaves - weniger als zehn - treiben, die verschiedene Aufgaben erledigen.

Am Master keine PullUps würde ich mal sagen und du kannst auf 2K runter gehn (ich schließe mich also meinen Vorrednern an :) ). Eine ähnliche konfiguration habe ich laufen mit 2.5m Kabel dazwischen und eben 2K PullUps.

oberallgeier
01.10.2012, 14:14
Hallo Kollegen,

für die prompten Anworten danke ich euch. Ich hatte (vor dem ersten Posting natürlich, gestern fast Mitternacht) die I2C-Tutorials im Ro boterNETZ/RN-W issen (http://www.rn-wissen.de/index.php/I2C) , im mikrocontroller.net (http://www.mikrocontroller.net/articles/I2C) , dort auch ziemlich genau mein Thema (http://www.mikrocontroller.net/articles/I2C_als_Hausbus#Kleinerer_Pull-Up) - daher auch der Trick mit dem PCA9600, und die ausführliche Dokumentation bei i2c-bus.org (http://www.i2c-bus.org/de/i2c-bus/) gelesen. Bei allen steht ja etwa das Gleiche drin das ihr mir ratet - bei den letzteren Leuten auch sehr ausführlich und anschaulich mit Terminierungen und Entstörungen durch C´s und R´s. Aber was genau wie klappt - da wollt ich mal ausnahmsweise nicht so viel experimentieren.


Hab ich das richtig verstanden ... ähnliche konfiguration ... 2.5m Kabel ... 2K PullUps ...Danke! Das lässt ja hoffen. Also werd ich mal DOCH experimentieren und die Bedrahtung der PullUpWiderstände am Master mal einfach aufknippsen. Auslöten und 2K PullUps krieg ich dann, wenn nötig, immer noch hin.

Danke !

oberallgeier
01.10.2012, 15:52
... DOCH experimentieren und ... PullUpWiderstände am Master mal einfach aufknippsen ...Na ja, die Arbeit stand dafür. ABER ich hätte natürlich den Leuten von der i2c-bus.org glauben sollen - die haben sehr hübsch dargestellt, wieso das eine Ende des I²C-Bus ne andere Aufgabe hat als das andere Ende *ggg*.

Kurz:
o Beide 10k am Master aufgeknipps - also ohne PullUp.
o Kommunikation schrittweise von 100k über 200k, 400 und 600 auf 800. Bis 600k läuft die Master-Slave-Übertragung, aber oberhalb von 200 läuft das Lesen des Masters (vermutlich wohl das Senden des Slave) nicht mehr, bei 200 bis 400 recht eingeschränkt.

Nun könnt ich mir mal nen Speicheroskar besorgen und das Ganze ansehen, vermutlich werden die 2k von Cracy Harry ne Weile reichen. Ähhh - natürlich könnte ich auch einen zukünftigen Kabelbaum (annähernd) aufbauen, die Kapazitäten messen und nach den Ausführungen in der NXP-Dokumentation UM10204 Rev. 4 — 13 February 2012 die Widerstände berechnen. Aber ich werde wohl gleich die Lösung mit dem Bustreiber machen. Scheint mir weniger Aufwand zu sein. Den gibts beim grossen R, SO-8 oder TSSOP8 - den kriegt man vermutlich sogar ganz gut an der Steckbuchse unter . . .

Fazit:
Gleich richtig gemacht ist manchmal die halbe Arbeit.

Valen
01.10.2012, 16:52
Etwas spät: http://www.dsscircuits.com/articles/effects-of-varying-i2c-pull-up-resistors.html

radbruch
01.10.2012, 17:07
Kurze Begriffe suche ich "extern":

https://www.google.de/search?q=roboternetz+i2c+mega1284

PICture
01.10.2012, 18:52
Unsere Suche für "I2C Bitrate" bringt 59 Ergebnisse und vielleicht ist dort auch etwas nützliches dabei. ;)

oberallgeier
01.10.2012, 19:27
Etwas spät: ...Trotzdem danke. Das ist so ähnlich wie die Darstellungen hier, (http://www.i2c-bus.org/de/terminierung-und-serienwiderstaende/) wobei hier auch der negative Einfluss des erhöhten Lowpegels diskutiert wird. Immerhin ist in den von Dir verlinkten Darstellungen sehr schön zu sehen, dass bei 100kbit und 10KΩ gerade noch eine Art 99%-Highpegel erreicht wird. Und knapp schneller ist dann eben unter der Spezifikation. Leider ist weder die Leitungskapazität noch der Leitungswiderstand der vermessenen Anordnung genannt - wenigstens eine etwas bessere Beschreibung des Aufbaus ("arduino" ist ja eher nicht sehr aussagefähig) wäre schon wünschenswert.


Kurze Begriffe suche ich "extern" ...Danke, das mache ich ebenso - ist halt für mich irgendwie die "letzte Rettung". Aber wirksam.

Klebwax
01.10.2012, 19:49
Na ja, die Arbeit stand dafür. ABER ich hätte natürlich den Leuten von der i2c-bus.org glauben sollen - die haben sehr hübsch dargestellt, wieso das eine Ende des I²C-Bus ne andere Aufgabe hat als das andere Ende *ggg*.

Kurz:
o Beide 10k am Master aufgeknipps - also ohne PullUp.
o Kommunikation schrittweise von 100k über 200k, 400 und 600 auf 800. Bis 600k läuft die Master-Slave-Übertragung, aber oberhalb von 200 läuft das Lesen des Masters (vermutlich wohl das Senden des Slave) nicht mehr, bei 200 bis 400 recht eingeschränkt.

Ich hab zwar nicht gelesen, was i2c-bus.org über die unterschiedlichen Seiten des Busses schreiben, elektrisch gibt es keinen. Sowohl SCL als auch SDA können und werden sowohl vom Master als auch vom Slave getrieben. Deine Tests ergeben das gleiche Bild.

Ich würde es daher symmetrisch machen. Die Treiber müssen 3mA liefern können und dabei noch einen logischen Low-Pegel erzeugen. Modernen CMOS-Bausteinen fällt das leichter, da sind leicht 20mA möglich, daher dürfen es auch etwas mehr als 3mA sein. Aus der Busspannung und 3mA läßt sich leicht der passende (kleinste) Widerstand ausrechnen. Diesen würde ich zur Hälfte auf der einen und der anderen Seite plazieren, also bei 3,3V je 2,2k. Selbst mit etwas größeren Widerständen hab ich mehrere Meter hinbekommen. In einem DVI-Kabel ist auch ein I2C Bus, das geht locker über 5m.

Ein weiteres häufig anzutreffendes Problem bei längeren Kabeln ist übersprechen. SCL und SDA sollten auf keinen Fall nebeneinander liegende Adern nutzen oder etwa miteinander verdrillt werden. 1 Meter Kabel hat typisch 50pF, wirkt also als ob man 50pF direkt von SCL nach SDA schaltet. Das kann man auch leicht mit einem Scope (auch ohne Speicher) ansehen. Einfach in einer Endlosschleife Start, ein Byte, Stop senden. Am besten sendet man so was wie 0x0f, dann kann man das Übersprechen von SCL sowohl bei SDA 0 und 1 sehen. Ein halber Meter verdrillter Klingeldraht liefert da tolle/erschreckende Bilder.

Die Verwendung von Buffern ist ein zweischneidiges Schwert. Da es kein Signal zur Richtungssteuerung des Busse gibt, leben sie davon, auf beiden Seiten einen leicht unterschiedlichen Low-Pegel zu haben. Das sind so etwa 200mV. Da je nach Device möglicherweise ein Low-Pegel nach TTL, also 800mV verlangt wird, reduziert sich der Störbstand signifikant. Manche Buffer darf man deshalb nicht kaskadieren. Sollte es ein Problem mit Übersprechen geben, können sie es verstärken, da sie steilere Flanken erzeugen.

Auf einem PC-Mainboard finden sich unter verschiedenen Name einige I2C Busse. Obwohl z.B. am SMBus alle Ramriegel die Temperatursensoren und manchmal auch die Lüftersteuerungen angeschlossen sind, habe ich dort noch keine Buffer gesehen. Und auf dem DVI gehts direkt über 5m und mehr zum Monitor.

Inwieweit die Software hereinspielt, kann ich nicht sagen. Ich kenne die Fleurylib nicht. Die paar Zeilen, um mit dem I2C Controler zu reden, mache ich selbst und die Initialisierung der Hardware ist hochgradig Chipabhängig. Ich habe aber vor kurzem einen Fall verfolgt, wo das I2C Problem in der Software lag. Es gab da einen Programmpfad, wo kein Stop gesendet wurde, kann passieren und ist leider blöd zu finden.

Ich hoffe, nicht zur allgemeinen Verunsicherung beigetragen zu haben

MfG Klebwax

Klebwax
01.10.2012, 20:05
Immerhin ist in den von Dir verlinkten Darstellungen sehr schön zu sehen, dass bei 100kbit und 10KΩ gerade noch eine Art 99%-Highpegel erreicht wird.

Ich sehe gerade erst diesen Post.

Das kann ich nicht sehen, da keine Scala zu sehen ist. High ist entweder 2/3 * Vcc oder TTL-maßig 2,4V. Wenn der Bus richtig implementiert ist, ist das kein Problem. Die Abläufe bei SCL sollten so sein:

der Master legt Low auf SCL
er wartet eine halbe Bitzeit
er läßt SCL los
er wartet bis er SCL High sieht
er wartet eine halbe Bitzeit
.... usw

Warum wartet er, bis er SCL High sieht? Weil der Slave ja SCL noch auf Low halten könnte, das ist sein gutes Recht. Und eine ungetriebene Leitung mit einem Pullup ist am Ende immer High.

MfG Klebwax

oberallgeier
01.10.2012, 21:02
... elektrisch gibt es keinen ...Hab ich missverständlich beschrieben (aber besser krieg ich es grad nicht hin). Jedenfalls hätte ich durch die Darstellung dort gleich merken müssen, dass meine Testlösung mit den abgeknippsten 10k`s auf nur einer Seite nicht befriedigend laufen wird.


... Ich würde es daher symmetrisch ...Deine Erklärungen sind ja prima verständlich. Das hilft mir dabei, die für mich als Nicht-Elektroniker schwer verständlichen Sachverhalte in der Dokumentation von NXP und in den Tutorials besser zu verstehen. Vor allem Deine Richtwerte "... 1 Meter Kabel hat typisch 50pF ..." und so helfen mir beim Begreifen der Sachverhalte. Danke. So halbwegs hatte ich die durch dieses Bild

......http://www.i2c-bus.org/typo3temp/pics/805eb8ee87.gif
......© by i2c-bus.org

ja schon mitgekriegt. Danke, das war gute Gehirnnahrung! Und das mit den Buffern/Treibern und dem Übersprechen (sind ordentlich gesendete Elektronen zu unterscheiden von übergesprochen-/induzierten?) ist mir jetzt auch klarer. Danke!

Ach so, "... sehen, dass ... eine Art 99%-Highpegel ..." mit den 99% meinte ich etwas leichtfertig "recht viel". Auch missverständlich.

Sternthaler
01.10.2012, 23:07
Hallo oberallgeier,

die I2C-Spezifikation gibt auch eine dynamische Lösung für den Pull-Up-Widerstand an.
Über http://www.i2c-bus.org/de/terminierung-und-kapazitaeten/ findet man die dort verlinkte Spezifikation http://www.classic.nxp.com/acrobat_download2/literature/9398/39340011.pdf

Auf Seite 41 ist im Kapitel "17.2 Switched pull-up circuit for Fast-mode I2C-bus devices" mit Fig.43 so eine Schaltung aufgeführt.

Ok, du benötigst hier auch noch ein zusätzliches Bauteil wie bei deinem Treiber-Chip. aber hier nur ein einfaches HCT4066 plus 2 weiterer Widerstände. (1/4 Chip + 1 R pro I2C-Leitung)

Gruß Sternthaler

oberallgeier
02.10.2012, 09:06
... die I2C-Spezifikation gibt auch eine dynamische Lösung für den Pull-Up-Widerstand an ...Hi, schön, dass Du wieder öfters im Forum zu lesen bist! Danke für den Link, ich kannte nur die vermutlich neueste NXP-Dokumentation, UM10204 User manual Rev. 4 — 13 February 2012 (kennen - den Titel, nicht den Inhalt parat haben!), da steht erheblich weniger als in der von Dir verlinkten "original Philips" THE I 2C-BUS SPECIFICATION VERSION, 2.1, JANUARY 2000 document order number: 9398 393 40011.

Eigentlich dachte ich, I²C sei easy. Einfach die Fleury-Lib einbinden und loslegen, auf den meisten käuflichen Platinen ist ja schon extra ein Stecker dafür da ... Und nun hats den Anschein, ich muss mich da richtig reinarbeiten. Das fängt mit diesen Busproblemen an und geht mit Fehlerverarbeitung weiter (was tun, wenn der Slave nicht korrekt antwortet oder unsinnig stretcht usw). Dabei drängt mich in meinem neuen Projekt die Zeit. Aber ok, nochmals danke für den Link, ich werde das erstmal in Stufen mit geringem Aufwand verbessern - 3k3 oder bei mehr Slaves weniger. Dann natürlich ein Kabel, bei dem die beiden Leitungen nicht nebeneinander liegen, vielleicht find ich eins mit getrennt geschirmten Adern (mein Leitungssponsor ist sehr entgegenkommend). Und dann mal die alte und die neue Leitung am DSO ansehen und vergleichen.

Crazy Harry
02.10.2012, 10:53
Hilft dir zwar nicht weiter, aber ..... Probleme mit I²C hatte ich nur ein mal: Das war ein Display mit I²C und einem angegebenen Innen-R der Eingänge von 600-1000 Ohm. Bei sowas tut man sich dann mit "normal" bemessenen PullUps schwer und ich hab auch in diesem Fall mehr als 100kBit nicht geschafft. Zum Glück hat dieses Display auch SPI (DOG-XL).

oberallgeier
02.10.2012, 23:19
Hilft dir zwar nicht weiter, aber ...Hilft mir doch, danke! Im Moment gehts nämlich nicht wirklich weiter. Aber der Reihe nach.

An beiden Platinen - RNControl und RN MotorControl - die 10k ausgelötet und durch 2k7 ersetzt. Happy und übermütig gleich ISP mit 800k angefangen. Ging nicht. Mehrere Tests brachten:
o Senden geht bis etwa 400 k recht ordentlich (fünf Motordaten: Aktualisierungscode, Richtung1-vor/zurück, PWM1, Richtung2-vor/zurück, PWM2).
o Rücklesen (oder empfangen?) geht bei 200 k gerade noch - manchmal, nicht immer (Eine initialisierte Ziffernfolge im Slave vom Master überschreiben und zurücklesen, mit geänderten Daten überschreiben und wieder zurücklesen). Ob die I2C-Kommunikation beim Senden, Lesen oder Empfangen hängen bleibt weiß ich (noch) nicht.

Eigentlich geht es zwischen diesen beiden Platinen mit dem 55cm Flachband (RN-Definition-Belegung = zwischen SCL und SDA liegt ein GND-Strängelchen) richtig ordentlich nur mit 100 kHz. Ok, ich werde mal ne Weile damit leben, sonst läuft mir die Zeit weg.

oberallgeier
03.10.2012, 17:25
Hilft mir doch, danke! ... Eigentlich geht ... nur mit 100 kHz ...Und bei den vielen Tests der letzten Tage war wohl der eine oder andere seltene Fall dabei, dass sich der Master auch bei 100 kHz aufgehängt hat - oder vom Slave aufgehängt wurde.

Codeschnippsel vom Master - Lesen I2C-Buffer


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Lesen vom Slave ##### mit Änderung/Zusatz
if(!(i2c_start(SLAVE_MoCo+I2C_WRITE))) //Slave bereit zum schreiben/lesen?
{ //
// - - - - - - - - - - - - - - - - - - - - - - - - - -
// Musterzeile vom RN Wissen
// i2c_write(0x00); //Buffer Startadresse zum Auslesen
// i2c_rep_start(SLAVE_ADRESSE+I2C_READ); //Lesen beginnen
// - - - - - - - - - - - - - - - - - - - - - - - - - -
i2cdmy = i2c_write(0x00); // Buffer Startadresse 0 zum Auslesen
i2c_stop(); //
i2cdmy = i2c_start(SLAVE_MoCo+I2C_READ); // <<<### Lesen beginnen
////i2cdmy = i2c_rep_start(SLAVE_MoCo+I2C_READ); // <<<### Lesen beginnen
btst1 = i2c_read (ACK); // 1. von 5 Bytes lesen...

Kann das an den Interrupt(s) liegen? Der Master (mega1284) hat einen Timer-Interrupt, 50µs von TIMER2 COMPA, der Slave (mega328) hat ebenfalls Timer-Interrupt, 50µs von TIMER2 COMPA, dazu werden kommen zwei extINT0 und ~1 von den Encodern, evtl. noch andere Interrupts. Der TIMER2 COMPA ist mit Vector 8 resp. 10 relativ hoch priorisiert, die extINT mit 2 bzw. 3 sehr hoch - dagegen ist der TWI mit vector 25 resp. 27 weit unten. Nun soll natürlich eine IRS immer warten, bis die laufende fertig ist - ich lasse keine nestet Interrupts zu - aber

es könnte Zeitverschiebungen in der I2C - Kommunikation geben. Macht das etwas? Könnte das der Fehler sein?

Sternthaler
25.10.2012, 23:54
Was ist denn hier los? NIX????

Hallo oberallgeier,

natürlich kann es an den Interrupts liegen.

------------- Halber - BLÖDSINN -------------------------------------------------
\/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/
Also als erstes: Die Fleurylib arbeitet NICHT mit Interrupts. Deine Ansatz mit dem INT-Vektor ist hier somit komplett vergeblich. Aber leider kommt es somit noch schlimmer.
Wenn nun die Fleurylib-Software ackert und das Timing durch NOP's oder Loop's erzeugt wird, dann jagen deine doch recht häufigen 50µs-Timer einiges an Zeit durcheinander. Zumindest deutet da vieles drauf hin.
/\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\
------------- Halber - BLÖDSINN -------------------------------------------------
Das da oben war nicht ganz richtig.

- Auf der Master-Seite wird nicht mit Interrupts gearbeitet.
Timing-Loops oder NOPs werden hier allerdings auch nicht benutzt. Die Lib arbeitet sauber mit den Statuswerten der I2C-Hardware. Somit läuft die Wartezeit ausserhalb der I2C-Hardware und darf entsprechend auch durch Interrupts unterbrochen werden. Die Hardware sollte dann aber ohne Probleme die Daten transportieren!

- Auf der Slave-Seite allerdings komplett im Interrupt.
Hier könnte die Fragestellung zur Priorität von oberallgeier also doch noch wichtig werden!
------------- Halber - BLÖDSINN - nachgearbeitet ende ---------------------------

Du solltest mal eine Abschätzung machen wie lange deine Interruptfunktion denn so benötigt.
Ein Ansatz zur Lösung könnte folgendermaßen aussehen:
- Am Ende der INT-Funktion setzt du einen Merker auf TRUE
- In deinem Hauptprogramm rufst du NUR dann eine I2C-Funktion auf, wenn der Merker gesetzt ist.
- Den Merker dann in dem if sofort zurücksetzten, damit eine weitere Main-Loop keine 2.tes I2C-Funktion aufruft.
- Main ackert weiter und bekommt nach dem Timer-Interrupt-Merker=TRUE wieder die Erlaubnis ein wenig Fleurylib-Zeit zu verbrennen.

Die Idee ist, dass du innerhalb der Fleurylib-Funktionen für die nächste Zeit nicht gestört wirst wenn die aufgerufene Fleurylib-Funktion selbst weniger als 50µs benötigt. Die Zeit kannst du ja selber mal nachrechen.
Wenn dein Rechen zu dem Schluss kommt, dass die Fleurylib-Funktion länger dauert, kannst du mein Geschreibsel sofort in die Tonne treten, da dann das Prinzip nicht mehr funktioniert.

Hier hätte ich aber auch noch einen Link zu einem Leidensgenossen von dir. Eventuell nützt es was: http://www.elektronik-projekt.de/thread.php?threadid=3197 (http://www.elektronik-projekt.de/thread.php?threadid=3197)

Gruß Sternthaler

oberallgeier
26.10.2012, 08:16
Was ist denn hier los? NIX???? ... Die Fleurylib arbeitet NICHT ...Danke erstmal für Deine freundliche Unterstützung und Deine Sorge.

Nix los? Na ja, es war die letzten Tage gigantisch sonniges Herbstwetter - oberhalb von 1200 MSL. Da rufen die Berge und die Kletterwände; Fliegen geht nicht, weil ALLE Landeplätze im Nebel liegen :-/ . Beispiel: Verschnaufpause knapp unter 2000 MSL mit freiem Oberkörper . . . auch geklettert wird derzeit öfters ohne Hemd. Aber Deine Frage zielt anderswo hin. Da ist auch nicht wenig los.

Servoplatine und -routine müssen noch werden. Die Routine hatte Probleme gemacht (https://www.roboternetz.de/community/threads/59608-Servosignal-von-Timer1-KanalA-und-B-zeigt-Ausfälle) (weil ich mich eigensinnig wie immer auf ein bestimmtes Konzept versteif(t)e). Mittlerweile läuft die 10-Servo-Routine störungsfrei am Breadboard-m328-20Mhz. Was heißt störungsfrei? Gestern Nacht, eher heute, habe ich durch die fliegende und daneben gesteckte Verdrahtung zwei Billigservos gebraten. Richtig verdrahtet liefs dann wieder. Und ich bin richtig stolz darauf, zehn Servos (na ja, auf den meisten Kanälen läuft derzeit nur der Oskar) mit unterschiedlichen Geschwindigkeiten und unterschiedlichen Start- und Zielpunkten (zeitlich und örtlich) mit einer selbstgebauten Routine ansteuern zu können. Die Routine braucht noch einen Feinschliff z.B. für den spätere I²C-Datenaustausch, das Abfangen von Fehlern etc. Bekanntlich frisst so etwas die meiste Zeit.

Das mechanische Konzept des gesamten Projektchens macht auch Arbeit - ausser einem DINA0 mit etlichen Strichen, viel zu wenigen, steht noch nix.

Dazu kommen noch Nebenarbeiten durch ein Sonderangebot von Motoren, (https://www.roboternetz.de/community/threads/59520-7-2-volt-akkuschrauber-motoren-mit-Spannungsreglern-betreiben?p=562324&viewfull=1#post562324) die ich für einen Hilfsantrieb einsetzen werde.

Schließlich zum I²C. Unser freundlicher Mathefreakkollege aus unseren gemeinsamen Navigationsdiskussionstagen unterstützt mich dabei. Da ich aber derzeit nur zwei endgültig einzusetzende Platinen habe, später werden es mehr, warte ich derzeit, bis ich a) die I²C-Geschichte des Kollegen halbwegs verstehe, b) mehr endgültige Platinen mit einer endgültigen Kabelbaumlänge habe und c) die kollegialen low-level-Programme des Kollegen mit meinen bescheidenen C-Kenntnissen ins fertige Projekt einbinden kann. Linken von relokativen Compilaten konnte ich vor vielen Jahren zu meiner Fortranzeit. Davon ist aber i) nix mehr übrig und ii) passt es sowieso nicht.

Du siehst - kein Moos, trotzdem was loos.

Freundliche Grüße aus dem mittlerweile kühlen Allgäu wo wir ruhig auf Winterreifen dem wochenendlichen Schneechaos entgegenträumen.

Nachtrag zum Wetter. Stand ungefähr Di, 23.10, 0830: meine Terrasse auf 812m MSL hatte 5°C, Terrasse einer Berghütte am Nebelhorn auf 1934m MSL hatte 16°C - da war es aber drei Stunden früher (also NACHTS!) etwas wärmer.

Sternthaler
27.10.2012, 00:03
Ahhh, Wetterbericht live. Das lobe ich mir, da ich nun eine Justage meiner Wetteraufzeichnungen vornehmen kann. Was war das nochmal? MSL? Mars Science Laboratory oder doch nur eher vollkommen durchschnittliches, von dir weit entferntes, Salzwasser?


Hallo oberallgeier,

schön, dass du selbst mit weit mehr als 400kHz durch die Berge 'tikst'. So langsam werde ich aber echt ungeduldig da ich immer noch nicht mitbekommen habe warum du so viele Servos steuern willst. Ich kann mir nicht vorstellen, dass du dir einen elektrischen Konkurrenten für das Wandern und Bergsteigen bastelst. Es muss also irgendetwas anderes Sinnvolles sein. Oktopussy für 008?
Warum nur dein Satz: "Dabei drängt mich in meinem neuen Projekt die Zeit."?

Ich bin gespannt, was die Mathefraktion beisteuert und was du daraus wieder zusammenstricken wirst.

Frohes schaffen und eisfrei Straßen wünscht
Sternthaler

oberallgeier
27.10.2012, 12:07
Ahhh, Wetterbericht live ... MSL? Mars Science Laboratory ...Na sooo weit rauf reichen unsere Berge nicht. Die langen nicht mal für Höhenkrankheit . . . Der MSL ist zwar keine bodenständige Sache - im wahrsten Sinne des Wortes - aber doch terrestrisch gebunden; weißt Du ja.


... immer noch nicht mitbekommen habe warum du so viele Servos steuern willst ...Top secret.


... muss also irgendetwas anderes Sinnvolles sein ... Warum nur ... "... drängt ... die Zeit."? ...Danke, dass Du mal was Nicht-Sinnfreies von mir erwartest. Denn so richtig sinnig ist es nicht, Getränkedosen so zu modden, dass man nicht mehr den Pullring mit der Hand ziehen muss, sondern die Dose mit der TV-Fernbedienung aufkriegt. Einen Vorteil aber hat mein "... drängt ... die Zeit ..." - Du musst nicht so lange warten, bis der Vorhang aufgeht. Hoffen wir beide jedenfalls.

Sternthaler
30.10.2012, 22:48
Ohh, Sternthaler hatte MIST geschrieben!!!

Bitte seht nochmal hier: https://www.roboternetz.de/community/threads/59388-I%C2%B2C-mit-Bitrate-100-kHz-nur-mit-Treiber/page2?p=562501&viewfull=1#post562501 nach meiner Korrektur. Ich hoffe, ihr könnt mir verzeihen.

Tenor ist, dass die Fleurylib-Lib auf Slave-Seite sehr wohl per Interrupts läuft.

Gruß, und jede Menge Ablassbriefe
Sternthaler

oberallgeier
08.11.2012, 12:12
Einige häufig publizierte und einsehbare Standardempfehlungen für den I²C-Bus sind: kurze Leitungen. In einer ausführlichen Darstellung zum Thema (http://www.i2c-bus.org/de/crosstalk-between-sda-and-scl/) lese ich z.B.
... Kapazität zwischen den Leitern kann durch Verringern der Leitungslängen vermindert werden ...Weitere Ansätze für die Reduzierung von Übersprecheffekten sind eine Erhöhung der Serienwiderstände sowie eine Verringerung der Terminierungswiderstände ...

Ok, die geringeren Terminierungen habe ich. Aber wie kriege ich die Erhöhung der Serienwiderstände bei möglichst kurzen Leitungen hin? Hauchdünne Litzen mit zwei, drei Drähten? Möglichst aus Eisen (nein, kein Konstantan) oder so?

Aus dem und Anderem zusammen mal die Frage:

Wie sieht ein erfahrungsbasierter I²C-Kabelbaum für ein bis eineinhalb Meter Gesamtlänge mit etwa fünf bis sieben Abzweigen - keine Verästelung - aus?

PICture
08.11.2012, 12:39
Eine Reduzierung von Übersprecheffekten in Flachbandkabeln bringt auch einer mit GND verbundene Leiter zwischen jeden zwei Signalleitungen. Bei I²C wäre es einfach nur eine GND Leitung zwischen den beiden Signalleitungen. ;)

Klebwax
08.11.2012, 19:11
Ok, die geringeren Terminierungen habe ich. Aber wie kriege ich die Erhöhung der Serienwiderstände bei möglichst kurzen Leitungen hin? Hauchdünne Litzen mit zwei, drei Drähten? Möglichst aus Eisen (nein, kein Konstantan) oder so?

Bei einem Open Collector Bus ist das mit den Serienwiderständen Mist. Auf dem Bild in dem Link kann man da etwas sehen. In der Mitte etwa ist SCL ein Stück wesentlich niedriger. Da treibt wohl ein Slave den Bus (clock stretching). Änliches sieht man bei SDA. Da der Master es nicht auf so niedrige Werte schafft, hat er wohl einen Serienwiderstand bekommen. Das verkleinert den Störabstand. Insbesondere wenn SM-Bus Devices im Spiel sind. Die schalten nach TTL Pegel, also mit Low bei ca. 0,8V. Bei diesem Bild würde ich mir mehr Sorgen um den Low-Pegel machen, als um das bißchen Übersprechen.

Und das mit "Terminierung" ist bei einem Open Collector System Unsinn, die Widerstände sind die Arbeitswiderstände der Treiberstufen.

Zum Kabel, es ist wie bei einem Kondensator. Je größer der Abstand zwischen den Leitern, desto geringer die Kapazität. Und je größer die Fläche (also Länge) desto größer auch die Kapazität. Bei einem Meter ist das alles noch harmlos. Wenn man Kabel mit Paaren hat, sollte man SCL und SDA nicht im gleichen Paar führen, um Übersprechen zu vermindern. Also GND und SCL als ein Paar, Vcc und SDA als ein anderes. Und wenn es flach ist, wie PICture sagt, GND, SCL, Vcc und SDA.

MfG Klebwax

oberallgeier
08.11.2012, 22:49
Hi PICture, hallo Klebwax,

denke für die Antwort. Die Separierung der Flachkabel-Adern habe ich schon, zwar nur durch je eine GND-Ader. Das fand ich zwar selbst sinnvoll, ABER es kam einfach von den beiden aktuellen Platinen von robotikhardware, deren I²C-Stecker schon automatisch diese Funktion (http://www.rn-wissen.de/index.php/RN-Definitionen#I2C-Bus_Stecker) hergibt.

Und Klebwax danke ich für das theoretische Privatissimum. So komme ich ja wieder ein Stück weiter in die tieferen Geheimnisse der Elektronik. Danke! Da fehlts mir ja wirklich an allen Enden und Ecken.

oberallgeier
14.11.2012, 17:20
Was bisher geschah:
- Eigene Platine für 10 Servos wurde fertiggestellt und entwanzt (SCL auf SDA und umgekehrt *greuel*). Fertig.
- Die I 2C-Bibliotheken des Forumkollegen (danke ...) wird durchgearbeitet. Ich bin noch dran.
- Die Application Notes von Atmel zu TWI, AVR311, ~12 und ~15 wurden durchgelesen. Fertig.
- Das U SB-I 2C-Testteilchen von ELV, Basis ATmega 88, wurde zusammengesteckt und getestet. Fertig.
- Das U SB-Teilchen wurde auf 400kbps gesetzt.
- Alle drei Platinen (2 fertige von robotikhardware, 1 eigene) sind mit dem U SB-Teilchen bei 400 kbps sicher ansprechbar. Getestet wurden z.B. Sendesequenzen von 16 Bytes und sofort anschließend 10 Bytes zurücklesen. Dabei traten keine Störungen auf.
- Die Tests mit dem U SB-I2 C-Tester wurden mit der identischen Hardwareausrüstung wie die Platine-zu-Platine-Tests durchgeführt - es wurde nur eben der Master gewechselt und ein Stück verdrilltes Kabel, 20 cm - 4 Drähte, an das ursprüngliche Flachbandkabel ZUSÄTZLICH angeschlossen.
- Alle drei Platinen sind als Master und als Slave mit und ohne Timerinterrupts, die unabhängig von der I2C-Geschichte sind, getestet worden.
- Mit den genannen drei Platinen sind Sendefrequenzen um 100 kHz (TWBR > 90) praktisch störungsfrei, höhere Sendefrequenzen werden sofort oder nach mehreren Datentelegrammen gestört.

Die AVR315 empfielt "TWBR should be 10 or higher if the TWI operates in Master mode". Ausserdem berichtet diese AppNote, dass die "CPU clock frequency in the Slave must be at least 16 times higher than the SCL frequency". Daraus müsste bei meinen 20MHz-an-20MHz-Platinen eine Kommunikation theoretisch mit 800 kbps möglich und eine mit 400 kHz eben schon sicher sein. 400 kbps sind mit dem U SB-Teilchen offenkundig möglich (die tatsächliche Taktrate bei eingerasteter 400 kHz-Kommunikation wurde noch nicht gemessen/bestätigt). Leider kenne ich auch nicht den Code dieses praktischen Werkzeugs.

Wo die Kommunikation hängen bleibt, konnte ich noch nicht feststellen, aber ich würde es schon gerne wissen.

Weitere Bemühungen zum I 2C pausieren aktuell.

Klebwax
15.11.2012, 00:59
@oberallgeier

I2C ist so ein Hobby von mir (ich würde also gerne helfen). Ich hab aber leider im Moment einen großen Brocken am Hals, so daß ich mich deinem Problem nicht mit der erforderlichen Sorgfalt widmen kann. Sei also nicht böse, wenn Antworten ausbleiben.

MfG Klebwax

oberallgeier
16.11.2012, 08:58
... Weitere Bemühungen zum I 2C pausieren aktuell ...... Nur pausiert das Gehirn nachts nicht immer. Das scheint nicht nur bei mir so zu sein, wenn ich mir so manches 2- (3- oder 4-) -Uhr-nachts-Posting ansehe.

Mir war ein-/aufgefallen, dass der Abbruch der I2C-Kommunikation immer nach einer ganz bestimmten, genau lokalisierbaren Aktion (UART-Ausgabe eines rückgelesenen Datensatzes) erfolgte, auch wenn oft vorher die gleiche oder ähnliche Test-Schreib- und Leseaktion durchgefahren wurde (läuft RC-5-gesteuert). Der Abbruch erfolgte mal nach mehr, mal nach weniger Durchläufen, manchmal sofort nach dem Lesen - je nach I2C-Geschwindigkeit. An dieser Stelle wurde die Leseadresse geschrieben - und danach ein "i2c_start(SLAVE_MoCo+I2C_READ)" gesendet. Jetzt, nachdem ich VOR diesem Readbefehl, nach dem Schreiben der Leseadresse ein i2c_stop gesetzt habe, rauscht mein I2C mit maximaler Geschwindigkeit - maximal nach ATMEL-Spezifikation: TWBR should be 10 or higher... , aktuell habe ich TWBR = 10.

Testaufbau: RNControl, m1284/20MHz, Eigenbau Servoplatine, m328/20MHz, 9-poliges Flachbandkabel, ca. 1m20.

Danke für die vielen hilfreichen Tips, danke m..c..


Anmerkung: Manche Menschen machen keinen Fehler zweimal, aber sie lassen auch keinen aus . . .

oberallgeier
28.11.2012, 16:17
... I2C mit maximaler Geschwindigkeit ... TWBR = 10 ...So, nun ist meine Stimmung doch deutlich gestiegen. Ich habe endlich einen halbwegs realistischen Testaufbau - drei Controller. Dazu ein fast zweieinhalb Meter langes 10fach-Flachkabel. Und I2C läuft mit TWBR = 5. Master wie vor mit 20 MHz. Da machts einfach gute Laune, wenn der Master bei einem Rundruf in seine - hier noch unbekannte I²C-Welt (...for ( uint8_t look=0x00; look <= 0xFC; look = look + 2 )...) auch die tatsächlich vorhandenen Controller erkennt , siehe Dump vom Terminal :


C501 R5M_x15-16 m1284p/20MHz 28Nov2012 16:46
I2C >>400kHz [t05], I2C mit Taste [gelb], dann [OK] zu MoCo328
Motoren rauf+runter mit Taste [P100]
Gute Funktion mit extINT2 für RC-5
Initialisierung ADC auf ADC5/PA5=Poti
UbattADC5 Min = 2 , Mess = 678

Es folgt Aufruf i2clook
Suche vorhandene I²C-Devices von 0x00 bis 0xFE
-----------------------------------------------------------------
Slave erkannt auf 130 dez = 0x82
Slave erkannt auf 132 dez = 0x84
------------------------------------------------------------
Rückkehr von i2clook

Beginn Schleife/RC-5-lesen in ~r1n15~
Aktiv : Taste [MIX], [P100], [9] und [gelb]
Bitte um Aktion _

Ach so - jedes Minus oben im Slave-Suchabschnitt ist eine nicht-antwortende Adresse.

Sternthaler
01.12.2012, 13:09
Hallo oberallgeier.

Gratulation zum Erfolg bei diesem Teil-Problem.


Gruß Sternthaler

oberallgeier
03.12.2012, 08:22
Das Thema ist erfolgreich abgeschlossen, im ersten Posting (klick) (https://www.roboternetz.de/community/threads/59388-I²C-mit-Bitrate-100-kHz-nur-mit-Treiber) ist ein Inhaltsverzeichnis der relevanten Beiträge.

oberallgeier
11.07.2014, 17:00
Viel Unverständnis zu diesem Zustand (passt halt nur so ungefähr in diesen Thread):

I2C-Lesen braucht ne Pause.

Vorgeschichte: Bei meinem Archie hängen an einem I²C-Master (mega1284/20MHz) mehrere Slaves, einer davon eine Motor-Steuerplatine (mega328/20MHz) mit Treiberplatine für zwei Motoren je max 60W. Die Befehle für die Motoransteuerung der beiden Motoren gehen vom Master zur Motor-Steuerplatine per I²C, das läuft prächtig. Lesen des Slavepuffers - z.B. Encoderstand oder Ist-Speed - ging oft, meist, führte bisher stehts nach 1 bis etwa 20 (evtl. mehr?) Lesevorgängen zum Blackout des Masters. Blackout: TWI-Übertragung stoppte (z.B. belegt durch testweise Ausgabe per UART), aber ISR (TIMER2_COMPA_vect) lief weiter mit 20kHz-Interrupt, erkennbar am Toggeln der 1-sec-Heartbeat-LED.

Sonstige Angaben: 2 UARTkanäle laufen per Interrupt - 1x 115,2 kBd fürs Terminal und 1x 57,6 kBd für die PingPong-LED-Anzeigetafel, ISR (TIMER2_COMPA_vect) mit 20 kHz, ADC im free running mit rund 15 kHz, External Interrupt 20 für RC5, I2C nach PFleury mit 100 kHz.

Fazit bisher: Telegramme werden an die Slaves per I²C nur gesendet, es wird nichts zurückgelesen. Ein ziemlich unbefriedigender Zustand (aber Archie lief (https://www.roboternetz.de/community/threads/61379-Kopfsache-und-ein-m1284-etliche-Servos-viel-Alu?p=600400&viewfull=1#post600400) ziemlich gut).

Versuch einer Nachbesserung heute, dazu zuerst Versuch einer Identifizierung der Abbruchstelle. Um die Absturzstelle des Codes zu identifizieren wurden zuerst kurze UART-Telegramme in die I²C-Lesesequenz eingefügt. Die erste im Master gleich nach dem Schreiben der Adresse des ersten zu lesenden Pufferbytes. Und schon läufts klaglos. Ein einziges Millisekundenwait tat den gleichen Nutzen, mittlerweile tuts ein wait von 100 Mikrosekunden. Kontrolle: ohne Wait bekomme ich den Master nach 1 bis 15 Lesevorgängen ins Koma.

Derzeit wurde als Testsequenz tausend Mal auf den Puffer zugegriffen und stets jeweils die gleichen fünf Bytes der Motorplatine ausgelesen, Slaveadresse 130 dez = 0x82, Startbyte zum Lesen = 23. No Problem, mit UART-Ausgabe und einem Wait von 50 ms in der Leseschleife eine Sache von gut 60 sec (die ersten fünf brauche ich um den Befehl per RC5 an den Master zu senden). Das sieht zum Schluss am Terminal so aus, die Sekunden ist die aktuelle Boardzeit mit Start beim Power on:


I2CMrid # 131/23 O-AL 23 O-AH 24 O-BL 25 O-BH 26 985 Zeit 65 sec
I2CMrid # 131/23 O-AL 23 O-AH 24 O-BL 25 O-BH 26 986 Zeit 65 sec
I2CMrid # 131/23 O-AL 23 O-AH 24 O-BL 25 O-BH 26 987 Zeit 65 sec
I2CMrid # 131/23 O-AL 23 O-AH 24 O-BL 25 O-BH 26 988 Zeit 65 sec
I2CMrid # 131/23 O-AL 23 O-AH 24 O-BL 25 O-BH 26 989 Zeit 65 sec
I2CMrid # 131/23 O-AL 23 O-AH 24 O-BL 25 O-BH 26 990 Zeit 65 sec
I2CMrid # 131/23 O-AL 23 O-AH 24 O-BL 25 O-BH 26 991 Zeit 65 sec
I2CMrid # 131/23 O-AL 23 O-AH 24 O-BL 25 O-BH 26 992 Zeit 65 sec
I2CMrid # 131/23 O-AL 23 O-AH 24 O-BL 25 O-BH 26 993 Zeit 65 sec
I2CMrid # 131/23 O-AL 23 O-AH 24 O-BL 25 O-BH 26 994 Zeit 65 sec
I2CMrid # 131/23 O-AL 23 O-AH 24 O-BL 25 O-BH 26 995 Zeit 65 sec
I2CMrid # 131/23 O-AL 23 O-AH 24 O-BL 25 O-BH 26 996 Zeit 65 sec
I2CMrid # 131/23 O-AL 23 O-AH 24 O-BL 25 O-BH 26 997 Zeit 66 sec
I2CMrid # 131/23 O-AL 23 O-AH 24 O-BL 25 O-BH 26 998 Zeit 66 sec
I2CMrid # 131/23 O-AL 23 O-AH 24 O-BL 25 O-BH 26 999 Zeit 66 sec
I2CMrid # 131/23 O-AL 23 O-AH 24 O-BL 25 O-BH 26 1000 Zeit 66 sec
Ende test841

Fazit: diese tausend Lesevorgänge lassen vermuten, dass zuküftig keine Störungen mehr auftauchen.

Hier zur Erläuterung der Leseabschnitt der Funktion void I2CMrid ( void ) // I2C, Motordaten auslesen über I²C

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Lesen vom Slave
if(!(i2c_start(SLAVE_MoCo+I2C_WRITE))) //Slave bereit zum schreiben/lesen?
{ //
i2c_stop(); // Dies scheint notwendig, um den Lesepointer korrekt
// zu positionieren
i2c_start(SLAVE_MoCo+I2C_WRITE); // Slave bereit zum schreiben/lesen?
// i2cdmy = i2c_write( 0x15 ); // Bufferadresse 15hex/21dez zum Lesen
// i2cdmy = i2c_write( 0x04 ); // Bufferadresse 04hex/04dez zum Lesen
i2cdmy = i2c_write( laddr ); // Lese Buffer ab Adresse laddr
i2c_stop(); //
//uputs0 ("\r\tLabel nach Start "); // Nach Einfügen dieser Zeile lief es gut!
// wms ( 1); // daher statt der UART-Ausgabe das wait
wmus ( 100); // kurzes Wait, ca. 0,1 ms
i2cdmy = i2c_start(SLAVE_MoCo+I2C_READ); // <<<### Lesen beginnen
ipwm12 = i2c_read (ACK); // Bytes lesen...
soll12 = i2c_read (ACK); //
ipwm34 = i2c_read (ACK); //
soll34 = i2c_read (ACK); //
i2cdmy = i2c_read (NAK); // letztes Byte lesen, NAK
i2c_stop(); // Zugriff beenden
} //
else // Wenn Fehler, dann nelde jetzt:
{ // Lesefehler, dazu Fehlerblinken
uputs0("\r\n\t### Kein Lesen möglich.\r\n"); //
i2cerr = 0b00000001; // Fehlercode zu i2c-read nicht möglich
} // Ende if(!(i2c_start(SLAVE_MoCo+I2C_WRITE)))

Frage/Bitte:
Kann mir jemand bitte erklären wo ungefähr die Leseroutine sich durch eine zu knappe zeitliche Bemessung aufhängen könnte? Ich dachte, dass das

oberallgeier
13.07.2014, 10:16
Das Problem ist offensichtlich gelöst - nach der Methode "Auch ein blindes Huhn ...". Eine Erklärung, warum die Verzögerung nötig ist habe ich nämlich nicht. Vielleicht werde ich mit einem DSO noch Messungen am I²C-Bus machen, aber das hat erstmal Zeit.

Was geschah?
Die kritische Stelle der I²C-Leserei hatte ich im obigen Posting wohl recht gut getroffen. Da die konstanten wait-Vorgaben doch unbefriedigend sind, hatte ich mal versucht die Stati des Busses abzufragen. Das klappte nicht wirklich, ist auch eine etwas seltsame Lösung.

Mittlerweile habe ich den Code geändert, der Befehl "..rep_start.." steht in einer while-Schleife. Und nun tuckerts klaglos, aktuell mit 800 kHz, das ist ein TWBR von 4 (eigentlich 4,5), PFleury nennt ein Minumum von 10 für stabilen I²C-Lauf.
Anmerkung: der "..rep_start.." in der PFleury-Bibliothek ist nur ein 1:1 umgeleiteter "... i2c_start ...", der ja mit dem Ergebnis einer Bus-Statusprüfung zurückkommt ;.-.)
Anmerkung2: Das Datenblatt des m1284 nennt als TWI-Frequenz eine obere Grenze von Slavetakt / 16. Diesen kann ich nicht erreichen. Mit TWBR 2 gehts nämlich schon nicht mehr ! . . .


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Lesen (read back) vom Slave ... mit der Routine aus fleury´s lib
i2c_start_wait(SLAVE_MoCo+I2C_WRITE); // set device address and write mode
i2c_write( laddr ); // write address = laddr, das angepeilte Byte
i2c_stop(); //

while ((i2c_rep_start(SLAVE_MoCo+I2C_READ))) {}// Slave bereit zum Lesen?
//i2c_rep_start(SLAVE_MoCo+I2C_READ); // set device address and read mode
ipwm12 = i2c_readAck(); // Bytes lesen... ab laddr = 0x33/51
soll12 = i2c_readAck(); //
ipwm34 = i2c_readAck(); //
soll34 = i2c_readNak(); // letztes Byte lesen, NAK
i2c_stop(); //

Ärgerlich für mich ist nur, dass diese Änderung wieder mal ne experimentelle Softwareentwicklung ist, weil mir der tatsächliche Grund für die Notwendigkeit dieser Verzögerung nicht klar ist.

Getestet wurde in diesem Zusammenhang in meinem aktuellen Archie-Aufbau mit Master (m1284/20MHz), drei Slaves: 2x1284/20MHz und 1x328/20MHz und einer rund 1,5 m langen I²C-Leitung mit zwei Zwischensteckern. Master und Slaves sind durch mehrere Interrupts "verseucht", der Motorcontroller z.B. durch Regelungsroutine ( > 2 x 100 Hz ), Encoder (2 Stk, bis > 500 Hz), Heartbeat+Boardtimer 20 kHz und UART-115kBd. Ähnlich auch der Master durch Heartbeat+Boardtimer, RC-5-Decoder, UART 1 x mit 115kBd und 1 x mit 57kBd. . .

Klebwax
13.07.2014, 17:10
@oberallgeier

Eine Erklärung, warum die Verzögerung nötig ist habe ich nämlich nicht.

Eigentlich schon. Manche Slaves, z.B.EEPROMS, zeigen an, daß sie nicht zum Lesen bereit sind, indem sie ihre Adresse nicht mit ACK bestätigen. Das nennt man glaube ich ACK-Polling. Ob dein Slave so reagiert, kann ich jetzt nicht sagen

Ich verwende "Repeated Start" nicht (Repeated Start braucht man nur bei Multimaster-Betrieb), sondern mache einen Stop und fange dann mit Start neu an. Und ich werte bei jedem Byte das ACK aus. Kommt das ACK nicht wie erwartet, breche ich den Vorgang mit Stop ab. Wenn danach der Bus nicht Idle wird, was vor dem Anlegen der nächsten Start-Condition geprüft wird, versuche ich den Slave mit bis zu 8 Pulsen auf der SCL-Leitungen zu resetten, d.h. den Bus in den Idle-Zustand zu bringen. Wenn das nicht klappt, ist die Hardware kaput (oder ich habe den Slave selbst programmiert;) )

Wie das irgendwelche Libraries machen, weiß ich nicht. Wenn man I2C Hardware benutzt, kann man die paar Registerzugriffe auch selber programmieren. Und selbst SW-I2C ist nicht wirklich kompliziert.

MfG Klebwax

oberallgeier
13.07.2014, 18:28
... Manche Slaves, z.B.EEPROMS, zeigen an, daß sie nicht zum Lesen bereit sind, indem sie ihre Adresse nicht mit ACK bestätigen ...Danke für diese Beschreibung. Ich sehe das hier bei mir auch so. Mittlerweile habe ich ja auch die Bibliothek einigermassen durchgehechelt - denn selbst diese Hardware-I²C braucht ja ein bisschen Software - und diese paar Zeilen stehen ja eigentlich fast identisch im Datenblatt. So blicke ich allmählich durch und verstehe was da abläuft. Und offensichtlich ging da bei mir einiges fehl, weil ich beim I²C-Start nicht immer prüfte, ob ich auch Antwort bekomme.


... was vor dem Anlegen der nächsten Start-Condition geprüft wird ...Da scheint bei einigen Beispielen der Hase im Pfeffer zu liegen. Und meine Probleme traten sicher dadurch auf, dass ich die Beispiele ohne Verständnis abgekupfert hatte. Egal - wie erwähnt geht mir langsam ein Licht auf. Und danke für den Trick mit den acht Pulsen (hatte ich wohl schon irgenwo mal gelesen - aber wenn man nicht weiß was da geht . . . ).

Den Repeated Start hatte ich ja schon identifiziert (siehe oben) als das identische Teil wie der "normale" Start (neee, eigentlich kein Teil sondern ein drübergestülptes "Mehr"), nur dass damit die "..rep_start.."-Routine aufgerufen wird - die mit demselben Parameter die "... i2c_start ..."-Routine aufruft. Also einfach nur Routinen-Overhead-Verplemperei.

oberallgeier
21.07.2014, 12:33
Gut, wer viel misst misst Mist. Kenne ich. Trotzdem hatte ich nach Einführung der Bereitschaftsprüfung beim I²C-lesen (danke Klebwax für den Ausdruck "ACK-Polling") mal die benötigten Zeiten wissen wollen. Hier sind diese Werte, bei denen vier (4) Bytes aus dem I²C-Puffer des Slaves gelesen wurden, natürlich mit den Zeiten für den zugehörigen Overhead :


I²C Δt1 Δt2
kHz tupsi tupsi ( 1 tupsi sind 50 µs)

100 22..26 14..17
400 13..15 4..6
800 11..13 2..4

Δt1 ist Messung EINSCHLIEßLICH UART-Ausgabe, Δt2 ist das wirklich interessierende Ding – NUR I²C-Übertragung, siehe Code im Kasten unten. Die Zeitangabe ist in tupsi, meiner Board-Zeiteinheit von 50 µs. Die angegebene I²C-Rate ist der Wert aus "#define SCL_CLOCK" in meiner twima_hze.c, real sind also z.B. 800 kHz; wegen der Rundung beim Berechnen von TWBR = ((F_CPU/SCL_CLOCK)-16)/2; sind das schon 833 kHz. Hier ist dann TWBR 4 -- und damit deutlich unter der verbreiteten Grenzangabe in den Libraries von 10. Trotzdem läuft die Chose bei mir klaglos.

Woher dieser Grenzwert stammt weiß ich noch nicht. Ebenso ist (mir, noch) unklar das Timing der I²C-Lese-Hardware der 8bittigen ATMEL Megas. Aber - abwarten.


// ================================================== =========================== =
// Lesen Daten von der Motorplatine, Slaveadresse 0x82/130dez;
// Ausgabe auf uart0
// - - - - - - - - - - - - - - - -
void I2CMrid ( void ) // I2C, Motordaten auslesen über I²C
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{ //
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
u8 ipwm12 = 99; // Read-back-Byte vom Slave
u8 soll12 = 98;
u8 ipwm34 = 97;
u8 soll34 = 96;
u8 laddr = 0x33; // Leseaddresse = 51dez
u8 i2cttt = 0; // Lokal gemessene Zeit

i2ctim = 0; // Sendedauer - siehe ~com~.h

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Lesen (read back) vom Slave ... mit der Routine aus fleury´s lib
i2c_start_wait(SLAVE_MoCo+I2C_WRITE); // set device address and write mode
i2c_write( laddr ); // write address = laddr, das angepeilte Byte
i2c_stop(); //

while ((i2c_start(SLAVE_MoCo+I2C_READ))) {} // Slave bereit zum Lesen?
//while ((i2c_rep_start(SLAVE_MoCo+I2C_READ))) {}// Slave bereit zum Lesen?
//i2c_rep_start(SLAVE_MoCo+I2C_READ); // set device address and read mode
ipwm12 = i2c_readAck(); // Bytes lesen... ab laddr = 0x33/51
soll12 = i2c_readAck(); //
ipwm34 = i2c_readAck(); //
soll34 = i2c_readNak(); // letztes Byte lesen, NAK
i2c_stop(); //

i2cttt = i2ctim; // Timerwert übernehmen
if ( ipwm12 <= 1 ) i2cRct++; // Wenn Lesebyte fehlerhaft scheint
// I2C-ERRorcounter hochzählen
// - - - - - - - - - - - - - - - - - - - -
// Ausgabe der Daten über UART - Fortsetzung der Startsequenz
uputs0 ("\r\tI²Crd # "); // Kennung dieser Routine
uputs0i(SLAVE_MoCo+I2C_READ); uputs0("/"); uputs0i ( laddr );
uputs0("\tP12 "); uputs0u(ipwm12);
uputs0("\tsp1 "); uputs0u(soll12);
uputs0("\tP34 "); uputs0u(ipwm34);
uputs0("\tsp4 "); uputs0u(soll34);
//uputs0("\ttmr "); uputs0u(i2ctim); // Timerwert ausgeben MIT UART
uputs0("\tttt "); uputs0u(i2cttt); // Gestoppte Zeit NUR I2C
//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// uputs0("\tEnde I2CMrid");
return; //
}
// === Ende void I2CMrid ( void )
// ================================================== =========================== =


Overhead rausmessen, sprich: NUR die reine Datenübertragung zu messen, wäre möglich. Aber wozu? Immerhin geben diese Werte einen Anhalt über den tatsächlichen Zeitaufwand bei mittelschnellem I²C.