I2C an Raspberry Pi

Hi,

zu diesem Thema gibt es ja eigentlich genügend im Internet zu lesen, aber ich stell mich gerade irgendwie zu doof an. Ich will mit meinem Raspberry Pi von meinem Arduino Daten empfangen.

Code auf dem Arduino [unwichtige Zeilen entfernt]:

#include <Wire.h>

void setup()
{
  Wire.begin(20);                
  Wire.onRequest(sendData);       
}

void loop()
{
  delay(100);
}

void sendData()
{
  Wire.write("hello World");
}

i2cdetect liefert folgendes:

i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- 14 -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

und von i2cget bekomme ich:

i2cget -y 1 0x14
0x1a
i2cget -y 1 0x14
0xff
i2cget -y 1 0x14
0x1a
i2cget -y 1 0x14
0xff
...

0x1a und 0xff bekomme ich immer im Wechsel. Das kann ich beliebig oft wiederholen. Immer 0x1a und beim nächsten i2cget kommt 0xff.

Ich weiß gerade echt nicht mehr, woran das liegen soll…
Ist das ein Fehlercode für irgendwas?
Bin gerade ratlos…

Hat jemand eine Idee?

Hallo,

wenn man nach "i2c arduino raspberry pi" sucht gibt es hunderte Seiten mit Beispielen ...

ja, die gibt es, die habe ich mir auch angesehen. Und eigentlich ist mein Code ja so, das er funktionieren müsste. Also meiner Meinung nach...

Ich bin jetzt auch nicht mehr so der blutige Anfänger, sondern habe schon einige Sachen gemacht, aber hier stehe ich irgendwie auf dem Schlauch...

Die i2c-tools-Library ist auf dem Raspberry Pi installiert (i2cdetect geht ja) und der Arduino wird im Bus ja auch erkannt... Da kann doch die Verkabelung eigentlich nicht mehr falsch sein, oder? Sonst dürfte er doch gar nicht erkannt werden... Kann der Arduino kaputt sein? Ich werde es morgen mal mit einem anderen probieren.

Oder hab ich doch noch irgendeinen dummen Fehler drin, den ich schon seit Stunden nicht sehe?

Gibt jede xxx.write()-Anweisung nicht ausschließlich einzelne Bytes aus?

Tobinator:
j
Da kann doch die Verkabelung eigentlich nicht mehr falsch sein, oder? Sonst dürfte er doch gar nicht erkannt werden… Kann der Arduino kaputt sein? Ich werde es morgen mal mit einem anderen probieren.

Oder hab ich doch noch irgendeinen dummen Fehler drin, den ich schon seit Stunden nicht sehe?

Die Verkabelung scheint soweit richtig zu sein. Denn du gibst dem Arduino die Adresse 20 (DEZIMAL). Mit i2detect auf dem Raspberry liest du 14 (0x14 HEXADEZIMAL) aus. Das passt soweit.

Teste zurerst mal die Kommunikation mit einzelnen Chars. Also wie sth77 schon angemerkt mit Wire.write(‘H’). Keine Ahnung, ob die write Funktion auch überladen wird. Ansonsten gibt es kein Wire.printf(“x”).?

Edit: bei write wird die Funktion scheinbar überladen. Somit sind auch Zeichenketten a la Wire.write(“Hallo Welt”) möglich.

Danke erstmal für eure Antworten,

ich habe es jetzt erstmal mit einem Byte probiert, also:

Wire.write(0x55);

Angekommen ist 0x2A

0x55 = 85 (dezimal) = 0b01010101
0x2A = 42 (dezimal) = 0b00101010

also alles um eins nach rechts geshiftet.

Hat einer ne Idee, wie das passieren kann?

Ok, Fehler gefunden: Der Level-Converter war Schuld. Ich hab keine Ahnung warum, aber nachdem ich ihn ausgebaut habe, hat es funktioniert.

Also falls noch jemand das Problem hat: Level-Converter ausbauen. Wenn ich das richtig gelesen habe, ist das auch kein Problem, wenn der Raspberry Pi der Master ist.

Viele Grüße Tobias.

Warum sollte der Raspberry Pi Probleme haben, der Master zu sein? In den meisten Fällen wird dieser als Master betrieben, und wenn nicht, dann ist ein anderer Controller der Chef :grin:

Level-Converter ausbauen. Wenn ich das richtig gelesen habe, ist das auch kein Problem, wenn der Raspberry Pi der Master ist.

Auch wenn der Pi der Master ist, wird dennoch der Slave Daten auf den Bus legen. Also kommen die 5V am Pi an. Er wird daran sterben.

Wenn ich das richtig deute, dann ist der Atmega das einzige I2C-Device am RaspberryPi. Soweit der Atmel keine externen PullUp Widerstände auf dem I2C Bus hat, wird kein PegelWandler benötigt. Erst wenn diese zum Einsatz komen, ist der Wandler notwendig, ansonsten brauchst du in absehbarer Zeit einen neuen Raspberry oder nimmst den nächsten aus dem Regal.

Wie sieht dein Pegelwandler aus? Handelt es dabei um einen bidirektionalen Pegalwandler?

Warum sollte der Raspberry Pi Probleme haben, der Master zu sein? In den meisten Fällen wird dieser als Master betrieben, und wenn nicht, dann ist ein anderer Controller der Chef :grin:

Ist kein Problem, ich wollte nur sagen, das er der Master sein muss, damit ich keinen Pegelwandler brauche.

Wenn man man google befragt, bauen ca 50% den Wandler ein und 50% lassen ihn raus. Ich muss mal lesen, wie I2C genau funktioniert. Wenn der Master immer auf High hält und der Slave nur auf Low zieht, dann dürfte es ja kein Problem sein. Aber das ist nur eine Vermutung. Müsste man mal genau nachsehen.

Mein Pegelwandler war ein recht preiswertes Teil aus China, bidirektional, so in der Art wie der hier: http://www.ebay.de/itm/New-IIC-I2C-Logic-Level-Converter-Bi-Directional-Module-5V-to-3-3V-For-Arduino-/310965629892?&_trksid=p2056016.l4276

Ich hab jetzt nochmal flüchtig gegooglet und ich scheine nicht der Einzige mit diesem Problem zu sein. Wenn ich nur Daten vom Raspberry Pi an den Arduino sende, gibt es dieses Problem nicht... sehr mysteriös...

I2C ist ja ein Bus, weshalb ein Ausgang nur GND oder hochohmig sein darf. Der 5V-Pegel wird durch Pullup-Widerstände erzeugt. Im Playground habe ich dann was über Levelshifter gefunden, wobei man pro Spannung zwei Pullup-Widerstände benötigt: "The resistors are not a part of the level shifter. They are the pull-up resistors required by the I2C bus. In this case they have to be on both sides of the level shifter."

Theorie ist grau, möglicherweise hilft es Dir trotzdem. :)

Hallo agmue, dass findest du auch in den AppNotes von NXP mit etwas mehr Erklärung, falls interessant.

http://www.nxp.com/documents/application_note/AN10441.pdf

Das ganze ist für einschließtlich FastMode gut geeignet (400kbits). Sowas sollte für die meisten µC Anwendungen reichen. Bislang kann der Raspberry Pi (einschließlich 2) aufgrund von fehldenen Kerneltreibern nur 100kbits statt 400kbits. Wobei das könnte ich die Tage testen, ich bin gerade noch dabei, die lcd Routine in GCC zu schreiben (Funktionen sind mit RW etc alles schon eingearbeitet, aber nun geht es an die Bugs). Gibt bei dem Pi leider viele Sachen und Beispiele nur in Python (hier könnte ein Kotz-Smiley stehen).

Danke für den Link, ist Teil meines "Werkzeugkastens" geworden. Hätte ich den gekannt, hätte ich mir nicht selbst die Finger gebrochen.

nur mal so nebenbei gefragt : warum i²c und nicht einfach uart wenn du daten hin und her tauschen willst?

~Straw

Danke für eure Anmerkungen und den Link, der ist wirklich nützlich. Manchmal ist es echt zum kotzen, auf was man alles achten muss und womit man alles seine kostbare Freizeit verschwenden kann... Ich glaube, auf China-Importe werde ich demnächst verzichten. Wenn ich mal so zusammenrechne, wie viel Zeit ich schon mit sowas verschwendet habe... Da hätte ich mit arbeiten gehen ne ganze Menge Geld verdienen können und mir besseres Zeug kaufen können...

@strawmedia: Weil ich mit I2C mehr Erfahrung habe. Mit uart habe ich noch nichts gemacht. Würde ich da das 3,3V-5V-Spannungsproblem umgehen?

Zur Info, falls das nicht bekannt ist, mit U(S)ART ist die serielle Schnittstelle gemeint. Diese ist im Vergleich zum I2C/TWI Bus einiges einfacher (nicht auf die fertigen Arduino Funktionen bezogen). UART hat hier aber den Nachteil, dass es nur eine P2P Verbindung ist. I2C kann da schon mit mehreren Kommunizieren.

Die Pegelwandler kannst du hier auch nicht vernachlässigen. Müssen aber nicht für beide Richtungen ausgelegt sein. RPi TX → Ard Rx Transistorschaltung(kann ggf. auch weggelassen werden)
Ard TX → RPI Rx Zwingend Spannungteiler oder richtige Levelshifter nutzen.

Umgehen kannst du das ganze Problem, in dem du auf 16MHz und 5V am Atmega verzichtest. Ist bei den meisten Projekten absolut unnötig.