Widerstandsmessung 1 k ... 10 M
Die Messung ist inspiriert durch den resistiven Feuchtesensor
mit einem Messbereich von 2 kOhm bis 10 MOhm. Der große Messumfang ist
mit einem 10-Bit-AD-Wandler kaum zu schaffen. Der Gedanke ging daher in
Richtung RC-Glied und Zeitmessung. Außerdem darf den Sensor keinen
Gleichstrom sehen. Und schön wäre es außerdem noch, wenn nur ein
einzelner Portpin des Mikrocontrollers gebraucht würde. Das Ergebnis
ist die folgende Messschaltung für einen Tiny13:
Rx
und C1 bilden ein RC-Glied, dessen Zeitkonstante gemessen werden soll.
C2 ist sowas wie die Pufferbatterie im Hintergrund, die den nötigen
Ladestrom liefert. Weil aber C2 über den Messwiderstand auch geladen
wird, ist der Gleichstrom durch Rx im Mittel Null. Die eigentliche
Messung läuft in drei Phasen ab:
1. Laden. Der Port wird niederohmig an VCC geschaltet, sodass C1 und C2 in aller Ruhe geladen werden.
2.
Entladen. Der Port wird sehr kurz an GND geschaltet, gerade so kurz,
dass C1 entladen ist, C2 aber noch fast die volle Spannung behält.
3. Messen. Der Port wird als hochohmiger Eingang konfiguriert. Dann wird die Zeit gemessen, bis der Eingang auf 1 kippt.
Download: Rmess.zip
'Rmess1.bas, 1k...10M gleichstromfrei
$regfile = "attiny13.dat"
$crystal = 1200000
$hwstack = 8
$swstack = 4
$framesize = 4
Dim Count As Word
Dim R As Word
Open "comb.1:9600,8,n,1,INVERTED" For Output As #1
Do
Count = 0
Portb.3 = 1
Ddrb.3 = 1 'Laden
Waitms 500
Portb.3 = 0 'Entladem
Waitus 20
Ddrb.3 = 0
Do
Count = Count + 1 'Messen
Loop Until Pinb.3 = 1 Or Count.15 = 1
Portb.3 = 1
Ddrb.3 = 1
Print #1 , Count
R = Count * 40 'Umrechnen in kOhm
R = R / 10
Print #1 , R
Loop
End
Ergebnis:
Bei 100 k ist die Messung recht genau. Im Bereich 20 k bis 1 M kann
man mit einer Abweichung bis 10% rechnen. Bei 10 M wird deutlich
zu wenig angezeigt, bei 1 k deutlich zu viel. Aber immerhin lassen sich
Widerstände in diesem großen Bereich deutlich unterscheiden. Wenn man
mal wieder auf einem Widerstand Braun, Rot oder Orange schlecht zu
unterscheiden ist, kann das Gerät helfen, ein brauchbares Schätzeisen.
Noch
eine Variation in der Schaltung: Weil RX und C2 in Reihe liegen darf
man sie auch vertauschen. Das ist technisch schöner, weil das
Messobjekt nun einseitig an Masse liegt. Und immer noch gilt: Kein
Gleichstrom, reine AC-Messung. Damit dürfte die Methode auch für den
resistiven Feuchtesensor brauchbar sein.
Vielleicht lässt sich
auch noch was verbessern. Z.B. könnte man noch einen kleinen Widerstand
in Reihe zu RX legen, denn deutlich unter 1 k versagt die Messung. Und
mit etwas Software ließe sich vielleicht auch die Linearität
verbessern.
Nachtrag: Verbesserte Software mit Assembler-Messschleife
Thomas
Baum hat das Programm weiter entwickelt und die Auflösung mit
einer Assembler-Zeitschleife verbessert. Außerdem hat es sich gezeigt,
dass der Entladeimpuls auf 10 µs verkürzt werden kann. In dieser
Version hat das Programm eine gute Messgenauigkeit im Bereich 1 kOhm
bis 1 MOhm und funktioniert bis über 22 MOhm hinaus.
Download: Rmess2.zip
'Rmess2.bas, 1k...10M gleichstromfrei
$regfile = "attiny13.dat"
$crystal = 1200000
$hwstack = 8
$swstack = 4
$framesize = 4
Dim Count As Word
Dim R As Word
Led2 Alias Portb.3
Open "comb.1:9600,8,n,1,INVERTED" For Output As #1
Do
Count = 0
Loadadr Count , Z
Portb.3 = 1
Ddrb.3 = 1 'Laden
Waitms 500
Portb.3 = 0 'Entladem
Waitus 10
Ddrb.3 = 0
$asm 'Messen in Asm
messure:
adiw r24, 1
breq break
sbis pinb, 3
rjmp messure
Break:
st Z+, r24
St Z, r25
$end Asm
Portb.3 = 1
Ddrb.3 = 1
Print #1 , Count
Count = Count - 1 'Korrektur untere Grenze
R = Count * 11 'Umrechnen in kOhm
R = R / 16
Print #1 , R
Loop
End
Logarithmische Messung, relative Luftfeuchte
Resistive
Feuchtesensoren haben eine in erster Näherung exponentielle Kennlinie. Man muss
also den Widerstand messen und dann logarithmieren. Eigentlich kein Problem,
aber die Rechnung mit realen Zahlen braucht viel Speicherplatz. Damit es auch
in den Tiny13 passt muss man versuchen mit Integer auszukommen.
Von Thomas Baum habe ich erfahren, wie es gehen kann. Man rechnet den
Logarithmus zur Basis Zwei aus, was weniger Aufwand macht. Die Umrechnung in
eine beliebige andere Basis erfordert dann nur noch eine einfache
Multiplikation. Zum Logarithmieren stellt man zunächst durch mehrfaches
Schieben die Größenordnung fest und hat dann den ganzzahligen Logarithmus
(links vom Komma). Beispiel: 0000 1001 1111 0011 (= &H 09F3 = 2547)
muss viermal nach links geschoben werden, damit eine 1 ganz links steht. Die
Größenordnung ist dann 15-4=11. Kontrolle: 2^11=2048, 2^12=4096, wäre also
schon zu viel. Es fehlen nur noch die Nachkommastellen. Dazu nimmt man
einfach näherungsweise die folgenden vier Bits, also 0011 (= 3/16 = 0,1875).
Dann wäre das Endergebnis: 11,1875. Kontrolle: 2^11,1875 = 2332, na gut, es ist
eine Annäherung. Das binäre Endergebnis lautet 1011 0011, wobei das obere
Nibble als Vorkommastellen und das untere als Nachkommastellen zu verstehen
ist. Im Endeffekt hat man eine 16-Bit-Zahl durch Logarithmieren in eine
8-Bit-Zahl gequetscht.
Um daraus dann die relative Luftfeuchte zu bestimmen braucht man nur
noch lineare Geradengleichungen. Im Beispiel sorgen eine Multiplikation mit
2,34 und ein Endpunkt 101 für eine brachbare Umrechnung. Das Ergebnis wird am
Ende als ein Byte ausgegeben. Für eine Printausgabe hat der Speicherplatz nicht
mehr gereicht, weil der Versuch mit dem Lernpaket Mikrocontroller durchgeführt
wurde und der Bootloader auch noch etwas Speicherplatz belegt. Der Sparrow
dagegen kommt ohne Bootloader aus, da wäre noch etwas Platz. Im Endergebnis
jedenfalls wird die relative Luftfeuchte feinstufig angezeigt, man sieht jede
Änderung in Prozentstufen.
Die Genauigkeit ist bescheiden, aber die Logarithmierung ist dabei die
geringste Fehlerquelle. Die größten Abweichungen entstehen durch
Exemplarstreuungen der Sensoren. Eine Kalibrierung ist aufwendig, und alle Vergleichsmessgeräte
im Umfeld sind ähnlich ungenau. Aber jedenfalls sieht man Änderungen der Luftfeuchte
sehr deutlich. Im Moment ist es draußen kalt, drinnen warm, der Sensor zeigt
40%, könnte stimmen. Die Blumen müssen dringend mal gegossen werden. Und sofort
steigt die Feuchtigkeit auf 41%. Größere Änderungen ergeben sich wenn ich die
Hand in die Nähe des Sensors halte. Zwischen zwei Finger gehalten zeigt
der Sensor ganz schnell über 80%.
Download: RelativeFeuchte.zip
'Rlog.bas, 1k...10M, Logaritmierung zur Feuchtemessung
$regfile = "attiny13.dat"
$crystal = 1200000
$hwstack = 8
$swstack = 4
$framesize = 4
Dim Count As Word
Dim R As Word
Dim Ll As Byte
Dim Hl As Byte
Dim F As Word
Dim Rf As Byte
Led2 Alias Portb.3
Open "comb.1:9600,8,n,1,INVERTED" For Output As #1
Do
Count = 0
Loadadr Count , Z
Portb.3 = 1
Ddrb.3 = 1 'Laden
Waitms 500
Portb.3 = 0 'Entladem
Waitus 10
Ddrb.3 = 0
$asm 'Messen in Asm
Messure:
adiw r24, 1
breq break
sbis pinb, 3
rjmp messure
Break:
st Z+, r24
St Z, r25
$end Asm
Portb.3 = 1
Ddrb.3 = 1
If Count = 0 Then Count = 1
' Print #1 , Count
Hl = 15 'log zut Basis 2
While Count.15 = 0
Shift Count , Left
Hl = Hl - 1
Wend
Ll = High(count)
Shift Ll , Right , 3
Ll = Ll And 15
Shift Hl , Left , 4
Hl = Hl + Ll 'bei 80%, 5,2k, Log = 50, bei 40% 400k, Log =145
F = Hl
F = F * 109
Shift F , Right , 8
Rf = F '/ 2,34
Rf = 101 - Rf
Put #1 , Rf 'relative Feuchte
Loop
End
Feuchtesensor ohne zusätzliche Bauteile
Der
Feuchtesensor ändert seinen Widerstand in einem großen Bereich zwischen
etwa 1 kOhm und 10 MOhm. Für eine einfache Messung im Spannungsteiler
reicht daher der interne Pullup eines AVR-Controllers von ca. 35 kOhm
bei 5 V. Allerdings muss der Sensor unbedingt gleichstromfrei betrieben
werden. Deshalb braucht man zwei Ports, an denen abwechselnd für einen
kurzen Moment der Pullup eingeschaltet wird. Weil der Sensor zwischen
beiden Ports liegt, fließt Strom in beide Richtungen. Im Mittel sieht
der Sensor keine Gleichspannung. Das Verfahren wurde mit gutem
Erfolg an einem ATtiny85 ausprobiert. Man braucht zwar nun zwei freie
Ports, aber außer dem Sensor sonst keine weiteren Bauteile.
'Rmess.bas Widerstand B2(ADC4) gegen B3(ADC3)
'Feuchtesensor, Messung gleichspannunsgfrei, Umrechnung in %
$regfile = "attiny85.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 40 'Rechnen!
$framesize = 40
Dim U As Long
Dim R As Long
Dim F As Single
Open "comb.1:9600,8,n,1" For Output As #1
Config Adc = Single , Prescaler = Auto
Do
Print #1 , Chr(13);
Ddrb.3 = 0 'Eingang
Portb.3 = 1 'Pullup ein
U = Getadc(3)
Portb.3 = 0 'Pullup Aus
Ddrb.3 = 1 'Nierohmig
Ddrb.4 = 0 'Eingang
Portb.4 = 1 'Pullup ein
U = U + Getadc(2)
Portb.4 = 0 'Pullup Aus
Ddrb.4 = 1 'Nierohmig
U = U / 2
R = 35000 * U 'int pullup 35k
U = 1023 - U 'R=35k*(U/1023-U)
If U > 0 Then
R = R / U
Else
R = 999999
End If
R = R - 450 '- interner Bahnwiderstand 0,45 k
Calculate Humidity
F = R / 280
F = Log(f) 'ln f
F = F * 8.9
F = 100 - F
F = Round(f)
Lcd "% "
Print #1 , R;
Print #1 , " Ohm ";
Print #1 , F;
Print #1 , " % ";
Waitms 500
Loop
End
Elektronik-Labor Projekte AVR