i2c Typ ermitteln

Hallo,

ist es möglich (per i2c-Bus Scan) nicht nur die Adresse und damit mögliche angeschlossene Devices zu erkennen, sondern auch deren Typ?

Ich denke hier speziell an MCP23017, MCP23008 oder PCF8574(A).

Weiterhin möchte ich die gefundenen Devices [unabhängig des TRyps] in ein Array (dynamisch) packen, wie ist da der beste Weg?

Danke & Grüße Fly

Unmöglich! Der Standard sieht kein Erkennungsschema vor.

Und in der Regel weiß der Entwickler, was er da einsetzt. Warum weißt du das nicht?

Es ist keine Erkennung des I2C devices vorgesehen. Jedes Device hat einen bestimmten möglichen Adressbereich aber aus der verwendeten Adresse ist nicht eindeutig das Device ersichtlich. Auch kenne ich keine vollständige Liste er Adressräume der I2C devices.

Grüße Uwe

FlyingEagle: ist es möglich (per i2c-Bus Scan) nicht nur die Adresse und damit mögliche angeschlossene Devices zu erkennen, sondern auch deren Typ?

Ich denke hier speziell an MCP23017, MCP23008 oder PCF8574(A).

Wenn Du in einem Automobilforum posten würdest, könnte sich das dann wohl so lesen:

Ist es eigentlich möglich, bei einem an meiner Adresse in der Garage geparkten Auto die genaue Marke und das Modell zu erkennen? Ich denke hier speziell an Ford Focus, Opel Astra, VW Golf oder Mercedes A-Klasse.

Ein einfacher Scan mit den Augen zeigt mir ja nur, dass das Auto vier Räder hat, die alle bis auf den Garagenboden herunterreichen.

Kann man da vielleicht mehr herausbekommen, zum Beispiel den genauen Typ? :D

Antwort ja: Wenn Du einen Test machst, ob das Auto vier Räder hat und ob diese bis auf den Garagenboden herunterreichen, dann bekommst Du auch nur genau das heraus.

Und wenn Du andere Tests machst, kannst Du ggf. mehr herausbekommen.

Das sollte bei einem IC2-Gerät nicht viel anders sein: Wenn Du nur testest, ob ein Gerät vorhanden ist, dann bekommst Du auch nur das heraus. Und wenn Du etwas anderes herausbekommen möchtest, müßtest Du andere Tests machen. Die meisten Chips haben zum Beispiel einen Aufdruck auf dem Gehäuse, Du könntest als Test zum Beispiel ablesen, was da als Aufdruck auf das Gehäuse aufgedruckt ist.

Also speziell den MCP23008 könnte man dann beispielsweise am Aufdruck MCP23008 erkennen. |500x375

Das war ja einfach! :smiling_imp:

FlyingEagle: Ich denke hier speziell an MCP23017, MCP23008 oder PCF8574(A).

Ich würde versuchen durch gezielte Registerzugriffe den Chip zu ermitteln. Jetzt müsstest du dir das Datenblatt vornehmen um zu ermitteln auf welche Register du schreibend und lesend zugreifen kannst, die bei den anderen Chips anders reagieren würden oder gar nicht erst vorhanden sind. Ein Blick auf die Schaltung ist wichtig, dass nichts kaputt geht, in dem du z.B. einen Eingang zum Ausgang umdefinierst und den angeschlossenen Sensor dadurch beschädigst.

Also ich finde den Gedanken nicht so verwerflich, auch wenn ich über die Antworten wieder erfrischend schmunzeln konnte :)

Und unser fliegender Vogel fragt ja genau danach, ob noch mehr geht also nur Adresse. Vermutlich möchte er eine universelle Routine für alles was nicht bei 3 auf dem I2C-Baum ist. Oder auch was ganz anderes. Ob das mit Theseus' Ansatz geht ... probieren.

Naja, manche antworten sind schon sehr humorvoll, insbesondere der Autovergleich, aber so ist das ja auch nicht so ganz in der realität.

klar logisch weiß man (= ich) ja was man verbaut, aber

a) hat es durchaus seine berechtigung danach zu fragen - wie ich denke …
und
b) will ich den i2c herausführen und per kabel x-platinen miteinander im späteren verlauf verbinden und den bus so erweitern (und da kann ich im vorfeld ohne neuprogrammierung nicht sagen adresse 0xYY ist nun der typ

ja, es soll ein etwas universellerer ansatz sein, nehmen wir an ich verwenden den 23017, dann hat der 16 i/o, der 23008 hingegen nur 8. wenn ich nun “wüßte” im code, welcher chip nun auf 0x20 sitzt, dann könnte ich die entsprechend ansteuern - ohne hier brute-force-bank-check zu machen bspw.

die PCF sind ja ab 0x40 bzw 0x70 beim A und liesen sich so ja “einfach” auseinanderhalten. beide sind 8 i/o.

und da ich schon mal so am fragen bin … eine sache bereitet mir noch etwas kopfzerbrechen im hinblick auf den ram etc.

ich will die steuerbefehle via ethernet schicken, da bekomme ich einen string (bzw char), in dem sich an einer bestimmten stelle innerhalb des die adresse des anzusteuerenden chips befindet, wie komme ich an diese adresse ran ohne aufwendigstes split, instr oder replace o.ä.?

ich möchte auch nochmal freundlich auf meine 2. frage eingangs hinweisen.

FlyingEagle: ich will die steuerbefehle via ethernet schicken, da bekomme ich einen string (bzw char[]), in dem sich an einer bestimmten stelle innerhalb des die adresse des anzusteuerenden chips befindet, wie komme ich an diese adresse ran ohne aufwendigstes split, instr oder replace o.ä.?

Da musst du schon genau beschreiben wie der String aussieht.

Generell kann man hier sagen: verwende klassische C Strings (d.h. null-terminierte Arrays aus char) und nicht die Arduino String Klasse. Das hat den riesigen Vorteil, dass man die Strings in situ behandeln kann statt ständig neue String Objekte geliefert zu bekommen. Oder wenn man nach einem Teil-String such bekommt man nicht einen Index, sondern einen Zeiger den man direkt an eine Konvertierungs- oder Ausgabe-Funktion weiterreichen kann

ich möchte auch nochmal freundlich auf meine 2. frage eingangs hinweisen.

Völlig unterschiedliche Klassen kannst du nicht zusammen in ein Array legen. Sowas geht mit Polymorphie, aber dazu müssen die Klassen eine gemeinsame Oberklasse haben.

EDIT: gekürzt, da irrelevant, da Frage falsch verstanden

die sehen dann z.b. so aus /bla/foo/bar/0x20/pin = 1. 1 ist hier dann entsprechend der payload. diese werden als char[] aus der lib zurückgeliefert.

zur frage mit den adressen = byte in einem dynamischen array und der antwort von serenifly: hä? ;-) vielleicht habe ich mich da misverständich ausgedrückt, ich will nur die bytes - sprich die adressen - der i2c devices speichern. damit ich nicht jedesmal einen scan oder auf gut glück was machen muss.

 /bla/foo/bar/0x20/pin = 1.

Du kannst z.B. per strstr() nach "0x" suchen. Und dann entweder strtoul() nehmen, oder die die Hex -> Dezimal Funktion selbst schreiben. Bei nur zwei Ziffern ist das kein Problem.

Für etwas mehr Sicherheit kann man auch adr=0x20 senden. Dann sucht man genauso mit strstr() nach "adr=" und macht + 4 um auf die Zahl zu kommen.

zur frage mit den adressen = byte in einem dynamischen array und der antwort von serenifly

Sorry, da hatte ich dich falsch verstanden. Ich dachte irgendwie du wolltest ein Array aus verschiedenen Objekten.

Wo ist dann das Problem?

ich will nur die bytes - sprich die adressen - der i2c devices speichern

Die helfen dir keinen Millimeter weiter! Du brauchst auch den Type.

Warum machst du dir nicht einen hübschen I2C Scanner, mit Weboberfläche, wo du dann den Baustein-Type in einem Formular einträgst/auswählst?

Dazu solltest du deine Software so aufgebaut haben, dass es alle deine verwendeten Bauteine kennt und ansprechen kann....

@combie

den typ will/wollte ich an die außenwelt mitteilen, damit die weiß was an der adresse ist. der arduino selbst soll quasi nur dann den wire befehl entsprechend der eingabe auf den port ausgeben. die steuerbefehle welche bank etc. kriegt er von außen oder über funktionen die dann entsprechend des types des devices ausgelegt sind.

@serenifly mein problem ist das dynamische array, wie füllt man das auf, wenn man nicht weiß ob was drin ist (und es drinne bleiben soll und anderseits man nicht weiß wieviele elemente reinkommen werden)

wäre ein byte myArr[127] zu brutal im umgang mit den ressourcen auch wenn ich am ende vielleicht nur 2,3,4 elemente drin habe?

Du kannst auch dynamischen Speicher mit new/delete nehmen und die Anzahl der Elemente zur Laufzeit bestimmen. Davon wird hier zwar oft kategorisch abgeraten, aber wenn man das mit Bedacht einsetzt ist es keine Katastrophe.

Aber wie schon gesagt, rein die Adresse zu wissen bringt dir gar nichts, denn damit alleine kannst du noch nichts machen.

Mir entzieht sich deine Logik....

Ich gehe dann mal los, hole mir eine Tüte Chips, und beobachte was dabei raus kommt. Helfen kann ich dir so leider nicht.....

Aus meiner Sicht hast du erfrischend wenig Ahnung von I2C und vom Programmieren, und dabei hochtrabende Vorhaben, wenn nicht sogar Wolkenkuckucksheime. Das ist im Grunde nicht schlimm, kannst du ja auf Dauer ändern... Aber alles in allem scheint es mir so, als wäre das eine brisante Mischung.

Du kannst auch dynamischen Speicher mit new/delete nehmen und die Anzahl der Elemente zur Laufzeit bestimmen.

Davon wird hier zwar oft kategorisch abgeraten, aber wenn man das mit Bedacht einsetzt ist es keine Katastrophe.

;-)

@combie mag sein das ich in C/C++ wenig(er) ahnung habe, aber in anderen bereichen bin ich durchaus in der lage mir zu helfen. finde es etwas 'unfair' wenn nicht sogar schon fast beleidigend was du hier schreibst. wenn du mir "so" nicht helfen kannst, dann a) lass es und schreib hier gar nix oder b) [=besser] sag mir was du gern hättest und ich antworte soweit möglich.

ich habe zu keinem zeitpunkt um was vorgekautes gebeten, maximal den einen oder anderen schnippel oder schupps in ne richtung erhofft.

wenn ich die adresse ermittelt habe, was ja mit nem scan geht, will ich den z.b. per serial ausgeben und ein externes programm erhält den (idealerweise mit dem zusatz um welchen typ (8er/16er z.b.) es sich handelt. das externe programm kümmert sich dann soweit um den rest.

@serenifly könntest du mir bitte beispiele zu dem new/delete geben/zeigen?

... und was das reine "wissen" um die adresse angeht, nun ja, machen kann man damit schon recht viel, man kann sie entsprechend ansteuern oder eben wie schon mal einer schrieb auf ne bank testen etc. so ganz abwägig sehe ich das nicht.

Den Typ herauszufinden ist aber sehr schwierig. Der PCF8574 z.B. hat nicht mal ein Register das man auslesen könnte. Jeder Lese- oder Schreibvorgang geht da gleich auf die I/O Pins.

Und wenn du die Adressen an ein externes Programm weiterreichen willst, wieso musst sie dann zwischenspeichern?

sag mir was du gern hättest

Was soll das am Ende werden? (und beschreibe bitte nicht den Weg, den der ist ja höchstvermutlich falsch)

Dann kann man/ich dir evtl. eine Alternative bieten....

FlyingEagle: wäre ein byte myArr[127] zu brutal im umgang mit den ressourcen auch wenn ich am ende vielleicht nur 2,3,4 elemente drin habe?

Wenn ich das richtig sehen, unterstützen die drei Chips Adressen zw. 0x20 und 0x27. Also braucht das Array 8 Einträge-soviel Ressourcen sind das nicht.

Serenifly: Und wenn du die Adressen an ein externes Programm weiterreichen willst, wieso musst sie dann zwischenspeichern?

den punkt habe ich auch nochmal überdacht, ja eigentlich hast du recht. ich wollte die zwischenspeichern, damit ich bei einer anfrage "was hast du" eben kein neuer scan gemacht werden muss. aber ich glaube, am ende ist der scan schneller (gemacht).

@combie: an meinem arduino hängen per i2c n-platinen mit nem i/o-expander drauf dran. wenn ich nun z.b. einen 23017 gegen einen 23008 tausche, muss - wie bereits erwähnt - der schreibvorgang ein anderer sein. ich dachte nun daran sowohl den typ als auch die adresse auszugeben und/oder zwischenzuspeichern. den typ werde ich mir wohl abschminken können. daher muss ich dann bei der ansteuerung von außen eben quasi manuell den typ dabei geben (kenne ja prinzipiell die geräte). dachte mir man könnte das evtl. auch dynamisch(er) machen und das scannen und zurückgeben. woraufhin mein externes programm automatisch auswerten und entscheiden kann. so kann ich mir nur die adressen geben lassen, und mass dann ne map extern vorhalten. das programm auf den arduino soll flexibel auf die typen reagieren können, daher die frage nach dem typ. hoffe jetzt etwas genau gewesen zu sein.

Theseus: Wenn ich das richtig sehen, unterstützen die drei Chips Adressen zw. 0x20 und 0x27. Also braucht das Array 8 Einträge-soviel Ressourcen sind das nicht.

naja, das gilt für den mix 23017/23008, man kann aber noch die PCF und PCF.A dranhängen, dann sind es schon 24 :-)

und theoretisch könnte ja auch noch ein temp-seonsor o.ä. dranhängen. es gehen ja theoretisch bis zu 127 devices per se.

Der PCF8574 liegt auch zw 0x20 und 0x27. Was meinst du mit PCF-A?

Bis jetzt hattest du ja nur die Portexpander angeführt.