Forum: Mikrocontroller und Digitale Elektronik DS1820


von ThomasW (Gast)


Lesenswert?

Hallo , ich verstehe nicht wie das funktioniert wenn man 2 DS1820 an 
einem AVR abfrägt . Wenn ich nicht falsch liege muss man jeden DS1820 
erst adressieren und dann kann man jeden über die adresse abfragen , 
vielleicht hat jemand ein Beispiel ( in Bascom ) , das was ich mir von 
dieser Seite runtergeladen habe ist nur für einen DS1820 .

Danke Mfg Thomas

von Peter D. (peda)


Lesenswert?

Hallo Thomas,

ich hätte da nur was in C:

http://www.specs.de/~danni/appl/soft/c51/thclock/index.htm

in "1-wire.c51"

Der Aufruf erfolgt in "meastemp.c51"


Peter

von Matthias (Gast)


Lesenswert?

Hallo, Ich bin Neueinsteiger in Sachen Mikrocontroller, und
versuche mich auch gerade an den DS1820, aber das will nicht
so ganz klappen.
Hast du mittlerweile was gefunden?

Ich nutze auch Bascom Basic
und den AT90S4433

Bei mir gehts schon mit der Hardware los
http://www.canathome.de/Dokumentation/Kapitel2.htm
Wie dort beschrieben hab ich den DS1820 angeschlossen.

Ist das soweit korrekt??
Die Software die ich mir runtergeladen habe, melde dutzende von Fehlern, 
wenn ich den port d durch c tausche!!
d mit b tauschen ist kein Thema!!
Woran kann das liegen??

Das Programm sieht so aus:

$regfile = "4433def.dat"
$crystal = 4000000

Config 1wire = Portb.4                                      'use this 
pin

Dim Ar(2) As Byte , A As Byte , I As Byte , Temperatur As Integer
Dim Halb As Byte
Config Lcdpin = Pin , Db4 = Portd.0 , Db5 = Portd.1 , Db6 = Portd.2 , 
Db7 = Portd.3 , E = Portd.5 , Rs = Portd.4
'These settings are for the AVR-Ctrl in PIN mode

Config Lcd = 24 * 2                                         'configure 
lcd screen
'other options are 16  4 and 20  4, 20 * 2 , 16 * 1a
'When you dont include this option 16 * 2 is assumed
'16 * 1a is intended for 16 character displays with split addresses over 
2 lines
Config Portd = Output                                       'configure 
portd as output
Config Portb = Input
Reset Portd.1                                               'write mode 
for display
Initlcd                                                     'init 
display again
Cursor On
Cls
Lcd "Temp:"
Do
  Wait 1
  1wreset                                                   'reset the 
device
  1wwrite &HCC                                              'read ROM 
command
  1wwrite &H44
  Waitms 100                                                'read ROM 
command
  1wreset                                                   'reset the 
device
  1wwrite &HCC                                              'read ROM 
command
  1wwrite &HBE                                              'read ROM 
command
  For I = 1 To 2
    Ar(i) = 1wread()                                        'place into 
array
  Next

  Locate 2 , 1
  Temperatur = Ar(1)

  If Ar(2) > 0 Then Temperatur = 0 Else Shift Temperatur , Right

  Lcd Temperatur ; ".";

  Halb = Ar(1) And 1

  If Halb = 1 Then Lcd "5" Else Lcd "0"

  Lcd " C"
Loop

End

als Temperatur zeigt er nur 0.0 grad an!!

Kann mir da irgendeiner helfen??
Schon mal besten Dank!

Gruß
Matthias

von Dieter Brüggemann (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Matthias

Habe dein Programm mal etwas geändert beim auslesen des ds1820. Bei 
läuft das so ganz gut. Mach doch mal die Definitionen unter Optionen in 
Bascom, dann sieht das oben nicht mehr so wild aus.

MFG
Dieter

von Dieter Brüggemann (Gast)


Lesenswert?

@ ThomasW

Jeder DS1820 hat eine feste Adresse "eingebrannt" die man erst mal 
kennen muß, von jedem DS1820 die an dem Bus liegt.

Mit dem Read_rom ( &H33) Befehl, kann man die Adresse aus dem DS 1820 
auslesen. Es darf dann aber nur ein Baustein am Bus hängen. Es können 
dann 8 Bytes ausgelesen werden:

1. Family Code DS1820 = &H10
2. bis 7. Adresse des DS1820   48 Bit Adresse
8. CRC Prüfsumme

Wenn du nur 2 am Bus daran hast, lese doch beide Bausteine nacheinander 
aus und schreibe dir die Adresse auf. Dann kannst du nachher über die 
Adresse beide Bausteine direkt ansprechen und auslesen.

MFG
Dieter

von Dieter Brüggemann (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Matthias

So, sollte jetzt so laufen wie gewünscht.

MFG
Dieter

von Matthias (Gast)


Lesenswert?

Ich danke dir !!

Ich habe in der Hardware einen Fehler gefunden, da habe ich einen 4,7k 
Widerstand vergessen.

Dumme Sache, direkt danach ging es.
Ich danke dir trotzdem für die Überarbeitung des Programms.

Gruß

Matthias

von A.Füßer (Gast)


Lesenswert?

> da habe ich einen 4,7k Widerstand vergessen
"Verbesserungsvorschlag" angenommen und Widerstand beschriftet.

Danke & tschüß,
 André.

von Matthias (Gast)


Lesenswert?

@Dieter Brüggemann

Wie meinst du das genau mit der Adresse auslesen?
Ich habe nämlich auch vor 2 von ds1820 an einem Bus zu hängen.

1wreset
1wwrite Read_rom                                             Ar(1) = 
1wread()
1wreset
Enable Interrupts
Lcd Ar(1)

Wenn ich das mache zeigt mir das Display 16 an.
Auch wenn ich den anderen Sensor an den Bus angeschlossen habe!

von Matthias (Gast)


Lesenswert?

Hallo!

Ich konnte das Problem zum Glück selber "lösen",
allerdings habe ich das denke ich mal ziemlich umständlich gemacht, also 
für Komprimierungsvorschläge wäre ich nach wie vor dankbar.

Das mit dem auslesen der nummer hat dann doch noch geklappt, dank dem 
Datenblatt.
Es ist eine 64Bit Nummer und ich hatte wie oben beschrieben nur 8 bit 
ausgelesen.




Const Read_rom = &H33                                       ' DS1820 
Commands
Const Skip_rom = &HCC
Const Convertt = &H44
Const Read_ram = &HBE
Const Match_rom = &H55
Const Write_ram = &H4E
Const Copy_ram = &H48
Const Recall_ee = &HB8
Const Read_power = &HB4
Config Lcdpin = Pin , Db4 = Portd.0 , Db5 = Portd.1 , Db6 = Portd.2 , 
Db7 = Portd.3 , E = Portd.5 , Rs = Portd.4
Config Lcd = 24 * 2                                         'configure 
lcd screen
Config Portd = Output                                       'configure 
portd as output
Config Portb = Input
Config 1wire = Portb.4
Reset Portd.1                                               'write mode 
for display
Initlcd                                                     'init 
display again
Cursor On
Timer1 = 65536 - 62500                                      ' Reload 
Timer1 for Period of 1 sec
Config Timer1 = Timer , Prescale = 64
On Timer1 Timer1_isr                                        ' Jump to 
Timer1 ISR
Enable Timer1                                               ' Enable the 
timer interrupt
Enable Interrupts                                           ' Enable 
Global Interrupt
Cls
Do
Start:
Do
   Wait 1
   Disable Interrupts                                       'soltte man 
machen, falls man mal Interrupts benutzt .Können aber beim auslesen 
stören
   1wreset                                                  '1wire Reset
    1wwrite Match_rom
    1wwrite 16
    1wwrite 129
    1wwrite 204
    1wwrite 60
    1wwrite 0
    1wwrite 8
    1wwrite 0
    1wwrite 9                                               'Read ROM 
command
   1wwrite Convertt                                         'Measure 
Temperature
   Do                                                       'warten bis 
fertig mit der Umwandlung
      Busy = 1wread()
   Loop Until Busy = &HFF                                   ' Wait for 
end of conversion
   1wreset                                                  ' 1wire 
Reset
    1wwrite Match_rom
    1wwrite 16
    1wwrite 129
    1wwrite 204
    1wwrite 60
    1wwrite 0
    1wwrite 8
    1wwrite 0
    1wwrite 9                                               'Read ROM 
command
    1wwrite Read_ram
    Ar(1) = 1wread()                                        'und 
auslesen
    Ar(2) = 1wread()
    1wreset                                                 ' 1wire 
Reset, fertig mit auslesen
     Enable Interrupts                                      'und wieder 
einschalten
   Temperatur = Ar(1)
   Temperatur = Temperatur / 2
   Locate 2 , 5
   Lcd Temperatur ; ".";
   Halb = Ar(1) And 1
   Locate 2 , 8
   If Halb = 1 Then Lcd "5" Else Lcd "0"
   Lcd " C"
   Wait 1
   Disable Interrupts                                       'soltte man 
machen, falls man mal Interrupts benutzt .Können aber beim auslesen 
stören
   1wreset                                                  '1wire Reset
    1wwrite Match_rom
    1wwrite 16
    1wwrite 196
    1wwrite 174
    1wwrite 60
    1wwrite 0
    1wwrite 8
    1wwrite 0
    1wwrite 5
   1wwrite Convertt                                         'Measure 
Temperature
   Do                                                       'warten bis 
fertig mit der Umwandlung
      Busy = 1wread()
   Loop Until Busy = &HFF                                   ' Wait for 
end of conversion
   1wreset                                                  ' 1wire 
Reset
    1wwrite Match_rom
    1wwrite 16
    1wwrite 196
    1wwrite 174
    1wwrite 60
    1wwrite 0
    1wwrite 8
    1wwrite 0
    1wwrite 5
    1wwrite Read_ram
    Ar(3) = 1wread()                                        'und 
auslesen
    Ar(4) = 1wread()
    1wreset                                                 ' 1wire 
Reset, fertig mit auslesen
     Enable Interrupts                                      'und wieder 
einschalten
   Temp2 = Ar(3)
   Temp2 = Temp2 / 2
   Locate 1 , 1
   Lcd Temp2 ; ".";
   Halb = Ar(4) And 1
   Locate 1 , 5
   If Halb = 1 Then Lcd "5" Else Lcd "0"
   Lcd " C"
   If K = 5 Then
   K = 0
   Goto Start
   End If
      While New_time = 1
       K = K + 1
       New_time = 0
      Wend
Loop
Loop
Timer1_isr:
    Timer1 = 65536 - 62576                                  ' Reload 
Timer1 for Period of 1 sec
    New_time = 1                                            ' 76 cycles 
correction
    Return
End

von Dieter Brüggemann (Gast)


Lesenswert?

Hallo Matthias

Ist doch schonmal gut, daß du weitergekommen bist. Routinen die man 
öfter braucht, sollte man in Funktionen packen. Schau mal in der Hilfe 
nach wie das geht. Damit wird der Code nachher übersichtlicher und 
meistens auch kürzer. Die Adressen der 2 DS1820 würde ich ins EEPROM 
schreiben und über eine Schleife auslesen, wenn ich sie brauche.

Schau dir mal folgende Befehle näher an.

Readeeprom, Writeeeprom  die gehen jetzt auch mit "Labels"

Oder ein kleiner Einstieg in Funktionen
Aufruf nachher hiermit, irgendwo im Programm
Temp = ds1820_read(1)
Temp = ds1820_read(2)

Function DS1820_read(byval nr As Integer) As word
  Hier kommt der Code rein z.B.:
  IF nr = 1 then adresse 1
  IF nr = 2 then adresse 2
 DS1820_read = ausgelesener Wert des Chip, wird zurückgegeben.
End Function

So nun an Werk. Bei Fragen melden. Die Funktion muß am Anfang noch 
deklariert werden, steht aber alles in der Hilfe.

MFG Dieter

von Matthias (Gast)


Lesenswert?

Danke für die Antwort,

Eine Funktion brauche ich daraus eigendlich nicht zu machen.
Also ich habe vor mir eine Lüftersteuerung für meinen PC zu basteln, mit 
2 Temperatursensoren und 2 Lüftern mit Drehzahlüberwachung.
Je nach Temperatur werden die Lüfter aus bzw.auf 6V bzw. auf
12V geschaltet.

Lange rede kurzer Sinn.
ich lasse einfach nur eine Schleife ablaufen:
1. Beide Temperaturen einlesen
2. erste Drehzahlüberwachung
3. zweite Drehzahlüberwachung

Wie sieht das denn mit dem Match_rom befehl aus,
ich muß den ja für jede Temperatur 2mal audführen, kann man das nicht 
irgendwie auch als Doppelwort bzw. long vergleichen
um den Code zu kürzen?

Gruß

Matthias

Also die Temperatur wird nur einmal in der Schleife aufgerufen, und die 
Funktion würde den Code denke ich mal nicht verkürzen.

von Dieter Brüggemann (Gast)


Lesenswert?

Hallo

Das ist ja gerade der Sinn der Funktion oder von subroutine.



sub match_1 ()
    1wwrite Match_rom
    1wwrite 16
    1wwrite 196
    1wwrite 174
    1wwrite 60
    1wwrite 0
    1wwrite 8
    1wwrite 0
    1wwrite 5
end sub

oben schreibst du dann nur noch call match_1. Dann hast du den Code nur 
noch einmal da stehen.

snip
1
   Disable Interrupts 'soltte man machen, falls man mal Interrupts 
benutzt .Können aber beim auslesen stören
   1wreset '1wire Reset
   call match_1
   1wwrite Convertt 'Measure Temperature
   Do 'warten bis fertig mit der Umwandlung
   Busy = 1wread()
   Loop Until Busy = &HFF ' Wait for end of conversion
   1wreset ' 1wire Reset
   call match_1
   1wwrite Read_ram
    Ar(1) = 1wread()
snip

MFG
Dieter

von Matthias (Gast)


Lesenswert?

Danke noch mal!
So hatte ich das noch nicht gesehen.

von Dubbster D. (dubbster)


Angehängte Dateien:

Lesenswert?

hey peter,du genie!

ich hab ebenfalls ein problem mit dem ds1820,bin ned wirklich weit 
gekommen,vielleicht könntest du mir ebenfalls weiter helfen! Ich füge 
mal hinzu,was ich schon habe,oder vielleicht jemand andere kann mir 
dabei helfen??


ich bring das nicht mit dem 1-wire port nicht,bzw weiss ich gar 
nicht,wann low oder high ist.

von Kay R. (trafowickler)


Lesenswert?

Ich habe ein Problem mit der Adressierung des DS1820.
Ich habe dieses Beispielprogramm hier genutzt, welches mir die Adresse 
"100E0CDD01080088" auf dem LCD ausgibt.

1
' Beispiel für das myAVR Board 1 & 2 mit LCD und 1wire Temperatursensor an Pin 5 von Port C
2
$regfile = "m8def.dat"
3
$crystal = 10000000
4
5
' LCD konfigurieren Port auf Ausgabe setzten und Pin's entsprechend zuordnen
6
Ddrd = &HFF
7
Config Lcdpin = Pin , Db4 = Portc.4 , Db5 = Portc.5 , Db6 = Portd.1 , _
8
   Db7 = Portd.0 , E = Portc.3 , Rs = Portc.2
9
Config Lcd = 16 * 2
10
Cursor Off
11
Cls
12
13
' Pin für 1wire Schnittstelle festlegen, Schnittstelle wird von BASCOM durch Software realisiert
14
Config 1wire = Portd.3
15
16
Dim Dsid(8) As Byte
17
Dim I As Byte
18
Dim Nr As Byte
19
20
Nr = 1
21
Cls
22
23
' Ersten angeschlossenen DS1820 finden und Adresse auslesen
24
Dsid(1) = 1wsearchfirst()
25
26
Locate 1 , 1 : Lcd "DS1820 Nr " ; Nr : Nr = Nr + 1
27
Locate 2 , 1
28
For I = 1 To 8
29
 Lcd Hex(dsid(i))
30
Next
31
32
' 10 Sekunden warten
33
Wait 10
34
35
Do
36
 ' Nächsten DS1820 suchen
37
 Dsid(1) = 1wsearchnext()
38
 ' Wenn kein Fehler, dann ausgeben
39
 If Err = 0 Then
40
  Locate 1 , 1 : Lcd "DS1820 Nr " ; Nr : Nr = Nr + 1
41
  Locate 2 , 1
42
  For I = 1 To 8
43
   Lcd Hex(dsid(i))
44
  Next
45
  Wait 15
46
 End If
47
Loop Until Err = 1
48
49
50
Do
51
 Waitms 100
52
Loop
53
54
End


Diese ist natürlich zu lang für meine als Byte deklarierte Variable in 
meinem Thermostatproggie.
Was davon ist nun der Teil, den ich als Adresse angeben muss?
Nicht schlagen, bin Neuling.

von G ast (Gast)


Lesenswert?

Den Aufbau der Adresse findst du im Datenblatt.
Aber in ein Byte wird die nicht reinpassen.

von Kay R. (trafowickler)


Lesenswert?

So, Problem gelöst.
Nun ist es ein Byte-Array "Dsid(8)".

Dabei gab es nun ein weiteres Problem.
Ich hole mir die Adresse mit "Dsid(1) = 1wsearchfirst : Dsid2(1) = 
1wsearchnext".
Da ich aber zu Testzwecken nur einen Sensor angeschlossen habe, 
antwortet er scheinbar auch auf das "1wsearchnext". Deshalb zeigten 
beide LCD - Zeilen, also Innen und Außen, den gleichen Wert.
Das habe ich nun so gelöst:
1
Dsid(1) = 1wsearchfirst
2
Dsid2(1) = 1wsearchnext
3
4
...
5
6
Temp1 = T
7
If Dsid(1) = Dsid2(1) Then
8
Temp2 = 0
9
Else
10
Temp2 = T2
11
End If

Das ist die Zusamenfassung von Codeschnipseln, daher die drei Punkte.

Das kann zwar für Verwirrung bei einem Sensorentausch sorgen, wenn sich 
plötzlich ein anderer als "First" meldet, aber so spare ich mir das 
Auslesen der Adresse vor Einbau des Sensor.
Wenn der Fall auftritt, werde ich einfach die Positionen der Werte im 
LCD tauschen und gut is'. ;-)

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.