www.mikrocontroller.net

Forum: Codesammlung Mehrere DS1820/DS18B20 auslesen


Autor: peter dannegger (Gast)
Datum:
Angehängte Dateien:

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
Autor: Bastian (Gast)
Datum:

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
Autor: peter dannegger (Gast)
Datum:

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
Autor: Bastian (Gast)
Datum:

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
Autor: peter dannegger (Gast)
Datum:

"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
Autor: Bastian (Gast)
Datum:

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..
Autor: Spatz2222 (Gast)
Datum:

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
Autor: peter dannegger (Gast)
Datum:

@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
Autor: Spatz2222 (Gast)
Datum:

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
Autor: peter dannegger (Gast)
Datum:

"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
Autor: Spatz2222 (Gast)
Datum:

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

also noch einen schönen Abend !
Autor: Peter-Christian Carstens (Gast)
Datum:

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
Autor: peter dannegger (Gast)
Datum:
Angehängte Dateien:

@Peter-Christian

Anbei die 1-Wire Funktionen in 8051 Assembler.

Der Aufruf erfolgt genauso wie im C-Programm.


Peter
Autor: Tobias (Gast)
Datum:

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
Autor: SIMON AMIR (Gast)
Datum:

I want to buy 300 parts of DS1820 , 3pin ,pr35 package.
Autor: Elektrikser (Gast)
Datum:

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
Autor: mthomas (Gast)
Datum:

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....
"fertiger" avr-gcc-Code bereitgestellt.

Bei der Gelegenheit: Danke dafuer, Peter.
Autor: Elektrikser (Gast)
Datum:

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
Autor: Peter Dannegger (Gast)
Datum:

"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
Autor: Elektrikser (Gast)
Datum:

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
Autor: Elektrikser (Gast)
Datum:

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)
Autor: peter dannegger (Gast)
Datum:

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
Autor: Elektrikser (Gast)
Datum:

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
Autor: Elektrikser (Gast)
Datum:

Danke Peter,
für deine Hilfe. Mit Hilfe deines Programmes habe ich das jetzt zum
Laufen gebracht.
Gruß gerd
Autor: Peter Dannegger (Gast)
Datum:

"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
Autor: Elektrikser (Gast)
Datum:

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)
Autor: Patrick Weggler (pw-sys) Benutzerseite
Datum:

Hallo,

ich versuche mich gerade an der Match ROM Funktion - leider erhalte ich
nur Misst:

//initialisierung
uint8_t festeid1[8] =   { 0x10,0xd9,0x9f,0xdd,0x01,0x08,0x00,0x30 };

//.....

//while(1) dann kommt:

start_meas();
    _delay_ms(1000);
    read_meas();
    _delay_ms(1000);
      
    
      uart_puts_P( "\r\n festeID: " );

      for( i = 0; i < 8; i++ )
      {
        sprintf( buffer, "%02X ", festeid1[i] );
        uart_puts( buffer );
      }
      onewire_command(MATCH_ROM, festeid1);
      
      onewire_byte_wr( READ );      // read command
      temperature = onewire_byte_rd();      // low byte
      temperature |= (uint16_t)onewire_byte_rd() << 8;  // high byte
      
      temperature <<= 3;    // 9 -> 12 bit
      
      
      sprintf( buffer, "  T: %04X = ", temperature );  // hex value
      uart_puts( buffer );
      sprintf( buffer, "%4d.%01d°C", temperature >> 4, (temperature << 12) / 6553 ); // 0.1øC
      uart_puts( buffer );uart_puts("\r\n");uart_puts("\r\n");uart_puts("\r\n");


Als Ausgabe erhalte ich für drei angeschlossene DS18S20:

ID: 10 6F 9B DD 01 08 00 9A   T: 0180 =   24.0°C
ID: 10 D9 9F DD 01 08 00 30   T: 0180 =   24.0°C
ID: 10 A8 AF DD 01 08 00 1B   T: 0180 =   24.0°C


 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
Autor: Patrick Weggler (pw-sys) Benutzerseite
Datum:

Hallo,

habe den Fehler nun gefunden!:
//nicht:

onewire_command(MATCH_ROM, festeid1);
      
onewire_byte_wr( READ );      // read command

temperature = onewire_byte_rd();      // low byte
temperature |= (uint16_t)onewire_byte_rd() << 8;  // high byte

//sondern:

onewire_command(READ, festeid1);
      
temperature = onewire_byte_rd();      // low byte
temperature |= (uint16_t)onewire_byte_rd() << 8;  // high byte



Gruß
Patrick
Autor: Jens Straube (straubej)
Datum:

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
Autor: Peter Dannegger (peda)
Datum:

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


Peter

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




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 erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net