Forum: Mikrocontroller und Digitale Elektronik DS18B20: Problem mit Temperaturauslesen


von Helmut D. (helmut89)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,
ich weiß, dass schon mehrere Beiträge zu dem DS18B20 hier im Forum 
befinden. Leider komme ich aber kein Stück weiter. Bekomme immer bei 
therm_reset() den Rückgabewert 1, das heißt, dass kein Sensor erkannt 
wird. Arbeite mit einem ATMEGA32, Internen 8MHz Quarz (64ms) und 
F_CPU=1000000UL. Habe mit dem Oszi auch schon die Signale für den Reset 
gemessen, das sollte alles passen. Vielleicht hatte jemand einen 
ähnlichen Fehler und kann mir weiterhelfen??

von Helmut D. (Gast)


Angehängte Dateien:

Lesenswert?

Übrigens habe ich den Sensor über einen 4,7k Pullupwiderstand auf 5V 
gezogen.

von cskulkw (Gast)


Lesenswert?

Helmut D. schrieb:
> wird. Arbeite mit einem ATMEGA32, Internen 8MHz Quarz (64ms) und
>
> F_CPU=1000000UL.

Abgesehen davon, dass ich gestern eine Diskussion gelesen hatte, die zum 
Ergebnis kam, dass die delay-Funktion nicht das hält was sie verspricht, 
ist mir aufgefallen. dass Du zwar die interne Takterzeugung 8MHZ 
verwendest und gleichzeitig die F_CPU auf 10 MHz definierst.

Wenn irgendwo F_CPU verwendet wird, die nicht mit der realen Taktrate 
übereinstimmt, würde ich vermuten, dass hier das Problem liegt.

Möglicherweise läuft Deine Delay-Funktion zu langsam und dann ist der 
Takt schon Resetimpuls schon zu Ende.

Tip: Setze vor dem Warten auf den Resetimpuls ein weiteres Ausgangspin, 
auf das Du dann mit Scope extern triggerst. Vor der Abfrageroutine setzt 
Du dieses Pin wieder zurück, dann weißt Du genau, ob Dein selbst 
organisiertes Abtast-Timming paßt.

Genau aus diessem Grund habe ich mir einen eigenen Scheduler 
geschrieben, der genau paßt. Die Abtastzeitpunkte habe ich mit einen 
2.Timer per Interupt gelöst. Dasnn läuft es zuverlässig.

Hoffe, konnte Dir helfen. Viel  erfolg

von Cyblord -. (cyblord)


Lesenswert?

cskulkw schrieb:

> Abgesehen davon, dass ich gestern eine Diskussion gelesen hatte, die zum
> Ergebnis kam, dass die delay-Funktion nicht das hält was sie verspricht,

Halte ich für irrelevant in diesem Fall. Ich betreibe meine 
Ätzbadsteuerung mit einem Atmega8 (interner 8 MHZ OSC) und einem 
DS18B20. Und ich erzeuge alle Wartezeiten für den 1Wire Bus direkt mit 
_delay_us().
1. Funktioniert das bis heute ohne Probleme, 2. sehen die Signalzeiten 
im Logic Analyzer sehr gut und stabil aus. Der 1Wire Bus ist ja nun auch 
nicht besonders kritsch und es werden relativ große Toleranzen 
akzeptiert in der Spezifikation.

gruß cyblord

von PuraVida (Gast)


Lesenswert?

cyblord ---- schrieb:
> cskulkw schrieb:
>
>> Abgesehen davon, dass ich gestern eine Diskussion gelesen hatte, die zum
>> Ergebnis kam, dass die delay-Funktion nicht das hält was sie verspricht,
>
> Halte ich für irrelevant in diesem Fall. Ich betreibe meine
> Ätzbadsteuerung mit einem Atmega8 (interner 8 MHZ OSC) und einem
> DS18B20. Und ich erzeuge alle Wartezeiten für den 1Wire Bus direkt mit
> _delay_us().
> 1. Funktioniert das bis heute ohne Probleme, 2. sehen die Signalzeiten
> im Logic Analyzer sehr gut und stabil aus. Der 1Wire Bus ist ja nun auch
> nicht besonders kritsch und es werden relativ große Toleranzen
> akzeptiert in der Spezifikation.
>
> gruß cyblord

Hi Cyblord,

hast die 1-Wire-Routine selbst geschrieben oder gibt es da eine Lib auf 
die ich zurückgreifen könnte? Die DS18B20 sollten auch bald bei mir 
aufschlagen. :-)

LG
Ernst

von cyblord (Gast)


Lesenswert?

> Hi Cyblord,
>
> hast die 1-Wire-Routine selbst geschrieben oder gibt es da eine Lib auf
> die ich zurückgreifen könnte? Die DS18B20 sollten auch bald bei mir
> aufschlagen. :-)
>
> LG
> Ernst

Hallo,
hab selber eine lib geschrieben, einfach stur nach Datenblatt.  Also 
erstmal eine lib nur für die 1wire kommunikation. Nicht explizit für den 
DS18B20.
Aber da ich vorher noch nie was mit 1wire gemacht habe, wollte ich da 
selber duchsteigen und keine fertigen libs benutzen. Nach einer Stunde 
lief die Kommunikation. Kann ich dir gern mal anhängen ist sehr 
minimalistisch. Aber dafür sollte es sowieso schon min. 10 libs geben.

gruß cyblord

von Cyblord -. (cyblord)


Angehängte Dateien:

Lesenswert?

Also hier mal der 1wire code.

Kurz zur Erläuterung:

in ow.h stellt man den Port ein welcher als 1wire dient.

zu beginn sollte man ow_init() aufrufen, hierbei werden die Portrichtung 
und idle states korrekt gesetzt. es wird auch gleich der interne Pullup 
aktiviert. Dieser ersetzt bei mir erfolgreich einen externen.

So wird der Code dann benutzt um direkt den 16 Bit Temp Wert des DS18B20 
auszulesen.
1
uint16_t readRawTemp() {
2
  uint16_t raw;
3
4
  ow_reset();
5
  ow_write(0xCC);
6
  ow_write(0x44);
7
8
  _delay_ms(1500);
9
10
  ow_reset();
11
  ow_write(0xCC);
12
  ow_write(0xBE);
13
14
  raw=ow_read(16);
15
  return raw;
16
}

von Mikrofun R. (mikrofun)


Lesenswert?

Hallo Helmut,

bei mir gab es mit den "Dannegger Routinen" timing-Probleme, weil die 
Wartezeiten irgendwie grenzwertig waren. Aufgefallen ist mir der kurze 
Delay von 1 µS in deiner Read-Bit routine.

Hier ist die Version, die bei mir auf einem ATMega2560 letztlich 
funktioniert hat, wobei ich hoffe, dass ich die Einzelteile hier richtig 
zusammenkopiert habe:

1
#define W1_PIN  PE0
2
#define W1_IN  PINE
3
#define W1_OUT  PORTE
4
#define W1_DDR  DDRE
5
#define DELAY_US(x)  ((uint)( (x) * 1e-6 * XTAL/1 )) //x=1..65535 for XTAL=4 MHz and prescaler=1
6
#define DELAY(x)  delay(x)
7
8
9
void delay( uint d )      
10
// Waits for d * 1/XTAL (with Timer1 prescaler=1)
11
// Uses TCNT1 which is incremented with frequency XTAL/1
12
{
13
  d += TCNT1;        // d = d0+ TCNT1
14
15
  while( (TCNT1 - d) & 0x8000 );  // while TCNT1 - TCNT1_Anfang < d0
16
}
17
18
19
uchar w1_bit_io( bit b )
20
{  //changed 2 µs into 4 µs everywhere in this function
21
  cli();
22
  W1_DDR |= 1<<W1_PIN;
23
  DELAY( DELAY_US( 4 ));
24
  
25
  if( b ) {
26
    W1_DDR &= ~(1<<W1_PIN);
27
    DELAY( DELAY_US( 10 - 4 ));
28
  } else
29
  DELAY( DELAY_US( 15 - 4 ));
30
  
31
  if( (W1_IN & (1<<W1_PIN)) == 0 )
32
    b = 0;
33
  DELAY( DELAY_US( 70 - 15 ));  //changed 60 µs into 70 µs here
34
  W1_DDR &= ~(1<<W1_PIN);
35
  sei();
36
  return b;
37
}

von cskulkw (Gast)


Lesenswert?

cyblord ---- schrieb:
> Halte ich für irrelevant in diesem Fall. Ich betreibe meine
>
> Ätzbadsteuerung mit einem Atmega8 (interner 8 MHZ OSC) und einem
>
> DS18B20. Und ich erzeuge alle Wartezeiten für den 1Wire Bus direkt mit
>
> _delay_us().
>
> 1. Funktioniert das bis heute ohne Probleme, 2. sehen die Signalzeiten
>
> im Logic Analyzer sehr gut und stabil aus. Der 1Wire Bus ist ja nun auch
>
> nicht besonders kritsch und es werden relativ große Toleranzen
>
> akzeptiert in der Spezifikation.
>
>
>
> gruß cyblord

Tu wichtig ...

Ich weiß nicht, ob die Delay-Funktion Genauigkeitsprobleme hat.

Wenn aber die Constante FCPU mit 10 Mhz eingestellt ist und der 
Taktgenerator mit 8 MHZ laufen sollte, dann kann die delay-Funktion 
nicht richtig zählen. Das und nur DAS war mein Hinweis.

Vielleicht sollte man bestimmte Aussagen nicht aus dem Zusammenhang 
reißen. Dann gäbe es auch keine Mißverständnisse.

von cyblord (Gast)


Lesenswert?

cskulkw schrieb:

> Wenn aber die Constante FCPU mit 10 Mhz eingestellt ist und der
> Taktgenerator mit 8 MHZ laufen sollte, dann kann die delay-Funktion
> nicht richtig zählen. Das und nur DAS war mein Hinweis.

Nein nicht nur DAS.

> Vielleicht sollte man bestimmte Aussagen nicht aus dem Zusammenhang
> reißen. Dann gäbe es auch keine Mißverständnisse.

Habe nichts aus dem Zusammenhang gerissen. Du hast sowohl auf die 
falsche F_CPU Einstellung ALS AUCH auf eine generelles Problem mit der 
delay.h hingewiesen.
Und ich habe auch nicht gesagt dass du damit falsch liegst, ich habe nur 
darauf hingewiesen dass dieses Problem (sofern es besteht) für eine 
1wire Kommunikation irrelevant ist, weil es eben trotzdem funktioniert.

gruß cyblord

von Mikrofun R. (mikrofun)


Lesenswert?

Mal eine generelle Frage:
Muss man sich beim 1-wire Bus eigentlich um Signalreflexionen z. B. am 
Temperatursensor oder am µC Ausgang Gedanken machen? In meinem Fall 
lagen dazwischen nur ein paar Zentimeter Leiterbahn, aber ich habe auch 
schon (sehr selten) Übertragungsfehler gehabt.

von Guck Mal (Gast)


Lesenswert?

Hast Du den C2 aus dem Datenblatt??

von Ernst B. (puravida)


Lesenswert?

Danke Dir Cyblord!

Mein Plan ist ja auch da mal selbst durchzusteigen aber wenn ich mich wo 
anhalten kann wenn ich nicht mehr weiter komme, dann bin ich da schon 
sehr froh darüber!

LG
Ernst

von Mikrofun R. (mikrofun)


Lesenswert?

> Hast Du den C2 aus dem Datenblatt??

Eben habe ich noch mal im Datenblatt des DS18S20 vom Reichelt-Server 
geschaut. Dort gibt es keinen C2. Der einzige Kondensator ist der 
interne Kondensator für die parasitäre Energieversorgung.

Was meinst Du genau?

von Lutz (Gast)


Lesenswert?

Er meint wahrscheinlich den C2 in der Schaltung im zweiten Post?
Und der kommt nicht aus dem Datenblatt. Denn der macht ja alles kaputt 
und gehört deshalb da weg! Wie sollen denn da noch saubere Flanken 
möglich sein? Das beeinflußt natürlich auch das Timing, da die 
erforderlichen Pegelstände sich erst später einstellen.

Übrigens: Die Aussage interner Oszillator mit 8 MHz (einen Quarz hat das 
Ding natürlich nicht, sondern einen RC-Oszillator!) und F_CPU mit 
1000000UL stellt noch keinen widerspruch dar, da 1 MHZ (und nicht 10 MHz 
wie behauptet) ja die Standardfuse ist.
Was auch immer das (64ms) bedeuten soll, ist mir aber schleierhaft.

von Helmut D. (Gast)


Lesenswert?

> Lutz schrieb:
> Was auch immer das (64ms) bedeuten soll, ist mir aber schleierhaft.

habe bei den Fuses folgendes ausgewählt: INTRCOSC_8MHz_6CK_64MS

> Lutz schrieb:
> Er meint wahrscheinlich den C2 in der Schaltung im zweiten Post?
> Und der kommt nicht aus dem Datenblatt. Denn der macht ja alles kaputt
> und gehört deshalb da weg! Wie sollen denn da noch saubere Flanken
> möglich sein? Das beeinflußt natürlich auch das Timing, da die
> erforderlichen Pegelstände sich erst später einstellen.

das könnte ich mir durchaus vorstellen, das das ein Problem ist. Ich 
habe das mit dem Kondensator wohl falsch rausgelesen aus dem Datenblatt. 
Habe gedacht, ich brauche ihn zum entstören.

von (prx) A. K. (prx)


Lesenswert?

Der Sensor wird hier nicht parasitär versorgt und C2 hängt zwischen VCC 
und GND. Weshalb sollte der stören? Notwendig ist er zwar nicht, weil 
der Sensor für die Unterstützung parsitärer Versorgung selbst einen 
Kondensator enthält, aber schaden tut er auch nicht.

von Horst H. (horha)


Lesenswert?

Hallo,

wenn er sich bei seinem 4,7 kOhm Widerstand auf Figure 1 + 5  im 
Datenblatt des 18B20 bezieht ist sein Vo == DQ also die Datenleitung und 
Vi ist Vdd.
Dann wäre C2 sehr unpassend.
Also wäre Vi und Vo vertauscht.

von Helmut D. (Gast)


Lesenswert?

> Horst Hahn schrieb:
> wenn er sich bei seinem 4,7 kOhm Widerstand auf Figure 1 + 5  im
> Datenblatt des 18B20 bezieht ist sein Vo == DQ also die Datenleitung und
> Vi ist Vdd.
> Dann wäre C2 sehr unpassend.
> Also wäre Vi und Vo vertauscht.

Habe den Kondensator entfernt, hat aber nichts gebracht. Sobald ich 
irgendwo ein Oszi auftreiben kann, werde ich mal meine Delay-Zeiten 
seitens des Mikrocontrollers nachmessen.

von Helmut D. (Gast)


Lesenswert?

Habe jetzt einen externen Quarz 8MHz eingefügt. Nun habe ich das 
Problem, dass ich selbst bei den folgenden Befehlen bei niedrigen 
delay-Zeiten nicht das erwartete messen kann.

DDRC=0xFF;
  while(1)
  {
     PORTC=0x00;
     _delay_us(1);
     PORTC=0xFF;
     _delay_us(1);
  }

 Dort kann nur jeweils eine reale Zeit von 265µs gemessen werden mit dem 
Oszi?? Obwohl ja eine Delayzeit von 1µs erwartet wird. Wie kann das 
sein?

von Karl H. (kbuchegg)


Lesenswert?

> _delay_us(1);
> Dort kann nur jeweils eine reale Zeit von 265µs gemessen werden

Optimizer nicht aktiviert?
F_CPU falsch angegeben?
Quarz ist zwar physisch drann, ist aber nicht aktiviert?

Kombination aus allen 3?

von Helmut D. (Gast)


Lesenswert?

> Karl Heinz Buchegger schrieb:
> Optimizer nicht aktiviert?
> F_CPU falsch angegeben?
> Quarz ist zwar physisch drann, ist aber nicht aktiviert?
>
> Kombination aus allen 3?

Wo kann ich den Optimizer aktivieren?
Habe F_CPU mit 8000000UL und auch schon mit 1000000UL angegeben, aber 
funktioniert trotzdem nicht.
Die Fuse EXTMEDFXTALRES_16KCK_64MS wurde ausgewählt für einen 8MHz 
Quarz.

von Helmut D. (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Optimizer nicht aktiviert?

Hab gerade nachgeschaut, er war nicht aktiviert...nun habe ich ihn auf 
Os aktiviert und siehe da-> es geht!!

Danke für den Tipp.

von Ernst B. (puravida)


Lesenswert?

cyblord ---- schrieb:
> Also hier mal der 1wire code.
>
> [...]

Hi!

Heute kamen endlich die Sensoren und ich habe Deinen Code ausprobieren 
können. Funktioniert auf anhieb. Und ist auch gut zu durchschauen. Jetzt 
überlege ich ob ich bei Deinem weiter aufbaue für Rom-Search und so 
weiter oder ob ich mir den Dannegger-Code mal anschaue...

Sag, warum verwendest Du noch die deprecated.h? Hat das einen bestimmten 
Grund?

Lg
Ernst

von Cyblord -. (cyblord)


Lesenswert?

Ernst B. schrieb:
> cyblord ---- schrieb:
>> Also hier mal der 1wire code.
>>
>> [...]
>
> Hi!
>
> Heute kamen endlich die Sensoren und ich habe Deinen Code ausprobieren
> können. Funktioniert auf anhieb.
Das freut mich!

> Sag, warum verwendest Du noch die deprecated.h? Hat das einen bestimmten
> Grund?

Ich benutze gerne die sbi() und cbi() Makros und die sind da halt drinn 
weil deprecated ;-)

von Ernst B. (puravida)


Lesenswert?

cyblord ---- schrieb:

> Ich benutze gerne die sbi() und cbi() Makros und die sind da halt drinn
> weil deprecated ;-)

Habe ich eh gesehen, habe ich wieder rausgeworfen das sbi() und cbi(). 
gg

Jetzt kämpfe ich gerade mit der Umrechnung. Versuche mich da in 
Festkommarithmetik aber nach einer Multiplikation bekomme ich plötzlich 
ein Minus vor meine Zahl... :-))

von Cyblord -. (cyblord)


Lesenswert?

Ernst B. schrieb:

> Jetzt kämpfe ich gerade mit der Umrechnung. Versuche mich da in
> Festkommarithmetik aber nach einer Multiplikation bekomme ich plötzlich
> ein Minus vor meine Zahl... :-))

In der Codesammlung habe ich letztens erst Code für ein "1Wire Display" 
eingestellt, dort ist eine Funktion drinn welches die Temperatur in 
einen String umwandelt. Mit einer Nachkommastelle.

gruß cyblord

von Ernst B. (puravida)


Lesenswert?

cyblord ---- schrieb:
> In der Codesammlung habe ich letztens erst Code für ein "1Wire Display"
> eingestellt, dort ist eine Funktion drinn welches die Temperatur in
> einen String umwandelt. Mit einer Nachkommastelle.
>
> gruß cyblord


Danke, werde ich mir anschauen. Aber ich habe es gestern eh noch lösen 
können. Ich stolpere immer wieder in die Überlauf-Falle. (in dem Fall 
war es itoa) :-) Habe die Temp jetzt zwei Nachkommastellen und die 
letzte Stelle kaufmännisch gerundet.

Was meinst, sollte ich den Rom-Search einbauen in meinen Code obwohl ich 
in der praktischen Umsetzung eh nur 1 one-wire Produkt dran hängen habe? 
G'hörat sich das?

von Ernst B. (puravida)


Lesenswert?

@Cyblord:

Ich habe jetzt zwar ein bisl gebraucht um zu durchschauen was Du da 
eigentlich machst bei der Umrechnung aber ich bin ziemlich begeistert. 
Vor allem, weil ich wohl selbst nicht auf die Idee gekommen wäre das so 
anzugehen und wieder eine Menge gelernt habe. Danke dafür!

LG
Ernst

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.