mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik DS18S20 Temperatur auslesen mit C geht nicht


Autor: unknown (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich versuche schon länger einen DS18S20 Temperatursensor zum laufen zu 
bringen, scheitere aber immer am Auslesen der Temperatur.

Um die Temperatur auslesen zu können muss ich laut Doku ein READ-Signal 
senden und danach die Temperatur empfangen. Da ich sowohl senden als 
auch empfangen muss um eine Temperatur zu bekommen weiß ich nicht in 
welcher Funktion der Fehler ist (vllt. auch in beiden).

Die Initialisierung des Sensors funktioniert auf jeden Fall, das hab ich 
bereits testen können - er ist also nicht defekt oder so.

Der Code:
void write(unsigned char c)
{
  char cnt;
  for (cnt = 0; cnt < 8; ++cnt) {
    DQ = 0;
    t0_wait(0xFF, 0xF1);   // 15µs
    DQ = (c >> cnt) & 1;   // write bit to sensor
    t0_wait(0xFF, 0xD3);   // 45µs
  }
}
void read()
{
  char cnt;
  write(FC_READ);
  for (cnt = 0; cnt < 8; ++cnt) {
    DQ = 0;
    t0_wait(0xFF, 0xFE);   // 1µs
    Tlow |= ((char) DQ << cnt);  // read bit from sensor
    t0_wait(0xFF, 0xC4);   // 60µs
  }
  DQ = 0;
  t0_wait(0xFF, 0xFE);   // 1µs
  Thigh = DQ;
}
DQ ist das Bit an das die Daten gesendet werden, Tlow das erste 
gesendete Byte, Thigh das Zweite (von dem ich aber nur ein Bit brauche).

Ich hoffe hier ist jemand dabei, der einen DS18S20 schon mal zum laufen 
gebracht hat und der mir sagen kann was da falsch dran ist. Das 
Datasheet: 
http://www.datasheetcatalog.net/de/datasheets_pdf/...

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schon mal die Suchfunktion bemüht?
Es gibt hier doch bestimmt schon lauffähige Lösungen.
Wenn nicht, kann ich auch eine herauskramen.

Autor: Benni L. (sutter_cain)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe gerade keine Zeit, das alles durchzuprüfen, aber ich hab hier 
mal bisschen was aus meine alten Code herausgekramt, ich hoffe das hilft 
dir:
void OW_write_bit (unsigned char write_bit)
{
  if (write_bit)
  {
    //writing a bit '1'
    drive_OW_low();         // Drive the bus low
    wait(DELAY_6Us);        // delay 6 microsecond (us)
    drive_OW_high ();          // Release the bus
    wait(DELAY_64Us);        // delay 64 microsecond (us)
  }
  else
  {
    //writing a bit '0'
    drive_OW_low();         // Drive the bus low
    wait(DELAY_60Us);        // delay 60 microsecond (us)
    drive_OW_high ();          // Release the bus
    wait(DELAY_10Us);        // delay 10 microsecond for recovery (us)
  }
}  
unsigned char OW_read_bit (void)
{
  unsigned char read_data; 
  //reading a bit 
  drive_OW_low();             // Drive the bus low
  wait(DELAY_6Us);            // delay 6 microsecond (us)
  drive_OW_high ();              // Release the bus
  wait(DELAY_9Us);            // delay 9 microsecond (us)

  read_data = read_OW();          //Read the status of OW_PIN

  wait(DELAY_55Us);            // delay 55 microsecond (us)  
  return read_data;
} 

Autor: Benni L. (sutter_cain)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So nun habe ich ein wenig Zeit gefunden, die beiden Dinge zu 
vergleichen:

Zu deiner read Funktion:
- warum liefert diese Funktion keine Werte zurück? bzw. wo befinden sich 
Tlow und Thigh? werden diese auch vor Aufruf der Funktion richtig 
initialsiert? Ich würde Pointer an die Funktion übergeben, dann richtig 
initialisieren und erst dann schreiben. Wäre dann übersichtlicher.

- zum Lesen solltest du den Bus wieder freigeben, das konnte ich bei dir 
nirgends finden da steht nur DQ=0. Ich gebe den Bus nach 6 µs wieder 
frei, 1µs sollte allerdings auch ausreichen.

- du liest direkt nach 1µs den Bus aus, das Signal des DS18S20 ist aber 
erst nach 15 µs nach den fallende Flange gültig, das steht im Text des 
Datenblatt unter READ-TIME SLOTS S.13

Zu deiner write Funktion:
- du solltest zwischen den Bits auch noch 1 µs warten. Das wären dann 
bei dir mind. 46 µs statt 45.
-sonst siehts gut aus


Probier das mal aus und berichte dann wieder.

Autor: unknown (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
> Schon mal die Suchfunktion bemüht?
> Es gibt hier doch bestimmt schon lauffähige Lösungen.
Ja, hab ich. Aber das hat mir alles leider nicht wirklich 
weitergeholfen.

Benni L. schrieb:
> - warum liefert diese Funktion keine Werte zurück? bzw. wo befinden sich
> Tlow und Thigh? werden diese auch vor Aufruf der Funktion richtig
> initialsiert? Ich würde Pointer an die Funktion übergeben, dann richtig
> initialisieren und erst dann schreiben. Wäre dann übersichtlicher.

Der Code ist noch im Betastatus, weshalb ich ihn erst auf die einfachste 
Weise geschrieben hab, die mir eingefallen ist. Sobald er mal läuft 
werde ich ihn überarbeiten. Ich lese in der read-Funktion gleich beide 
Bytes aus, weshalb ich auch keine Werte zurückgeben brauche. Die 
einzelnen Bits schiebe ich dann einfach an den richtigen Platz. Das hab 
ich im Simulator-Debugger getestet und das hat auch funktioniert.
Tlow und Thigh sind global und initialisiert.

Benni L. schrieb:
> - zum Lesen solltest du den Bus wieder freigeben, das konnte ich bei dir
> nirgends finden da steht nur DQ=0. Ich gebe den Bus nach 6 µs wieder
> frei, 1µs sollte allerdings auch ausreichen.
Hab gedacht das freigeben würde automatisch über diesen "pullup 
resistor" erfolgen. Hab ich zu Testzwecken aber mal eingebaut.

Benni L. schrieb:
> - du liest direkt nach 1µs den Bus aus, das Signal des DS18S20 ist aber
> erst nach 15 µs nach den fallende Flange gültig, das steht im Text des
> Datenblatt unter READ-TIME SLOTS S.13
Da steht doch: "Output data from the DS18S20 is valid for 15μs after the 
falling edge that initiated the read-time slot." Das bedeutet doch, dass 
die Daten nur 15μs gültig sind und nicht, dass sie es erst ab 15μs 
gültig sind.

Benni L. schrieb:
> - du solltest zwischen den Bits auch noch 1 µs warten. Das wären dann
> bei dir mind. 46 µs statt 45.
Hab mir gedacht, dass der Code ja auch noch Zeit benötigt bis er 
ausgeführt ist, weshalb ich das nicht berücksichtigt hab. Aber hab es 
sicherheitshalber mal eingebaut.

Trotz aller Ratschläge bekomme ich dennoch kein Signal vom Sensor.
Ich hab deinen Code, Benni, mal fast 1:1 übernommen, er geht bei mir 
aber dennoch nicht:
void write(unsigned char c)
{
  char cnt;
  for (cnt = 0; cnt < 8; ++cnt) {
    DQ = 0;
    if (((c >> cnt) & 1) == 1) {
      t0_wait(0xFF, 0xFA);  // 6µs
      DQ = 1;
      t0_wait(0xFF, 0xC0);  // 64µs
    } else {
      t0_wait(0xFF, 0xC4);  // 60µs
      DQ = 1;
      t0_wait(0xFF, 0xF5);  // 10µs
    }
  }
}
void read()
{
  char cnt;
  write(FC_READ);
  for (cnt = 0; cnt < 8; ++cnt) {
    DQ = 0;
    t0_wait(0xFF, 0xFA);  // 6µs
    DQ = 1;
    t0_wait(0xFF, 0xF6);  // 9µs
    Tlow |= ((char) DQ << cnt);
    t0_wait(0xFF, 0xC9);  // 55µs
  }
  DQ = 0;
  t0_wait(0xFF, 0xFA);  // 6µs
  DQ = 1;
  t0_wait(0xFF, 0xF6);  // 9µs
  Thigh = DQ;
}

Autor: Klaus Wachtler (mfgkw)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht gehen ja die Dateien im Anhang.
Damit hatte ich mal erfolgreich von einem DS1820 gelesen
(atmega32, 16MHz).

Leider in C++, aber der für dich relevante Teil ist reines C.
Als Ausgangsbasis kannst du ja damit anfangen und weglassen, was
du nicht brauchst (in C++ ist eigentlich nur die LCD-Ausgabe).

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PS: sehe gerade, daß da auch noch auskommentiert das gleiche
Spiel für einen TSic 206 dabei ist.

Ebenso wird irgendwo eine LED an- oder asusgeschaltet, der
Kommentar dazu faselt von einem Relais (für das der Quelltext später 
verwendet wurde).

Nicht verwirren lassen!

Autor: BvB (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du kannst auch mal hier schauen, da wird speziell das Timing und der 
Zugriff auf den DS18S20er recht gut erklärt:

Beitrag "1-Wire-Bus-Projekt: DS1820  DS18S20  DS2450  DS2408  unter C und 8051"

Bernd

Autor: unknown (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für eure Codes, die kann ich auf meinem μC aber leider nicht 
benutzen. Und große Unterschiede zu meinem Code kann ich nicht erkennen 
- trotzdem geht er nicht.
Ansonsten bin ich genau so vorgegangen wie in deinem Dokument, BvB, das 
echt super ist. Dennoch funktioniert nach wie vor nur das Resetsignal.

Ich hab den Code jetzt zwar so umgeschrieben, dass der komplette 
Scratchpad (9 Bytes) ausgelesen wird, ich erhalte aber nur lauter Einsen 
als Ausgabe, was bedeutet, dass der Sensor nicht reagiert:
void write(unsigned char c)
{
  char cnt;
  for (cnt = 0; cnt < 8; ++cnt) {
    DQ = 0;
    if ((c >> cnt) & 1 == 1)
      DQ = 1;
    delay_us(12); // 100µs
    DQ = 1;  
  }
}
void read()
{ 
  char cnt, i;
  for (i = 0; i < 9; ++i) {
    for (cnt = 0; cnt < 8; ++cnt) {
      DQ = 0;
      DQ = 1;
      delay_us(2);  // 15µs
      ds1820[i] |= ((char) DQ << cnt);
      delay_us(12);  // 100µs
    }
  }
}
Ich setze DQ ja immer auf 1, weshalb diese auch immer in das Array 
ds1820 geschrieben wird.
Da alle gelesenen Bits kein Signal zurückgeben, muss der Fehler muss 
entweder in der Zeitverzögerung der read-Funktion liegen (zu kurz), oder 
in der write-Funktion. Ich hab schon alle möglichen minimale bis 
maximale mögliche Werte probiert, aber leider keine Änderung.

Weiß jemand wie der Sensor reagiert, wenn der vorhergehende READ-Befehl 
nicht erfolgreich war? Antwortet er dann überhaupt?

Autor: Benni L. (sutter_cain)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe da gerade so eine Befürchtung ;)

was benutzt du eigentlich für einen Controller? Und kannst du mal hier 
posten wie DQ definiert ist.

Ich befürchte nämlich, dass du den Bus mit beim Lesen nicht in den 
hochohmigen Zustand versetzt sondern auf aktiv High (Pin von Output auf 
Input ändern beim Lesen). Bei Atmel musst du dazu das DDR ändern, bei 
PIC das TRIS Register.

unknown schrieb:
> Weiß jemand wie der Sensor reagiert, wenn der vorhergehende READ-Befehl
>
> nicht erfolgreich war? Antwortet er dann überhaupt?

Das meine ich mit meinem Post. Er wird womöglich versuchen zu antworten, 
aber es nicht schaffen den Bus gegen den Controller herunterzuziehen.

Autor: unknown (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab einen AT89C5131 von Atmel. Kompilieren tu ich mit dem 
C51-Compiler, der auch von Atmel ist.
sfr p = 0xA0;       // Port 2
sbit DQ = P2^0;     // Daten I/O

Bisher hab ich nur auf DQ zugegriffen. Beim DDR hab ich nichts gemacht. 
Ich wüsste auch gar nicht was man da ändern kann. ;)

Wäre schön wenn du mir das noch genauer erklären könntest.

Autor: Benni L. (sutter_cain)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
http://www.mikrocontroller.net/articles/Ausgangsst...

Beim AVR kann man über das DDR (DataDirectionRegister) in den 
hochohmigen Zustand schalten.

http://www.freewebs.com/maheshwankhede/basic.html
Da ist so einiges beschrieben. Meine Vermutung ist, du musst entweder 
die OpenDrain I/O an P0 benutzen oder die selbst eine Ausgangsstufe 
diskret bauen.

Autor: unknown (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also selber bauen geht leider nicht, da ich davon keine Ahnung hab. Ich 
steuere die Bausteine nur an, kann sie aber nicht selbst herstellen...

Und den Sensor an P0 anzuschließen hat leider auch keinen Erfolg 
gebracht. Aber das liegt vllt. auch daran, weil der bei mir irgendwie 
defekt ist. Da funktioniert nicht einmal das Reset-Signal. Aber sind die 
Signale denn nicht identisch? Ich mein, wenn der Sensor auf einen Reset 
antworten kann, dann müsste er doch auch auf einen Lese-Befehl antworten 
können.

Autor: Benni L. (sutter_cain)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm ich hab mir das Bild der I/O vom AT89C5131 nochmal genauer 
angeschaut. Du hast recht, es sollte auch mit P2 funktionieren und DQ = 
1. Wie hast du den DS18S20 angeschlossen? VCC und GND und den Bus mit 
Pullup? Oder mit parasitärer Versorgung nur über den Bus?

Woher weisst du, dass du den Presence Pulse sicher empfängst? Dürfte ich 
da mal die Funktion dafür sehen? Ein Oszi hast du nich zufällig?

Autor: unknown (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab den Sensor mit allen drei Anschlüssen am Port angeschlossen.

Die reset-Funktion:
char TEMP_SENSOR_reset()
{
  char ret = 0;

  DQ = 0;
  delay_us(500);
  DQ = 1;
  delay_us(70);
  ret = DQ;
  delay_us(500);
  return ret;
}
Wenn ich DQ nicht angeschlossen hab wird eine 1 zurückgegeben, ansonsten 
eine 0 - was bedeutet, dass der Sensor geantwortet hat.

Autor: unknown (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und nein, ich hab keinen Oszi.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.