Forum: Mikrocontroller und Digitale Elektronik I2C "Arbitration lost" im master-slave modus


von dede (Gast)


Lesenswert?

Hallo alle miteinander

Ich habe ein komisches problem mit einer I2C verbindung. Ein Master 
(Arduino) sendet jeweils 4 bytes über den I2C bus, 3 datenbytes und eine 
checksum. Am bus hängen momentan 2 slaves (2x attiny24 mit dem USI code 
von Don Blake). Der Master am einen Ende der Leitung hat einen Pullup 
von 2k, der Slave am Ende der Leitung einen von 5k. Die Leitung ist 
5-Adrig, 2m lang und nebst GND, SCL und SDA noch zwei adern mit 230VAC. 
I2C clock ist bei 10kHz.
Problem: nach einigen hundert bis tausend commands kommt  es immer 
wieder vor, dass der master sich mit dem TWI-errorcode "0x38 = 
Arbitration lost in SLA+W or data bytes" meldet. Bei einem erneuten 
senden der bytes reagiert der Slave nicht und der master bleibt deshalb 
hängen.
Ich denke die Ursache liegt im Rauschen der Leitung, sodass der Master 
eine kollision detektiert oder der slave einen falschen Befehl empfängt 
und anfängt dem Master reinzufunken.
Kennt jemand dieses Problem und weiss die genaue Ursache oder noch 
besser: eine Lösung?

von nicht Gast (Gast)


Lesenswert?

dede schrieb:
> Die Leitung ist
> 5-Adrig, 2m lang und nebst GND, SCL und SDA noch zwei adern mit 230VAC.
Grusel... Was ist das für eine Leitung, Isolierung zwischen den Adern 
ausreichend?

von dede (Gast)


Lesenswert?

Isolierung der Adern ist mit 500VAC angegeben, müsste eigentlich reichen 
;)

von Jens M. (Gast)


Lesenswert?

Geht es denn mit einem kurzen Kabel ohne 230~ ?

von Harald M. (mare_crisium)


Lesenswert?

Dede,

versuch's doch mal mit geringerer Bitrate. Ausserdem würde ich mich auf 
einen Pullup pro Leitung beschränken. Bei zwei Pullups an derselben 
Leitung bilden eine VCC-Schleife und begünstigen Einstreuungen.

mare_crisium

von dede (Gast)


Lesenswert?

Jens Martin schrieb:
> Geht es denn mit einem kurzen Kabel ohne 230~ ?

Ja, bei einem Test mit kurzem Kabel (ca. 30cm) ohne 230V hats problemlos 
funktioniert.

Das mit den pullups hatte ich anfangs anders, die pullups am ender der 
Leitung haben die kommunikation eher verbessert, der Fehler trat danach 
weniger schnell auf, viel geholfen hats aber nicht.

von Michl (Gast)


Lesenswert?

I²C ist eigentlich zur Kommunikation auf verschiedenen Komponenten AUF 
einer Platine gedacht. Für größere Strecken ist I²C schlichtweg nicht 
vorgesehen. Versuchs mal probeweise mit I²C-Bus-Extendern. Gibts von 
verschiedenen Firmen, unter anderem glaube ich auch von Texas 
Instruments. Also einfach mal samples ordern und versuchen. Die 230V 
begünstigen natürlich auch nicht unbedingt. Wenn du ein Oszi hast schau 
dir mal den Signalverlauf an. Und zwar bei 2m + 230V und bei den 30cm. 
Da wirste schöne Unterschiede feststellen.

von Harald M. (mare_crisium)


Lesenswert?

dede,

dann stimme ich Michl zu. Du solltest es mit Busextendern versuchen 
(z.B. dem PCA9513 oder dem PCA9515). Reiche Auswahl findest Du hier
http://www.nxp.com/#/page/content=[f=/dynamic/datasheets/tid-71114_sid-41735/data.xml]

mare_crisium

von Peter D. (peda)


Lesenswert?

nicht Gast schrieb:
> dede schrieb:
>> Die Leitung ist
>> 5-Adrig, 2m lang und nebst GND, SCL und SDA noch zwei adern mit 230VAC.
> Grusel... Was ist das für eine Leitung, Isolierung zwischen den Adern
> ausreichend?

Doppel-Grusel.
Warscheinlich ist dann die GND-Leitung gleich auch noch der 
Schutzleiter.

Daß es nicht funktioniert, ist kein Wunder.
Daß es funktioniert, wäre aber ein Wunder.


Peter

von Klaus 2. (klaus2m5)


Lesenswert?

Bei einer Single-Master Implementierung wird Arbitration nicht 
gebraucht. Einfach alle Abfragen auf USIDC auskommentieren!

Aber ich stimme Peter zu - I2C und 230V im gleichen Kabel sind einfach 
gruselig.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Klaus 2m5 schrieb:
> I2C und 230V im gleichen Kabel sind einfach gruselig.
Und schon I²C und "2m" sind grenzwertigst... ;-)

Man sollte sich immer im Hinterkopf behalten, dass der IIC für 
"Inter-IC" Kommunikation (Fernsehgeräte, Videogräte, Autoradios...) 
ausgelegt wurde.

von Jens M. (Gast)


Lesenswert?

Lothar Miller schrieb:
> Und schon I²C und "2m" sind grenzwertigst... ;-)

Kommt auf die Taktrate an. Als erstes würde ich einen Pullup wegnehmen 
und den anderen auf 1 kOhm runtersetzen.

von dede (Gast)


Lesenswert?

Danke für die vielen Antworten.
Also dass I2C nur für kurze Leitungen gemacht wurde ist wohl richtig, 
anscheinend wird aber auch z.b. bei HDMI Kabeln eine TWI Verbindung 
zwischen den Geräten geführt, was ja auch problemlos zu funktionieren 
scheint. Gelesen hab ich schon, dass man anscheinend Leitungen bis 10m 
problemlos betreiben kann, wenn man die taktrate runter nimmt und 
kleinere pullups verwendet.
Dass ein pullup auf beiden Seiten der Leitung stören soll versteh ich 
nicht. Vcc wird ja nicht über die Leitung übertragen. Jeder Slave wird 
über 230V gespiesen und hat seinen eigenen 5V-regler. Nur die GND 
leitung, SCL, SDA sowie 230VAC sind auf der leitung. Schutzerdung brauch 
ich nicht, die Gehäuse sind aus Holz (hmm, nicht wirklich Feuersicher 
merk ich grad...).
Die kommunikation funktioniert eigentlich ziemlich gut, es tritt nur 
alle paar hundert bytes ein NACK auf, womit ich problemlos leben kann. 
Das eigentliche Problem besteht darin, dass der Slave ein "Arbitration 
lost" im master verursacht (vermutlich ist läuft der timer durch ein 
rauschen im clock zu früh ab und er zieht den SDA runter) und danach 
nicht mehr reagiert.
Wenn ich jetzt einfach eine STOP condition erzeuge falls der Fehler 
detektiert wird und dann wieder sende, wartet der Master vergeblich auf 
ein ACK nach dem START.
So wie ich die Programmierung von Don Blake verstehe, müsste der Slave 
bei detektiertem STOP wieder auf ein START reagieren, tut er aber nicht. 
Der bleibt irgendwo hängen und ich finde nicht raus wo, da es ja keine 
unendlichen while-loops in der programmierung gibt, die nicht auf ein 
STOP reagieren.

Ich werde mir die Signale mal auf dem Oszi anschauen, habe das zwas 
schon gemacht, jedoch auf Master seite, die können ja beim Slave ganz 
anders ankommen...

von Peter D. (peda)


Lesenswert?

Irgendeine Schaltstörung auf den 230V koppelt kapazitiv ein und erzeugt 
für den Slave einen zusätzlichen SCL-Impuls. Der Slave legt nun sein ACK 
zu früh an und der Master erkennt die Kollision.
Der Master kann aber kein Stop senden, da der Slave ja SDA auf low 
zieht.
Du mußt also das HW-TWI abschalten und per SW-I2C einen SCL-Puls 
generieren und dann versuchen, Stop zu senden. Erst dann ist der Slave 
wieder adressierbar.

Trotzdem ist 230V und Niederspannung auf dem selben Kabel verboten.


Peter

von dede (Gast)


Lesenswert?

Hab mal mein oszi angehängt, die signale kommen absolut sauber beim 
Slave an, taktrate 40kHz.

von chris (Gast)


Lesenswert?

Auf der Software-Seite zu suchen ist sicherlich auch kein Fehler.
Wenn ein Spike den Bus aufhängt, sollte eine Softwaremaßnahme dagegen 
helfen.

von Michael L. (michaelx)


Lesenswert?

Peter Dannegger schrieb:
> Trotzdem ist 230V und Niederspannung auf dem selben Kabel verboten.

Genau so ist es. - K.A. warum der Frager so einen groben Unfug treibt.

Separates Kabel für die Daten, dann geht I2C vermutlich auch über 2 
Meter.

von Michael K. (mmike)


Lesenswert?

Ein einfacher Workaround wäre:


1. TWI Modul am Master abschalten.
2. Am Master SDA als Input und SCL als Output konfigurieren.
3. SCL im TWI Takt so lange toggeln bis SDA wieder high ist
4. TWI wieder initialisieren und weiter machen ...

Ist zwar nicht schön, aber sehr effektiv um den Bus respektive den Slave 
wieder in Gang zu kriegen ...

Grüße,
Michael

von dede (Gast)


Lesenswert?

Michael L. schrieb:
> Peter Dannegger schrieb:
>> Trotzdem ist 230V und Niederspannung auf dem selben Kabel verboten.
>
> Genau so ist es. - K.A. warum der Frager so einen groben Unfug treibt.

Den unfug treib ich, weil ich nicht zwei leitungen ziehen will, sieht 
unschön aus im Wohnzimmer.
Wenn alles fehlschlägt werd ich wohl oder übel ein kabel mit 
paarverseilten und isolierten leitern suchen müssen... was ich da bis 
jetzt gefunden habe ist entweder nicht bis 400V betreibbar oder nur in 
grau erhältlich, ich will aber ein schwarzes kabel.

Hab mittlerweilen einiges versucht. Der Slave stürzt nun nicht mehr ab, 
da ich dort den TWI bei ausbleiben von daten auf "RECEIVE START" mode 
setze.
Wenn ich die Arduino TWI library (interruptbasiert) verwende, läuft die 
kommunikation einige sekunden, auch bei Taktraten von über 100kHz. Dann 
ist aber fertig.
Bei der Sendemethode aus dem Atmega datenblatt (ohne TWI interrupt) 
funktionierts eher weniger. Meistens kommt der Fehler 0x20 = kein ACK 
bei der adresse, sonst kommt 0x30 =kein ACK bei den Daten (adresse aber 
erfolgreich übertragen). So alle paar hundert versuche kommt mal ein 
Befehl komplett durch, dann gibts aber datenübertragungsfehler, die 
checksum stimmt nicht.

Irgendwo muss da zuviel noise sein, obwohl die Signale am Oszi sauber 
aussehen.
Gibt es eine Möglichkeit die HIGH und LOW pegel von atmelchips 
einzustellen? Dann könnte ich den Slave auf noise weniger empfindlich 
machen.
Alternative werde ich versuchen einen hardware filter einzubauen. Ich 
bin mir ziemlich sicher, dass die probleme von noise kommen, denn bei 
höheren clockrates funktioniert die kommunikation besser als bei tiefen 
(da geht gar nix) was heisst, dass der Slave vermutlich mehr clocks 
sieht als der Master sendet und darum keine Daten bestätigt.

von dede (Gast)


Lesenswert?

update:

habe mit Filterung experimentiert, ein RC Filter am SDA pin macht das 
Ganze schon viel stabiler (einige Minuten fehlerfrei). Es scheint 
wirklich zu viel noise auf dem Bus zu haben, eingefangen über die AC 
leitung. Wenn ich z.B. die Lampe an der selben Steckdose ausschalte, 
bleibt die Kommunikation hängen. Da muss wohl auch noch eine Drossel an 
den AC Eingang.

Aber etwas ist noch ganz komisch: in meiner Softwareroutine wird der Bus 
nach einer Übertragung nicht freigegeben, sondern beide Leitungen sind 
Low (im gegensatz zur standard Arduino TWI library). Ich habe den code 
mit diesem abgeglichen:

http://www.nongnu.org/avr-libc/user-manual/group__twi__demo.html

nach einem STOP bleiben aber beide Leitungen low...

von dede (Gast)


Lesenswert?

Ok, problem gelöst:
1. der clock darf nicht zu tief sein da sonst das signalrauschen stärker 
reinspielt
2. Eine drossel auf der AC linie dämpft das Rauschen ein bisschen
3. Die Arduino TWI library stürzt öfters mal ab wenn noise auf dem Bus 
vorhanden ist. Diese reset funktion schafft abhilfe:

void resetTWI(void) //resets TWI pins and registers
{
   TWCR &= ~(1<<TWEN); //disable TWI
 //release TWI lines:
   pinMode(18, INPUT);
   pinMode(19, INPUT);
   digitalWrite(18, HIGH); //activat internal pullups
   digitalWrite(19, HIGH);
   delay(1); //wait for the lines to be released
   Wire.begin(); //TWI reinitialize
    TWBR = ((CPU_FREQ / TWI_FREQ) - 16) / 2; //set TWI frequency (if 
necessary)
  // Serial.println("TWI reset");
}

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.