PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : i2c - mehrere Sensoren auslesen



Haveaniceday
02.03.2008, 16:34
Hallo zusammen,
weiß nicht so recht weiter... Will mehrere DS1621 über einen i2c bus auslesen, aber weiß nicht so recht wie. Habe bis jetzt nur einen am laufen. Benutze die libary von Peter Fleury.

Folgender maßen sieht das program bis jetzt aus:



#define GETTEMP 0xAA
#define I2CTHERMO 0x90
#define STARTCONVERT 0xEE




i2c_start_wait(I2CTHERMO + I2C_WRITE);
i2c_write(GETTEMP);
i2c_rep_start(I2CTHERMO + I2C_READ);

temperaturVK = i2c_readAck();
temperaturNK = i2c_readNak();
i2c_stop();


Muss ich diese funktionen für jeden Sensor einzeln eingeben? Also beispielweise für Sensor mit Adressierung A0=1, A1=0, A2=0:


#define GETTEMP2 0xAA
#define I2CTHERMO2 0x92
#define STARTCONVERT2 0xEE




i2c_start_wait(I2CTHERMO2 + I2C_WRITE);
i2c_write(GETTEMP2);
i2c_rep_start(I2CTHERMO2 + I2C_READ);

temperaturVK2 = i2c_readAck();
temperaturNK2 = i2c_readNak();
i2c_stop();


LG Hannes

linux_80
02.03.2008, 18:36
Hallo,

schreib einfach eine Function der Du die SlaveAdresse des gewünschten Sensors mitgibst.

Haveaniceday
03.03.2008, 10:19
Hallo,

schreib einfach eine Function der Du die SlaveAdresse des gewünschten Sensors mitgibst.

Sorry, kann dir gerade nicht ganz folgen. Weiß nich genau was du meinst...

Das Program sieht im prinzip so aus:



#include <avr/io.h>
#include "i2cmaster.h"
#define GETTEMP 0xAA
#define I2CTHERMO 0x90
#define STARTCONVERT 0xEE

int main(void) {
char TemperaturVK;
char TemperaturNK;
DDRD = (1<<PD5)|(1<<PD6);
i2c_init();
i2c_start(I2CTHERMO+I2C_WRITE);
i2c_write(STARTCONVERT);
i2c_stop();
for(;;) {
i2c_start_wait(I2CTHERMO+I2C_WRITE);
i2c_write(GETTEMP);
i2c_rep_start(I2CTHERMO+I2C_READ);
TemperturVK = i2c_readAck();
TemperturNK = i2c_readNak();
i2c_stop();
if (TemperturVK[0] >= 25)
PORTD =(1<<PD5);
else
PORTD =(1<<PD6);
}
return 0;
}


Und will einen 2. Sensor hinzufügen

Pascal
03.03.2008, 11:02
Du hast doch eine Konstante namens I2CTHERMO in deinem Programm. Die dürfte ja die Adresse der Thermometers für deine Konfiguration der Adresseingänge enthalten. Wenn du die Adresseingänge des Thermometers allerdings anders beschaltest, hat das dann ja ne andere Adresse. Wenn du nun mehrere Thermometer verwenden willst, muss du denen jeweils ne andere Adresse geben und das bei i2c_start berücksichtigen, indem du dann eine andere Adresse übergibst.

Haveaniceday
03.03.2008, 13:38
Ja, aber genau das war ja meine frage, wie man das macht^^



#define GETTEMP 0xAA
#define I2CTHERMO1 0x90
#define I2CTHERMO2 0x92
#define STARTCONVERT 0xEE



i2c_start_wait(I2CTHERMO1+I2C_WRITE);
i2c_write(GETTEMP);
i2c_rep_start(I2CTHERMO1+I2C_READ);
TemperturVK1 = i2c_readAck();
TemperturNK1 = i2c_readNak();
i2c_stop();

i2c_start_wait(I2CTHERMO2+I2C_WRITE);
i2c_write(GETTEMP);
i2c_rep_start(I2CTHERMO2+I2C_READ);
TemperturVK2 = i2c_readAck();
TemperturNK2 = i2c_readNak();
i2c_stop();



etwa so?

Pascal
03.03.2008, 16:43
Ja, passt.
Ich bin halt davon ausgegangen, dass du den code selbst programmiert hast und dann müsstest du auch wissen, wie das geht. Anscheinend kannst dus ja, auch wenn dus nicht unbedingt glaubst ;-)

izaseba
03.03.2008, 18:07
Hallo Hannes,

Es gibt mehrere Ansätze Dein 'Problem' zu Lösen.

Du kannst natürlich die paar Zeilen so oft hintereinander schreiben, wie Du möchtest, bei 2 oder 3 Sensoren ist das kein Problem.

Du könntest Dir so wie Linux80 sagt eine Funktion basteln an die Du z.B. Die Slaveadresse und ein Zeiger auf ein 2 Byte Array übergibst.
Das sieht dann z.B. so aus:


void LeseTemp(uint8_t Adresse,char* Temp) {
i2c_start_wait(Adresse+I2C_WRITE);
i2c_write(GETTEMP);
i2c_rep_start(Adresse+I2C_READ);
*Temp++ = i2c_readAck();
*Temp = i2c_readNak();
i2c_stop();
}


Im Programm sehe das etwa so aus:

#define SensorBoden 0x90
#define SensorLuft 0x92
char TempBoden[2];
char TempLuft[2];

for(;;) {
LeseTemp(SensorBoden,TempBoden);
LeseTemp(SensorLuft,TempLuft);
...
...
...
}

Wenn man alles in einem Array haben möchte und die Slave Adressen schön um 2 versetzt sind, könnte man anstatt der Funktion eine for Schleife nutzen etwa so:

#define Sensor1 0x90
#define AnzahlSensoren 3
...
...
char Temperaturen[AnzahlSensoren*2];
uint8_t a;
for (a=0;a< (AnzahlSensoren+1)*2;a+=2){
i2c_start_wait(Sensor1+a+I2C_WRITE);
i2c_write(GETTEMP);
i2c_rep_start(Sensor1+a+I2C_READ);
Temperaturen[a] = i2c_readAck();
Temperaturen[a+1] = i2c_readNak();
i2c_stop();
}

Wie Du siehst, gibt es mehrere Wege nach Rom...

Viel Spaß Sebastian

P.S. Das zweite Beispiel gefällt mir nicht ganz, vielleicht könnte man das besser schreiben :-&

Haveaniceday
08.03.2008, 17:53
Hab es jetzt einfach mal so probiert wie ich gedacht hatte:




i2c_start_wait(I2CTHERMOb + I2C_WRITE);
i2c_write(GETTEMP);
i2c_rep_start(I2CTHERMOb + I2C_READ);

temperaturVKb = i2c_readAck(); /
temperaturNKb = i2c_readNak();
i2c_stop();



i2c_start_wait(I2CTHERMO + I2C_WRITE);
i2c_write(GETTEMP);
i2c_rep_start(I2CTHERMO + I2C_READ);

temperaturVK = i2c_readAck();
temperaturNK = i2c_readNak();
i2c_stop();



Allerdings bekomme ich bei dem zweiten Sensor keine richtige Temperatur ausgegeben (196°C), wenn ich beide parallel betreibe, mit dem obrigen code.
Wenn aber nur einer angeschlossen ist (code mit nur einer Sensor Ansteuerung) liefert jeder einen richtigen Tempertur Wert.

Einer ne idea wodran das liegen könnte?

LG Hannes

linux_80
08.03.2008, 22:59
Funktioniert es denn wenn Du im Programm beide abfrägst, aber nur einen anschliesst, also einmal den einen und dann nur den andren, oder gehts nur wenn Du das Programm änderst ?
Sind die Adressen an den 1621 richtig eingestellt ?
Wie wurde verkabelt ?
Hast Du dem 1621 vorher gesagt, das er die Temperatur messen soll, oder liest Du die Werte nur aus ?

Solange nach dem Reset nicht gemessen wurde, kommt immer -96° raus.

Haveaniceday
09.03.2008, 17:29
Funktioniert es denn wenn Du im Programm beide abfrägst, aber nur einen anschliesst, also einmal den einen und dann nur den andren, oder gehts nur wenn Du das Programm änderst ?

Wenn das Programm für beide Programmiert ist aber nur einer angeschlossen ist, tut sich garnix. Also auch der angeschlossene gibt kein Signal mehr aus... (wird einfach nix ausgegeben)



Sind die Adressen an den 1621 richtig eingestellt ?

Ja, Adresse ist einmal 0x90 und 0X92, laufen ja wenn ich sie einzeln Programmiere bzw. Messen lasse.



Wie wurde verkabelt ?
Einfach 4 Leitungen an die Beinchen gelötet...



Solange nach dem Reset nicht gemessen wurde, kommt immer -96° raus.
Er zeigt aber 196, nicht -96 an...



Hast Du dem 1621 vorher gesagt, das er die Temperatur messen soll, oder liest Du die Werte nur aus ?

Weiß nicht genau was du damit meinst... Ich schiecke doch dem Sensor denn befehl zu Messen, erfasse dann den Messwert, Speichere ihn in der Variablen "temperturVK" und dann wird der bus gestopt und wieder gestartet, aber mit ner anderen Adresse... (siehe Code)

LG Hannes

linux_80
09.03.2008, 19:04
Einen Wert grösser 127.5 kann der DS1621 nicht ausgeben, denn darüber ist alles negativ (Bit 7 gesetzt), dann stimmt nur die Umrechnung nicht !

Wenn man eine Temperatur vom 1621 haben will, muss er erst eine Messung druchführen, diese startet man mit dem Kommando $EE, nach diesem wird einmal gemessen.
Der 1621 braucht mind. 400ms um zu messen, wenn man vorher ausliest, geht das zwar, aber es kommt der Wert der letzten Messung raus, oder -96 falls noch garnicht gemessen wurde.

D.H. also, dass vor jedem Auslesen eine Messung gestartet werden muss, anschliessend mind. 400ms warten, dann erst den Wert lesen.

Alternativ kann man den 1621 auf Kontinuierliche Messung umstellen, ein Beispiel ist in seinem Datenblatt enthalten.

Haveaniceday
09.03.2008, 19:30
Ja gut. Genau dies tue ich ja...
Aber die "wartezeit" müsste doch i.O. sein, sonst würde er bei nur einem Sensor auch nix messen oder?
Weiß im mom echt nicht weiter. Ist alles viel viel schwerer als ich gedacht habe... :(

linux_80
09.03.2008, 22:16
Es ist nicht schwer,
höchstens für uns leser, die versuchen zu helfen, wenn nicht mehr Info kommt als das, das es nicht geht.
zB. mal das ganze Programm posten, oder zumindest mehr als nur diese Zeilen, wär ganz praktisch (für Dich),
dann genau wie das verkabelt ist, Schaltplan usw., aber so wie es ist, nicht wie es sein sollte ;-)

Wenn man etwas selber gebaut hat ist es natürlich leicht erstmal zu sagen "es ist alles richtig angeschlossen". Aber wenns nicht geht, muss doch irgendwo ein Bug sein, und den können wir von hier nicht sehen !

Haveaniceday
10.03.2008, 17:18
Du hattest recht. Habe mir gerade nochmal den Code angesehn und festegellt, das ich eifnach nur vergessen hab den 2. Sensor zu initalisieren^^ ](*,)

Oh man bin ich jetzt happy.

Jetzt hab ich nurnoch das problem, das ich Kabel mit der länge von 2m für den Sensor benutzen wollte... Aber er dann auch nur misst ausgibt.
Dazu hast du nicht zufällig auchnoch eine idea oder? ^^

LG Hannes