Forum: Mikrocontroller und Digitale Elektronik 1-Wire Temperatursensor DS18S20 mit Atmega8 Ansteuern


von Jonix (Gast)


Lesenswert?

Hallo zusammen,

ich versuche schon seit mehreren Wochen mit dem Atmega8 den digitalen 
1-Wire Temperatursensor DS18S20 anzusteuern und die Temperatur 
auszulesen.

Leider hat bis jetzt erst die Initialisierung geklappt, ich habe es noch 
nicht geschafft, dem Sensor ein brauchbares Byte zu entlocken.

Vielleicht kann mir ja einer von euch sagen, was ich falsch gemacht 
habe. Hier sind meine Lese- und Schreibroutinen, ich denke dass hier der 
Fehler versteckt ist:
1
Schreibe1:
2
out DDRD, Hi    ; Sensor Ausgang
3
cbi PORTD,7    ; Sensor 0
4
rcall Wait10    ; Warte 10µs
5
sbi PORTD,7    ; Sensor 1
6
rcall Wait58    ; Warte 58µs
7
ret
8
9
Schreibe0:
10
out DDRD, Hi    ; Sensor Ausgang
11
cbi PORTD,7          ; Sensor 0
12
rcall Wait10    ; 10µs warten
13
rcall Wait58    ; 58µs warten
14
out PORTD,7    ; Sensor 1µs Recovery Time
15
rcall Wait2    ; 2µs Recovery Time
16
ret
17
18
Lesen:
19
out DDRD,Hi    ; PORTD Ausgabe
20
out PORTD, Lo          ; Pulldown
21
rcall Wait2    ; 2 µs
22
out DDRD, Lo          ; PIND Eingang
23
rcall Wait10          ; Warte 10µs
24
rcall Wait2    ; Warte 2µs
25
in r24, PIND          ; Lese PIND
26
or r25, r24    ; Wert von Pin 7 in r25 schreiben
27
lsr r25      ; Eine Stelle nach rechts schieben
28
ret

Ein Fertig ausgelesenes Byte soll dann am Ende im Register r25 stehen.

Hier als Hilfe noch der Link zum Datenblatt des Sensors:
http://datasheets.maxim-ic.com/en/ds/DS18S20.pdf

Im Datenblatt steht außerdem, dass der Sensor bei der Ausgabe immer mit 
dem niedrigsten Bit anfängt, muss dann auch beim Schreiben eines Befehls 
mit dessen niedrigsten Bit anfangen?

Vielen Dank für eure Hilfe schon mal im Voraus

von Wolfgang S. (wsm)


Lesenswert?

hab auch damit (erfolgreich) experimentiert.

hast du eine Versorgungsspannung angeschlossen?

Während der AD-Wandlung braucht der 18S20 das.

Ohne die Versorgungsspannung klappt nur die Initialisierung.



W.

von Jonix (Gast)


Lesenswert?

Ich denke ich habe alles  korrekt angeschlossen.

Ich betreibe ihn  mit externer Stromversorgung, GND->GND, DQ->µC, 
VDD->+5V und mit 4,7k gegen DQ.

von Andy H. (vinculum) Benutzerseite


Lesenswert?

Dazu gibt es ja jede Menge Code im Internet. Da würde ich das Rad nicht 
neu erfinden.

von Jonix (Gast)


Lesenswert?

Im Datenblatt des Sensors steht folgendes:
" To generate a Write 1 time slot, after pulling the 1-Wire bus low, the 
bus master must release the 1-Wire
bus within 15μs " ( http://datasheets.maxim-ic.com/en/ds/DS18S20.pdf )

Bedeutet "release the bus" das ich den µC Pin in Richtung Ausgang auf 1 
setze, oder dass ich den Pin als Eingang setzen soll?

von Tim (Gast)


Lesenswert?

"release the bus" == Finger weg! == Eingang.
Der Code oben sollten passen.

Wegen der Reihenfolge:
Ich sende Bit 0 und schiebe dann 1 nach rechts.
Beim lesen schiebe ich 1 nach rechts und speichere in Bit 7.
Ergo immer kleinstes Bit zuerst.

Genereller Ablauf bei einem Device:
1. Bus reset
2. SKIP ROM Command (CCh)
3. Convert Command (44h)
4. 1 Sek warten.
5. Bus reset
6. SKIP ROM Command (CCh)
7. Read Scratchpad Command (BEh)
8. jetzt 2-9 Byte lesen (Temperatur + x + CRC)

Unbedingt das Timing einhalten.
Ein Oszi hilft.

von Gim (Gast)


Lesenswert?

ignoriert mich, wenn ich mich irre, aber man muss doch den DS18S20 ueber 
eine Adresse ansprechen, kennst Du diese und machst Du das richtig?

von Tim (Gast)


Lesenswert?

@Gim:
Ja, 1-Wire Slaves kann man über ihre Adresse ansprechen.
Die muss man aber vorher erst mal ermitteln.
Wenn nur ein Slave am Port hängt kann man sich den
Aufwand sparen (SKIP ROM).

von mage (Gast)


Lesenswert?

Hi,
könntest du mal den ganzen code posten, weil ich bei 1Wire auch nicht 
richtig durchblicke und dein code gut kommentiert ist. Kleine Fehler 
stören nicht.

von Tim (Gast)


Lesenswert?

Sorry, ich hatte deinen ASM Code nur kurz überflogen...
(ASM ist bei mir schon eine weile her...)
Mir sind da jetzt doch ein parr Dinge aufgefallen....

Wie hast du Hi und Lo definiert?
Sind das 2 Register die 0xff bzw. 0x00 enthalten?
Ich frage so blöd weil du out anstatt sbi/cbi verwendest...

Nach "Schreibe1:" und "Schreibe0:" bleibt der Port
als Ausgang konfiguriert. Laut pdf muss der Port aber
hochohmig werden -> Eingang.
Setze doch PORTD Bit 7 nach dem Reset auf 0 und
Schalte NUR noch DDRD Bit 7.

Was soll das machen? Bzw. was steht in r7?
1
Schreibe0:
2
[...]
3
out PORTD,7    ; Sensor 1µs Recovery Time
Oder hätte das vielleicht sbi sein sollen?

in "Lesen:" veroderst du jedes mal das gesamte PIND Register:
1
in r24, PIND          ; Lese PIND
2
or r25, r24    ; Wert von Pin 7 in r25 schreiben
3
lsr r25      ; Eine Stelle nach rechts schieben
Hast du sichergestellt das die restlichen Pins 0 haben?
Sonst streust du dir da munter irgendwelche Bits ein.
Außerdem blockierst du so den gesamten PORTD für weitere Nutzung...
Ein andi r24, 0x80 hilft.


Ansonsten Poste mal mehr Code.

von Peter D. (peda)


Lesenswert?


von Jonix (Gast)


Angehängte Dateien:

Lesenswert?

Vielen Dank für eure Antworten, dadurch bin ich auf sehr viele Fehler 
aufmerksam geworden.

Im Anhang ist mein ganzer Assembler Quellcode, ich hoffe er ist 
einigermaßen übersichtlich.
Verzeit bitte, dass ich bei den Befehlen jedes Bit einzeln mit rcall 
Befehlen übertrage, ich möchte das Programm erst einmal so einfach wie 
möglich halten und wenn es dann funktioniert mit der Vereinfachung und 
Optimierung beginnen.

@ Tim:
- ich wusste nicht, dass man die Datenrichtungsregister direkt mit 
"cbi/sbi" als Ausgang/Eingang konfigurieren kann, deswegen habe ich 
alles mit "out" gemacht, habe es jetzt abgeändert
- nach "Schreibe0" und "Schreibe1" DDRD als Eingang --> geändert
- Das "out" bei "Schreibe0" war ein Tippfehler --> geändert
- Schau mal ob du das mit dem andi so gemeint hast:
1
in r24, PIND         ; Lese PIND
2
andi r24,0b10000000  ; Bit 0-6 null setzen
3
or r25, r24          ; Wert von Pin 7 in r25 schreiben
4
lsr r25              ; Eine Stelle nach rechts schieben

von Peter R. (pnu)


Angehängte Dateien:

Lesenswert?

Es kommt vielleicht etwas spät, aber im Anhang meine funktionierende 
asm-Lösung

von Tim (Gast)


Lesenswert?

> - ich wusste nicht, dass man die Datenrichtungsregister direkt mit
> "cbi/sbi" als Ausgang/Eingang konfigurieren kann, deswegen habe ich
> alles mit "out" gemacht, habe es jetzt abgeändert

Kommt auf den AVR und das gewünschte register an...
Cbi/sbi kann nur IO-Adressen 0x0..1F bearbeiten.
Da beim M8 der Port D auf 0x10..12 liegt (Siehe Register Summary) geht 
das.
Bei grösseren AVRs reicht dann teilweise in/out nicht mehr da
in/out nur 0x00..0x3f kann :-)

> - Schau mal ob du das mit dem andi so gemeint hast:
Ja, genau so.

1
ConT:
2
[..]
3
; Warte bis Temp. konvertieren fertig
Du liest hier nur den Pin zustand aus.
Die PDF sagt aber: "...the master can issue read-time slots after 
the..."
== rcall Lesen + auswertung
Habe ich mir gespart. 1 Sek warten war einfacher ;-)

> - nach "Schreibe0" und "Schreibe1" DDRD als Eingang --> geändert
> - Das "out" bei "Schreibe0" war ein Tippfehler --> geändert
Hmm... Dachte eigentlich das du NUR noch DDRD änderst.
Also nach deinem Stack init ein cbi PORTD, 7.
Und wenn der Bus 0 haben soll, einfach der Port via DDRD als
Ausgang setzten, ansonsten Eingang. Der Externe 4,7K Pullup
sorgt schon für die 1 auf der Leitung. Oder ist die zu lang?
1
Schreibe1:
2
[..]
3
Schreibe0:
4
[..]
5
rcall Wait2      ; 2�s Recovery Time
Lösche da den PORTD kram mal raus.
Wozu rcall Wait2?

1
Lesen:
2
rcall Wait2      ; 2 �s
3
cbi DDRD, 7      ; PIND Eingang
4
rcall Wait10    ; Warte 10�s
5
rcall Wait2      ; Warte 2�s
Du liest nach 2+10+2 µS, das könnte etwas (2µS) zu lang sein...
1
or r25, r24      ; Wert von Pin 7 in r25 schreiben
2
lsr r25        ; Eine Stelle nach rechts schieben
== Neues Bit vom Bus in Bit 7 dann alles 1 nach rechts (und Bit7 = 0)
So hast du nach 8 lesezugriffen: Bit 7 = 0, Bit 6-0 = Bits 7-1 vom Bus.
Bit 0 vom Bus ist weg. Also die 2 Zeilen drehen.

von Jonix (Gast)


Angehängte Dateien:

Lesenswert?

So, ich habe das Programm mal abgeändert, dass es nach der Temperatur 
Konvertierung eine Sekunde wartet.
Jetzt habe ich auch verstanden wie du das mit dem "nur DDRD setzen bzw. 
löschen" meinst, habe ich auch geändert.

Wegen dem "Wait2" bei "Schreibe0", das steht doch im Datenblatt auf 
Seite 14 in dem Diagramm. Nach "Master Write 0 Slot" steht dort "2µs < 
Trec < ∞ ", deswegen warte ich 2 µs. Korrigiere mich bitte wenn ich mich 
irre.

Beim Lesen steht im Diagramm auch, dass der Master erst ganz am Ende 
Sampeln soll, grob abgelesen nach 14µs

Die Zeilen mit dem lsr habe ich jetzt vertauscht, du hast natürlich 
recht.


Der entscheidende Fehler lag aber an der Länge des Lese-Timeslots. Der 
Slot muss ja laut Datenblatt mindestens 60 µs + Recovery Time dauern, 
ich habe jedoch gleich nach dem lesen nach 14 µs mit dem Nächsten Bit 
begonnen, das war der Fehler.
Jetzt warte ich nach dem Lesen einfach noch mindestens 45 µs + mind. 1 
µs Recovery time, und sofort hat es funktioniert.

Also Vielen dank für eure großartige Hilfe, ohne euch hätte ich es 
trotzdem nicht geschafft

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.