PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Fehler in For-Schleife mit I2C Kommunikation



uffi
14.03.2011, 21:50
Hallo,

ich brauche Eure Hilfe bei einer Fehleranalyse, hab im Moment keine Ideen mehr.

Folgendes Problem:

Hardware: ATMEGA16, der über software I2C mit 3 Ultraschallsensoren und einem weiteren Sensor-Board kommuniziert. LCD zum Debuggen im 4-bit Datenmodus.

Setup: externer Quartz mit 18,432 MHz (übertaktet), Fehlerbild ist bei Nutzung des internen RC-Oszillators mit 8 MHz aber identisch.

Software: C-Code anbei, nutzt die I2C Lib (mit Software-TWI und Assembler Source) und LCD Lib (4-bit Datenmodus) von Peter Fleury.

Zuerst wird der I2C Bus initialisiert und die Messungen auf den 3 US-Sensoren wird mit einem General-Schreibbefehl (Adresse 0x00) und das weitere Sensorboard mit einem Schreibbefehl an die I2C Adresse 0xD0) gestartet.
18244

Zum Auslesen der 3 US-Sensoren wird eine For-Schleife benutzt. Je nachdem, an welcher Stelle der Aufruf i2c_stop() plaziert wird innerhalb der Schleife, ergeben sich unterschiedliche Fehlerbilder.

Fall1: i2c_stop(); im Code direkt nach dem Lesen des US-Sensors plaziert. Die 3 Senoren (I2C-Adresse E0, E2 und E4) werden richtig gelesen. Aber danach wird die For-Schleife nicht wie beabsichtigt beendet, sondern es wird versucht, weiter endlos die jeweils um 2 inkrementierten Addressen zu lesen. Die FOR-Schleife wird endlos ausgeführt.
18243


// select display
lcd_select(0);
// move cursor to position on line 0
lcd_gotoxy(10,0);

for ( i = 0 ; i < 3 ; i++ )
{
// check if ultrasonic sensor is busy
busy_US = i2c_start(US_left + (2*i) + I2C_READ);

// address I2C device ultrasonic sensor with read access
if (busy_US == 0)
{
distance = i2c_readNak(); // read one byte

[I] i2c_stop(); // release I2C bus

utoa(distance, buffer, 10);

// put string to display (line 0)
lcd_puts(buffer);
lcd_puts(" ");

if (i==2)
{
i2c_start(US_general + I2C_WRITE);
// address I2C device ultrasonic sensor with write access
i2c_write(Start_US); //start new ultrasonic measurement
i2c_stop(); // release I2C bus
}

}

else
{
i2c_stop(); // release I2C bus
}
}


Fall2: i2c_stop(); im Code erst nach der LCD Ausgabe weiter hinten plaziert. Nur noch der erste Sensor wird korrekt gelesen. Dann folgt zweimal ein i2c-Schreibbefehl an die i2c Adresse 0x02. Die Schleife wird sodann beendet und das andere Sensorboard wird korrekt ausgelesen (i2c Adresse 0xD0).
18245


// select display
lcd_select(0);
// move cursor to position on line 0
lcd_gotoxy(10,0);

for ( i = 0 ; i < 3 ; i++ )
{
// check if ultrasonic sensor is busy
[I] busy_US = i2c_start(US_left + (2*i) + I2C_READ);

// address I2C device ultrasonic sensor with read access
[I] if (busy_US == 0)
{
distance[I] = i2c_readNak(); // read one byte

utoa(distance[I], buffer, 10);

// put string to display (line 0)
lcd_puts(buffer);
lcd_puts(" ");

[I] i2c_stop(); // release I2C bus

if (i==2)
{
i2c_start(US_general + I2C_WRITE);
// address I2C device ultrasonic sensor with write access
i2c_write(Start_US); //start new ultrasonic measurement
i2c_stop(); // release I2C bus
}

}

else
{
i2c_stop(); // release I2C bus
}
}



Fall3: zusätzlich noch 2 (leicht modifizierte) Zeilen zum LCD select und Positionieren des Cursors in die Schleife gezogen vor den Aufruf i2c_stop(); Die I2C Kommunikation läuft korrekt ab. Nur die LCD Ausgabe ist fehlerhaft.
18246


for ( i = 0 ; i < 3 ; i++ )
{
// check if ultrasonic sensor is busy
busy_US = i2c_start(US_left + (2*i) + I2C_READ);

// address I2C device ultrasonic sensor with read access
[I] if (busy_US == 0)
{
distance[I] = i2c_readNak(); // read one byte

utoa(distance[I], buffer, 10);

[I]// select display
lcd_select(0);
// move cursor to position on line 0
lcd_gotoxy(10+(4*i),0);

// put string to display (line 0)
lcd_puts(buffer);
lcd_puts(" ");

[i][I] i2c_stop(); // release I2C bus

if (i==2)
{
i2c_start(US_general + I2C_WRITE);
// address I2C device ultrasonic sensor with write access
i2c_write(Start_US); //start new ultrasonic measurement
i2c_stop(); // release I2C bus
}

}

else
{
i2c_stop(); // release I2C bus
}
}


Die betreffenden Ausschnitte der I2C Kommunikation, wie ich sie mit einem Logic Analyser aufgezeichnet habe, seht ihr in den 3 anhängenden Bildern:

i2c_fall1.png
i2c_fall2.png
i2c_fall3.png

Der Code ist auch angehängt.



Folgende Fehlermöglichkeiten habe in bisher in Betracht gezogen:

Übertaktung (18,432 MHz), kann ich aber ausschließen, da das Fehlerbild mit 8 MHz identisch ist.
Alterung des Flash, Code wird fehlerhaft gelesen. Unwahrscheinlich, da ich den Chip nun seit 5 Jahren betreibe, aber sicher nur an 30 Tagen im Jahr mit ca. 10 Löschvorgängen pro Tag (macht 1500 Programmierzyklen).
Compiler-Fehler, dafür hab ich auch die Listings angehängt, evtl mal draufschauen.
Bitte helft mir mit Ideen.

Danke, uffi.

uffi
14.03.2011, 22:01
Hier noch besser aufgelöste Bilder als *.png.

uffi
14.03.2011, 22:07
irgendwie wandelt der Uploader meine png immer in blöde jpg um, daher hier nochmal als einzelne zip Dateien:

sternst
15.03.2011, 13:37
Folgende Fehlermöglichkeiten habe in bisher in Betracht gezogen:

Übertaktung (18,432 MHz), kann ich aber ausschließen, da das Fehlerbild mit 8 MHz identisch ist.
Alterung des Flash, Code wird fehlerhaft gelesen. Unwahrscheinlich, da ich den Chip nun seit 5 Jahren betreibe, aber sicher nur an 30 Tagen im Jahr mit ca. 10 Löschvorgängen pro Tag (macht 1500 Programmierzyklen).
Compiler-Fehler, dafür hab ich auch die Listings angehängt, evtl mal draufschauen.Es ist mit ziemlicher Sicherheit Möglichkeit #4, eine data/stack-Collision. Du versuchst mehr RAM zu verwenden, als überhaupt da ist. Da werden dann Daten zerstört und die merkwürdigsten Effekte sind die Folge.

uffi
15.03.2011, 14:57
Ja, super Idee. Allerdings sagt der Compiler:

Size after:
allrounder.elf :
section size addr
.text 4236 0
.data 570 8388704
.bss 14 8389274
.eeprom 512 8454144
.stab 1440 0
.stabstr 183 0
.debug_aranges 64 0
.debug_pubnames 531 0
.debug_info 2184 0
.debug_abbrev 838 0
.debug_line 3084 0
.debug_frame 432 0
.debug_str 801 0
.debug_loc 1141 0
Total 16030

Sehe ich das richtig, dass der Compiler von den 1kByte SRAM 570 Bytes für die Variablen reserviert?
Dann müßte der Stack aber schon sehr lang werden, damit das die Ursache für den Fehler sein kann...

Oder liege ich da falsch?

Danke und Gruß, uffi.

sternst
15.03.2011, 17:23
Sehe ich das richtig, dass der Compiler von den 1kByte SRAM 570 Bytes für die Variablen reserviert?Nein, 584 Bytes. Und das sind nur die statischen Variablen.


Dann müßte der Stack aber schon sehr lang werden, damit das die Ursache für den Fehler sein kann...
Ja, wird er ja aber auch. Allein mit der Variable "distRAM" belegst du 512 Bytes auf dem Stack. Und schon bist du über den 1024 Bytes.


Da du ja wohl kaum die Funktion main rekursiv aufrufen willst, solltest du als erstes mal die lokalen Variablen dort static machen. Dann sind sie vom Stack runter und tauchen mit in der Auflistung vom Compiler auf. Das gibt dir etwas mehr Überblick. Dann reduzierst du den RAM-Verbrauch, indem du alle konstanten Strings ins Flash verbannst. Und dann sehen wir weiter.

Und mal so nebenbei:
Dieses SREG-Gefummel in den ISRs ist völlig überflüssig. Darum kümmert sich der Compiler.

uffi
15.03.2011, 17:27
Vielen Dank sternst!!!

Thema ist damit gelöst.

Ich habe mit dem kleinen Program avrstackview und meiner .elf Datei den Stack-Verbrauch berechnen lassen. Hier das Ergebnis:

Analysis complete: 0 errors, 0 warnings
flash usage (words): 2118
global RAM usage (bytes): 1096
maximum func. subroutine levels: 6
maximum func. stack (bytes): 554
maximum int. subroutine levels: 1
maximum int. stack (bytes): 9
nested interrupts: 0
maximum nest. int. stack (bytes): 0
maximum total stack (bytes): 563
maximum total subroutine levels: 7
maximum total RAM usage (bytes): 1659

Ich benutze also 1659 Bytes RAM und habe nur 1024.

Vielen, vielen Dank nochmal, das ist die Lösung meines Problems!!!

uffi
15.03.2011, 22:32
Uups, leider zu früh gefreut.

Hab jetzt den Code nach Stefan's Hinweisen modifiziert und das Stack-Problem beseitigt. Die Simulation mit avrstackview bringt nun folgendes Ergebnis:

Analysis complete: 0 errors, 0 warnings
flash usage (words): 2155
global RAM usage (bytes): 609
maximum func. subroutine levels: 6
maximum func. stack (bytes): 35
maximum int. subroutine levels: 1
maximum int. stack (bytes): 8
nested interrupts: 0
maximum nest. int. stack (bytes): 0
maximum total stack (bytes): 43
maximum total subroutine levels: 7
maximum total RAM usage (bytes): 652

Also o.k.

Jedoch zeigt sich nun folgendes Fehlerbild:
Nur noch der erste Sensor (Adresse E0) wird korrekt gelesen. Der zweite mit Adresse E2 wird auch noch gelesen, aber der Wert 02 kann nicht sein (so nahe Werte kann der US Sensor nicht ausgeben), auf dem LCD wird dieser Wert auch nicht mehr ausgegeben, sondern abrupt die FOR-Schleife vorzeitig beendet.
Dann wird das andere Sensorboard korrekt ausgelesen (i2c Adresse 0xD0).

Hat jemand noch eine Idee?
Anbei nochmal alle Sourcen, Daten und ein Bild vom Logic Analyzer gesammelt im File "Problem.zip".

Danke, Dirk.

P.S. Frage noch an Stefan: welches sind string Konstanten in meinem Code?
P.P.S. Wenn ich die Schleife auflöse und alle 3 US-Sensoren einzeln abfrage, funktioniert alles!!! Es muß also an dieser verflixten FOR-Schleife liegen, so sieht sie jetzt aus:


// select display
lcd_select(0);

for ( i = 0 ; i < 3 ; i++ )
{
// check if ultrasonic sensor is busy
busy_US[i] = i2c_start(US_left + (2*i) + I2C_READ);

// address I2C device ultrasonic sensor with read access
if (busy_US[i] == 0)
{
distance[i] = i2c_readNak(); // read one byte
i2c_stop(); // release I2C bus

utoa(distance[i], buffer, 10);

// move cursor to position on line 0
lcd_gotoxy(10+(4*i),0);
// put string to display (line 0)
lcd_puts(buffer);
lcd_puts(" ");

if (i==2)
{
i2c_start(US_general + I2C_WRITE);
// address I2C device ultrasonic sensor with write access
i2c_write(Start_US); //start new ultrasonic measurement
i2c_stop(); // release I2C bus
}

}

else
{
i2c_stop(); // release I2C bus
}
}

sternst
16.03.2011, 10:26
Wie groß können denn die gelieferten Werte werden? Bestimmt doch auch größer als 99, oder? In dem Fall ist buffer zu klein. Für eine dreistellige Zahl muss buffer die Größe 4 haben (drei Ziffern plus Null-Terminierung).


P.S. Frage noch an Stefan: welches sind string Konstanten in meinem Code?All die Strings in Anführungszeichen, z.B.
lcd_puts("Sensor Board 2 Results: ");Die belegen aktuell auch Platz im RAM, was aber nicht nötig wäre.

uffi
16.03.2011, 12:31
ja, Du hast Recht, bei buffer kommen Zahlen bis 3-stellig vor:

es muß heißen static char buffer(4);

Komischerweise hat das aber bisher keinen Fehler gegeben, die LCD Anzeige ist korrekt mit 3 Ziffern. Kann das für den Schleifenabbruch verantwortlich sein?

Vielen Dank für Deine Hilfe!

sternst
16.03.2011, 19:24
Komischerweise hat das aber bisher keinen Fehler gegeben, die LCD Anzeige ist korrekt mit 3 Ziffern.Klar, für die Ausgabe ist ja primär auch nur wichtig an der entsprechenden Adresse die entsprechenden Daten zu finden. Dass bei der Erstellung der Daten andere Variablen zerstört wurden interessiert da ja erst mal nicht.


Kann das für den Schleifenabbruch verantwortlich sein?Du überschreibst dort eine andere Variable (außer du hast das Glück, dass buffer die letzte Variable im Speicher ist). Das kann alle möglichen Auswirkungen haben. Wie wäre es einfach mit Ausprobieren?

uffi
16.03.2011, 21:25
o.k. hab es ausprobiert:

Leider ist der fehler unverändert da.

Noch eine Idee?

uffi
18.03.2011, 10:34
Hallo,

irgendwo muß noch der Wurm drin sein.
Ich vermute ja nach wie vor die FOR Schleife!
Aber was mache ich da falsch?

Bitte helft mir weiter, ich steh auf dem Schlauch...

Danke und Gruß, uffi.

sternst
18.03.2011, 12:06
Wie sieht der Code jetzt aus?
Wie sieht der weiter oben erwähnte funktionierende Code ohne for-Schleife aus?

uffi
18.03.2011, 12:49
Der fehlerbehaftete Code entspricht noch dem aus dem Anhang "Problem.zip", außer dass buffer[4] statt buffer[3] deklariert wurde.

Der fehlerfreie Code sieht so aus (FOR-Schleife aufgelöst):



// select display
lcd_select(0);

// check if ultrasonic sensor is busy
busy_US[0] = i2c_start(US_left + I2C_READ);

// address I2C device ultrasonic sensor with read access
if (busy_US[0] == 0)
{
distance[0] = i2c_readNak(); // read one byte
i2c_stop(); // release I2C bus

utoa(distance[0], buffer, 10);

// move cursor to position on line 0
lcd_gotoxy(10,0);
// put string to display (line 0)
lcd_puts(buffer);
lcd_puts(" ");
}
else
{
i2c_stop(); // release I2C bus
}

busy_US[1] = i2c_start(US_front + I2C_READ);

// address I2C device ultrasonic sensor with read access
if (busy_US[1] == 0)
{
distance[1] = i2c_readNak(); // read one byte
i2c_stop(); // release I2C bus

utoa(distance[1], buffer, 10);

// move cursor to position on line 0
lcd_gotoxy(14,0);
// put string to display (line 0)
lcd_puts(buffer);
lcd_puts(" ");
}
else
{
i2c_stop(); // release I2C bus
}

busy_US[2] = i2c_start(US_right + I2C_READ);

// address I2C device ultrasonic sensor with read access
if (busy_US[2] == 0)
{
distance[2] = i2c_readNak(); // read one byte
i2c_stop(); // release I2C bus

utoa(distance[2], buffer, 10);

// move cursor to position on line 0
lcd_gotoxy(18,0);
// put string to display (line 0)
lcd_puts(buffer);
lcd_puts(" ");
}
else
{
i2c_stop(); // release I2C bus
}

i2c_start(US_general + I2C_WRITE);
// address I2C device ultrasonic sensor with write access
i2c_write(Start_US); //start new ultrasonic measurement
i2c_stop(); // release I2C bus

sternst
18.03.2011, 13:48
Der fehlerfreie Code sieht so aus (FOR-Schleife aufgelöst):Der logische Ablauf ist aber nicht der gleiche. Dieser Teil
2c_start(US_general + I2C_WRITE);
// address I2C device ultrasonic sensor with write access
i2c_write(Start_US); //start new ultrasonic measurement
i2c_stop(); // release I2C buswird hier immer ausgeführt, in der Schleifen-Variante aber nur bei "busy_US[2] == 0".

uffi
18.03.2011, 13:57
Das ist korrekt.
Im Fehlerfall springt er aber schon vorher aus der Schleife raus.
Das kann also nicht die Ursache für den Fehler sein

sternst
18.03.2011, 14:17
Das ist korrekt.
Im Fehlerfall springt er aber schon vorher aus der Schleife raus.
Das kann also nicht die Ursache für den Fehler seinWarum bist du dir da so sicher? Außenrum ist auch noch eine Schleife. Woher weißt du, dass der Fehlerfall nicht genau dann auftritt, wenn im Durchlauf vorher (bezogen auf die äußere Schleife) das entsprechende Code-Fragment nicht ausgeführt wurde?

uffi
18.03.2011, 14:28
Die äußere FOR-Schleife ist auskommentiert.
Oder meinst Du die while-Schleife?

sternst
18.03.2011, 14:47
Die äußere FOR-Schleife ist auskommentiert.
Oder meinst Du die while-Schleife?Welche Rolle spielt das jetzt? Der entscheidende Punkt ist, dass die innere for-Schleife mehrfach hintereinander ausgeführt wird, und mir mein obiges Szenario durchaus plausibel erscheint (*). Wenn du dir so sicher bist, dass das nicht sein kann, solltest du das schon genau begründen. Auch deshalb, weil sich aus diesem "genau begründen" neue Anhaltspunkte ergeben könnten.

Und warum zum Teufel weist du diese Möglichkeit gleich zurück und fängst das Diskutieren an, statt es einfach mal auszuprobieren? Wenn es eine funktionierende und eine nicht funktionierende Variante gibt, und es einen konkreten Unterschied zwischen beiden gibt, dann ist dieser Unterschied doch wohl mal einen genaueren Blick wert, und sei es auch nur, um eine weitere mögliche Fehlerquelle sicher auszuschließen.

(*): Ich kenne allerdings deine Sensoren nicht, und habe auch keine Lust mich damit auch noch zu beschäftigen, um zu analysieren, was das Nichtausführen des Code-Teils genau impliziert.

uffi
18.03.2011, 14:56
sorry, ich sitze hier im Job und kann es im Moment nicht ausprobieren. Das werde ich heute abend natürlich machen. Meine Absicht war das Thema vorher schon genauer einzukreisen.
Also mein Verständnis des Ablaufes mit der inneren FOR Schleife ist so:

i=0, der erste Sensor wird ausgelesen, Antwort ok, Wert wird auf LCD ausgegeben.
i=1, der zweite Sensor wird ausgelesen, Antwort kann nicht sein, Wert wird nicht auf LCD ausgegeben, Schleife wird abgebrochen, die Sensoren werden nicht neu gestartet und der weitere Code wird ausgeführt.

Mein Verständnis des Codes ohne innere FOR-Schleife ist so:
i=0, der erste Sensor wird ausgelesen, Antwort ok, Wert wird auf LCD ausgegeben.
i=1, der zweite Sensor wird ausgelesen, Antwort ok, Wert wird auf LCD ausgegeben.
i=2, der dritte Sensor wird ausgelesen, Antwort ok, Wert wird auf LCD ausgegeben.
Anschließend wird eine neue Messung der Sensoren mit einem general i2c Kommando an Adresse 0x00 neu gestartet.

Da im Fehlerfall oben schon bei i=1 die Schleife abgebrochen wird, kommt es nicht mehr zum Neustart der Messung.

sternst
18.03.2011, 15:18
Und meine Frage wäre dann (wie schon oben), warum du dir so sicher bist, dass es nicht genau deshalb beim Sensorauslesen zum Fehler kommt, weil schon im vorigen Durchlauf die Sensoren eben nicht neu gestartet wurden (weil dort das i2c_start für Sensor 3 (i=2) gescheitert ist).


i=0, der erste Sensor wird ausgelesen, Antwort ok, Wert wird auf LCD ausgegeben.
i=1, der zweite Sensor wird ausgelesen, Antwort kann nicht sein, Wert wird nicht auf LCD ausgegeben, Schleife wird abgebrochen, die Sensoren werden nicht neu gestartet und der weitere Code wird ausgeführt.
Apropos: mich würde mal interessieren, wie du das "Schleife wird abgebrochen" genau feststellst/schlussfolgerst. Woher weißt du, dass die Schleife abbricht, und nicht einfach nur das i2c_start fehlschlägt?

uffi
18.03.2011, 15:24
Weil es schon beim ersten Ausführen der Schleife auftritt. Dies erkennt man daran, dass nach dem Reset zuerst die Sensoren über I2C general Command an Adresse 0x00 gestartet werden. Danach wird die Schleife das erste Mal ausgeführt, Antwort ist mit 0x0F im erwarteten Bereich, dieser Wert ist auch auf dem LCD zu sehen. Bei i=1 wird der zweite Sensor adressiert, die Antwort ist 0x02 (was nicht erwartet wird, da der US Sensor so dicht gar nicht messen kann), dieser Wert wird auf dem LCD nicht mehr ausgegeben. Als nächstes wird das Sensorboard2 addressiert und ausgelesen. Das ist jedenfalls auf dem I2C Bus und auf dem LCD zu sehen.

Zur Info: Der Logik Analyser wird mit der SDA Leitung auf negative Flanke getriggert und der Baustein wird aus dem Reset losgelassen.

Dass die Schleife abgebrochen wird, merke ich daran, dass gar nicht mehr versucht wird, mit i=2 den 3. Sensor abzufragen. Ein entsprechendes I2C Read Kommando an Adresse 0xE4 (bzw. 0xE5, da es ein read ist) wird vom I2C Master nicht mehr ausgegeben.

sternst
18.03.2011, 15:46
Darf ich daraus schließen, dass du LA-Protokolle von jeweils der kompletten I2C-Kommunikation hast? Poste die bitte mal (auch wenn ich nicht so der I2C-Experte bin). Und baue doch mal ein paar Marker in den Code ein, die dann auch auf dem LA zu sehen sind. Z.B. in der For-Schleife als erstes einen Port-Pin auf High und als letztes wieder auf Low setzen (um zu sehen, ob die Schleife über einen unzulässigen Pfad verlassen wird). Und nach der Schleife den Wert von i ausgeben lassen.

Wenn die Schleife tatsächlich abgebrochen wird, sehe ich nur die Möglichkeit eines Fehlers im I2C-Code oder dass i irgendwo korrumpiert wird.

Ergänzung: oder im LCD-Code natürlich ;-)

uffi
18.03.2011, 16:01
o.k. stelle ich am Wochenende ein.

uffi
22.03.2011, 08:47
So, hab nun nochmal die i2c-Signale am Logik-Analyser aufgezeichnet für drei Fälle. Für alle drei Fälle ist die Startsequenz auf dem i2c Bus identisch, siehe Datei i2c_first_start.png. Nun die 3 Fälle:

1. ohne FOR-Schleife US-Sensoren einzeln abgefragt und Messung neu gestartet: das ist die Referenz, alles läuft wie es soll, siehe Dateien i2c_first_meas.png und i2c_second_start.png.

2. mit FOR-Schleife von i=0 bis i=2 alle US-Sensoren abgefragt, er versucht noch den 2. Sensor zu lesen, aber die Schleife wird nicht weiter ausgeführt, siehe Datei i2c_first_meas_error.png.

3. wie Fall 2, bloß noch einen Marker eingefügt nach der LCD Ausgabe, bei dem der Wert von i auf den i2c Bus ausgegeben wird. Dies ist bei i=0 auch der Fall, aber i=1 wird nicht mehr ausgegeben, d.h. die Schleife wird gar nicht bis dort ausgeführt, siehe Datei i2c_first_meas_error_marker.png.

Der Code (mit jeweils auskommentierten Sequenzen) ist ebenfalls beigefügt: allrounder.c

Bitte schaut nochmal drauf und gebt mir Tipps, was der Fehler sein könnte mit der Ausführung der FOR-Schleife. Eigentlich sehe ich im Moment nur die Erklärung, dass bei i=1 die Abfrage des 2. US Sensors mit busy[1]=... dazu führt, dass dieser noch als busy angesehen wird (dies ist auch bei allen folgenden Abfragen der Fall [Ausführung der großen while Schleife] und die Sensoren werden nie mehr neu gestartet mit einer Messung). Aber warum? Denn im Fall 1 ohne FOR Schleife ist er ja nicht busy.

Hier der Code für Fall 1 (ohne FOR-Schleife, wird fehlerfrei abgearbeitet):

busy_US[0] = i2c_start(US_left + I2C_READ);

// address I2C device ultrasonic sensor with read access
if (busy_US[0] == 0)
{
distance[0] = i2c_readNak(); // read one byte
i2c_stop(); // release I2C bus

utoa(distance[0], buffer, 10);

// move cursor to position on line 0
lcd_gotoxy(10,0);
// put string to display (line 0)
lcd_puts(buffer);
lcd_puts(" ");
}

else
{
i2c_stop(); // release I2C bus
}

busy_US[1] = i2c_start(US_front + I2C_READ);

// address I2C device ultrasonic sensor with read access
if (busy_US[1] == 0)
{
distance[1] = i2c_readNak(); // read one byte
i2c_stop(); // release I2C bus

utoa(distance[1], buffer, 10);

// move cursor to position on line 0
lcd_gotoxy(14,0);
// put string to display (line 0)
lcd_puts(buffer);
lcd_puts(" ");
}

else
{
i2c_stop(); // release I2C bus
}

busy_US[2] = i2c_start(US_right + I2C_READ);

// address I2C device ultrasonic sensor with read access
if (busy_US[2] == 0)
{
distance[2] = i2c_readNak(); // read one byte
i2c_stop(); // release I2C bus

utoa(distance[2], buffer, 10);

// move cursor to position on line 0
lcd_gotoxy(18,0);
// put string to display (line 0)
lcd_puts(buffer);
lcd_puts(" ");

i2c_start(US_general + I2C_WRITE);
// address I2C device ultrasonic sensor with write access
i2c_write(Start_US); //start new ultrasonic measurement
i2c_stop(); // release I2C bus
}

else
{
i2c_stop(); // release I2C bus
}


Hier der Code für Fall 2 & 3 (mit FOR-Schleife, bricht bei i=1 ab):

// select display
lcd_select(0);

for ( i = 0 ; i < 3 ; i++ )
{
// check if ultrasonic sensor is busy
busy_US[i] = i2c_start(US_left + (2*i) + I2C_READ);

// address I2C device ultrasonic sensor with read access
if (busy_US[i] == 0)
{
distance[i] = i2c_readNak(); // read one byte
i2c_stop(); // release I2C bus

utoa(distance[i], buffer, 10);

// move cursor to position on line 0
lcd_gotoxy(10+(4*i),0);
// put string to display (line 0)
lcd_puts(buffer);
lcd_puts(" ");

//marker: put out i on i2c bus
i2c_start(i);
i2c_stop();

if (i==2)
{
i2c_start(US_general + I2C_WRITE);
// address I2C device ultrasonic sensor with write access
i2c_write(Start_US); //start new ultrasonic measurement
i2c_stop(); // release I2C bus
}

}

else
{
i2c_stop(); // release I2C bus
}
}

Danke und Gruß, Dirk.