Welchen Abschnitt im Datenblatt verstehst du nicht?
MfG Klebwax
Hallo miteinander,
ich spiele seit gestern zum ersten Mal mit einem i2c-fähigen Sensor.
Dazu habe ich ihn über einen Raspberry Pi angeschlossen und werte ihn über die GPIO-Pins aus.
Ich habe einen Codefetzen im Netz gefunden, der auf den tmp102 ausgerichtet war, mit aber auch die Temperatur des tmp100 ausgibt:
Laut Datenblatt soll der tmp100 ein einstellbare Auflösung haben. Aber ich bin noch nicht wirklich dahinter gestiegen, wie ich die Auflösung einstellen kann.Code:#include <stdio.h> #include <stdlib.h> #include <linux/i2c-dev.h> #include <fcntl.h> #include <string.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int main(int argc, char **argv) { unsigned int temp = 0; unsigned char msb, lsb; int fd; // File descritor char *fileName = "/dev/i2c-1"; // Name of the port we will be using int address = 0x4f; // Address of TP102 unsigned char buf[10]; // Buffer for data being read/ written on the I2C bus if ((fd = open(fileName, O_RDWR)) < 0) { // Open port for reading and writing printf("Failed to open I2C port\n"); exit(1); } if (ioctl(fd, I2C_SLAVE, address) < 0) { // Set the port options and set the address of the device we wish to speak to printf("Unable to get bus access to talk to slave\n"); exit(1); } buf[0] = 0; // This is the register we wish to read from if ((write(fd, buf, 1)) != 1) { // Send register to read from printf("Error writing to I2C slave\n"); exit(1); } if (read(fd, buf, 1) != 1) { // Read back data into buf[] printf("Unable to read from slave\n"); exit(1); } else { for (;;) { msb = buf[0]; if (read(fd, buf, 1) != 1) { printf("Unable to read from slave\n"); exit(1); } else { lsb = buf[0]; temp = (msb<<8) | lsb; temp >>= 4; printf("Temp: %f \n",temp*0.0625); printf("Raw: %f \n\n", temp*1.00); usleep(1000000); } } } return 0; }
Momentan kann ich nur Messwerte in 1°C-Schritten auslesen. Da der Sensor einen Messbereich von 180°C hat und mit 12Bit = 4096 Werten auflösen können soll, ergibt sich doch theoretisch eien Schrittweite von 180/4096 von 0.0439453125°C.
Allerdings bekomme ich imemr nur volle Werte alla 23.06250°C oder 24.06250°C ausgegeben.
Die Zahl dieht verdammt nach dem Umrechnungsfaktor aus. Aber ohne den Multiplkator bekomme ich nichts ausgegeben.
Wie kann ich den Sensor nun dazu bewegen, feiner aufgelöste Werte auszuspucken?
Welchen Abschnitt im Datenblatt verstehst du nicht?
MfG Klebwax
Strom fließt auch durch krumme Drähte !
Puh, da gibts mehrere Denkschwierigkeiten.
Das wären einmal die Bitoperatoren im Code
Und dann gehts im Datenblatt los auf Seite 5 unten:Code:msb = buf[0]; ... lsb = buf[0]; temp = (msb<<8) | lsb; temp >>= 4;
Temperaturregister:
P1: 0 P0: 0
Read only
...12-bit read only register
Die Table 3, 4 & 6 sagen mir überhaupt nichts
Also liefert der Sensor eigentlich schon die ganze Zeit 12-bit-Werte? Oder muss ich das erst mit Hilfe der Tabelle 6 einstellen, da der Sensor ja 9-12 Bit liefern könnte?
Hmmm...okay, auf 12-Bit stellt man m.H. der Tabelle 7. Aber wie teile ich das dem Sensor mit?
Btw: Wenn ich nen Rohwert von buf[0] ausgebe, bekomme ich was, das ich weder lesen noch benennen kann. Ein Rechteck mit scheinbar 4 Zahlen drin.
Geändert von Cysign (05.04.2013 um 16:04 Uhr)
Der Ablauf sieht so aus:
für Lesen:Code:Start Adresse senden (beim TMP100 und ADD0 und ADD1 auf 0V => 10010000 => Hex 90) Pointerregister senden Variable schreiben Stopp
Wenn du jetzt also nur die Temp lesen willst schreibst du:Code:Start Adresse senden (beim TMP100 und ADD0 und ADD1 auf 0V => 10010000 => Hex 90) Pointerregister senden Repeated Start (mit Adresse Hex 91 => durch R/W Bit) Variable lesen immer mit ACK bestätigen, Ausnahme letztes Byte dort mit NACK abschließen Stopp
Mit diesem Code hast du 9Bit Auflösung, wenn du 12Bit brauchst/willst musst du das zuerst im Configurationregister einstellen (einmal bei Programmstart)Code:Start Adresse Pointer (0x00 => 0000 0000) repeated start Highbyte lesen Lowbyte lesen stopp
Der Ablauf sieht so aus:
Das lesen funktioniert dann wie oben.Code:Start Adresse Pointeradresse (0x01 => 0000 0001) Configbyte schreiben (0x60 => 0110 0000) Stopp
MfG Hannes
Wenn ich ehrlich bin, ist mir das noch ne Ecke zu hoch.
Kannst du diene Erklärung vielleicht ein bisschen anfängerfreundlicher formulieren?
Es hapert schon daran, das ich nicht weiß, was ich für einen Rückgabewert bekomme.
Wenn ich buf[0] einfach ausgebe, bekomme ich etwas, das aussieht wir ein Rechteck mit 4 Ziffern drin.
Ist das ein Byte, das mittels lsb und msb in Binärcode umgeschrieben wird?
Können wir den Code vielleicht mal auseinander nehmen?
Hier wird festgelegt, dass auf ic2 zugegriffen wird.Code:(fd = open(fileName, O_RDWR)
Was bedeutet das O_ vor dem ReadWrite?
ioctl = input output control?Code:ioctl(fd, I2C_SLAVE, address)
Sensor dieser Adresse als I2C_SLAVE definieren
'buf' an Gerät 'fd' übergeben. Wofür steht die 1?Code:write(fd, buf, 1)
Steht buf also für ein Array, das 10 byte = 10 Register beinhaltet, die jeweils 8 bit groß sind?
Wieder diese 1. Hier wird das Array Buf also dann mit den Sensordaten gefüllt.Code:read(fd, buf, 1)
Code:msb = buf[0];Hier wird das erste Register, welches die Temperatur beinhaltet, aus dem Array gezogen und an lsb übergeben.Code:lsb = buf[0]; temp = (msb<<8) | lsb;
In temp wird der Rückgabewert gespeichert, der mittelsirgendwie umformatiert wird. Was geschieht hier genau?Code:(msb<<8) | lsb;
Und hier haben wir schon die nächste Transformation, die ich nicht verstehe.Code:temp >>= 4;
Wofür werden die Pina ADD0 und ADD1 benötigt?
Woher kommt der Wert Hex 90?
Wie kann ich die Hex-Codes alla 0x01, 0x00, etc. interpretieren bzgl. der am Anfang stehenden "0x"?
Das sind vielleicht ein paar viele Fragen...aber ich häng schon den ganzen Tag davor und werd nicht so wirklich schlau darauß.
Irgendwie hab ich kein wirklich vollständiges Tutorial gefunden.
Wie du den I2C Bus von deinem Controller (Raspberry) ansteuerst weiß ich nicht. Buf ist ein Array, das mit 10 definiert ist, das bedeutet 10Byte. Bei der Read bwz write Funktion könnte ich mir vorstellen das das so aufgebaut ist: z.B.
jedoch kann es auch etwas anderes bedeuten. Du solltest mehr darüber im Handbuch, Hilfe,... erfahren. Eventuell findest du mehr in der Headerdatei bzw C-Datei (werden C-Dateien verwendet?).Code:read(Ort von dem die Daten übernommen werden, Variable, Anzahl der Bytes)
Zu den einzelnen Umwandlungen kannst du den Windowsrechner recht gut verwenden (bei "Ansicht" umschalten auf "Programmierer").
"|" bedeutet bitweises Oder, byteweise wäre "||"
(msb<<8 ) bedeutet z.B. die Variable msb um 8 nach links schieben (beim Win Rechner ist das "RoL" => Rotate left),
das gleiche gilt auch mit >>, bedeutet rechts schieben (RoR),
temp>>=4 bedeutet temp wird gelesen, um 4 nach rechts geschoben und dieser Wert wird dann wieder in die Variable temp geschrieben (ist eine Kurzform von temp = temp>>4)
Wofür die ADD Pins sind findest du auf S8.
Die Adresse beginnt immer mit 1001, dann kommt es auf die Konfiguration der ADD Pins an, als letztes Bit ist das R/W Bit, dieses Bit wird dazu genutzt um dem Slave zu sagen ob geschrieben wird oder gelesen wird.
In der Tabelle zu den ADD Pins findest du die bezeichnung 0, 1 und Float. 0 bedeutet das dieser Pin mit Masse (GND) verbunden ist, 1 bedeutet das dieser Pin mit VCC (pos. Versorgungsspannung) verbunden ist, Float bedeutet das dieser weder mit GND, noch mit VCC verbunden ist, der Pin wird einfach unbeschalten gelassen.
Wenn du jetzt also ADD0 und ADD1 mit Masse verbindest hast du die Adressen: 1001000x (x steht für das R/W Bit), wenn du das umwandelst in Hex hast du 90 (wenn RW Bit 0 ist => Master sendet an Slave) bzw 91 (wenn RW Bit 1 ist => Master liest vom Slave). Das kannst du ebenfalls mit dem Win Rechner kontrollieren.
Ich habe z.B. 0x00 geschrieben. Das 0x ist ein Präfix und bedeutet das die Zahl als Hex geschrieben wird (du hast somit 0x00 bis 0xff bei einem Byte). Diese Schreibweise ist in C-Dateien üblich. Wenn man keinen Präfix verwendet (z.B. 100) ist das automatisch Dezimal, bei Binär muss man 0b am Anfang schreiben (also z.B. 0b10010000 bei deiner Adresse).
Hier noch ein Link zum I2C Bus http://www.timmermann.org/ralph/inde...tronik/i2c.htm
Wenn du die Registerbits liest musst du einmal grundsätzlich das Byte kennen bzw deren Aufbau (als Beispiel das Configuration Register), das du auf S6 findest (Table 6):
Der Aufbau ist: OS/Alert R1 R0 F1 F0 POL TM SD
Das nutzt dir aber so noch nichts, da du nicht weißt was die einzelnen Bits bedeuten. Du musst jetzt durchlesen was die einzelnen Bits bedeuten.
SD: ist das Shutdown Bit, damit kannst du den Sensor "schlafen legen", damit dieser Strom spart, er mist aber in dieser Zeit nicht. Mit einer 1 aktivierst du den Schlafmodus, mit 0 wird dieser deaktiviert.
TM: damit aktivirerst du den Thermostat Mode, dazu findest du die Tabelle
POL: damit kann man einstellen ob bei einem Fehler (Thigh oder Tlow über- bzw unterschritten) eine 1 oder 0 beim OS/Alert bzw Alarm Output (beim TMP101) geschrieben wird
F1, F0: sind die Fault Queue Bits, damit stellst du die Anzahl ein bevor ein Alarm ausgelöst wird
R1, R0: sind Auflösungsbits, damit stellst du die Auflösung des Sensors ein.
OS/Alert: Dieser hat je nach Configuration 2 Aufgaben. Wenn du im SD Bit eine 1 stehen hast (Shutdownmode) löst du mit diesem Bit eine Messung aus, der TMP geht dann wieder in den Schlafmodus zurück, wenn SD jedoch 0 ist wird dieses Bit als Alarm Bit genutzt (die Grenze im Thigh bzw Tlow Register wurde über bzw unterschritten).
Wenn du den TMP an die Versorgungsspannung legst (bei jedem einschalten) sind alle Bits 0 (außer das Temparaturregister). Somit musst du bei jedem Start einmal die Einstellungen senden (wird in einem Ram gespeichert).
Wenn du eine Funktion nicht brauchst ignorierst du es einfach.
OS/Alert => brauchst du nicht => 0
R1/R2 => für 12Bit beides auf 1 schalten (Table 8 )
F1/F0 => brauchst du nicht => beides 0
POL => Brauchst du nicht => 0
TM => Brauchst du nicht => 0
SD => Brauchst du nicht => 0
Somit ergibt sich: 0b01100000 => 96 => 0x60
MfG Hannes
Lesezeichen