Forum: Mikrocontroller und Digitale Elektronik Dallas 18S20 Reset Problem


von moehrlin (Gast)


Lesenswert?

Was habe ich falsch gemacht! Oder ist mein Sensor defekt?

// Sensor-Reset
uint8_t reset(void)
{
  DQ_DDR|=(1<<DQ_uC);    // DQ_uC als Ausgang setzen
  DQ_PORT&=~(1<<DQ_uC);    // DQ_uC an DQ_PORT auf 0 setzen
  _delay_us(480);

  DQ_DDR&=~(1<<DQ_uC);    // DQ_uC als Eingang setzen
  DQ_PORT|=(1<<DQ_uC);    // DQ_uC an DQ_PORT auf 1 setzen
  _delay_us(60);

  if(!(DQ_PIN & (1<<DQ_uC)))  // Erfüllt wenn DQ_uC auf 0 liegt
  {
    return(1);
  }

  return(0);
}

Diese Funktion sollte eine 1 zurückgeben, es kommt aber immer eine 0 
zurück. Ich kann keinen. Wenn ich extern mit einer Drahtbrücke den DQ_uC 
Pin auf GND lege kriege ich eine 1 zurück. Die Funktion scheint also zu 
stimmen.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Stimmen die Zeiten in den delay Funktionen? Fuses, F_CPU und kompilieren 
mit Optimierung AN prüfen.

Wenn das nix hilft, ich habe einen DS18S20 hier und kann am Wochenende 
auch mal testen. Der funktioniert auch, denn dieses Jahr hatte ich schon 
mal ein DS18S20 Problem hier im Forum debuggt (#1). Müsstest dann nur 
erzählen/zeichnen, wie der DS18S20 bei dir angeschlossen ist.

#1 Beitrag "DS18S20, Atmega8 und Winavr"

von Lutz (Gast)


Lesenswert?

>DQ_DDR&=~(1<<DQ_uC);    // DQ_uC als Eingang setzen
>DQ_PORT|=(1<<DQ_uC);    // DQ_uC an DQ_PORT auf 1 setzen

Wenn ich mich auf die Schnelle nicht vertue, schaltetst Du mit der 
letzten Zeile den pull-up-widerstand ein; am EingangsPIN wird dann 
natürlich eine 1 gemessen, sofern die externe Beschaltung den pin nicht 
runterzieht.

von Anton (Gast)


Lesenswert?

Es könnte sein, dass die letzte Pause länger sein muss.
Bevor der Status zurueckgegeben wird, muss eine Pause der Länge "J" 
(1wire app note von Maxim) abgewartet werden.
Zumindest habe ich das mal in meiner verwendeten 1wire-Bibiothek so 
geändert, da ich auch mal das Problem hatte. Zumindest funktioniert es 
bei so einwandfrei.
Du musst ja mindestens 60us warten. Ich warte bei mir 480us auf den 
presence pulse, was eigentlich zu lange ist, wie ich gerade im 
Datenblatt nachgeschaut habe.
Also mit 180us Pause (statt Deiner 60us) müsstest Du genau drin liegen. 
Das werde ich bei mir nochmal überprüfen müssen ...

von moehrlin (Gast)


Lesenswert?

@ Lutz: Soweit ich das Datenblatt richtig deuten, zieht man den DQ-Pin 
des DS18S20 480µs auf low, "released" die Leitung für 15-60µs und wartet 
darauf, dass der Sensor mit seinem "Presence Pulse" von 60-240µs die 
Leitung auf LOW zieht.

von Lutz (Gast)


Lesenswert?

Da hast Du recht.

Vielleicht bin ich bisher fälschlicherweise von allerhand falschen 
Voraussetzungen ausgegangen, wie z.B. daß Du einen AVR uC ATMega (z.B. 
ATMega 168) benutzt.

Den 4k7 Pullup, der den Bus nach dem reset wieder "hochholt", wird ja 
bestimmt vorhanden sein.

Der Master muß für mindestens 480 us den DS18S20 low ziehen. Versuch 
spaßeshalber mal _delay_us(520) statt der 480.

Bei ATMegas gilt: Wenn ein Pin im DDR auf Eingang (DDRpin=0) geschaltet 
wurde und danach im PORT eine 1 (PORTpin=1) geschrieben wurde, wird an 
diesem Eingang der interne Pullupwiderstand aktiviert. Und das machst Du 
unnötiger Weise in der zweiten Zeile (vermute ich). Interessant wäre es, 
wenn Du die #defines Deiner pins posten könntest.
>DQ_DDR&=~(1<<DQ_uC);    // DQ_uC als Eingang setzen
>DQ_PORT|=(1<<DQ_uC);    // DQ_uC an DQ_PORT auf 1 setzen
Pullup macht schon der 4k7 am Bus. Das der interne Pullup und der 
externe 4k7 Pullup sich nun in die Haare kriegen (interner Pullup treibt 
stärker als der DS18S20 lowziehen kann) halte ich für unwahrscheinlich, 
da der interne Pullup der Größere ist.

von (prx) A. K. (prx)


Lesenswert?

Der interne Pullup stört nicht weil viel zu gross. Interessanter ist in 
dieser Hinsicht das andere Ende, auch wenn das hier nicht die Ursache 
ist: Wenn ein als Open Collector zu verwendender Portpin erst als 
Ausgang definiert und dann runtergezogen wird, dann zieht er u.U. erst 
einmal kurz aber knackig hoch. Da ist dringend die umgekehrte 
Reihenfolge empfohlen, wobei man eine solchen Pin auch gleich anfangs 
dauerhaft auf PORTxy=0 setzen und danach ausschliesslich mit der 
Richtung steuern kann.

von moehrlin (Gast)


Lesenswert?

1
#define DQ_PIN  PINB
2
#define DQ_uC   PB2 
3
#define DQ_DDR  DDRB
4
#define DQ_PORT PORTB
5
6
#define F_CPU 8000000

von Lutz (Gast)


Lesenswert?

>DQ_DDR|=(1<<DQ_uC);    // DQ_uC als Ausgang setzen
heißt mit Deinen #defines
DDRB |= (1<<PB2);
            ^^^
=> Muß aber DDB2 heißen.

Schau Dir mal die anderen #defines und das Datenblatt (speziell also die 
PORTx-, DDRx- und PINx-Register sowie ihre Bedeutung) an.

Die Zeile
if(!(DQ_PIN & (1<<DQ_uC)))
sieht dann auch nicht so gut aus ...

von (prx) A. K. (prx)


Lesenswert?

Lutz wrote:

> DDRB |= (1<<PB2);
>             ^^^
> => Muß aber DDB2 heißen.

Kann, muss aber nicht, denn das ist so oder so nichts anderes als 
(1<<2). Grad wenn man Portpins zentral per #define zuordnet ist es bloss 
unnütze Arbeit, da noch zwischen PINxy, PORTxy und DDRxy zu 
unterscheiden.

von Lutz (Gast)


Lesenswert?

Da ist natürlich was dran, obwohl das natürlich (wie so vieles) 
Geschmackssache ist. Aber wenn man das konsequent durchzieht, warum 
nicht.

Das Problem ist aber, das man (zumindest als Anfänger) den Unterschied 
zwischen DDRx, PORTx und PINx so gar nicht wahrnimmt ("es funktioniert 
doch, wo ist denn das Problem?"), was früher oder später garantiert zu 
gravierenden Problemen führt.

von moehrlin (Gast)


Lesenswert?

hab mal das beispiel hex file auf mein entwicklungsboard geflasht! 
temperatur sensor funktioniert einwandfrei! leider hab ich von dem hex 
file keine sourcen ;-( (habe das EASY AVR 5A)

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.