Forum: Projekte & Code Mehrere DS1820/DS18B20 auslesen


von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

Da hier im Forum doch größere Probleme bei der Verwendung der Maxim 
Temperatursensoren auftreten, anbei nun meine 8051-Routine auf einem 
ATTINY12 in Assembler implementiert.

Eine ausführliche Beschreibung werde ich später dazustellen.


Die Sensoren werden über Parasite-Power versorgt, d.h. es reicht eine 
2-Draht-Leitung aus. Dazu wird der 1-Wire-Portpin während der Wandlung 
als Ausgang geschaltet.
Da die DS18B20 bis zu 750ms benötigen, wird für eine Wandlung 1s 
gewartet. Während dieser Zeit können die Sensoren nicht ausgelesen 
werden.

Mittels einer Taste kann zwischen den Sensoren umgeschaltet werden.

Die Temperatur wird beim DS18B20 in 0,1°C-Schritten angezeigt.


Als Pull-Up habe ich 2,2kOhm verwendet.
Das ganze habe ich mit 7 Sensoren an 20m Klingeldraht getestet.


Peter

von Bastian (Gast)


Lesenswert?

Hallo Peter,

wie steuerst du einzelne ds1820 im bus über das eeprom an?
du meintest mal, man sollte jedem eine nummer geben und dann diese
ansprechen. hast du da eine routine für?


Gruss

Bastian

von Peter D. (peda)


Lesenswert?

Code für den AVR habe ich nicht.

Wie man einen Wert speichert, steht im Datenblatt.

Und beim Auslesen der Temperatur liest man diesen Wert eben mit aus und
vergleicht ihn, ob es die gewünschte Messtelle ist.

Mann kann ihn aber auch als Index nehmen, an welcher Adresse in einer
Tabelle die Temperatur zu speichern ist.
D.h. man speichert alle Werte ab und hat sie dann in der Tabelle nach
der Nummer die im EEPROM steht sortiert vorliegen.


Peter

von Bastian (Gast)


Lesenswert?

Achso, ich dachte man könnte direkt die Adresse zum ansprechen des
Sensors im EEPROM speichern.

Wenn man mehrere Sensoren am Bus hat muss man ja jeden einzeln zum
abfragen adressieren

von Peter D. (peda)


Lesenswert?

"Wenn man mehrere Sensoren am Bus hat muss man ja jeden einzeln zum
abfragen adressieren"

Eben nicht !

Mit dem ROM-Search wird einer nach dem anderen adressiert und kann
ausgelesen werden. Aber wer der erste und wer der letzte ist, ist von
den Adressen abhängig. Es ergibt sich also eine zufällige Reihenfolge,
deshalb der Trick mit der Indexadresse im EEPROM.


Ein Beispiel:

Der Sensor für die 5.Messtelle wird beim ROM-Search z.B. als 3.
gefunden. Aber die Nummer 5 im EEPROM bewirkt, daß dessen
Temperaturwert in der Meßwerttabelle an 5. Stelle abgespeichert wird.

Nun ist er kaputt und durch einen anderen ersetzt worden, dem ebenfalls
die 5 in den EEPROM geschrieben wurde.
Der neue wird jetzt aber z.B. als 6. gefunden. Aber die Nummer 5 im
EEPROM bewirkt wieder, daß er in der Meßwerttabelle an 5. Stelle
abgespeichert wird.


Peter

von Bastian (Gast)


Lesenswert?

Ich fürchte das ist im Moment noch zu komplex für mich. Das krieg ich
noch nich hin. Muss mich erstmal genauer mitm AVR und Assembler
vertraut machen. Mal sehen wann ich soweit bin mal 1Wire Routinen
richtig zum laufen zu bringen..

von Spatz2222 (Gast)


Lesenswert?

Hallo Peter,

ich habe folgendes Programm ich habe ein Bus mit 5 Ds1820

diese lese ich der Reihe nach mit ROM-search aus.
funkt. auch recht gut ...

jetzt kann es aber in meinem Einsatz passieren, daß mal ein Sensor
kaputt geht oder die Strippe zum Sensor abreißt.
Nun überspringt einfach ROM-Search den def. Sensor und macht mit dem
nächsten weiter ... und da ich die Werte in ein EEProm speichere kommt
da so einiges durcheinander.
Ich will das so machen wenn der eine nicht mehr ansprechbar ist das
soll z.B. der ausgelesen Wert auf 0 gehen etc.

jetzt habe ich das mit der Adressierung über das EEProm gelesen ...
bin aber im Datenblatt nicht ganz schlau geworden !

kannst Du das mal bitte ganz grob erläutern wie man das eeprom
beschreibt und wie die Adressierung dann aussieht ?


ich mach das jetzt wie folgt : (halb Basic ...)
'****************************************************
reg_nr(1-8) = ROMsearch
Match ROM
Convert
Match ROM
Read RAM
Empf1 = Scratch(1)
'****************************************************

man könnte zwar die Adressen der einzelnen Ds1820 vorher im Programm
speichern jedoch würde das viel RAM verbrauchen ...


Gruß Tobias

von Peter D. (peda)


Lesenswert?

@Tobias,

ich habs ja oben schon versucht zu erklären:

Wenn Du nach Auslesen der Temperatur noch die 2 nächsten Bytes liest,
sind das die beiden EEPROM-Bytes, die du frei verwenden kannst, z.B.
als Meßstellennummer.

Und diese EEPROM-Bytes must Du eben irgendwann einmal entsprechend
beschrieben haben. Wie man das macht geht am besten aus dem
Flußdiagramm im Datenblatt hervor.


Peter

von Spatz2222 (Gast)


Lesenswert?

gut die zwei Byte zu beschreiben sollte kein Problem sein ...
jedoch wie jetzt Adressieren ? mit ROM-Search und dann abfragen ob z.B.
das z.B. Sendor 3 ist oder so ? oder kann man den dirket adressieren
über diese 2 Bytes ?

aber ich denke mal nicht ...


Aber die Antwort hat schon weitergeholfen Danke !


Gruß Tobias

von Peter D. (peda)


Lesenswert?

"jedoch wie jetzt Adressieren ? mit ROM-Search und dann abfragen ob
z.B.
das z.B. Sendor 3 ist oder so ?"

Ganz genau !

Um nur einen bestimmten Sensor auszulesen must Du dann solange
ROM-Searchen, bis der richtige gefunden ist.


Peter

von Spatz2222 (Gast)


Lesenswert?

Peter ich Danke Dir... - hat mir sehr geholfen !

also noch einen schönen Abend !

von Peter-Christian Carstens (Gast)


Lesenswert?

Hi, habe es mit 8051 Assembler hingekriegt, eine DS2401 Seriennummer
oder einen DS1821 Temperatursensor auszulesen. Brauche jetzt mal eine
8051-Assembler Routine "ROM-Search" die mir alle Seriennummern
anzeigt die auf dem Bus sind. Flussdiagramm dazu habe ich aber ist mir
doch ein wenig zu mühselig dass alles umzusetzen..
Mit besten Grüssen

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

@Peter-Christian

Anbei die 1-Wire Funktionen in 8051 Assembler.

Der Aufruf erfolgt genauso wie im C-Programm.


Peter

von Tobias (Gast)


Lesenswert?

Hallo alle,
ich bin auf der Suche nach einem DS1820, der in einem Wandgehäuse
montiert ist und mit Schraubklemmen o.ä. an ein Kabel angeschlossen
werden kann.
Habt Ihr eine Ahnung, wo es sowas fertig zu kaufen gibt?
Liebe Grüße
Tobias

von SIMON AMIR (Gast)


Lesenswert?

I want to buy 300 parts of DS1820 , 3pin ,pr35 package.

von Elektrikser (Gast)


Lesenswert?

Hallo Peter,
führe mir gerade deinen Code für den Attiny12 zu Gemüte. Ich habe es
zwar geschafft einen einzelnen DS1820 mit einem Atmega8L auszulesen und
als Thermometer zu verwenden, aber jetzt will ich mehrere an einem Bus
hängen. Ich programmiere in AVR-GCC. Ich habe aber das ROM-Search noch
nicht ganz begriffen. Du hast in deinem ersten Post geschrieben:
"Eine ausführliche Beschreibung werde ich später dazustellen."
Das würde mir vielleicht ein ganz schönes Stück weiterhelfen, oder eine
bessere Kommentierung :-)
Der Ablauf, wie ich ihn verstehe:
-Reset
-Such-Kommando senden: 0xF0
-Erstes Bit lesen
-Zweites Bit lesen (Komplement-Bit)
-Master sendet erstes Bit zurück ->derjenige Busteilnehmer, der diesen
Wert hat, bleibt noch aktiv, der Rest wartet.

Das mache ich dann mit allen 63-Bit,bis einer übrig bleibt, oder?
Also immer 2 Bit empfangen und eines senden.
Habe ich das, kann ich ihm in seinen Scratchpad eine Nummer vergeben.
Dann mache ich diese Sucherei solange, bis ich alle gefunden habe und
ihnen eine Nummer vergeben habe.
Habe ich das richtig verstanden, oder gibt es noch einen anderen Weg?

Gruß Elektrikser

von mthomas (Gast)


Lesenswert?

Hilft nicht direkt weiter, aber: Wenn man etwas Controller-Speicher frei
hat (z.B. im AVR-EEPROM), kann man sich auch die eindeutigen ROM-Codes
(Family-Code, Seriennummer, evtl. auch CRC) "merken" und muss nicht
in das Scratchpad des DS18x20 schreiben. Indizierung dann ueber den
gespeicherten Code. Etwas komplexer zu programmieren, aber koennte
einfacher handhabbar sein, falls ein (oder mehr) defekter(e) Sensor(en)
ausgetauscht werden mu(e)ss(en).

Von Peter Dannegger wurde im Thread
http://www.mikrocontroller.net/forum/read-4-84831.html#102216
"fertiger" avr-gcc-Code bereitgestellt.

Bei der Gelegenheit: Danke dafuer, Peter.

von Elektrikser (Gast)


Lesenswert?

O.K. dann habe ich das falsche erwischt.
Werde mir das mal ansehen. Ich habe mittlerweile das AN162 bei Dallas
gefunden. Das hilft auch schon weiter, obwohl es ein C-Code für ein
8051er ist. Aber so viel scheint sich da nicht zu ändern. Der Code für
den Rom-Search ist dort schon größer als meine Auswertung des einen
DS18S20.
Jetzt hilft nur noch try and error.

Gruß Elektrikser

von Peter D. (peda)


Lesenswert?

"Jetzt hilft nur noch try and error."

Warum ?

Das was Du oben geschrieben hast, ist doch vollkommmen richtig.
So macht es auch mein Programm.


Peter

von Elektrikser (Gast)


Lesenswert?

In C bin ich noch ein relativ blutiger Anfänger. (Mein Einstieg war
Assembler mit den 8051ern.) Aber ich habe es mir in den Kopf gesetzt
und jetzt wird es probiert. Dafür, dass ich vor fünf oder sechs Wochen
damit richtig angefangen habe, geht es gar nicht mal so schlecht.

Keine Angst, wenn ich Bahnhof verstehe, melde ich mich wieder! :-)

Gruß Elektrikser

von Elektrikser (Gast)


Lesenswert?

Hallo Peter,

Ich habe mir jetzt dein Programm für den AVR angesehen (den Link, den
mthomas gepostet hat: 1wire.zip). Ich habe noch ein Verständnisproblem,
vielleicht hilfst du mir:
"uchar w1_rom_search( uchar diff, uchar idata *id )"

Die Funktion habe ich im groben verstanden, komme aber mit der Übergabe
der Funktion nicht klar. idata hast du in der main.h definiert. *id ist
ja ein Zeiger, der in der Tempmeas.c durch den Aufruf:
"diff = w1_rom_search( diff, id );"
auf die erste Adresse des ersten Feldes von id[8] zeigt. Soweit ok.
Was bezweckt dieses idata? Warum schreibst du nicht einfach uchar *id?


Gruß Gerd G. (Elektrikser)

von Peter D. (peda)


Lesenswert?

Das Programm habe ich ursprünglich für den 8051 geschrieben, für den AVR
hab ich "idata" einfach drin gelassen.

Der 8051 hat verschiedene Speicherbereiche, "idata" ist besonders
schnell und codesparend zugreifbar und erlaubt auch viele Operationen
direkt auszuführen, ist aber auf 256 Byte beschränkt.

"data" ist für häufige und lokale Variablen, "idata" für kleine
Datenfelder und "pdata" oder "xdata" für selten benötigte Variablen
oder große Felder (bis 64kB).

Beim 8051 kann man also durch geschickte Auswahl des Speichersegments
besonders schnelle und codesparende Programme schreiben.


Peter

von Elektrikser (Gast)


Lesenswert?

Aber bringt das beim AVR etwas? Wo kann ich darüber Infos bekommen?
Naja, werde dein Programm compilieren und mal damit rumspielen. Später
werde ich das ROM-Search mal in mein Programm einbauen.

Danke für die Hilfe,

Gerd

von Elektrikser (Gast)


Lesenswert?

Danke Peter,
für deine Hilfe. Mit Hilfe deines Programmes habe ich das jetzt zum
Laufen gebracht.
Gruß gerd

von Peter D. (peda)


Lesenswert?

"Aber bringt das beim AVR etwas?"

Nein, der kann ja sowas nicht.
Deshalb wird es dort auch durch nichts ersetzt:

#define idata

Ist einfacher, als sämtliche Quelltexte umzueditieren.


Peter

von Elektrikser (Gast)


Lesenswert?

Habe es mir schon gedacht. Aber da hatte ich diese Zeile in der main.h
überlesen gehabt.
Muß mir das beim 8051er ansehen. Ich programmiere da zwar immer noch
mit Assembler, aber das mit dem Speicherbereich ist interessant. Werde
mal meine Unterlagen wälzen, mal sehen was ich da so finde. Irgendwie
scheint mir da was entgangen zu sein....

Gruß Gerd G. (Elektrikser)

von Patrick W. (pw-sys) Benutzerseite


Lesenswert?

Hallo,

ich versuche mich gerade an der Match ROM Funktion - leider erhalte ich 
nur Misst:
1
//initialisierung
2
uint8_t festeid1[8] =   { 0x10,0xd9,0x9f,0xdd,0x01,0x08,0x00,0x30 };
3
4
//.....
5
6
//while(1) dann kommt:
7
8
start_meas();
9
    _delay_ms(1000);
10
    read_meas();
11
    _delay_ms(1000);
12
      
13
    
14
      uart_puts_P( "\r\n festeID: " );
15
16
      for( i = 0; i < 8; i++ )
17
      {
18
        sprintf( buffer, "%02X ", festeid1[i] );
19
        uart_puts( buffer );
20
      }
21
      onewire_command(MATCH_ROM, festeid1);
22
      
23
      onewire_byte_wr( READ );      // read command
24
      temperature = onewire_byte_rd();      // low byte
25
      temperature |= (uint16_t)onewire_byte_rd() << 8;  // high byte
26
      
27
      temperature <<= 3;    // 9 -> 12 bit
28
      
29
      
30
      sprintf( buffer, "  T: %04X = ", temperature );  // hex value
31
      uart_puts( buffer );
32
      sprintf( buffer, "%4d.%01d°C", temperature >> 4, (temperature << 12) / 6553 ); // 0.1øC
33
      uart_puts( buffer );uart_puts("\r\n");uart_puts("\r\n");uart_puts("\r\n");


Als Ausgabe erhalte ich für drei angeschlossene DS18S20:
1
ID: 10 6F 9B DD 01 08 00 9A   T: 0180 =   24.0°C
2
ID: 10 D9 9F DD 01 08 00 30   T: 0180 =   24.0°C
3
ID: 10 A8 AF DD 01 08 00 1B   T: 0180 =   24.0°C
4
5
6
 festeID: 10 D9 9F DD 01 08 00 30   T: FFF8 = 4095.5°C

Die Temperatur von FFF8 kann nicht sein, aber egal welche ID ich 
verwende kommt der gleiche Murks!

Was mache ich falsch bin beinahe am verzweifeln!

Gruß
Patrick

von Patrick W. (pw-sys) Benutzerseite


Lesenswert?

Hallo,

habe den Fehler nun gefunden!:
1
//nicht:
2
3
onewire_command(MATCH_ROM, festeid1);
4
      
5
onewire_byte_wr( READ );      // read command
6
7
temperature = onewire_byte_rd();      // low byte
8
temperature |= (uint16_t)onewire_byte_rd() << 8;  // high byte
9
10
//sondern:
11
12
onewire_command(READ, festeid1);
13
      
14
temperature = onewire_byte_rd();      // low byte
15
temperature |= (uint16_t)onewire_byte_rd() << 8;  // high byte

Gruß
Patrick

von Jens S. (straubej)


Lesenswert?

Hallo Zusammen,

ich habe mir den ASM Code von Peter zu Gemüt geführt - erst mal vielen 
Dank an Peter - und versucht ein wenig mehr Kommentare rein zu machen,
denn wie in den Foren zu lesen ist ROM_SEARCH kein Pappensiel.. grad für 
Anfänger.

Ich habe auch noch ein paar Fragen, vielleicht kann mir da jemand 
helfen, gehöre nämlich auch zu den Anfängern ....

So nun Peters Code und meine Kommentare:

;----------------------------------------------------------------------- 
--
;        ROM Search
;----------------------------------------------------------------------- 
--
;Input  a0 = bit to resolve
;Output  a0 = next bit to resolve
;Used  a0, a1, a2, a3, zl
w1_rom_search:
  mov  a3, a0          ; a3 = FF
  rcall  w1_reset      ; reset bus
  ldi  a0, presence_err    ; a0 = FF -> bei fehler ist das der return 
wert
  brcs  _wrs7        ; wenn error dann ende sonst weiter
  ldi  a0, search_rom
  rcall  w1_byte_wr      ; sende search rom
  ldi  zl, romcode        ; point to rom code memory 0x01 ? warum ?
  ldi  a0, last_device      ; a0 = 0x00
  ldi  a2, 8 * 16 - 1      ; 8 bytes a 8 bit -> 1111111  7 mal 1
_wrs1:
  rcall  w1_bit_rd      ; READ I read bit c=0
  sbc  a1, a1          ; H = C
  rcall  w1_bit_rd      ; READ II read complement bit
  ld  a1, z          ; lade a1 aus speicher
  brhc  _wrs2        ; READ I  =0 wenn H=0 sprung an _wrs2
  brcc  _wrs4        ; READ II =0 wenn C=0 sprung an _wrs4 , bit 1 
RESOLVED
  ldi  a0, data_err      ; wenn READ I und II = 1 dann Fehler
  ret
_wrs2:              ; READ I  =0
  brcs  _wrs5        ; READ II =1 sprung an _wrs5 , bit = 0 -> RESOLV
                ; READ I & II = 0
  cp  a2, a3          ; vergleiche a2 und a3 , a3=initialwert von a0
  breq  _wrs5        ; bit 0 RESOLVED - warum ?
  brcs  _wrs3        ; bit = 1, resolve - warum ?
  sbrs  a1, 0        ; skip next wenn a1 an position 0 (ganz rechts) = 
1;
  rjmp  _wrs5        ; bit = 0
_wrs3:
  mov  a0, a2          ; bit = 1

_wrs4:              ; bit 1 RESOLVED
  sec              ; Set carry bit
  rjmp  _wrs6

_wrs5:              ; bit 0 RESOLVED
  clc              ; Clear carry bit

_wrs6:              ; Speichere bits im ROM an Z Position
  ror  a1            ; C->b7------------------b0->C
  st  z, a1          ; speicher a1
  rol  a1            ; C<-b7------------------b0<-C
  rcall  w1_bit_wr      ; sende Bit bei (Bit 0 RESOLVED send 0)
  subi  a2, 2        ; after 8 times: H = 1
  brhc  _wrs1        ; wenn byte noch nicht fertig dann sprung
  inc  zl            ; next byte im speicher
  brcc  _wrs1        ; wenn noch keine 64 bits fertig dann sprung
_wrs7:  ret
;----------------------------------------------------------------------- 
--



Was mir allerdings nicht ganz klar geworden ist ist die 1wire.h Datei 
...
und zwar die Definition der Register a0 bis zl

hier der Ausschnitt:
1wire.h

.def  a0    = r27    ;working registers
.def  a1    = r28
.def  a2    = r29    ;lcd: a0..a2
.def  a3    = r31    ;1wire: a0..a3, zl
.def  z0    = r30    ;z pointer
.def  z1    = r31
;----------------------------------------------------------------------- 
--

Warum ist a3 = zl?
Ist zl (Doppelregister Z (R30 low R31 high) nicht eigentlich ZH d.h beim 
Inkrement von zl in ROM_SEARCH springe ich im Speicher gleich 255 Bytes 
nach oben?

Zum inc Befehl habe ich generell noch eine Frage, wäre hier nicht adiw 
z0,1 die bessere Wahl um einen Übertrag bei z0 = FF zu ermöglichen?

Wo wird R30 und R31 auf den Anfang des SRAM gesetzt, hab ich irgendwie 
nicht gefunden?

Ok, weiter Fragen sind in den Kommentaren ... an der entsprechenden 
Stellen ... so wirds klarer wo es kneift.

Also vielleicht hat jemand Lust und Zeit mich hier ein wenig 
aufzuschlauen

Cheers Jens

von Peter D. (peda)


Lesenswert?

Der ATtiny12 hat keinen SRAM, daher werden einige Register als SRAM 
mißbraucht.
Und auch die Arbeitsregister mehrfach verwendet (nicht gleichzeitig).


Peter

von Lothar (Gast)


Lesenswert?

Hallo

Ich habe versucht das Programm auf dem ATmega 32 laufen zu lassen. Ich 
scheitere aber bislang an der Definition von " convert ".
Kann mir da jemand weiterhelfen?

Gruss und danke
Lothar

Beitrag #5645322 wurde von einem Moderator gelöscht.
Beitrag #5661862 wurde von einem Moderator gelöscht.
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.