Forum: Mikrocontroller und Digitale Elektronik ALIX 6B2 und I2C-Bus mit PCF8574 mit voyage-Linux


von Thorn W. (dafatfairy)


Lesenswert?

Hallo zusammen,

ich bräuchte mal dringend Hilfe. Ich möchte mittels eines ALIX-Boards 
6B2 (PC-Engines) und einem dort installierten voyage-Linux 0.5.2 (kernel 
2.6.30) mittels des implementierten I2C-Busses mit einem PCF8574 
(Horter&Kalb - I2C-Ausgabe) kommunizieren.
Jetzt die Frage aller Fragen: Wie stelle ich das an?

Ich habe bereits einige Sachen ausprobiert - leider recht erfolglos.
Zuerst hatte ich mir die i2c-tools installiert (
1
apt-get install i2c-tools
). Ebenso die Kernel-Module i2c_dev und i2c_core.
Somit habe ich anscheinend mittlerweile ein Device namens /dev/i2c-0.
Wenn ich jetzt mit
1
i2cdetect -l
 mir die erkannten Bus-geräte anzeigen lasse, erhalte ich folgende 
Ausgabe:

i2c-0  smbus  CS5536 ACB0  SMBus adapter

Dann kann man ja mit
1
i2cdetect -y 0
 sich die Geräte auf dem Bus anzeigen lassen. Das sieht dann bei mir so 
aus:
1
WARNING! This program can confuse your I2C bus, cause data loss and worse!
2
I will probe file /dev/i2c-0.
3
I will probe address range 0x03-0x77.
4
Continue? [Y/n] y
5
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
6
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
7
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
8
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
9
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
10
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
11
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
12
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
13
70: -- -- -- -- -- -- -- --
Tja...und ich denke genau hier liegt der Hase im Pfeffer. Normalerweise 
sollte hier ja bei 0x42 (Hex für die ID 66) irgendetwas stehen ( siehe: 
http://ubuntuforums.org/showthread.php?t=1181192 - ca. Mitte).
Auch wenn ich manuell versuche mittels i2cget  i2cset  i2cdump 
irgendwelche Informationen auszulesen, schlägt dies fehl (Error: Read 
failed). Des Weiteren bekomme ich auf der Konsole(RS232), die 
anscheinend als stdErr fungiert, folgende Fehlermeldungen:

i2c-adapter i2c-0: bus error in state write , bzw.
i2c-adapter i2c-0: bus error in state read

Dieser Fehler wird für jeden Doppelstrich in der Tabelle ausgegeben. 
Daraufhin hatte ich bereits die Vermutung, dass die Pullup-Widerstände 
fehlen würden. Somit hatte ich dann zwei Potis in meinen Aufbau 
integriert (+3,3V zu SCL; +3,3V zu SDA) und diese auf ca. 1,1k 
eingestellt. Die Fehlermeldungen konnten somit zwar unterbunden werden, 
aber meine Tabelle sah immer noch unverändert aus. Nachdem ich mir dann 
nochmal das Board des 6B2 genauer angesehen habe, konnte ich am Port des 
I2C zwei kleine SMD-Widerstände entdecken, die laut PC-Engines die 
Pull-Up-Widerstände darstellen. Somit habe ich die Potis wieder entfernt 
(allerdings sind somit die Fehlermeldungen auch wiedergekommen). Noch 
ein Wort zu den Leitungslängen - ich arbeite hier mit einer Buslänge von 
ca. 30cm. Allerdings habe ich die Kabel der einzelnen Busteilnehmer 
zusammen auf eine Experimentierplatine gesteckt - soll heißen: es ist 
keine "klassische" Busverdrahtung (von Peer zu Peer zu Peer zu Peer...). 
Aber ich denke, dass ich mir bezüglich irgendwelcher etwaigen 
Signal-Reflektionen keine Gedanken machen muss (wie gesagt...30cm max.).
Nachdem ich hier nicht so recht weiterkam, versuchte ich den Ansatz per 
C-Programmierung. Dabei orientierte ich mich an dieser Dokumentation ( 
http://www.mjmwired.net/kernel/Documentation/i2c/dev-interface )
Das sah dann bei mir so aus:
1
#include <stdio.h>
2
#include <linux/i2c-dev.h>
3
#include <linux/types.h>
4
#include <sys/ioctl.h>
5
#include <fcntl.h>
6
#include <sys/stat.h>
7
8
int main (int argc, char *argv[])
9
{
10
  int file;
11
  int adapter_nr = 0;
12
  char filename[20];
13
14
  snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);
15
  file = open(filename, O_RDWR);
16
  if (file < 0){
17
    /* Errorhandling */
18
    printf("Kann /dev/i2c-%d nicht oeffnen.\n", adapter_nr);
19
    return(1);
20
  }
21
22
  int addr = 0x42;
23
  if (ioctl(file, I2C_SLAVE, addr) < 0){
24
    /* Errorhandling */
25
    printf("Kein Kontakt zu ID %d.\n", addr);
26
    return(1);
27
  }
28
29
  __u8 reg = 0x10; /*Device register to access*/
30
  __s32 res;
31
  char buf[10];
32
33
  /* i2c-read*/
34
  if (read(file, buf, 1) != 1){
35
    /* Error i2c-transaction*/
36
    printf("i2c-read fehlgeschlagen\n");
37
  }else{
38
    /* buf[0] contains read-Byte */
39
    printf("Ausgabe: %s\n", buf[0]);
40
  }
41
cd /roo
42
  return(0);
Hier verlässt er mich dann mit "i2c-read fehlgeschlagen"

Weiter Recherchen haben dann ergeben, dass es wohl für den PCF8574 
I2C-Controller ein eigenes Kernel-Modul gibt ( pfc857x ). Einige Infos 
habe ich hier dazu gefunden ( 
http://www.mjmwired.net/kernel/Documentation/i2c/chips/pcf8574 ).
Dort heißt es dann ja, dass der Chip "fies und gemein" ist, da er 
anscheinend nicht gefunden werden kann und dass man beim Laden des 
Kernels durch den Parameter force=<irgendwas> den Bus und die ID 
übergeben soll. Wie dieser Parameter aber dann wirklich heißt, bleibt 
ein großes Geheimnis. Ich hatte mal einen Versuch mit
1
modprobe pcf857x force=0,0x42

gemacht, allerdings gab es dann im stdErr nur den Hinweis, dass dieser 
Parameter (force) ungültig sei.
Ich muss gestehen, dass ich auch noch nicht so wirklich geblickt habe, 
ob ich das Kernel-Modul für den PCF857x überhaupt brauche. Ziel ist es 
ja eigentlich, später per Programmierung (ob Shell oder C ist mir 
ziemlich egal) mit den E/As interagieren zu können. Für mein Verständnis 
wir diese Kommunikation ja über den I2C-Controller des CS5536 gehen. Dem 
gebe ich dann doch die ID des Gerätes , mit dem ich kommunizieren will, 
und dieser gibt diese Inforamtion dann auf die Busleitung, oder? 
Weswegen muss der kernel dann wissen, wie er mit einem PCF8574 zu 
kommunizieren hat?

Nun...ich muss gestehen, dass ich an einer Stelle angelangt bin, wo ich 
ein wenig ins Straucheln gerate, da mir die Ideen ausgehen.
Ich möchte noch anmerken, dass ich außer dem PCF8574 auch noch zwei 
weitere I2C-Chips an dem Bus habe, die ebenfalls nicht erkannt werden ( 
PCF8591 (analog E/A); LM75 (Thermosensor)). Ich hatte auch schon 
versucht die Module einzeln an das Board anzuschließen - ohne Erfolg.
Eingangs hatte ich mit einem RS232-zu-I2C-Konverters (Horter&Kalb) 
bereits mit den Komponenten problemlos kommunizieren können (da gab es 
ja diese Excel-Demo-Applikation).

Nun, ich will das Vorangegangene nochmal in einem Wort zusammenfassen:

HILFE!

Schöne Grüße

von Εrnst B. (ernst)


Lesenswert?

Vorneweg: Sicher dass du den richtigen I2C-Bus benutzt? Deiner hört sich 
so an, als würde er vom "AMD Geode™ CS5536 Companion Device" 
bereitgestellt, gibt es evtl. einen zweiten I2C-Bus?

von Thorn W. (dafatfairy)


Lesenswert?

Nein. Das ist der einzige I2C-Bus auf dem Board.

von Εrnst B. (ernst)


Lesenswert?

Thorn W. schrieb:
> Nein. Das ist der einzige I2C-Bus auf dem Board.


Ja, ist mir beim Schaltplanüberfliegen auch grad so vorgekommen.

Hast du ein Oszi (notfalls LED+Widerstand) um mal zu sehen, ob sich an 
den Leitungen überhaupt was tut?

von Thorn W. (dafatfairy)


Lesenswert?

Tjoa...na da brat mir doch einer ´nen Elch.

Da habe ich es gut mit dem Board gemeint und wollte verhindern, dass es 
durch etwaige höhere Ströme beschädigt wird. Zwecks dessen hatte ich dem 
I2C eine separate Spannungs/Stromversorgung spendiert. Das war dann wohl 
nicht so gut. Nachdem ich die Platinen direkt (wie vorgesehen) an das 
Board angeschlossen habe, klappt es auch mit der Kommunikation.
Allerdings habe ich jetzt ein anderes Problem. Das Board mit den DIs 
scheint nicht mehr genug Spannung für den Betrieb zu bekommen. Die 
Platinen sind für 5V ausgelegt, das ALIX liefert aber nur 3,3V. Bei den 
DOs funktioniert das. Das LM75 scheint da auch nicht so empfindlich zu 
sein. Aber die analoge KArte und die DIs scheinen mit den 3,3V ihre 
Probleme zu haben.
Hat ggf. jemand eine Idee, wie ich die Module fremdspeisen kann? 
Vielleicht kann ich ja auch...hmm...ich habe da gerade ein 
Verständnisproblem. Wenn ich das Datenblatt des PCF8574 richtig 
interpretiere, dann haben diese ICs eine Versorgungsspannung von min 
2,5V und max 6V. Das Platinenlayout ( 
http://www.horter.de/i2c/i2c-eingabe/eingabe_2.html ) besagt ja, dass 
mein V-DD direkt an dem IC anliegt. Allerdings geht dort ebenfalls ein 
Kondensator ab und läuft auf GND?! Was bewirkt das? Dient diese 
Schaltung irgendwie der Spannungsanpassung?

von Andreas F. (aferber)


Lesenswert?

Auf dem fünfpoligen Header für die zweite serielle Schnittstelle (direkt 
neben dem I2C-Header) ist auf Pin 5 auch +5V verfügbar. Damit betreibe 
ich hier am Alix 2D13 ein LCD mit I2C-Schnittstelle, funktioniert 
wunderbar. In meinem Fall kommt das Display auch mit einem I2C-Pegel von 
3,3V klar (natürlich darfst du keinen Pull-Up auf 5V anbringen, das mag 
der CS5536 dann nicht!). Falls das bei dir nicht der Fall ist, brauchst 
du noch einen Pegelwandler für den I2C-Bus.

Andreas

von Thorn W. (dafatfairy)


Lesenswert?

Das mit dem Pegelwandler klingt erst einmal sehr spannend. Das werde ich 
mir morgen mal in Ruhe ansehen.
Ich habe das jetzt vorläufig so gelöst, dass ich den V-DD des GAL20V8 
von der restlöoichen Spannungsversorgung der Platine separiert habe und 
dann die externe Speisespannung (sind bei mir 5V) für die DIs an diesen 
Pin (Pin 24) angelegt habe. Somit ging die Platine einwandfrei in 
Betrieb.
Es scheint somit wirklich so zu sein, dass die PCF857x-ICs mit 3,3V 
betrieben werden können. Kann ich das eigentlich bedenkenlos so laufen 
lassen, oder besteht da irgendeine Gefahr, dass da schlimme Dinge 
geschehen?

Ach ja - wegen der modprobe-Geschichte vom Anfang - mich würde wirklich 
mal interessieren, ob das jemand erfolgreich zum Einsatz bringen konnte 
und vor allem wie!?

Danke an dieser Stelle erst einmal an die Helfenden. <thumbsup>

von Nico K. (brainhunter)


Lesenswert?

ich hab einen PCF9515 I2C Puffer schonmal als Levelshifter an einem alix 
verwendet (jedoch ein alix.1d wobei das ja egal ist...). läuft wuderbar!
falls jmd interesse hat:
http://nota-lan.de/wiki/index.php/I2c_-_1-Wire_Wandler

von Thorn W. (dafatfairy)


Lesenswert?

Ich habe da zu den Pegelanpassungen nochmal eine Frage. Wenn mein 
I2C-Master auf dem Mainboard mit 3,3V arbeitet und dort auch mit einem 
Client kommuniziert, kann ich dann den bestehenden Bus zwischendrin 
einfach mit einem Pegelwandler mit einer höheren Spannung versorgen? 
Lässt sich das auch kaskadieren (warum auch immer man das wollen 
sollte)?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Da bietet sich ein PCA9306 an.

von Andreas F. (aferber)


Lesenswert?

Thorn W. schrieb:
> Ich habe da zu den Pegelanpassungen nochmal eine Frage. Wenn mein
> I2C-Master auf dem Mainboard mit 3,3V arbeitet und dort auch mit einem
> Client kommuniziert, kann ich dann den bestehenden Bus zwischendrin
> einfach mit einem Pegelwandler mit einer höheren Spannung versorgen?

Natürlich, der Pegel vor dem Wandler bleibt ja auf 3,3V. Es ist ja 
gerade der Sinn eines Pegelwandlers, dass er auf beiden Seiten 
unterschiedliche Pegel hat, Devices auf dem Mainboard "sehen" also 
nachwievor nur 3,3V.

> Lässt sich das auch kaskadieren (warum auch immer man das wollen
> sollte)?

Du meinst z.B. 1,8V <-> 3,3V <-> 5V?

Das kommt auf den Pegelwandler an. Mit dem PCA9515 z.B. geht es nicht 
(Details siehe Datenblatt), mit dem PCA9306 dagegen geht es.

Mit der Simpelvariante miteinem MOSFET aus der Philips-Application-Note 
wäre ich vorsichtig, da der nach low schaltende Ausgang da dann schon 
den Strom von 3 Pull-Ups "wegziehen" müsste.

Andreas

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.