Forum: Mikrocontroller und Digitale Elektronik SHT21 auslesen mit I2C Lib von P.Fleury


von Dionysos 3. (dionysos328)


Lesenswert?

Hallo Leute,

ich verusche zur Zeit, den Sensor SHT21 mit einem ATmega128 auszulesen.
Ich will dazu die I2C-Lib von P.Fleury nutzen.

Die Lib habe ich bereits in mein Projekt eingebunden.

Unter "Projekte&Code" gibt es eine I2C-Sensor-Codesammlung, die auch den 
SHT21 beinhaltet und die P.Fleury-Lib verwendet, leider ist der Code 
fehlerhaft und unkompilierbar.

hat jemand etwas ähnliches versucht und etwas Code zum bereitstellen?

Grüße und Danke,
dionysos

von Karl H. (kbuchegg)


Lesenswert?

dionysos 328 schrieb:

> Unter "Projekte&Code" gibt es eine I2C-Sensor-Codesammlung, die auch den
> SHT21 beinhaltet und die P.Fleury-Lib verwendet, leider ist der Code
> fehlerhaft und unkompilierbar.

recht weit kann er aber nicht daneben sein.
Das kommt schon mal vor, dass insbesondere älterer Code in der 
Codesammlung, für eine ältere Compilerversion geschrieben wurde, die 
noch nicht so pingelig war.
Allerdings: meistens sind es Kleinigkeiten, die einen C-Programmierer 
nicht wirklich vor große Probleme stellen sollten sie an die heutigen 
Gegebenheiten anzupassen. Das Grundprinzip hat sich ja in der 
Zwischenzeit nicht geändert.

Die erste Fehlermeldung lesen. Die entsprechende Stelle im Code 
aufsuchen und den Fehler korrigieren. Wenn es mehrere Fehlermeldungen 
gibt, dann sind die meistens vom gleichen Typ, wenn sie nicht ohnehin 
durch die Korrektur das ersten Problems verschwinden. Also nicht durch 
50 Fehlermeldungen verdriessen lassen. Das ist meistens schneller 
korrigiert als die meisten 'Piep' sagen können. Die reine Zahl 50 beim 
ersten Compilierversuch sagt da gar nichts aus. 1 Fehler korrigiert und 
damit fallen dann oft schon wieder 30 weitere Folgefehler weg.

: Bearbeitet durch User
von Ulli-B (Gast)


Lesenswert?

dionysos 328 schrieb:
> leider ist der Code
> fehlerhaft und unkompilierbar.
>
> hat jemand etwas ähnliches versucht und etwas Code zum bereitstellen?

Der Code ist ganz bestimmt nicht fehlerhaft!
Zeig mal her was du bisher programmiert hast und erklære am besten noch 
was der Code macht und was er nicht macht.
Falls du den Code nur kopiert hast (was ich stark vermute), dann fang 
damit an eine LED blinken zu lassen.

Ulli-B

von Dionysos 3. (dionysos328)


Lesenswert?

Mir ist schon klar, wie man kleine Fehler im Sourcecode behebt.
Nur ist dieser Code teilweise fernab von dem, was wir als 
Programmiersprache C kennen :D

Beitrag "C: AVR: Library für verschiedene I2C-Chips unter Verwendung der P.Fleury-Lib inkl. Datenblätter"

etwas die Diskussion überfliegen gibt ein Bild davon, was ich meine.

von Karl H. (kbuchegg)


Lesenswert?

dionysos 328 schrieb:

> Beitrag "C: AVR: Library für verschiedene I2C-Chips unter Verwendung der P.Fleury-Lib inkl. Datenblätter"
>
> etwas die Diskussion überfliegen gibt ein Bild davon, was ich meine.

Jetzt ist allerdings alles klar.

Ich hätt ja gerne geschrieben, dann nimm halt den oder diesen Code. Aber 
ich muss dich freisprechen: Mit den Stichwort SHT21 findet sich 
tatsächlich nichts anderes in der Codesammlung.

Obwohl: ich hab mir mal das Datenblatt zum SHT21 angesehen. Das kommt 
mir sehr bekannt vor. Das hatten wir doch hier im Forum vor nicht 
allzulanger Zeit schon mal.

Da du die Fleury Funktionen benutzt: Was spricht dagegen, selbst etwas 
zu machen. So schwer sieht das laut Datenblatt nicht aus.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Nicht mit Peters Bibliothek, aber hier ist, was ich bei meinem Sensor
mache:
1
      rv = sht21_measure(0xe3, b, 3);
2
      if (rv < 0)
3
        {
4
          PRINT("sht21_measure() failed\r\n");
5
          twiinit();
6
          continue;
7
        }
8
      v = ((uint16_t)b[0] << 8) | b[1];
9
      double t = -46.85 + 175.72 * (double)v / 65536.0;
10
11
      rv = sht21_measure(0xe5, b, 3);
12
      if (rv < 0)
13
        {
14
          PRINT("sht21_measure() failed\r\n");
15
          twiinit();
16
          continue;
17
        }
18
19
      v = ((uint16_t)b[0] << 8) | (b[1] & 0xfc);
20
      double h = -6.0 + 125.0 * (double)v / 65536.0;

und
1
int
2
sht21_measure(uint8_t cmd, uint8_t *buf, int len)
3
{
4
  return i2c_measure(TWI_SLA_SHT21, cmd, buf, len);
5
}

Vielleicht kannst du das ja auf die Fleury-Lib anpassen.

t ist die Temperatur und h die Feuchtigkeit.

von Karl H. (kbuchegg)


Lesenswert?

Jörg Wunsch schrieb:

>       rv = sht21_measure(0xe3, b, 3);

Wie hast du das Clock Stretching gelöst?
TWI abschalten und Leitung überwachen?

> Vielleicht kannst du das ja auf die Fleury-Lib anpassen.

Die Fleury kann Clock Stretching nicht.

von Dionysos 3. (dionysos328)


Angehängte Dateien:

Lesenswert?

Karl Heinz schrieb:

> Jetzt ist allerdings alles klar.
>
> Ich hätt ja gerne geschrieben, dann nimm halt den oder diesen Code. Aber
> ich muss dich freisprechen

Dankesehr :)

es spricht nichts dagegen, selber etwas zu schreiben, nur würde ich mich 
gerne an etwas bestehendem entlanghangeln um einen groben Überblick 
davon zu haben, was umzusetzten ist.
Man muß denke ich nicht jedes mal das Rad neu erfinden.

Ich habe versucht, den Code aus der Sammlung etwas auszumisten/zu 
korrigieren.

Die sht21_init ist nun soweit kompilierbar.

Die Funktion zum Datenauslesen macht mir aber größere Kopfschmerzen:

int get_sht21_data_str (int measuretype, int holdmode, int crcmode)
{
  int holdmode;
  int crcmode;
  int measuretype;
  int string[8] AS command;
  int string[16] AS sht21_data;

  command.0 =1;
  command.1 =1;
  command.2 =1;
  command.3 =holdmode;
  command.4 = 0;
  command.5 = measuretype.0;
  command.6 = measuretype.1;
  command.7 = measuretype.3

...

}

Die AS befehle kenne ich so nicht und auch nicht die Form der Befehle:
command.0...

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

Siehe Anahng. Ist aber für eine selbstgestrickte Soft-I2C Lib. Kann man 
aber sehr leicht anpassen, einfach das i2c_start() mit dem 
darauffolgenen i2c_write() verheiraten.

von Karl H. (kbuchegg)


Lesenswert?

dionysos 328 schrieb:

> Man muß denke ich nicht jedes mal das Rad neu erfinden.

In dem Fall schon.
Der Code aus der Codesammlung taugt nix.

Kannst du ganz leicht erkennen. Wenn ein Programmierer ohne Rücksicht 
auf Verluste überall einfach int benutzt, dann hat er ein oder zwei 
grundlegende Dinge der µC-Programmierung nicht begriffen. Ihm fehlen da 
noch mindestens ein paar Monate, bis er das erste mal etwas 
veröffentlichen sollte.

> Die AS befehle kenne ich so nicht und auch nicht die Form der Befehle:
> command.0...

Da hat er sich einen Bitzugriff gebaut. Normalerweise würde man das mit 
einem Bitfeld machen (Bitangaben in einer Struktur). Ist nur hier 
sinnlos, weil es eh nur 2 relevante Kommandos gibt.

Du musst dich entscheiden:
Hold Mode oder Nicht Hold Mode.

Der Hold Mode beruht auf Clock Stretching. Das ist etwas, was die AVR so 
nicht unterstützen. Müsste man selber machen. Fr mich wär die Sache 
klar: Nicht Hold Mode. Und damit gibt es dann nur noch 2 Kommandos.
0xF3  für Tempertur abfragen
0xF5  für Feuchtigkeit auslesen.

Und der Rest findet sich in geballter Form im Diagramm 16 vom Datenblatt 
wieder
http://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/Humidity/Sensirion_Humidity_SHT21_Datasheet_V4.pdf

Für die Umrechnung hat Jörg schon was gepostet.

Edit: Und Falk wohl auch.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz schrieb:
> Der Hold Mode beruht auf Clock Stretching. Das ist etwas, was die AVR so
> nicht unterstützen.

Doch, ich denke schon, das ist ganz normales I²C-Prozedere.

Die i2c_measure()-Routine ist von meinem eigenen Beispielcode aus
den avr-libc-Beispielen abgeleitet:
1
static int
2
i2c_measure(uint8_t sla, uint8_t cmd, uint8_t *buf, int len)
3
{
4
  uint8_t twcr, n = 0;
5
  uint16_t spincount;
6
  int rv = 0;
7
8
  /*
9
   * Note [8]
10
   * First cycle: master transmitter mode
11
   */
12
  restart:
13
  if (n++ >= MAX_ITER)
14
    return -1;
15
  begin:
16
17
  TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); /* send start condition */
18
  for (spincount = 65535;
19
       (TWCR & _BV(TWINT)) == 0;
20
       spincount--)
21
    /* wait for transmission */
22
    if (spincount == 0)
23
      return -1;
24
  switch ((twst = TW_STATUS))
25
    {
26
    case TW_REP_START:          /* OK, but should not happen */
27
    case TW_START:
28
      break;
29
30
    case TW_MT_ARB_LOST:        /* Note [9] */
31
      goto begin;
32
33
    default:
34
      return -1;                /* error: not in start condition */
35
                                /* NB: do /not/ send stop condition */
36
    }
37
38
  /* Note [10] */
39
  /* send SLA+W */
40
  TWDR = sla | TW_WRITE;
41
  TWCR = _BV(TWINT) | _BV(TWEN); /* clear interrupt to start transmission */
42
  for (spincount = 65535;
43
       (TWCR & _BV(TWINT)) == 0;
44
       spincount--)
45
    /* wait for transmission */
46
    if (spincount == 0)
47
      return -1;
48
  switch ((twst = TW_STATUS))
49
    {
50
    case TW_MT_SLA_ACK:
51
      break;
52
53
    case TW_MT_SLA_NACK:        /* nack during select: device busy writing */
54
                                /* Note [11] */
55
      goto restart;
56
57
    case TW_MT_ARB_LOST:        /* re-arbitrate */
58
      goto begin;
59
60
    default:
61
      goto error;               /* must send stop condition */
62
    }
63
64
  TWDR = cmd;
65
  TWCR = _BV(TWINT) | _BV(TWEN); /* clear interrupt to start transmission */
66
  for (spincount = 65535;
67
       (TWCR & _BV(TWINT)) == 0;
68
       spincount--)
69
    /* wait for transmission */
70
    if (spincount == 0)
71
      return -1;
72
  switch ((twst = TW_STATUS))
73
    {
74
    case TW_MT_DATA_ACK:
75
      break;
76
77
    case TW_MT_DATA_NACK:
78
      goto quit;
79
80
    case TW_MT_ARB_LOST:
81
      goto begin;
82
83
    default:
84
      goto error;               /* must send stop condition */
85
    }
86
87
  /*
88
   * Note [12]
89
   * Next cycle(s): master receiver mode
90
   */
91
  TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); /* send (rep.) start condition */
92
  for (spincount = 65535;
93
       (TWCR & _BV(TWINT)) == 0;
94
       spincount--)
95
    /* wait for transmission */
96
    if (spincount == 0)
97
      return -1;
98
  switch ((twst = TW_STATUS))
99
    {
100
    case TW_START:              /* OK, but should not happen */
101
    case TW_REP_START:
102
      break;
103
104
    case TW_MT_ARB_LOST:
105
      goto begin;
106
107
    default:
108
      goto error;
109
    }
110
111
  /* send SLA+R */
112
  TWDR = sla | TW_READ;
113
  TWCR = _BV(TWINT) | _BV(TWEN); /* clear interrupt to start transmission */
114
  for (spincount = 65535;
115
       (TWCR & _BV(TWINT)) == 0;
116
       spincount--)
117
    /* wait for transmission */
118
    if (spincount == 0)
119
      return -1;
120
  switch ((twst = TW_STATUS))
121
    {
122
    case TW_MR_SLA_ACK:
123
      break;
124
125
    case TW_MR_SLA_NACK:
126
      goto quit;
127
128
    case TW_MR_ARB_LOST:
129
      goto begin;
130
131
    default:
132
      goto error;
133
    }
134
135
  for (twcr = _BV(TWINT) | _BV(TWEN) | _BV(TWEA) /* Note [13] */;
136
       len > 0;
137
       len--)
138
    {
139
      if (len == 1)
140
        twcr = _BV(TWINT) | _BV(TWEN); /* send NAK this time */
141
      TWCR = twcr;              /* clear int to start transmission */
142
      for (spincount = 65535;
143
           (TWCR & _BV(TWINT)) == 0;
144
           spincount--)
145
        /* wait for transmission */
146
        if (spincount == 0)
147
          return -1;
148
      switch ((twst = TW_STATUS))
149
        {
150
        case TW_MR_DATA_NACK:
151
          len = 0;              /* force end of loop */
152
          /* FALLTHROUGH */
153
        case TW_MR_DATA_ACK:
154
          *buf++ = TWDR;
155
          rv++;
156
          break;
157
158
        default:
159
          goto error;
160
        }
161
    }
162
  quit:
163
  /* Note [14] */
164
  TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN); /* send stop condition */
165
166
  return rv;
167
168
  error:
169
  rv = -1;
170
  goto quit;
171
}

von Karl H. (kbuchegg)


Lesenswert?

Jörg Wunsch schrieb:
> Karl Heinz schrieb:
>> Der Hold Mode beruht auf Clock Stretching. Das ist etwas, was die AVR so
>> nicht unterstützen.
>
> Doch, ich denke schon, das ist ganz normales I²C-Prozedere.

Autsch.
Wo hab ich das jetzt wieder aus dem Gedächtnis ausgekramt. Hab im 
Datenblatt vom M32 nachgesehen: jep, der Slave darf SCL auf Low ziehen.

Mea culpa.

von Dionysos 3. (dionysos328)


Lesenswert?

Falk Brunner schrieb:
> Siehe Anahng. Ist aber für eine selbstgestrickte Soft-I2C Lib.
> Kann man
> aber sehr leicht anpassen, einfach das i2c_start() mit dem
> darauffolgenen i2c_write() verheiraten.

Vielen Dank!
dürfte ich die zugehörige I2C-Lib auch einsehen, um Unterschiede zu der 
Implementation von P.Fleury ausmachen zu können?

von Karl H. (kbuchegg)


Lesenswert?

Falk schreibt
1
    i2c_start();
2
    if (!i2c_write(SHT21_I2C_ADR)) return 0;

in der Fleury Lib gibt man die Adresse des Bausteins gleich direkt beim 
i2c_start an.
1
    i2c_start( SHT21_I2C_ADR );

That's it. Sonst sehe ich keine wesentlichen Abweichungen.

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

Genau!

von Dionysos 3. (dionysos328)


Lesenswert?

okay, also so:

1
uint8_t sht21_read(int8_t* temperature, int8_t* humidity) {
2
3
  uint8_t low, high;
4
  uint16_t temp;
5
6
  // read temperature
7
8
  i2c_start(SHT21_I2C_ADR);
9
  i2c_write(SHT21_CMD_MEAS_T_NO_HOLD);
10
  i2c_stop();
11
  _delay_ms(150);
12
13
  i2c_start(SHT21_I2C_ADR+1);
14
  high = i2c_read(1);
15
  low  = i2c_read(0);
16
  i2c_stop();
17
18
  temp = ((uint16_t)high<<8) + (low & 0b11111100);
19
  
20
  // T = - 46.85 + 175.72 * S_T / 2^16
21
22
  *temperature = ((176L * temp) >> 16) - 47;
23
24
  // read relative humidity
25
26
  i2c_start(SHT21_I2C_ADR);
27
  i2c_write(SHT21_CMD_MEAS_RH_NO_HOLD);
28
  i2c_stop();
29
  _delay_ms(50);
30
31
  i2c_start(SHT21_I2C_ADR+1);
32
  high = i2c_read(1);
33
  low  = i2c_read(0);
34
  i2c_stop();
35
36
  temp = ((uint16_t)high<<8) + (low & 0b11111100);
37
38
  // RH = - 6 + 125 * S_RH / 2^16
39
40
  *humidity = ((125L * temp) >> 16) - 6;
41
  if (*humidity <1) *humidity=1;
42
43
  return 1;
44
}

Eine Verständnisfrage habe ich noch, mit welchen Argumenten ruft man die 
Funktion auf?

Sie erwartet ja ein int8_t* temperature und int8_t* humidity, wenn ich 
das richtig sehe.

ich hätte jetzt gedacht, dass die Werte durch die Funktion zurück 
geliefert werden, und nicht übergeben werden müssen

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

dionysos 328 schrieb:
> ich hätte jetzt gedacht, dass die Werte durch die Funktion zurück
> geliefert werden, und nicht übergeben werden müssen

Und wie willst du zwei Werte zurückgeben?

Allerdings: ehrlich gesagt, einen SHT-21 benutzen und dann das
Ergebnis auf den minimalistischen Wertebereich eines int8_t zu
beschränken, das passt zwar zu Falk :-), ist aber ansonsten Perlen
vor die Säue geschmissen.  Der SHT-21 kann Temperaturschwankungen
im Bereich von wenigen 10 mK sicher detektieren (*), da sollte man
ihm schon ein paar Bits mehr für das Ergebnis spendieren.

(*) Zwei SHT-21, nebeneinander montiert, geben in ruhiger Umgebung
in der Tat bis auf wenige 10 mK identische Werte.  Bereits ein leichter
Luftzug lässt sie unterschiedliche Werte berichten.

: Bearbeitet durch Moderator
von Karl H. (kbuchegg)


Lesenswert?

dionysos 328 schrieb:

> ich hätte jetzt gedacht, dass die Werte durch die Funktion zurück
> geliefert werden, und nicht übergeben werden müssen

Du sollst auch nciht die Werte übergeben, sondern jeweils einen Pointer 
auf die Variablen, in denen die Funktion die Werte hinterlassen soll
1
  int8_t temp, hum;
2
3
  sht21_read( &temp, &hum );

bis eben hatte ich noch eine prinzipiell gute Meinung zu deinen C 
Kenntnissen :-)

: Bearbeitet durch User
von Dionysos 3. (dionysos328)


Angehängte Dateien:

Lesenswert?

Ich versuche nun, die erste Kommunikation aufzubauen und muss 
feststellen, dass mein sht21 nicht antwortet, bzw nichtmal 
Konfigurationsbefehle annimmt.

da mein µC mit 5V versorgt wird, habe ich einen pegelwandler realisiert, 
dieser funktioniert auch soweit (geprüft mit Oszilloskop)

schon beim ausführen meiner init routine bleibt die Kommunikation 
hängen, der µC taktet immer wieder den Startbefehl raus. (Oszilloskop)

nach dem i2c_start_wait(SHT21+I2C_WRITE); bleibt das Programm hängen, da 
der µC abwartet, ob der Sensor busy ist.
1
void sht21_init (int resolution, int end_of_batt, int OCH, int OTP_r)
2
{
3
  int userreg;
4
  
5
  i2c_start_wait(SHT21+I2C_WRITE);
6
  
7
  i2c_write(0b11111110); //soft reset 
8
  
9
  _delay_ms(20);  //wait for the sht21 to reboot
10
  
11
  i2c_rep_start(SHT21+I2C_WRITE);
12
  
13
  i2c_write(0b11100110); //enter config register
14
15
...


was könnte die Ursache sein?

3V Versorgung kommt am Sensor an.

edit: okay fehler gefunden, die angabe der adresse funktioniert so 
nicht.
(code stammt zum teil aus der lib hier in der codesammlung)

(SHT21+I2C_WRITE) ergibt nicht, wie im datenblatt gefordert 0b10000000, 
sondern 0b100000, was natürlich käse ist :-)

ich berichte weiter 8-)

: Bearbeitet durch User
von Dionysos 3. (dionysos328)


Lesenswert?

ich habe eine kleine Funktion erstellt:
1
uint8_t sht21_read_temp() {
2
3
  uint8_t low, high;
4
  uint16_t temp;
5
6
  // read temperature
7
8
  i2c_start(SHT21_I2C_ADR);
9
  i2c_write(SHT21_CMD_MEAS_T_NO_HOLD);
10
  _delay_us(50);
11
  i2c_stop();
12
  _delay_ms(150);
13
  
14
  i2c_start(SHT21_I2C_ADR+1);
15
  high = i2c_read(1);
16
  low  = i2c_read(0);
17
  _delay_us(50);
18
  i2c_stop();
19
20
  temp = ((uint16_t)high<<8) + (low & 0b11111100);
21
  
22
  // T = - 46.85 + 175.72 * S_T / 2^16
23
24
  temperature = ((176L * temp) >> 16) - 47;
25
26
  return temperature;
27
}

diese wird jedoch nicht korrekt abgearbeitet.
der erste teil mit dem senden von SHT21_CMD_MEAS_T_NO_HOLD läuft durch 
bis i2c_stop();

der zweite teil zum lesen hängt sich allerdings auf.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Vielleicht versuchst du ja erstmal, auf die Pegelwandler zu
verzichten und lässt den Controller auf 3,3 V laufen?

Bidirektionale Pegelwandler sind nicht so ganz trivial.

von Dionysos 3. (dionysos328)



Lesenswert?

steht nicht in meiner entscheidungsgewalt, eval board und sensor sind 
gesetzt.

pegelwandler passt schon [quelle anbei]

denke eher, dass der code noch hakt.

von Falk B. (falk)


Lesenswert?

@dionysos 328 (dionysos328)

>feststellen, dass mein sht21 nicht antwortet, bzw nichtmal
>Konfigurationsbefehle annimmt.

Warum hast du die Prüfung rausgeschmissen, ob der SHT21 antwortet?

>schon beim ausführen meiner init routine bleibt die Kommunikation
>hängen, der µC taktet immer wieder den Startbefehl raus. (Oszilloskop)

Mein SHT21 braucht die nicht.

>nach dem i2c_start_wait(SHT21+I2C_WRITE); bleibt das Programm hängen, da
>der µC abwartet, ob der Sensor busy ist.

Dann stimmt wohl die Adresse nicht.
Ausserdem wäre ein VOLLSTÄNDIGER Quelltext nicht ganz falsch.

>(SHT21+I2C_WRITE) ergibt nicht, wie im datenblatt gefordert 0b10000000,
>sondern 0b100000, was natürlich käse ist :-)

I2C_WRITE sollte 0 sein.

von Dionysos 3. (dionysos328)


Angehängte Dateien:

Lesenswert?

hier der vorläufige code

bin zunächst nur an der funktion read_temp dran.

die init funktion läuft mittlerweile durch (unabhängig ob benötigt oder 
nicht).

die LCD ausgaben sind nur zu debugzwecken

von Falk B. (falk)


Lesenswert?

@dionysos 328 (dionysos328)

>hier der vorläufige code

Man braucht nur EINE Adresse, meist die zum Schreiben (LSB=0). Die zu 
lesen ergibt sich aus der Veroderung mit 0x01.

Ausserdem sollte man sehen/wissen, dass die Funktion i2c_start() der I2C 
Lib von Perter Fleury im Fehlerfall den Wert 1 liefert und nicht wie 
meine eigene Null! Also eher so und  nicht einfach auskommentieren weil 
es nicht geht!

if (i2c_start(SHT21_I2C_ADR)) return 0;

Logisch dass dazu SHT21_I2C_ADR per #define definert sein muss! vOK, ist 
es im .h File.

Die Funktion ist real getestet, sie funktioniert.

von Dionysos 3. (dionysos328)


Lesenswert?

okay, mit der zeile

if (i2c_start(SHT21_I2C_ADR)) return 0;

läuft die messung nicht durch, die funktion liefert einen fehler zurück.

von Falk B. (falk)


Lesenswert?

Dann reagiert dein SHT21 nicht. Möglicherweise ein Problem mit deinem 
Pegelwandler.

von Dionysos 3. (dionysos328)


Lesenswert?

okay.

also bei der Kommunikation µC => Sensor scheint der Pegelwandler zu 
funktionieren. Die 5V µC Signale kommen am Sensor mit 3V an.

In die andere Richtung ist es nicht so einfach, das mit dem Oszilloskop 
nachzuvollziehen.

Ein Fehler ist also nicht komplett auszuschließen.

Die Schaltung für den Pegelwandler habe ich aus dem Philips Dokument 
(Quelle weiter oben) entnommen. Dem schenke ich also erstmal vertrauen.

Andererseits läuft meine init Routine ja durch.
Und dort gibt es ja ein start_wait().

Wäre der Sensor busy/nicht zu erreichen, würde die Funktion doch nicht 
durchlaufen, oder?

edit: ich habe gerade rausgefunden, dass die delays in meiner sht21.c 
nicht richtig funktionieren.
delays, die in der main.c aufgerufen werden, haben die richtige dauer.

in der sht21.c scheit es, als würden sie garkeine verzögerung bewirken.

in beiden dateien sind sie mit

#include <util/delay.h>

eingebunden.

edit II:

delays werden nun korrekt abgearbeitet, sensor antwortet.

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@ dionysos 328 (dionysos328)

>In die andere Richtung ist es nicht so einfach, das mit dem Oszilloskop
>nachzuvollziehen.

Warum? Wo liegt das Problem? Einfach Osziu anklemmen und gut!

>Die Schaltung für den Pegelwandler habe ich aus dem Philips Dokument
>(Quelle weiter oben) entnommen. Dem schenke ich also erstmal vertrauen.

Der funktioniert auch, WENN man die richtigen Bauteile verwendet und 
diese richtig anschließt. Welche Transistoren hast du benutzt?

>Andererseits läuft meine init Routine ja durch.
>Und dort gibt es ja ein start_wait().

Kann Zufall sein.

>edit: ich habe gerade rausgefunden, dass die delays in meiner sht21.c
>nicht richtig funktionieren.
>delays, die in der main.c aufgerufen werden, haben die richtige dauer.

>in der sht21.c scheit es, als würden sie garkeine verzögerung bewirken.

>in beiden dateien sind sie mit

>#include <util/delay.h>

>eingebunden.

Und wo ist das #define F_CPU ?

>delays werden nun korrekt abgearbeitet, sensor antwortet.

AHA!

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.