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?
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?
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
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.
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.
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
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.
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.
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.
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...
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
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.
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
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.
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...
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");
}