ich wurschtel mich gerade durch meinen Code, also nicht böse sein wenn das nicht 100% der Norm entspricht.
Zu meinem Problem, ich habe einen Teensy4.1, am I2C habe ich 4 bzw. 5 PCF8574A/T und einen eeprom, die PCF haben ja je nach Typ haben die eine andere Adresscodierung, was ich noch gelöst bekomme.
Nun möchte ich Prüfen ob alle Teilnehmer da sind, aber irgendwie komme ich da nicht sinnvoll weiter.
Ich habe den I2C_Scanner bisschen umgeschrieben, das die Zuweisung der Adressen funktioniert.
Ich hänge einfach mal den Codeschnippsel an, vielleicht hat einer eine andere Lösung.
Warum nimmst Du nicht erst mal den originalen I2C-Scanner und lässt Dir einfach die Adressen anzeigen, die er findet?
Ansonsten solltest Du zu Deinem Code schon ansagen, was passt und was nicht.
der Scanner findet die Adressen alle, das passt soweit, auch die richtige Zuweisung.
Alle Teilnehmer sind HW Seitig andressiert, nur gibt es bei den PCF8574 zwei typen mit unterschiedlichen Adressbereichen, deswegen die Zuweisung.
Ich werde den code der einfachheithalber noch kommentieren, da gebe ich dir recht.
Wenn er alle Adressen richtig findet, wo ist dann Dein Problem?
Du musst nur wissen, welcher IC zu welcher Adresse gehört. Dazu im Zweifel eine LED (mit Vorwiderstand) an dem Baustein an Pin 0 ansteuern.
Wobei die Zuordnung ja bereits durch die HW-Beschaltung klar sein sollte.
Kommentare dürften da wenig bringen oder ich verstehe Dein Problem nicht.
zum Hintergrund, das wird eine Ansteuerung für eine Endstufe, ich habe eine Bootroutine, die soweit alle Parameter prüft, wenn jetzt ein I2C Teilnehmer fehlt, soll die Endstufe in den Protect gehen.
Ich hatte den fall, das ein Out Teilnehmer aufgrund einer kalten Lötstelle nicht da war, man merkt das dann erst im Betrieb, wo es zu spät sein könnte, deswegen will ich wissen ob die Adressen vergeben/ gefunden worden.
Aber du weist doch welche pcf typen du verbaust. Entweder mit a oder ohne. Daher sind auch die Adressen klar. 27 oder 3f. Das ändert sich ja nicht zufällig
Und dann bei jeder gefundenen Adresse das Array durchgehen und bei Übereinstimmung found auf true setzen. Wird die Adresse nicht gefunden --> Error.
Am Ende über alle Elemente drüber gehen und wenn bei einem found == false ist --> Error.
Das erscheint mir übersichtlicher. Codefragment nicht getestet, nur als Denkanstoß.
@KeBeNe
wozu scannst du 127 addressen wenn dich eh nur ein paar wenige interessieren?
Vorschlag:
Man sucht ganz explizit nach einem PCF. Wenn error, sucht man die Alternativ-Adresse.
Ist die auch nicht da - kann man eh schon abbrechen. Es fehlt was.
Der Code ist keine Schönheit *), aber imho geht das in die richtige Richtung.
mit einem 0x3F und ein paar auskommentierten Zeilen erfolgreich getestet:
Dann sollte man konsequent die durchnummerierten Variablen durch Arrayelemente ersetzen, auch die beiden möglichen Adressen (struct).
Bei dem Codemonster sieht doch in spätestens 4 Wochen keiner mehr durch.
Dann würde ich, wie schon geschrieben, nicht 127 Adressen scannen, sondern die notwendigen überprüfen. Idealerweise sollte das dann auch während des Programmlaufs geschehen, eine kalte Lötstelle oder andere Fehler können jederzeit auftreten. Getestet mit DS3231 und EEPROM:
#include "Wire.h"
enum {DS3231_I2C_ADDRESS, EEPROM_I2C_ADDRESS};
const uint8_t adresse[] = {0x68, 0x50};
uint8_t fehler = 0;
void setup()
{
Wire.begin();
Serial.begin(115200);
delay(500);
Serial.println("\nStart ...");
for (auto &a : adresse)
{
Wire.beginTransmission(a);
if ( Wire.endTransmission() ) fehler = a;
}
}
void loop()
{
if (fehler)
{
Serial.print(F("I²C Fehler Adresse 0x"));
Serial.print(fehler, HEX);
Serial.println(F("\nProgramm angehalten!"));
while (1);
}
displayTime(); // display the real-time clock data on the Serial Monitor,
delay(1000); // every second
}
void displayTime() {
byte second, minute, hour;
readDS3231time(&second, &minute, &hour); // retrieve data from DS3231
char buf[10] = {'\0'};
snprintf(buf, sizeof(buf), "%02u:%02u:%02u\n", hour, minute, second);
Serial.print(buf);
}
void readDS3231time(byte *second, byte *minute, byte *hour)
{
int a = adresse[DS3231_I2C_ADDRESS]; // mit int ist die Bibliothek glücklich!
Wire.beginTransmission( a );
Wire.write(0); // set DS3231 register pointer to 00h
if ( Wire.endTransmission() ) fehler = a;
Wire.requestFrom(a, 3);
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f);
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return ( (val / 16 * 10) + (val % 16) );
}
nur mal eine Randbemerkung. Der gültige 7Bit Adressbereich liegt zwischen 0x08 und 0x77. Außerhalb dessen kann das ansonst zu unschönen Effekten und langer sinnfreier Fehlersuche führen.
Das Problem vom TO verstehe ich auch nicht. Man kennt die Adressen die man selbst durch Bausteinbeschaltung festgelegt hat. Wenn die alle vom Scanner gefunden werden ist alles i.O. Welche Adresse welcher Baustein hat ist vorher schon bekannt. Nur wenn eine Adresse fehlt oder gar eine Adresse zu viel auftaucht hätte man ein Problem.
Das heißt einfach nicht alle 128 Zahlen, die man mit 7 Bit darstellen kann können als I2C Adresse verwendet werden.
16 der 128 möglichen Adressen sind für Sonderzwecke reserviert.
siehe:
PCF8574 hat 8 Adressmöglichkeiten
PCF8574A hat weitere 8 Adressmöglichkeiten
Ein EEprom je nach Modell hat bis zu 8 Adressmöglichkeiten.
Also mußt Du max 24 Adressen abfragen. Da Du aber nur 4 /5 PCF8574x Bausteine verwenden willst weißt Du welche Adressen Du verwenden / Einstellen willst. Also beschränkt sich die Abfrage auf 8/10 Adressen für die Expander und 1 für das EEprom.
danke für die vielen Guten Ideen, manchmal sieht man den Wald vor lauter Bäumen nicht.
Der Einwand mit dem scannen der 127 Adressen ist vollkommen berechtigt und ich werde mir die Sache mit dem struct genau ansehen.
Dazu benötige ich 1-2 tage Zeit, da ich dieses "kleine" Projekt so nebenbei mache.
Ich bin eher der HW Entwickler als SW´er, also entschuldigt meinen Code, der ist weit von perfekt entfernt.