PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Einstiegshilfe: Tempmessung mit KTY



forty
02.10.2005, 12:59
Hi,

kann mir einer von euch ein einfaches Beispiel geben um mit einem KTY und einem ATMega Temp zu messen? Ich hab schon gesucht und das Prinzip verstanden, aber an der Umsetzung haperts noch ....
Ein einfaches Schaltbild und ein kurzes Beispiel wie ich die Messspannung im ATMega auslese wären super, dann kann ich weiter probieren ....

Danke!

eric101
02.10.2005, 15:39
also ich hab das ma so gemacht:

5V---------r1----adc0----kty--------gnd

adc0= adc eingang am kontroller

Ist also vom Prinzip her ein einfacher spannungswandler. als adc referenzspannung nimmst auch 5V und für r1 zum beispiel 3,9k.
Mit 10bit genauigkeit kannst du dann zum beispiel folgende Formel verwenden: (1023*x)\(x+3900)
X ist der Widerstandswert abhängig von der Temperatur(im datenblatt nachschauen) des kty in ohm.
Das Ergebnis ist dann das was der ad Wandler rausbekommt, halt in Dezimal ^^
Nach dem Prinzip hab ich ein Thermometer mit mega8 und LCD als ausgabe gemacht, wenn du willst kann ich noch den quellcode posten

02.10.2005, 23:27
ja quellcode wäre super!

oparuebe
03.10.2005, 03:09
Ich habe auch interesse am Quellcode!

Lektor
03.10.2005, 10:29
Hallo,
ja ein Beispiel Quellcode ist immer gut.
Habe aber noch eine Frage. Suche bei Reichelt einen PT1000 Sensor finde aber nur NTC Widerstände. Bin dann über diesen Thread auf den KTY gestoßen, welcher auch einen positiven Temperaturkoeffizienten hat. Gibt es vielleicht doch einen PT1000 aber unter einer anderen Bezeichnung, oder müßte ich eine KTY nehmen und den Unterschied zu einem PT1000 mit einer Reihenschaltung mit einem anderen Widerstand ausgleichen. PT100 und PT1000 sind doch recht gängige Fühler; kann mir nicht vorstellen, dass Reichelt die nicht hat. Brauche auch nur den Widerstandsbereich von 20°C bis 70°C

Bernhard667
03.10.2005, 11:46
Hallo,
PT1000 ist ein Platinsensor.
Das hat allerlei Vorteile (Messbereich, Linearität, ...)
Jedoch ist die Empfindlichkeit deutlich kleiner als bei den Silizium Sensoren (KTY10, KT100,...)

Die Siliziumsensoren kannst Du nach Methode von eric101 machen.
Bei PT1000 brauchst Du noch OP´s um das Signal zu verstärken.

Bernhard

Lektor
03.10.2005, 20:21
ok, danke für die Info

eric101
03.10.2005, 22:37
So also hier mein quellcode:


.include "C:\Dokumente und Einstellungen\eric\Desktop\asm\m8def.inc"



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;
;;Thermometer 4Mhz Eric Schneider ;;
;; ;;
;; ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;






.def temp1 = r16
.def temp2 = r17
.def temp3 = r18
.def adcwh = r19
.def adcwl = r20




.cseg
; ############
; ##Tabellen##
; ############
.org 0x0071
.db 0b01010101, 0b01010100, 0b01010011, 0b01010010, 0b01010001, 0b01010000 ;-55 bis -50
.db 0b01001001, 0b01001000, 0b01000111, 0b01000110, 0b01000110, 0b01000101 ;-49 bis -45
.db 0b01000100, 0b01000011, 0b01000010, 0b01000001, 0b01000000, 0b00111001 ;-44 bis -39
.db 0b00111000, 0b00110111, 0b00110110, 0b00110101, 0b00110100, 0b00110011 ;-38 bis -33
.db 0b00110010, 0b00110010, 0b00110001, 0b00110000, 0b00101001, 0b00101000 ;-32 bis -28
.db 0b00100111, 0b00100110, 0b00100101, 0b00100101, 0b00100100, 0b00100011 ;-27 bis -23
.db 0b00100010, 0b00100001, 0b00100000, 0b00011001, 0b00011001, 0b00011000 ;-22 bis -18
.db 0b00010111, 0b00010110, 0b00010101, 0b00010100, 0b00010100, 0b00010011 ;-17 bis -13
.db 0b00010010, 0b00010001, 0b00010000, 0b00001001, 0b00001000, 0b00001000 ;-12 bis -8
.db 0b00000111, 0b00000110, 0b00000101, 0b00000100, 0b00000100, 0b00000011 ;-7 bis -3
.db 0b00000010, 0b00000001, 0b00000000, 0b00000001, 0b00000001, 0b00000010 ;-2 bis 2
.db 0b00000011, 0b00000100, 0b00000101, 0b00000101, 0b00000110, 0b00000111 ;3 bis 7
.db 0b00001000, 0b00001001, 0b00001001, 0b00010000, 0b00010001, 0b00010010 ;8 bis 12
.db 0b00010010, 0b00010011, 0b00010100, 0b00010101, 0b00010110, 0b00010110 ;13 bis 16
.db 0b00010111, 0b00011000, 0b00011001, 0b00100000, 0b00100000, 0b00100001 ;17 bis 21
.db 0b00100010, 0b00100011, 0b00100011, 0b00100100, 0b00100101, 0b00100110 ;22 bis 26
.db 0b00100110, 0b00100111, 0b00101000, 0b00101001, 0b00110000, 0b00110000 ;26 bis 30
.db 0b00110001, 0b00110010, 0b00110011, 0b00110011, 0b00110100, 0b00110101 ;31 bis 35
.db 0b00110110, 0b00110110, 0b00110111, 0b00111000, 0b00111001, 0b00111001 ;36 bis 39
.db 0b01000000, 0b01000001, 0b01000010, 0b01000010, 0b01000011, 0b01000100 ;40 bis 44
.db 0b01000101, 0b01000101, 0b01000110, 0b01000111, 0b01001000, 0b01001000 ;45 bis 48
.db 0b01001001, 0b01010000, 0b01010001, 0b01010001, 0b01010010, 0b01010011 ;49 bis 53
.db 0b01010100, 0b01010100, 0b01010101, 0b01010110, 0b01010111, 0b01010111 ;54 bis 57
.db 0b01011000, 0b01011001, 0b01100000, 0b01100000, 0b01100001, 0b01100010 ;58 bis 62
.db 0b01100010, 0b01100011, 0b01100100, 0b01100101, 0b01100101, 0b01100110 ;62 bis 66
.db 0b01100111, 0b01101000, 0b01101000, 0b01101001, 0b01110000, 0b01110001 ;67 bis 71
.db 0b01110001, 0b01110010, 0b01110011, 0b01110100, 0b01110100, 0b01110101 ;71 bis 75
.db 0b01110110, 0b01110111, 0b01110111, 0b01111000, 0b01111001, 0b01111001 ;76 bis 79
.db 0b10000000, 0b10000001, 0b10000010, 0b10000010, 0b10000011, 0b10000100 ;80 bis 84
.db 0b10000101, 0b10000101, 0b10000110, 0b10000111, 0b10001000, 0b10001000 ;85 bis 88
.db 0b10001001, 0b10010000, 0b10010001, 0b10010001, 0b10010010, 0b10010011 ;89 bis 93
.db 0b10010011, 0b10010100, 0b10010101, 0b10010110, 0b10010110, 0b10010111 ;93 bis 97
.db 0b10011000, 0b10011001, 0b10011001, 0b00000000; 100




.org 0x0000
rjmp reset ;reset
reti ;int0
reti ;int1
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
rjmp adccomp ;adc complete





reset: ldi temp1, low(ramend) ;Stack initialisiern
out spl, temp1
ldi temp1, high(ramend)
out sph, temp1
ldi temp1, 0x00 ;Porteingang initialisieren
out DDRC, temp1 ;input
ldi temp1, 0x00
out PORTC, temp1 ;interne pullups aus
ldi temp1, 0b00111111 ;lcd ausgänge initialisieren
out DDRD, temp1
cbi ADMUX, 7
cbi ADMUX, 6 ;reference spannung an Aref
cbi ADMUX, 5 ;rechts(9..0) angeordnetes Ergebnis
cbi ADMUX, 0
cbi ADMUX, 1
cbi ADMUX, 2
cbi ADMUX, 3 ;ADC0 ist analoger eingang
sbi ADCSRA, 7 ;ADC einschalten
cbi ADCSRA, 5 ;free running mode aus
sbi ADCSRA, 3 ;ADC interrupt ein
sbi ADCSRA, 0
cbi ADCSRA, 1
sbi ADCSRA, 2 ;Prescaler auf 32
SEI ;interrupts anschalten
rcall lcd_init ;lcd initialisieren



main:
ldi temp1, 0x01
sbi ADCSRA, 6 ;adc starten
fertig: cpi temp1, 0x00
brne fertig
andi adcwh, 0b00000011 ;bit 9 und 10 ausmaskieren
sbrc adcwh, 0 ;Vorzeichen erkennen, ab 175 ohne minus
rjmp pos
cpi adcwl, 0xaf
brlo neg ;springe wenn weniger
rjmp pos
neg: ldi temp1, 0b10110000 ;minuszeichen
rcall lcd_data
rjmp hunderter
pos: ldi temp1, 0b00100000 ;leerstelle
rcall lcd_data
hunderter: sbrs adcwh, 0 ;überprüfen ab wert 308 oder mehr, fals ja dann temperatur dreistellig
rjmp leer ;sonst leerstelle
cpi adcwl, 0x34 ;springe wenn mehr oder gleich
brsh hundert
leer: ldi temp1, 0b00100000
rcall lcd_data ;leerstelle ausgeben
rjmp rest
hundert: ldi temp1, 0b00110001 ;eins ausgeben
rcall lcd_data

rest: ldi temp1, 0x71 ;tabellenadresse festlegen
add adcwl, temp1 ;zu low adc wert dazu zählen
brcc keinue
inc adcwh ;carry in high adc wert
keinue: mov zh, adcwh
mov zl, adcwl ;in das pointerregister laden
LPM ;programminhalt laden
mov temp1, r0
swap temp1
andi temp1, 0b00001111 ;zehnerstelle sind obere 4bit
sbr temp1, 0b00110000
rcall lcd_data
mov temp1, r0
andi temp1, 0b00001111 ;einerstelle sind untere 4bit
sbr temp1, 0b00110000
rcall lcd_data
rcall grad
rcall time
rjmp main



time: ldi temp1, 0x20
loop2: ldi temp2, 0xff
loop1: ldi temp3, 0xff
loop0: dec temp3 brne loop0
dec temp2
brne loop1
dec temp1
brne loop2 ret

grad: ldi temp1, 0b01000111 ;"G"
rcall lcd_data
ldi temp1, 0b01110010 ;"r"
rcall lcd_data
ldi temp1, 0b01100001 ;"a"
rcall lcd_data
ldi temp1, 0b01100100 ;"d"
rcall lcd_data
ret


; ##############
; ##Interrupts##
; ##############

adccomp: in adcwl, ADCL ;Ergebnis in adcwl (untere 8bit)
in adcwh, ADCH ;Ergebnis in adcwh (0bere 2bit)
clr temp1
rcall lcd_clear ;lcd reset
reti







.org 0x0100





; ############
; ##routinen##
; ############

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; LCD-Routinen ;;
;; ============ ;;
;; (c)andreas-s@web.de ;;
;; ;;
;; 4bit-Interface 4Mhz temp1-3 ;;
;; DB4-DB7: PD0-PD3 2 und 3 noch ;;
;; RS: PD4 verwendbar ;;
;; E: PD5 1 ist befehl ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



;sendet ein Datenbyte an das LCD
lcd_data:
push temp2
mov temp2, temp1 ;"Sicherungskopie" für
;die Übertragung des 2.Nibbles
swap temp1 ;Vertauschen
andi temp1, 0b00001111 ;oberes Nibble auf Null setzen
sbr temp1, 1<<4 ;entspricht 0b00010000
out PORTD, temp1 ;ausgeben
rcall lcd_enable ;Enable-Routine aufrufen
;2. Nibble, kein swap da es schon
;an der richtigen stelle ist
andi temp2, 0b00001111 ;obere Hälfte auf Null setzen
sbr temp2, 1<<4 ;entspricht 0b00010000
out PORTD, temp2 ;ausgeben
rcall lcd_enable ;Enable-Routine aufrufen
rcall delay50us ;Delay-Routine aufrufen
pop temp2
ret ;zurück zum Hauptprogramm

;sendet einen Befehl an das LCD
lcd_command: ;wie lcd_data, nur ohne RS zu setzen
push temp2
mov temp2, temp1
swap temp1
andi temp1, 0b00001111
out PORTD, temp1
rcall lcd_enable
andi temp2, 0b00001111
out PORTD, temp2
rcall lcd_enable
rcall delay50us
pop temp2
ret

;erzeugt den Enable-Puls
lcd_enable:
sbi PORTD, 5 ;Enable high
nop ;3 Taktzyklen warten
nop
nop
cbi PORTD, 5 ;Enable wieder low
ret ;Und wieder zurück

;Pause nach jeder Übertragung
delay50us: ;50us Pause
ldi temp1, $42
delay50us_:dec temp1
brne delay50us_
ret ;wieder zurück

;Längere Pause für manche Befehle
delay5ms: ;5ms Pause
push temp2
ldi temp1, $21
WGLOOP0: ldi temp2, $C9
WGLOOP1: dec temp2
brne WGLOOP1
dec temp1
brne WGLOOP0
pop temp2
ret ;wieder zurück

;Initialisierung: muss ganz am Anfang des Programms aufgerufen werden
lcd_init:
push temp3
ldi temp3,50
powerupwait:
rcall delay5ms
dec temp3
brne powerupwait
ldi temp1, 0b00000011 ;muss 3mal hintereinander gesendet
out PORTD, temp1 ;werden zur Initialisierung
rcall lcd_enable ;1
rcall delay5ms
rcall lcd_enable ;2
rcall delay5ms
rcall lcd_enable ;und 3!
rcall delay5ms
ldi temp1, 0b00000010 ;4bit-Modus einstellen
out PORTD, temp1
rcall lcd_enable
rcall delay5ms
ldi temp1, 0b00101000 ;noch was einstellen...
rcall lcd_command
ldi temp1, 0b00001100 ;...nochwas...
rcall lcd_command
ldi temp1, 0b00000100 ;endlich fertig
rcall lcd_command
pop temp3
ret

;Sendet den Befehl zur Löschung des Displays
lcd_clear:
ldi temp1, 0b00000001 ;Display löschen
rcall lcd_command
rcall delay5ms
ret


ist leider alles etwas verrutscht, da ichs im texteditor etwas zu breit geschrieben hab, müsst ihr halt gegebenfals überarbeiten :-b
Also die ADC Werte nehm ich als Sprungadresse und an dieser stehen dann die Zahlen im ASCII und zwar immer die unteren nibbles beider zahlen. die tabelle ist leider nötig da sich der temperatursensor nicht linear verhält. ich habs bis jetzt von -55 bis 100 gerechnet. Die Zeitverzögerung hab ich gemacht damit das Thermometer nicht ständig springt O:) Alles klar soweit?

eric101
03.10.2005, 22:46
achja nochwas zur abweichung, die ist bei mir relativ gering. ich habs mit nem infrarot thermometer geprüft und sie liegt bei unter einem grad. voraussetzung dafür ist natürlich das man einen präzisionswiderstand verwendet und die leitungen vom spannungsteiler sowie zum adc eingang so kurz wie möglich macht O:)

forty
06.10.2005, 21:27
(1023*x)\(x+3900)

Leider kann ich asm nicht lesen ;(

kannst du mir deine formel nochmal kurz erklären?
ich komm noch nicht ganz her wie ich aus dem ergebnis am adc z.b. 2,73V den widerstandswert des kty bekomme - dann könnte ich ja in der tabelle nachschauen welche temp am besten hinkommt ....

danke!

eric101
07.10.2005, 17:37
achso und ich kann leider kein c 8-[

also folgendes:

5V----------------r1----------r2-------------gnd


unbelasteter spannungsteiler:
u zwischen r1 und r2= Uz
dann haben wir: Uz/5V=r2/(r1+r2)

beim 10bit modus werden die 5V in 1023 teile eingeteilt, also wäre dann eins: 5V/1023

lösen wir nach Uz auf und setzen für den temp sensor x ein da sich ja sein wert verändert:
Uz=(x/(r1+x))*5V
Uz teilen wir dann durch unser 5V/1023
oder in einer Formel:
adc wert=((x/(r1+x))*5V)/(5V/1023)
schon fertig! mein cad rechner hat das dann noch etwas gekürzt:
(1023*x)/(x+r1)

Morlos
09.05.2006, 11:30
Hi

da Ihr Euch alle mit dem KTY so gut auskennt....

Der KTY verhält sich wie eim metallischer Widerstand, also PTC Verhalten. Intern ist der KTY aber ein dotierter Halbleiter und Halbleiter haben normalerweise NTC Verhalten. Kann jemand diesen Widerspruch auflösen?

Grüße

Morlos

Manf
09.05.2006, 14:26
Beim KTY wird der Ausbreitungswiderstand gemessen. Ich hatte schon mal eine einfachere Beschreibung davon.
Hier erst einmal ein paar Quellen zum Thema.
Manfred

http://mikro.ee.tu-berlin.de/hlb/praktika/dateien/G_Versuch_V1.pdf

http://www.linuspithan.de/schule/MST/Messtechnikkompendiumsensoren.pdf

http://www.fh-coburg.de/fileadmin/FB_EINF/images/VeranstaltungenAbNov2005/Mut-November-2005/Projekt_Mut_EINF_Nov_2005.pdf

Morlos
09.05.2006, 14:45
Danke für die schnelle Antwort.

Ich hab auch noch weiterrecherchiert. wenn ich es richtig verstanden habe weisen Halbleiter prinzipiel NTC-Verhalten auf. Die besonderheit beim KTY ist, dass er bei Temperaturen von -50 bis 150 Grad C eingesetzt wird. Dieser Bereich liegt inneralb der Störstellenerschöpfung, d.h. alle Störstellen sind ionisiert und die mit steigeneder Temperatur zunehmnenden Gitterschwinungen verringern die Beweglichkeit der Elektronen (n-Halbleiter) und somit erhöht sich auch der Widerstand. Bei höheren Temperatueren jenseits der 150 Grad C kommt man in den Bereich der Eigenleitung. Das hat zur Folge, dass weitere Elekrtonen vom Valenz ins Leitungsband angehoben werden und den Effekt der Gitterschwingungen um ein Vielfaches überlagern. Dann haben wir nämlich NTC Verhalten.

Morlos

Crazy Harry
10.05.2006, 16:35
ich schreib jetzt mal eine größere story, wie ich das mit den sensoren immer mache ... sofern es widerstandssensoren sind.

ich nehme mal an, daß ich einen kty81-110 verwenden will (1000 ohm @ 25°C)

ich bin ein fan von brückenschaltungen (siehe bild "brücke.jpg"). als erstes erstelle ich eine excel-tabelle mit temperatur/widerstand und schau mir in einem diagramm die kurve an (in diesem fall "relativ" linear). siehe bild "kty01.jpg"

dann lasse ich mir von excel die brücke berechnen und gebe dabei UB und R1 vor.
nun kann ich den von mir gewünschten temp-bereich festlegen, z.b. -20 .. 70°C.

bei R1=4.7k und UB=5V beträgt die spannung Uf 0.63522 - 1.14248 V ... entspricht einer differenz von 0.50726 V.

bei -20°C hat der KTY 684 ohm ---> somit wird R4 auf den nächst niedrigeren wert festgelegt = 680 ohm (ja es gibt auch 681 ohm ;) ) und R2=R1. somit beträgt die ausgangsspannung Ud im bereich von -20 .. +70°C ca. 0 - 0.50 V

um nun das signal zu verstärken schalte ich eine op nach (mein lieblingstyp TS912). siehe bild "op.jpg".
wenn man die 5V betriebsspannung voll ausnutzen will ist eine verstärkung von 5V/0.50V erforderlich ---> 10

da aber ein op nicht von 0 an verstärken kann bzw. einen gewissen offset braucht um verstärken zu können UND er die betriebsspannung nicht voll durchschalten kann, wähle ich einen verstärkungsfaktor von z.b. 9.
damit ist R5=R6=10 k (hab ich so festgelegt) und R7=R8=90 k.
wegen der obigen einschränkungen des op hab ich auch R4 nicht mit 684 ohm festgelegt ;)

der von mir genannte op TS912 kommt übrigens recht nahe an 0 bzw. +Ub heran (rail-to-rail-OP) - leider ist er etwas 10x so teuer wie ein LM358.

mit dieser lösung kann man jeden widerstand-sensor benutzen. als letztes noch ein bild von einem NTC. dieser hat ansich eine schreckliche kennlinie (siehe bild "ntc01.jpg") die man aber mit einem einfachen trick verschönern kann (siehe bild "ntc02.jpg") : in diesem fall ein widerstand parallel zum fühler. all das kann man sich mit excel berechnen lassen ;)

wen das jetzt nicht interessiert hat umsonst gelesen - den anderen hoffe ich hat es was gebracht :)

Manf
10.05.2006, 18:32
Zur Auswahl des Linearisierungswiderstands R1 im Spannungsteiler mit dem KTY Temperatursensor ist hier etwas angegeben.
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=68651#68651

Er kann nach Empfindlichkeit oder besser nach Linearität über den gewünschten Temperturbereich gewählt werden.

In jedem Fall sollte der Strom und die Eigenerwärmung beachtet werden.
Manfred

Crazy Harry
10.05.2006, 22:07
ich arbeite mit einer lookup-table - gerade im fall eines ntc's bietet sich das an

stormracer
30.01.2007, 20:32
ich arbeite mit einer lookup-table - gerade im fall eines ntc's bietet sich das an

Moin, auch wenn das Thema schon etwas älter ist...
Ich habe auch mal eine Frage. und zwar versuche ich auch gerade einen Temp. Sensor auszuwerten (KTY81-210).
Crazy Harry hat was von einer Look-Up Tabelle geschrieben, gibt es so etaws unter C auch und wenn ja wie funktioniert das?

Crazy Harry
01.02.2007, 07:59
bei meinem compiler ist das als fertige funktion dabei, ich glaub bascom hat das auch (?) ... andere kenn ich nicht.

bei mir wird eine tabelle angelegt die zum wert des ad-wandlers die entsprechende temperatur enthält. die auflösung/schrittweite wird selber festgelegt. zwischenwerte werden zur programmlaufzeit automatisch interpoliert.

die eingabe der tabelle erfolgt mit einem programm und sieht so aus

stormracer
04.02.2007, 15:46
Moin,
das sieht ja gut aus, was für ein Compiler benutzt du denn?
Ich benutze Programmers Notepad2 aus WinAVR.

Stormracer

Crazy Harry
04.02.2007, 21:40
das steht in meiner signatur ;)

stormracer
05.02.2007, 12:32
OH Stimmt sry, sollte ich wohl mal öfters lesen^^