Widerstandsmessung 1 k ... 10 M          

           
Elektronik-Labor   Projekte   AVR 

 

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