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 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:
PHP-Code:
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
Code:
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// 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
Lesezeichen