I2C - Programmierung

Hallo Arduino-User,

ich möchte I2C-Module verwenden, um Lichtsignale einer Modellbahn anzusteuern. Soweit so gut.
Jetzt habe ich pro I2C-Modul mehrere Lichtsignale, möchte aber nur bei einem von Grün auf Rot wechseln (also z.B. A0 auf Low, A1 auf High), die anderen Ausgänge sollen ihren Zustand behalten...
Jetzt die Frage:
Kann ich - und wenn ja wie - einzelne bits des I2C-Moduls ansteuern, ohne die restlichen bits zu ändern? Oder muss ich vorher immer rücklesen...

Vielen Dank für Eure Antworten.
TSausM

Das kommt jetzt darauf an was das für I2C-Module sind.
Ich nehme an alle Lichter werden von deinem Programm gesteuert
dann weiß dein Programm zu jedem Zeitpunkt den Schaltzustand von jedem bit.
Da muss nix zurückgelesen werden. Wenn du ein Bit änderst dann macht das dein Programm. Und dann weiß dein Programm auch den Schaltzustand vor dem ändern und nach dem ändern.

Wenn es dein Programm nicht weiß dann musst du ihm eben einen "Notizblock" zur Verfügung stellen in Form einer Variablen in der der momentane Schaltzustand gespeichert ist, und dann wird nur der Inhalt dieser Variablen geändert und an deinen I2C-IO-Expander übertragen.

Das beste ist du postest deinen kompletten Code als code-section
Komplett heißt wirklich KOMPLETT auch wenn dein Code 2000 Zeilen hat.

vgs

merk dir den ausgegebenen Wert in einer Variable.
Wenn du dann später A2 auf LOW setzen musst, schreibst du zunächst nur das entsprechende bit in die Variable und sendest die Variable via I2C.

Danke für die Antworten.
Da muss ich mich doch mal mit der "Bit-Programmierung" beschäftigen

Je nach dem welchen I2C-Portexpander (z.B. MCP23017 o. PCF8574) gibt es passend Libraries, die auch wunderbar die einzelnen Bits anspricht. Damit gelingt es dir sicher ganz einfach deine Leds zum Leuchten zu bringen.
Z.B. diese und diese.

Offensichtlich kannst du es nicht, denn sonst müsstest du nicht fragen.
Und ich kann dir keine Antwort geben, da du dein Modul geheim hältst.

Was ist zu tun?
Das Datenblatt des Chips lesen, welcher sich auf dem Modul befindet.
Darin steht, was möglich ist, und wie man es tut.

mmmhhhh, das ist natürlich richtig, den Modul-Typ hatte ich nicht genannt: MCP23017.

Aber die Antwort von noiasca hat mich auf den Weg gebracht (bitwrite()). Damit kann ich - wenn ich es richtig verstehe - jedes Bit (--> jede LED) einzeln ansprechen und dann einmal pro loop auf den I2C-Bus senden. Danke.

Wenn Du die Adafruit_MCP23017_Arduino_Library verwendest, genügt mcp.digitalWrite(LED_PIN, HIGH); zum Schalten einer LED.

Mit mcp.digitalRead(LED_PIN); kannst Du den aktuellen Zustand auch lesen.

Eigentlich nur, wenn sich was ändert.

I²C funktioniert nur mit kurzen Leitungen, nicht über eine Modellbahnanlege. Außer Z und N im Koffer oder Tisch.

Du solltest dir schon die Zeit nehmen und alle Antworten durchlesen. Und bedenke, das programmieren des I2C zu lernen braucht auch Zeit.

Was schlägst du anstatt I²C-Bus vor?

ansonsten es gibt sogenannte I²C-Bus range-extender

vgs

Ich habe dazu keinen Vorschlag, da mir viel zu viele Informationen fehlen.

Vor meinem geistigen Auge eine H0- oder TT-Anlage, in der einen Ecke ein Arduino, in der anderen Ecke das Lichtsignal, dazwischen I²C könnte wegen der Entfernung problematisch werden.

Den I2C innerhalb der 20 cm (besser 10 cm) vom Arduino weg und dann von dort die Leitungen zu den LED, die sind ja weitgehend unkritisch. Oder gleich LED-Konstantsrom-Treiber mit I2C-Steuerung wenn es noch weiter wird. (z.B. PCA9685)

Gruß Tommy

Über welche Größenordnungen redest Du denn?
Wie groß ist die Platte/weiteste Entfernung und wieviele Kanäle denkst Du denn zu brauchen?

Also erst einmal vielen Dank für eure Antworten - die ich auch alle genau lese.
(ja, es ist richtig, auf einige Sachen hätte ich auch selbst kommen können)

Ich teste derzeit, wie weit ich mit dem I2C-Bus komme. Ein guter halber Meter ohne irgendwelche Schirmmaßnahmen funktioniert bisher ohne Probleme (mit einem Mega und 2 externen MCP23017). Und da ich mehrere lokale Steuerungen "über die Platte" verteilt habe, reicht mir das auch völlig aus.
Da die Signale aber schnell mal 5 einzeln anzusteuernde LED´s haben, reicht eben auch ein MEGA nicht mehr aus (4 Ausfahrtsignale mit Rangiersignal erfordern schon 20Pins nur für die Lichtsignale...). Deshalb die Idee mit dem I2C und den MCP23017.

Aber bestimmt nur so lange du keine Störungen von außerhalb bekommst.
Das können dei Loks oder andere Motoren sein. Oder aber Lampen im Raum wie z.b. Leuchtstoffröhren. Diese Störungen bringen deine I2C-Bus gern und empfindlich durcheinander. Das äußerst sich durch einfaches hängen bleiben des Controllers.

Mal drüber nachgedacht evtl. einen RS485 / alterntiv einen CAN ans Signal zu ziehen und dort mit nem Tiny die MCP zu füttern?

Die 50cm I2C halte ich auch für sehr grenzwärtig.

ja, daran habe ich schon gedacht, deshalb ja auch Testaufbau mit DCC-Signal und Loks und allem, was ich sonst als Störquelle finde. Wie geschrieben, bisher recht positiv.
Wenn es klemmt, dann müssen ggf. die LED-Zuleitungen länger werden - hier gibt es das Problem nicht - oder den BUS range-extender....

Naja, meist reicht auch eine Abschirmung.
Ich seh schon, du bist vorbereitet.

Dann ist ja mein Hinweis bei Dir gut aufgehoben.

DCC-Dekoder für Arduino sind Dir sicherlich auch bekannt. Ich möchte nur ein "Hätte ich das doch früher gewußt!" verhindern :slightly_smiling_face:

... ein bißchen schon, nur bei den gezielten Ansteuerung der einzelnen Pins bin ich völlig auf dem Schlauch gestanden....

ja, danke. Aber immer einen Schritt nach dem anderen :wink:. Eine DCC-Zentrale gibt es und ich "steuere" auch nur mit Arduino (Weichen, Gleisfreigaben usw.) .