PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Temperatursensor DS18S20 Bascom



PImo
10.12.2013, 12:47
Hi Leute,

ich mцchte gerne einen/mehrere Temperatursensoren vom Typ DS18S20 mit einem Atmega8 betreiben und mir die ausgegeben Temperatur auf einem LCD Display darstellen lassen.

Jetzt zu meinem Problem: egal welchen Code ich dafьr ausprobiert habe ich bin immer dabei gelandet, dass ich eine Fehlermeldung des Sensors erhalten habe. Hier mal ein Beispiel-Code aus einem Buch zu Bascom (Kьhnel):

$regfile = "m8def.dat"
$crystal = 1000000
$baud = 9600

Config Lcd = 16 * 2
Config Lcdpin = Pin , Db7 = Portd.7 , Db6 = Portc.3 , Db5 = Portd.6 , Db4 = Portc.2 , E = Portc.1 , Rs = Portd.2
Initlcd

Config 1wire = Portb.0

Const Ds18s20 = &H10

Const Skiprom = &HCC 'Ьberspringe Rom Kommandos
Const Read_rom = &H33 'lese Rom
Const Convertt = &H44 'Start Temperaturmessung
Const Read_ram = &HBE 'Lese Scratchpad Ram
Const Write_ram = &H4E 'Schreibe Scratchpad RAM
Const Copy_ram = &H48 'Kopiere Scratchpad RAM
Const Recall_ee = &HB8 'Kopiere EEPROM nach RAM
Const Read_power = &HB4 'Abfrage Spannung

Dim Family_code As Byte
Dim Serial_number(6) As Byte 'Sensor Seriennummer
Dim Crc As Byte 'DS18S20 Crc
Dim Scratch(9) As Byte 'Scratchpad RAM Kopie

Dim I As Byte
Dim Temp As Word
Dim Temp1 As Integer
Dim Stemp As Single

Do
1wreset
If Err = 1 Then Lcd "Sensor Fehler"
Wait 1
Cls

1wwrite Read_rom 'Lese ROM Kommando

Family_code = 1wread() 'Auslesen ROM Inhalt
Lcd Family_code
Wait 5
Cls
For I = 1 To 6
Serial_number(i) = 1wread()
Next
Crc = 1wread()

If Family_code <> Ds18s20 Then Exit Do

1wwrite Convertt 'starte Temperaturmessung

Wait 2 'warte Temperaturmessung ab

Do
Temp = 1wread()
Loop Until Temp = &HFF 'warte bis Temperaturmessung beendet ist

1wreset
If Err = 1 Then Lcd "Sensor Fehler"
Wait 1
Cls

1wwrite Skiprom
1wwrite Read_ram

For I = 1 To 9
Scratch(i) = 1wread()
Next

Temp = Scratch(2)
Shift Temp , Left , 8

Temp = Temp + Scratch(i) 'Word Format
Temp1 = Temp 'Integer Format
Lcd "T=" ; Temp ; "Counts."
Wait 1
Cls
Temp1 = Temp1 / 2
Lcd "T=" ; Temp1 ; "Grad Celsius"
Wait 1
Cls
Stemp = Scratch(8) - Scratch(7) 'Interpolation
Stemp = Stemp / Scratch(8)
Stemp = Stemp + Temp1
Stemp = Stemp - 0.25
Lcd "exakte T="
Wait 1
Cls
Lcd Fusing(stemp , "#.##")
Wait 1
Cls
Lcd "Grad Celsius"
Wait 2
Cls

Loop

Lcd "Kein Temperatursensor"
Wait 1
Cls

End

Der Family Code sollte H10 also 16 betragen aber ausgegeben wird mir 256. Dieses Programm ist eigentlich fьr einen DS1820 geschrieben worden, liegt hier vielleicht das Problem? Im Datenblatt des DS18S20 (http://pdfserv.maximintegrated.com/en/ds/DS18S20.pdf) finde ich auch gar keinen Family Code...
Bei anderen getesteten Programmen (siehe http://www.avr-praxis.de/forum/showthread.php?108-Ds18s20 , http://bascom-forum.de/showthread.php?3052-Temperaturmessung-mit-DS18S20 , http://mikrocontroller.jacob-pirna.de/1wire_bascom_ds1820_2.html) kam teilweise auch einfach der Standard Wert von 127° heraus.
Ich habe den Sensor genau wie im Datenblatt beschrieben angeschlossen, 1 auf GND , 2 mit 4,7k Vorwiderstand auf Vcc und 3 auf Vcc. 2 hab ich dann mit meinem Anschluss B0 am Atmega8 verbunden. D.h. ich hab den Sensor mit einer externen Spannung versorgt und ihn nicht parasitдr betrieben.
Ich habe auch bereits verschiedene DS18S20 Sensoren getestet, die waren alle neu aber bei allen kam die gleiche Fehlermeldung (Zahl) heraus.
Kann mir jemand weiterhelfen und erklдren wo hier das Problem liegt?

Schonmal Danke im vorraus! :)

Bumbum
10.12.2013, 17:08
Hallo PImo,

ich habe mich auch vor kurzem mit diesen Sensoren beschдftigt und lange an der harten Nuss zu knabbern gehabt. Leider habe ich noch nie Bascom genutzt und kann deshalb deinen Code nicht prьfen.

Meine Fehlerursache war aber das Timing. Die Zeiten im Datenblatt mьssen sehr genau eingehalten werden. Ich habe stundenlang die Zeitdiagramme studiert und Codezeile fьr Codezeile damit abgestimmt.
Bei mir hat ein Atmel mit 1MHz Takt auch nicht gerreicht um die Delays prдzise genug einzuhalten! Ich habe dann das CDIV8 Flag gelцscht und den Prozessor dann mit 8MHz betrieben und damit ist es dann gelaufen. Ich habe dann noch versucht mit optimieren das Programm auf 1MHz zum laufen zu bekommen, es aber nicht geschafft.

Dein Projekt scheint auf 1Mz konfiguriert zu sein. Meinen Erfahrugnen nach kann es so nicht funktionieren.
Weiterhin weiЯ ich nicht, was die Wait-Anweisungen in Bascom macht (Milli oder Mikrosekunden?) Die meissten Wartezeiten im Datenblatt des DS sind mдmlich Mikrosekunden, deshalb muss vermutlich der Takt so schnell sein, damit die Delays auch genau genug eingehalten werden kцnnen.

Viele GrьЯe
Andreas

fredred
11.12.2013, 09:35
Hallo,
hier meimein Test-Code. Musst nur die Port's und LCD anpassen.
Funktioniert ohne Probleme mit Minuszeichen und Kommastellen.


'****************** Test-Platine ************************
'* ist ein Testmodul fьr Digital Temperatur-Sensoren *
'* [DS18x20] DS18S20 ist ein 9 Bit Family Adr &H10 *
'* und DSB20 ein 12 Bit Family Adr &H28 *
'* somit groЯe Unterschiede bei der "Empfindlichkeit" *
'* Das lesen der Bit's ist somit auch Unterschiedlich. *
'************************************************* *******


$regfile "m32def.dat"
$crystal = 16000000
$hwstack = 32
$swstack = 32
$framesize = 40
$baud = 19200

'### LCD Verbindungen mit Controller###
Lcd_db4 Alias Portd.5
Lcd_db5 Alias Portd.4
Lcd_db6 Alias Portd.3
Lcd_db7 Alias Portd.2
Lcd_e Alias Portd.6
Lcd_rs Alias Portd.7

Config Lcdpin = Pin , Db4 = Lcd_db4 , Db5 = Lcd_db5 , Db6 = Lcd_db6 , Db7 = Lcd_db7 , E = Lcd_e , Rs = Lcd_rs

Config Lcd = 16 * 2 'dies ist die Kennung fьr Lib Lcdpin
Cursor Off Noblink 'Aus und nicht blinken
Lcdinit
Waitms 100

'fьr Test die am Port B.0 angeschlossenen Temperatursensoren
Declare Sub Ds1820_alleseriennummern()

'Temperatursensor AnschluЯ an Portpin B.0
Dim 1wtemp_adresse_1(8) As Byte ' Adresse des Temperatursensors 1
Dim 1wtemp_adresse_2(8) As Byte ' Adresse des Temperatursensors 2
Dim Temp_bytes(9) As Byte
Dim Tempdif As Integer
Dim Tempdif1 As Integer 'Variable zur Temp. Berechnung DeziGrad
Dim Temp1 As Single
Dim Temp2 As Single

'Format fьr Single zwei Nachkommastellen
Config Single = Scientific , Digits = 1 'wenn 2 benцtigt Dann Digits = 2 (macht aber kein Sinn)
'Temperatursensoren DS 18S20 an PortB.0 (Bascom Unterprogramm einbinden)
Config 1wire = Portb.0 'Temperatursensor 1und2
Portb.0 = 1 'Port auf H schalten

'------Temperatursensor erkennen-------
'testet die am Portpin B.0 angeschlossenen Temperatursensoren
Call Ds1820_alleseriennummern()

1wtemp_adresse_1(1) = 1wsearchfirst() 'ist der erste gefundene Sensor
1wtemp_adresse_2(1) = 1wsearchnext() 'suche nдchsten
'1wtemp_adresse_3(1) = 1wsearchnext() 'wenn noch mehr erweitern

Cls


Do

'Temperatursensoren Daten einlesen
Gosub Temperaturmessung
' Print " Temp1 " ; Temp1
' Print " Temp2 " ; Temp2
'nun was anzeigen
Locate 1 , 1 'Cursor auf 1 Zeile, 1 Spalte
Lcd " Temp1 " ; Temp1
Locate 2 , 1 'Cursor auf 2 Zeile, 1 Spalte
Lcd " Temp2 " ; Temp2

Loop
End


Temperaturmessung:
' bei allen Sensoren den Messvorgang starten
1wreset
1wwrite &HCC ' SKIP ROM, alle Sensoren ansprechen
1wwrite &H44 ' CONVERT T, Temperatur messen
'Zeit zum Messen geben
Waitms 50

'===== erster Temp.-Sensor ist ein S Typ=====

1wreset
1wverify 1wtemp_adresse_1(1)
1wwrite &HBE ' Read Scratchpad, Temperatur auslesen
'Zeit zum Messen geben
Waitms 100
Temp_bytes(1) = 1wread(8)
Tempdif = Makeint(temp_bytes(1) , Temp_bytes(2)) 'erstes und 2 Byte(LSB+MSB) zusammenfьgen

Tempdif = Tempdif * 50
Tempdif = Tempdif - 25.6
Tempdif1 = Temp_bytes(8) - Temp_bytes(7)
Tempdif1 = Tempdif1 * 100
Tempdif1 = Tempdif1 / Temp_bytes(8)
Tempdif = Tempdif + Tempdif1
Temp1 = Tempdif / 100

'(
'===== zweiter Temp.-Sensor wenn auch ein S Typ =====
' Anfrage senden
1wreset
1wverify 1wtemp_adresse_2(1)
1wwrite &HBE ' Read Scratchpad, Temperatur auslesen
Temp_bytes(1) = 1wread(8)
Tempdif = Makeint(temp_bytes(1) , Temp_bytes(2)) 'erstes und 2 Byte(LSB+MSB) zusammenfьgen.

Tempdif = Tempdif * 50
Tempdif = Tempdif - 25.6
Tempdif1 = Temp_bytes(8) - Temp_bytes(7)
Tempdif1 = Tempdif1 * 100
Tempdif1 = Tempdif1 / Temp_bytes(8)
Tempdif = Tempdif + Tempdif1
Temp2 = Tempdif / 100
'Zeit zum Messen geben
Waitms 10
')

'===== erster Temp.-Sensor wenn es ein B Typ ist =====
' Anfrage senden
1wreset
1wverify 1wtemp_adresse_2(1)
1wwrite &HBE ' Read Scratchpad, Temperatur auslesen
'Zeit zum Messen geben
Waitms 100

Temp_bytes(1) = 1wread(8)
Tempdif = Makeint(temp_bytes(1) , Temp_bytes(2)) 'erstes und 2 Byte(LSB+MSB) zusammenfьgen.
Tempdif = Tempdif / 8 'hier der Unterschied
Tempdif = Tempdif * 50
Tempdif = Tempdif - 25.5
Tempdif1 = Temp_bytes(8) - Temp_bytes(7)
Tempdif1 = Tempdif1 * 100
Tempdif1 = Tempdif1 / Temp_bytes(8)
Tempdif = Tempdif + Tempdif1
Temp2 = Tempdif / 100

Return


'-------------------------------------------------------------------------------

'############# nach Neustart Temperatursensor Test ###############

'wird dieser Test Erfolgreich beendet wird die "Messung" oben in den Variablen
'geschrieben [1wtemp_adresse_1(1)] ist der erste Sensor und
'und [1wtemp_adresse_2(1)] ist der zweite usw.

'Gibt die Seriennummer aller Sensoren des Bus ьber COM(TTL) aus.
'wenn Hardware-Fehler wird dieser angezeigt.

Sub Ds1820_alleseriennummern()
Local Crc As Byte
Local I As Integer
Local Anzahl As Integer
Dim Adresse(8) As Byte
Adresse(1) = 1wsearchfirst() 'prьft den ersten Teilnehmer am Bus
If Err = 0 Then 'Wenn err, dann gibt es keinen Sensor

'ist nur fьr Info die Hex-Adresse ist "Name" mit dieser Kenntnis
'kannst Du mit [1wwrite &H55 und 1wwrite Sensor1_id("Name") , 8
'jeden einzeln ansprechen. Mach bei mehreren Sensoren Sinn.

Print "sind Hex-Adresse der Ds1820"

'ab hier prьfen
Do
Crc = Crc8(adresse(1) , 7)
If Crc <> Adresse(8) Then Print "Daten fehlerhaft gelesen (CRC-Fehler)!"
For I = 1 To 8
Print Hex(adresse(i)) ;
Print " ";
Next
Print

Adresse(1) = 1wsearchnext() 'nдchste suchen
Loop Until Err = 1
End If
'Print
Anzahl = 1wirecount() 'Anzahl der Sensoren
Print "Anzahl der Sensoren am Bus: " ; Anzahl
Print
Print "Test abgeschlossen"
Print "Hauptprogramm wird gestartet"
Print
Wait 5
End Sub




Dim Sngeeprom As Single 'Single to/from EEPROM
Dim Bytsngeep(4) As Byte At Sngeeprom Overlay
Dim Wrdaddr As Word 'EEPROM address
Dim Byttmp0 As Byte 'Temporary byte variable
Dim Sngtmp0 As Single 'Temporary single variable

'Declare subs
Declare Sub Eepromwritesng(byref Sngsingle As Single)
Declare Sub Eepromreadsng(byref Sngsingle As Single)

Wrdaddr = 11 'EEPROM start address
Sngtmp0 = 123.456 'Single to be stored in EEPROM
Call Eepromwritesng(sngtmp0) 'Store sngTmp0 to EEPROM

Wrdaddr = 11
Call Eepromreadsng(sngtmp0) 'Retrieve sngTmp0 from EEPROM

'================================================= =============================
Sub Eepromwritesng(byref Sngsingle As Single)
'Decode sngSingle to 4 bytes of bytSngEEP for writing to EEPROM
'Input sngSingle is set to sngEEPROM, overlayed with bytSngEEP(i), i=1...4
'The 4 bytes bytSngEEP(i)are written to EEPROM
'Input: sngSingle to be decoded & written to EEPROM
' wrdAddr first EEPROM address

Sngeeprom = Sngsingle 'Set input
For Byttmp0 = 1 To 4
Writeeeprom Bytsngeep(byttmp0) , Wrdaddr
Incr Wrdaddr
Next Byttmp0
End Sub

'================================================= =============================
Sub Eepromreadsng(byref Sngsingle As Single)
'Encode 4 bytes read from EEPROM to sngSingle
'The 4 bytes are read to bytSngEEP(i), i=1...4
'bytSngEEP is overlayed @ sngEEPROM
'sngEEPROM is set to output sngSingle
'Input: wrdAddr first EEPROM address
'Output: sngSingle encoded to single variable read from EEPROM

For Byttmp0 = 1 To 4
Readeeprom Bytsngeep(byttmp0) , Wrdaddr
Incr Wrdaddr
Next Byttmp0
Sngsingle = Sngeeprom 'Set output
End Sub

Hoffe es Hilft weiter.

Rofo88
11.12.2013, 18:30
Was kommt als ERR nach dem 1wreset? Taktfrequnz passt?

Djohn_kg
11.12.2013, 20:30
$regfile = "m8def.dat"
$crystal = 16000000
$hwstack = 40
$swstack = 16
$framesize = 32








Config Lcd = 16 * 2 ' LCD

Config Lcdpin = Pin , Db4 = Portb.2 , Db5 = Portb.3 , Db6 = Portb.4 , Db7 = Portb.5 , E = Portb.1 , Rs = Portb.0 'LCD PINs

Config Portd.0 = Input ' Menu Key

Config Portd.1 = Input 'UP Keu

Config Portd.5 = Input 'Down Key

Config Portd.2 = Input 'Int on press ANY Key

Config Portd.6 = Output ' Driver


On Int0 Menu


Enable Interrupts

Enable Int0




Config 1wire = Portc.5 ' Configuration of 1wire bus

' *** Заводим переменные

Dim Byte0 As Byte

Dim Byte1 As Byte

Dim Sign As String * 1

Dim T As Byte

Dim T1 As Byte

Dim T2 As Byte

Dim M As Byte 'Menu Counter

Dim Tempon As Byte ' TempON-Switch ONN

Dim Tempoff As Byte 'TempOFF SwitchOFF

Dim Tempon1 As Eram Byte

Dim Tempoff1 As Eram Byte

Dim P As Byte ' Key Delay Time

Dim W As Byte ' Exit Time



P = 200 ' Key Delay

W = 100

Tempon = Tempon1

Tempoff = Tempoff1



Cls
Cursor Off


'***ОСНОВНАЯ ПРОГРАММА

Do

' начало цикла

1wreset

If Err = 1 Then 'если при опросе небыло ответа ставим флаг ошибки

Cls


Lcd " Eror " ' выводим надпись об отсутствии датчика
Locate 2 , 1
Lcd "Sensor not found."

Wait 1

Else ' иначе, если ошибки не было, продолжаем опрос датчика

1wwrite &HCC ' Выдаем команду чтения ПЗУ
1wwrite &H44 ' Запуск измерения

Waitms 750 ' Ждем окончания преобразования

1wreset
1wwrite &HCC
1wwrite &HBE ' Команда чтения ОЗУ датчика


Byte0 = 1wread() ' Читаем нулевой байт

Byte1 = 1wread() ' Читаем первый байт

If Byte1 > 248 Then ' Проверка на отрицательность температуры
Byte0 = &HFF - Byte0
Byte1 = &HFF - Byte1
Sign = "-"

Else
Sign = "+"
End If

T1 = Byte0 / 16 ' Сдвигаем нулевой байт вправо на 4 бита (2*2*2*2=16)
T2 = Byte1 * 16 ' Сдвигаем первый байт влево на 4 бита (2*2*2*2=16)

T1 = T1 + T2 ' Формируем результат для вывода на дисплей


' *** Коррекция полученных значений

If Sign = "-" Then ' для корректного вывода отрицательных температур
T1 = T1 + 1
End If

If Sign = "+" And T1 = 0 Then ' убираем знак "+" с нулевой температуры
Sign = " "
End If



' *** Выводим результат на дисплей

Rem Температура
Lcd " Temperature" ' тут пишем что измеряем

Locate 2 , 6
Lcd Sign ; T1 ; ' выводим знак и температуру на дисплей
Locate 2 , 9

Lcd Chr(223) ; "C" ' Сhr(223) - символ "градус"

Cursor Off

End If

If T1 => Tempon Then

Portd.6 = 1

End If

If T1 < Tempoff Then

Portd.6 = 0

End If

If Portd.6 = 0 Then

Locate 2 , 13

Lcd "OFF"

Else

Locate 2 , 13

Lcd "ON"

End If


Waitms 750



Loop ' повторяем цикл

End

Menu:

Cls

Do

W = W - 1



If Pind.0 = 0 Then 'Menu Key

M = M + 1



Waitms P

End If





If M = 1 Then 'Tempon menu keys

Locate 1 , 1

Lcd "TempON > "

Locate 2 , 1

Lcd "TempOff "

If Pind.1 = 0 And M = 1 Then 'Tempon +

Tempon = Tempon + 1

Waitms P

End If

If Pind.5 = 0 And M = 1 Then 'Tempon -

Tempon = Tempon - 1

Waitms P

End If

Locate 1 , 12

Lcd Tempon

Locate 2 , 12

Lcd Tempoff


End If


If M = 2 Then 'Tempoff menu keys

Locate 1 , 1

Lcd "TempON "

Locate 2 , 1

Lcd "TempOff >"

If Pind.1 = 0 And M = 2 Then

Tempoff = Tempoff + 1 'Tempoff +

Waitms P

End If

If Pind.5 = 0 And M = 2 Then 'Tempoff -

Tempoff = Tempoff - 1

Waitms P

End If

Locate 1 , 12

Lcd Tempon

Locate 2 , 12

Lcd Tempoff

End If


If M = 3 Then

M = 1

End If


If Pind.2 = 0 Then

W = 100

P = P - 3

If P < 50 Then

P = 30

End If

Else

P = 200

End If


If Tempoff > Tempon Then

Tempoff = Tempon

End If






Loop Until W = 0

M = 0



Tempon1 = Tempon

Tempoff1 = Tempoff

Return




End


Hier ist meine code zum vergleichen.

funktioniert 100%

- - - Aktualisiert - - -

schaltplan26901

oderlachs
11.12.2013, 21:08
Bitte schreibt doch Code auch dahin, wo er hingehцrt
... ich seh nur "Kauderwelsh" bei einigen Codezeilen...

Nur als Hinweis...keine Kritik...auch ich mache Fehler.. ;)

Gerhard

fredred
12.12.2013, 12:48
Hallo Rofo88,


Es kommt auf die Bascom- Version an in veraltete oder nur Demo muss noch Port und Pin angegeben werten. Markiere [1WRESET] und drьcke F1, dort findest Du eine gute Beschreibung fьr Hilfe.

Habe Vollversion 2.0.7.6.

Nur mal so nebenbei:

Schicke seit ca. 2 Jahren ьber meine Funkbrьcke (RFM12 mit Mega 8) 6 Temperaturwerte. Zusдtzlich noch 6 analoge und 3 digitale. Dies alles im Sekundentakt ohne Probleme .

Alle Temperatursensoren an einem Pin des Mega8 (Sender) funktioniert alles bestens.


P.S was ist damit gemeint.
1. Signatur??? kann ich mir nicht leisten!!!

MfG und Danke
Fred

PImo
13.12.2013, 14:12
Danke fьr eure Beispiel Codes, mein Problem war viel einfacher und zwar war eine Taktfrequenz von 1MHz einfach zu wenig.
Habe diese dann auf 8MHz eingestellt und seit dem funktioniert auch mein Programm tadellos :) .
Der nдchste Schritt wдre jetzt mehrere Sensoren gezielt anzusprechen und zum Messen zu veranlassen, falls ich hier nochmal Probleme habe komme ich auf euch zurьck!
Danke nochmal

Bumbum
13.12.2013, 18:02
Habe diese dann auf 8MHz eingestellt und seit dem funktioniert auch mein Programm tadellos :) .

Habe ich doch gleich gesagt. ;-) Danke fьr die Bestдtigung!