05.11.2013 Aufrufe

Projektbericht 796.8 KByte - Technikpreis

Projektbericht 796.8 KByte - Technikpreis

Projektbericht 796.8 KByte - Technikpreis

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

<strong>Technikpreis</strong> 2006 des VDE Rhein-Ruhr e. V.<br />

Projektdokumentation<br />

Bau und Entwicklung einer<br />

Wettermessstation<br />

mit Anbindung<br />

ins Packet Radio Netz<br />

Reinhold Bertram<br />

St. Antonius Gymnasium, Lüdinghausen<br />

Betreuer : Herr Dr. Ruttert<br />

Eingereicht am : 7. Juni 2006


Danksagung<br />

Ich danke besonders dem VDE Rhein-Ruhr e.V. für die finanzielle Unterstützung dieser<br />

Arbeit.<br />

Herrn Dipl. Ing. Thomas Aundrup gilt mein besonderer Dank für die engagierte Betreuung<br />

meines Projekts.<br />

Die schnellen Antworten und Hilfen haben mir sehr geholfen.<br />

Außerdem gilt mein Dank meinem Bruder Clemens, sowie dem DARC OV Lüdinghausen.<br />

Ohne ihre Hilfe wäre die Arbeit nicht so gut gelungen.


III<br />

Inhaltsverzeichnis<br />

Inhaltsverzeichnis<br />

Danksagung<br />

II<br />

1 ”Und nun das Wetter” 1<br />

2 Messwerterfassung 3<br />

2.1 Allgemeines über die serielle Schnittstelle . . . . . . . . . . . . . . . . . . 3<br />

2.2 Funktionsweise des TLC 549 . . . . . . . . . . . . . . . . . . . . . . . . . 3<br />

2.3 Multiplexer/Demultiplexer . . . . . . . . . . . . . . . . . . . . . . . . . . 5<br />

2.4 Achtstufiger Binärzähler als Seriell/Parallel-Wandler . . . . . . . . . . . 5<br />

3 Sensortechnik 6<br />

3.1 Temperatursensor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6<br />

3.2 Lichtsensor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9<br />

3.3 Feuchtesensor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10<br />

3.4 Drucksensor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12<br />

4 Software 13<br />

4.1 Steuerung des A/D-Wandler über serielle Schnittstelle . . . . . . . . . . . 13<br />

4.2 Steuerung des Analog-Multiplexer . . . . . . . . . . . . . . . . . . . . . . 14<br />

4.3 Umwandlung der Spannungswerte in Wetterdaten . . . . . . . . . . . . . 14<br />

4.4 Dokumentation der Messparameter . . . . . . . . . . . . . . . . . . . . . 15<br />

5 Übertragung 16<br />

5.1 Packet Radio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16<br />

5.2 Packet Radio Station . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17<br />

5.3 Terminalprogramm Paxon . . . . . . . . . . . . . . . . . . . . . . . . . . 17<br />

5.4 Übertragung in eine Mailbox . . . . . . . . . . . . . . . . . . . . . . . . . 19<br />

6 Schlussbetrachtung 20<br />

7 Ausblick 22<br />

Literatur 23<br />

A Schaltpläne 25<br />

B Fotos 28


IV<br />

Inhaltsverzeichnis<br />

C Stückliste 32<br />

D Quellcode 34


1 1 ”Und nun das Wetter”<br />

1 ”Und nun das Wetter”<br />

Mit diesen Worten leiten Nachrichtensprecher zum vielleicht spannendsten Teil der Nachrichten,<br />

der Wettervorschau für die nächsten Tage, über. Menschliches Handeln und Tun<br />

ist massiv vom Wetter beeinflusst. Die Wahl der Kleidung, der Sportunterricht und die<br />

Organisation der Grillparty am nächsten Samstag sind genauso vom Wetter abhängig<br />

wie die Arbeit der Gärtner und Bauern. Die Bedeutung der Wettervorhersage für Sturm,<br />

Hagel und Hochwasser für unser aller Wohl liegt klar auf der Hand.<br />

Auslöser für die Entwicklung und den Bau einer lokalen Wetterstation ist ein Projekt<br />

der Biologischen Station Lüdinghausen zur Wiederansiedlung von Wanderfledermäusen<br />

in unserer Region. Eine Gruppe, die sich aus Ornithologen, Naturschützern, Biologen,<br />

Gärtnern und Schülern zusammensetzt, hat im Biologischen Zentrum Lüdinghausen einen<br />

Fledermausstollen gebaut, der den Tieren als Herberge und Nistbaustätte dienen soll.<br />

Für eine erfolgreiche Ansiedlung der Wanderfledermaus gehört sicherlich ein biologisches<br />

intaktes Umfeld, das sich in einer reichen Artenvielfalt an Pflanzen und Insekten widerspiegelt,<br />

und klimatisch passenden Bedingungen.<br />

In der Gruppe stellten wir uns deshalb die Frage, inwieweit das Verhalten der Tiere durch<br />

das Wetter beeinflusst wird. Bei welchen Lichtverhältnissen verlassen die Fledermäuse<br />

den Stollen? Fliegen sie bei jeder Temperatur aus oder verbleiben sie im Stollen, wenn<br />

es draußen zu kalt ist? Wie verhalten sich die empfindlichen Tiere bei Regenwetter? Aus<br />

dieser Fragestellung entstand die Idee, das Wetter in unmittelbarer Nähe zum Stollen<br />

zu messen und zeitgleich das Verlassen und Zurückkehren der bedrohten Tiere in ihre<br />

Behausung durch Lichtschranken zu registrieren.<br />

In dem vorliegenden Bericht möchte ich mich allein auf die Darstellung der Wetterstation<br />

beschränken. Hier werden die Arbeitsergebnisse der letzten vier Monate beschrieben. Bei<br />

der Planung habe ich von Beginn ab an beabsichtigt, leicht zugängliche elektronische<br />

Bauteile zu verwenden, damit auch andere Naturgruppen die Anlage einfach nachbauen<br />

können. Die Wetterdaten werden im Packet Radio Netz der Funkamateure übertragen<br />

und somit einer breiten Öffentlichkeit zugänglich gemacht. Somit ist es möglich, das


2 1 ”Und nun das Wetter”<br />

Verhalten der Tiere in Lüdinghausen mit denen in anderen Städten zu vergleichen, um<br />

so zu einem besseren Verständnis der Tiere und zum Artenschutz beizutragen.<br />

Vielleicht wird die Wetterstation, die ich hier beschreiben werde, auch nur von interessierten<br />

Schülerinnen und Schülern nachgebaut, weil sie wissen wollen, wie das Wetter<br />

an ihrer Schule gerade ist. Für die Weiterverarbeitung des von mir entwickelten Systems<br />

an interessierte Gruppen ist allerdings eine präzise Bauanleitung mit detaillierten<br />

Schaltplänen notwendig, um auch bei elektrotechnisch unerfahrenen Interessenten den<br />

erfolgreichen Nachbau zu ermöglichen. Der vorliegende Bericht dokumentiert zunächst<br />

einmal die grundlegenden technischen Ideen meines Projekts.<br />

Nach der Einleitung folgt im zweiten Kapitel des Berichts die Erläuterungen zu den zentralen<br />

elektronischen Bauteilen zur Messung der Wetterparameter Temperatur, Licht, relative<br />

Luftfeuchtigkeit und Druck. Dazu gehört die serielle Schnittstelle, der TLC 549, der<br />

Multiplexer/Demultiplexer und der achtstufige Binärzähler als Seriell/Parallel-Wandler.<br />

Im 3. Kapitel stelle ich die Sensoren kurz vor und beschreibe die Erzeugung von Spannungswerten<br />

aus den gemessenen Wetterparametern. Nach der Hardware wird im 4. Abschnitt<br />

die Software vorgestellt, die von mir selbst entwickelt wurde. Die Beschreibung<br />

der Übertragung der Daten wird im 5. Abschnitt behandelt. Der vorliegende Bericht<br />

schließt mit einem Ausblick auf die mögliche Weiterentwicklung der Messstation.


3 2 Messwerterfassung<br />

2 Messwerterfassung<br />

2.1 Allgemeines über die serielle Schnittstelle<br />

Ich habe mich für die Abfrage über die serielle Schnittstelle entschieden, weil sie relativ<br />

einfach zu programmieren ist und häufig in älteren PCs eingebaut ist. Die serielle Schnittstelle<br />

verfügt über neun Anschlüsse, von denen drei Sendeleitungen und fünf Empfangsleitungen<br />

sind. Der neunte Anschluss geht nach Masse. Da die Steuerung der seriellen<br />

Schnittstelle asynchron erfolgt (oder overlapped, wie es unter Windows heißt), können<br />

nur vier Empfangsleitungen genutzt werden. Für den A/D-Wandler TLC549 werden zwei<br />

Steuerleitungen und eine Empfangsleitung benötigt, weshalb eine Steuerleitung und drei<br />

Empfangsleitungen zunächst frei bleiben 1 .<br />

2.2 Funktionsweise des TLC 549<br />

Anhand der Darstellung (Abbildung 2.1) erkennt man, dass bei Anschluss 1 und 3 die<br />

obere und untere Referenzspannung anliegt, welche mit der von Pin 2 kommenden analogen<br />

Spannung im 8-Bit Analog-to-Digital Converter ins Output Data Register geschrieben<br />

wird. Über ChipSelect und I/O Clock wird mit Hilfe des Control Logic and Output<br />

Counter nacheinander bitweise die Spannung als digitaler Wert ausgegeben.<br />

Abbildung 2.2 zeigt den zeitlichen Verlauf zweier Abfragen: Mit der fallenden Flanke<br />

an ChipSelect (CS) liegt an DataOut (Pin6) das höchstwertige Bit des acht Bit langen<br />

digitalen Wertes an. Nach einer steigenden Flanke liegt das nächste Bit am Ausgang.<br />

Nach achtmal Schalten ist der komplette digitale Wert ausgegeben worden.<br />

Mit einem einzigen A/D-Wandler ist zunächst nur eine Messwerterfassung möglich, da<br />

ich aber bis zu 8 Sensoren benutzen möchte, benötige ich eine Schaltung die mehrere<br />

1 Vgl. H.-J. Berndt/B. Kainka, Messen, Steuern und Regeln mit Word und Excel, Poing, Francis-Verlag,<br />

2001 3 , 100ff.


4 2 Messwerterfassung<br />

Abbildung 2.1: Functional block diagram (Quelle: Datenblatt TLC549 )<br />

Abbildung 2.2: Operating sequence (Quelle: Datenblatt TLC549 )


5 2 Messwerterfassung<br />

Leitungen möglich macht. Man könnte mehrere A/D-Wandler benutzen, welche man<br />

über Digital-Multiplexer an die serielle Schnittstelle anschließt. Oder man nutzt einen<br />

Analog-Demultiplexer um acht Leitungen seriell, d.h. nacheinander abzufragen.<br />

2.3 Multiplexer/Demultiplexer<br />

Als Analog Multiplexer/Demultiplexer verwende ich den CD4051, der für acht Leitungen<br />

ausgelegt ist. Um die Leitungen durchzuschalten ist ein achtstufiger Binärzähler notwendig.<br />

2.4 Achtstufiger Binärzähler als<br />

Seriell/Parallel-Wandler<br />

Ein achtstufiger Binärzähler lässt sich aus drei jk-Master-Slave FlipFlops aufbauen, wie<br />

er in ”Einführung in die Elektronik 2 / Kontaktlose Signalverarbeitung” von K. Block,<br />

H.-J. Hölzel, L. Wölfing und P. Zachert auf Seite 206 beschrieben ist. Dazu schließt man<br />

den Ausgang des ersten FF als Clock-Signal an den zweiten FF und dessen Ausgang als<br />

Clock-Signal des dritten Ausgangs. Mit jedem Ausgang hat man dann insgesamt drei<br />

Leitungen die 2 3 = 8 unterschiedliche Zustände annehmen können. Diese kann man nun<br />

an den Multiplexer anschließen.<br />

Wenn man das Signal der seriellen Schnittstelle direkt als erstes Clock-Signal weitergibt,<br />

kann es dazu kommen, dass der achtstufige Binärzähler weiter zählt als zu erwarten<br />

ist. Es lässt sich vermuten, dass sich dahinter ein Kontaktprellen verbirgt, weshalb eine<br />

Vielzahl von Impulsen gezählt wird. Um dies zu verhindern könnte man wie auf S.<br />

207 des schon genannten Buches ”Einführung in die Elektronik 2” zwei NAND-Stufen<br />

benutzen. Ich habe mich allerdings für die Schaltung über zwei Transistoren, die die 5<br />

Volt-Versorgungsspannung schalten, entschieden, mit der das unerwünschte Weiterschalten<br />

auch vermieden wird.<br />

Mit der bis hierhin beschriebenen Schaltung ist es also möglich, acht Leitungen im Bereich<br />

von 0 bis 5 Volt mit einer Genauigkeit von 8-bit über die serielle Schnittstelle<br />

nacheinander abzufragen.


6 3 Sensortechnik<br />

3 Sensortechnik<br />

Da der TLC549 einen Spannungsbereich von 0 bis 5 Volt abdeckt, ist es notwendig alle<br />

zu ermittelnden Werte, wie Temperatur, Licht, Luftdruck usw. in veränderliche Spannungswerte<br />

umzuwandeln.<br />

3.1 Temperatursensor<br />

Der Temperatursensor ist ein PTC-Widerstand (Positive Temperature Coeffizient Widerstand<br />

- Kaltleiter). Dies bedeutet, dass er bei hohen Temperaturen einen größeren<br />

Widerstand besitzt als bei niedrigeren. Da es aber aufwendiger wäre den Widerstand<br />

des PTCs zu messen als eine Spannung ist es sinnvoll die Widerstandsänderung in eine<br />

Spannungsänderung umzusetzen. Dafür benutzt man eine Widerstandsbrückenschaltung.<br />

Sie besteht aus zwei in Reihe geschalteten Widerständen zwischen denen die Spannung<br />

abgegriffen wird.<br />

Die Spannungsänderung ergibt sich aus der Widerstandsänderung wie folgt:<br />

In einer Reihenschaltung fließt durch jedes Bauteil ein gleich großer Strom: I 1 = I 2 = I ges .<br />

Die Spannung teilt sich allerdings an jedem Bauteil und addiert sich zur Gesamtspannung<br />

U 1 + U 2 = U ges . Das Ohmsche Gesetz besagt I ges = U ges /R ges . Mit R ges = R 1 + R 2 folgt<br />

daraus für den Gesamtstrom I ges = U ges /(R 1 + R 2 ). Da in der Mitte zwischen beiden<br />

Widerständen die Spannung abgegriffen wird, gilt für sie U 1 = R 1 · I ges , also:<br />

U 1 = R 1 · U ges /(R 1 + R 2 )<br />

Für R 1 > R 2 ist U 1 > 1/2U ges ,<br />

für R 1 = R 2 ist U 1 = 1/2U ges und<br />

für R 1 < R 2 ist U 1 < 1/2U ges .<br />

Dies zeigt, wie sich eine Widerstandsänderung leicht in eine Spannungsänderung umwandeln<br />

lässt.


7 3 Sensortechnik<br />

Abbildung 3.1: Schaltplan für Temperatursensor


8 3 Sensortechnik<br />

Das Datenblatt des benutzten Sensors (KTY 81-210) gibt an, dass der Widerstandswert<br />

des Sensor bei 10 ◦ C 1772 Ohm beträgt. Wenn nun der 1. Widerstand ebenfalls auf diesen<br />

Wert eingestellt wird, ergibt sich somit eine Spannung von 2,5 V. Bei einer Veränderung<br />

der Temperatur ändert sich der Widerstand; die Spannung wird somit geändert. Bei dem<br />

benutzten Sensor spielt sich die Bandbreite der Widerstandswerte in einem Bereich von<br />

-20 ◦ C bis 40 ◦ C bei 1367 Ohm bis 2245 Ohm ab. Damit ergeben sich Spannungen im<br />

Bereich von:<br />

U 1 (−20 ◦ C) = 5V ·<br />

1367Ω<br />

1367Ω + 1772Ω<br />

= 2, 17V<br />

U 1 (40 ◦ C) = 5V ·<br />

2245Ω<br />

2245Ω + 1772Ω<br />

= 2, 79V<br />

Diese Spannungsbandbreite reicht für eine adäquate Messwertbestimmung jedoch nicht<br />

aus. Aus diesem Grund muss sie verstärkt werden. Dies geschieht mit einem Operationsverstärker<br />

als Differenzverstärker, der über R 4 und R 5 etwa eine Verstärkung v U um das<br />

etwa fünffache bewirkt (berechnet sich nach der Formel v U = 1 + R 5 /R 4 = 5, 6, siehe<br />

Fußnote 1 ).<br />

Daraus folgt:<br />

Differenz von 2,5 Volt ohne Verstärkung:<br />

∆U 1 (−20 ◦ C) = 2, 17 − 2, 5V = −0, 33V<br />

∆U 1 (40 ◦ C) = 2, 80 − 2, 5V = 0, 30V<br />

Mit Verstärkung von v U = 5, 6 :<br />

−0, 33V · 5, 6 = −1, 848V<br />

0, 30V · 5, 6 = 1, 680V<br />

Damit:<br />

U1(-20 ◦ C) = 2,5 - 1,848 V = 0,652 V<br />

U1(40 ◦ C) = 2,5 + 1,680 V = 4,18 V<br />

1 W.-D. Schmidt, Sensorschaltungstechnik, S.30


9 3 Sensortechnik<br />

Mit dieser Differenz von insgesamt 3,528 Volt auf 60 ◦ C ergibt sich:<br />

3,472 V / 60 ◦ C = 0,0588 V/ ◦ C bzw. 17,01 ◦ C/V<br />

Bei einer Genauigkeit des A/D-Wandlers von 8bit bedeutet dies:<br />

5V/2 8 bit = 0, 019V/bit<br />

17, 01 ◦ C/V · 0, 019V/bit = 0, 323 ◦ C/bit<br />

Die Messung findet also mit einer Genauigkeit von 0,323 ◦ C statt (ungefähr 1/3 ◦ C<br />

bzw. 3bit/ ◦ C).<br />

Diese Berechung gilt für die vom Datenblatt angegebenen typischen Widerstandswerte<br />

des Sensors. Das Datenblatt gibt allerdings auch maximale und minimale Werte für jede<br />

Temperatur an, zwischen denen der tatsächliche Widerstandswert liegt. Laut Datenblatt<br />

liegt der Fehler dabei im Bereich von ±2%.<br />

3.2 Lichtsensor<br />

Ähnlich wie der Temperatursensor besitzt der Lichtsensor (LDR 03) einen veränderlichen<br />

Widerstandswert, der im Bereich von 2 Megaohm bei Dunkelheit und unter 100 Ohm<br />

bei Sonnenlicht liegt. Im Schatten besitzt er immerhin noch ungefähr 2000 Ohm. Da in<br />

dieser Arbeit keine absolute Lichtstärkemessung vorgenommen werden soll, sondern nur<br />

eine relative Helligkeit festgestellt werden soll, besteht die Schaltung für den Lichtsensor<br />

nur aus einer Brückenschaltung mit einem Präzisionstrimmer, mit welchem man den<br />

gewünschten Schwellenwert für eine Messung von Hell/Dunkel einstellen kann. Aufgrund<br />

des stark veränderlichen Fotowiderstands ist es nicht notwendig, die Spannung weiter zu<br />

verstärken.<br />

Abbildung 3.2: Schaltplan für Lichtsensor


10 3 Sensortechnik<br />

3.3 Feuchtesensor<br />

Der Feuchtesensor besitzt eine veränderliche Kapazität, weshalb er mit den bisherigen<br />

Methoden nicht gemessen werden kann.<br />

Meine Idee dazu sieht folgendermaßen aus:<br />

Abbildung 3.3: Schaltplan für Feuchtesensor<br />

Der Feuchtesensor ist als Kondensator im RC-Glied, des Timer-Schaltkreises mit einem<br />

NE555 getaktet. Abhängig von der Kapazität entsteht eine variable Frequenz 2 . Da mit<br />

meiner restlichen Hardware keine Frequenzmessung möglich ist, soll die Frequenz mit<br />

einem Frequenz-Spannungs-Wandler umgewandelt werden und mit einem Operationsverstärker,<br />

wie er auch schon benutzt wurde, angepasst werden. Die Frequenz des astabilen<br />

Multivibrators berechnet sich mit f =<br />

1<br />

0,7(R 4 +2R 2 )C (siehe Fußnote3 ) . Mit den berechneten<br />

Werten für die Widerstände kommt man auf eine mittlere Frequenz von ungefähr 10<br />

kHz, die um ungefähr 3 kHz nach oben und unten schwankt. Die Ausgangsspannung des<br />

2 Vgl. Schmidt, Sensorschaltungstechnik, S.134ff.<br />

3 Schmidt, Sensorschaltungstechnik, S. 136 und Datenblatt NE555


11 3 Sensortechnik<br />

Frequenz-Spannungs-Wandlers LM2917 berechnet sich nach: 4<br />

V out = f in · V c · R 1 · C 1<br />

Weshalb R 1 · C 1 = 1 · 1 kHz sein soll.<br />

2 10<br />

Der NE555 liefert eine positive Rechteckspannung, weshalb die Schaltung so noch nicht<br />

funktioniert, da der LM2907 eine Frequenz erwartet, die zwischen positiven und negativen<br />

Spannungen pendelt. Dieses Problem lässt sich beheben, indem man an Pin 11 des<br />

LM2907 eine Spannung anlegt, die zwischen den Spitzen der Rechteckspannung liegt.<br />

Aus dem Diagramm des Datenblattes kann man für den Feuchtigkeitssensor folgende<br />

Werte entnehmen:<br />

Kapazität des Feuchtesensors bei 0% r.F. ungefähr 100pF<br />

Kapazität des Feuchtesensors bei 43% r.F. ungefähr 120pF<br />

Kapazität des Feuchtesensors bei 100% r.F. ungefähr 150pF<br />

Mit den benutzten Bauteilen errechnen sich folgende Werte für die Schaltung:<br />

Frequenz am Ausgang des NE555:<br />

für 0% r.F.:<br />

f =<br />

1<br />

0, 7(R4 + 2R2)C => f 0 =<br />

1<br />

0, 7(47kΩ + 2 · 530kΩ) · 100pF<br />

= 13, 0kHz<br />

für 43% r.F.:<br />

=> f 1 =<br />

1<br />

0, 7(47kΩ + 2 · 530kΩ) · 120pF<br />

= 10, 8kHz<br />

für 100% r.F.:<br />

=> f 2 =<br />

1<br />

0, 7(47kΩ + 2 · 530kΩ) · 150pF<br />

= 8, 7kHz<br />

Spannungswerte für die Frequenzen:<br />

V = f · 5V · 100kΩ · 470pF = f · 0, 000235V s<br />

V 0 = f 0 · 0, 000235V s = 3, 056V<br />

V 1 = f 1 · 0, 000235V s = 2, 54V<br />

V 2 = f 2 · 0, 000235V s = 2, 038V<br />

4 National Semiconductor,LM2907/LM2917 Frequency to Voltage Converter, DATA SHEET, 18 Seiten,<br />

1995


12 3 Sensortechnik<br />

Somit gibt es also eine Spannungsdifferenz von etwa 1V. Für die Messung muss sie also<br />

um das Fünffache verstärkt werden. Der Verstärkungsfaktor v U berechnet sich nach v U<br />

= 1 + R 11<br />

R 10<br />

= 5, siehe Fußnote 5<br />

mit R 11 = 10kΩ folgt:<br />

4 · R 10 = 10kΩ => R 10 = 2, 5kΩ<br />

3.4 Drucksensor<br />

Als Drucksensor kommt ein integrierter Sensor der Firma Motorola zum Einsatz, der im<br />

Bereich von 15 bis 115 kPa ein lineares Spannungssignal im Bereich von 0.2 bis 4.8 Volt<br />

ausgibt. Dieses wird nur noch durch die bereits beschriebene Operationsverstärkerschaltung<br />

an die Messstation angepasst.<br />

5 Schmidt,Sensorschaltungstechnik, S.30


13 4 Software<br />

4 Software<br />

Zur Programmierung der Software habe ich mich für die Programmiersprache Delphi<br />

entschieden, da sie sowohl einfachen Gebrauch von der Windows-API machen kann als<br />

auch eine leichte Programmierung der Benutzeroberfläche ermöglicht und zudem objektorientiert<br />

ist.<br />

4.1 Steuerung des A/D-Wandler über serielle<br />

Schnittstelle<br />

Zunächst muss die serielle Schnittstelle geöffnet werden. Die Funktion CreateFile öffnet<br />

diese und gibt ein Handle von ihr zurück. Dies wird in der Variablen PortHandle<br />

gespeichert, da es später für den Aufruf der übrigen Funktionen benötigt wird.<br />

Die einzelnen Sendeleitungen werden mittels EscapeCommFunction gesetzt und zurückgesetzt.<br />

Der Status der Empfangsleitungen wird mit GetCommModemStatus abgefragt. Um<br />

den A/D-Wandler TLC549 nun abzufragen, wird zunächst der Variablen BitWert der<br />

Wert 128 und b der Wert 0 zugewiesen. Durch einmaliges ein- und ausschalten von RTS<br />

liefert der A/D-Wandler das höchstwertige Bit an der CTS-Leitung. Diese Leitung wird<br />

in einer for-Schleife achtmal abgefragt, während I/O-Clock weitergeschaltet wird. Am<br />

Ende ist in der Variablen b der Wert des TLC549 gespeichert und wird von der Funktion<br />

zurückgegeben.<br />

function TSerialThread.ByteRead : Integer; stdcall;<br />

var BitWert, b, i : Integer;<br />

BitWert := 128;<br />

b := 0;<br />

//Chipselect ein und ausschalten<br />

SetzeRTS;<br />

ClearRTS;<br />

//Am Dataout liegt jetzt das 1. Bit<br />

for i := 0 to 7 do // 8 mal weiterschalten


14 4 Software<br />

begin<br />

if CTS = True then<br />

b := b + BitWert;<br />

//I/O-Clock weiterschalten<br />

SetzeDTR;<br />

ClearDTR;<br />

//nächstes Bit nur noch halbwertig<br />

BitWert := BitWert div 2;<br />

end;<br />

result := b;<br />

end;<br />

Vgl. Berndt/Kainka, Messen, Steuern und Regeln mit Word und Excel, S. 103, Listing<br />

6.7<br />

4.2 Steuerung des Analog-Multiplexer<br />

Wie schon in Abschnitt 2.4 beschrieben, reicht eine Sendeleitung für das Weiterschalten<br />

des Achtstufigen Binärzählers aus, welcher den Analog-Multiplexer steuert. Hierfür wird<br />

die TXD-Leitung genutzt, die insgesamt achtmal umgeschaltet wird, um anschließend<br />

den Rückgabewert des TLC549 zu ermitteln und mit einer Wertetabelle für den Sensor<br />

zu vergleichen. Zuletzt wird ein String mit allen Werten der Sensoren gefüllt, der in einer<br />

Datei gespeichert und in eine Mailbox des Packet Radio Netz geschickt werden kann.<br />

for SenNr := 0 to 7 do<br />

begin<br />

if mySerialThread.StatTXD = True then mySerialThread.ClearTXD<br />

else if mySerialThread.StatTXD = False then mySerialThread.SetzeTXD;<br />

Sensor[SenNr] := RoundTo(frmCalibSensor.CalibArray[SenNr,ByteWert],-2);<br />

str := str + IntToStr(SenNr)+ ’;’ + FloatToStr(Sensor[SenNr]) + ’;’;<br />

mySensorString := str;<br />

end;<br />

4.3 Umwandlung der Spannungswerte in Wetterdaten<br />

Um aus den ermittelten Spannungswerten die Wetterdaten zu gewinnen, kann man zwei<br />

verschiedene Wege gehen. Zum einen kann man den Spannungswert einfach in eine Funk-


15 4 Software<br />

tion einsetzen und den Funktionswert angeben. Eine andere Möglichkeit ist es, den Spannungswert<br />

mit einer Tabelle zu vergleichen, in der für alle 256 möglichen Spannungswerte<br />

ein entsprechender Wert eingetragen ist. Der erste Weg eignet sich besonders gut für lineare<br />

Sensoren und Systeme mit geringer Speicherkapazität und Rechenleistung. Für<br />

den zweiten Weg spricht, dass er die Kalibrierung auch nicht linearer Sensoren einfach<br />

ermöglicht, sowie gezielte Korrekturen der Messwerte vorgenommen werden können. Der<br />

Nachteil des etwas größeren Speicherbedarfs von 8 <strong>KByte</strong> spielt allerdings auf PCs, wie<br />

sie hier benutzt werden, keine Rolle. Anders sähe es bei einer Mikrocontroller gesteuerten<br />

Station aus.<br />

4.4 Dokumentation der Messparameter<br />

procedure WriteMyData(FileName: OpenString; Data : OpenString);<br />

var myFile : TextFile;<br />

begin<br />

AssignFile(myFile,FileName);<br />

try<br />

if FileExists(FileName) = True then Append(myFile) else Rewrite(myFile);<br />

writeln(myFile,Data);<br />

finally<br />

CloseFile(myFile);<br />

end;<br />

end;<br />

Zunächst wird überprüft, ob die Datei schon existiert, anschließend wird sie geöffnet<br />

oder erzeugt und die Daten werden in die Datei geschrieben. Zum Schluss wird die Datei<br />

wieder geschlossen.


16 5 Übertragung<br />

5 Übertragung<br />

Für die Übertragung ist es vorgesehen, dass eine automatische Übertragung in eine Packet<br />

Radio Mailbox stattfindet, die auch über das Internet erreichbar ist. So können die Daten<br />

z.B. auf http://www.db0res.de:8080/ angesehen werden.<br />

5.1 Packet Radio<br />

Packet Radio ist eine digitale Betriebsart des Amateurfunks. Sie dient dem Aufbau von<br />

Verbindungen zu anderen Funkamateuren und dem weltweiten Informationsaustausch.<br />

So genannte Digipeater, automatisch arbeitende Packet Radio Amateurfunkstationen an<br />

exponierten Standorten bilden das Gerüst des Packet Radio Netzes. Die Digipeater sind<br />

untereinander verlinkt. Sie tauschen untereinander ständig Routeninformationen aus, so<br />

dass sie wie das Internet die effektivste Verbindung zwischen zwei Usern herstellen. Vor<br />

Ort bieten sie den Nutzern einen lokalen User-Einstieg ins Netz.<br />

Der Nutzer kann, nachdem er einen Digipeater connectet hat, sich mit weiteren Stationen<br />

verbinden. Im Netz besteht die Möglichkeit, Nachrichten und Binärdateien in eine<br />

Mailbox zu senden oder herunter zu laden. So besteht zum Beispiel auch die Möglichkeit,<br />

sich Satellitenbilder anzusehen oder schnell Wetterdaten abzurufen.<br />

Die Übertragung findet im 23cm, 70cm und 2m Band statt. Üblich sind dabei Übertragungsraten<br />

von 1k2 bit/s und 9k6 bit/s bei Nutzereinstiegen und 19k8 bit/s bis zu<br />

mehreren Megabit/s bei Linkstrecken zwischen Digipeatern.<br />

Packet Radio wird durch Frequenzumtastung moduliert (FSK-Modulation). Moderne<br />

kommerzielle Datenfunkanwendungen wie GPRS und WLAN nutzen die gleiche, wenn<br />

auch weiterentwickeltere Modulation.


17 5 Übertragung<br />

5.2 Packet Radio Station<br />

Für die Datenübertragung benötigt man neben einem Computer und einem handelsüblichen<br />

Amateurfunk-Transceiver ein Modem. Das Modem stellt zusammen mit entsprechender<br />

Software (z.B. FlexNet) die Verbindung zum Packet Radio Netz her und<br />

bewerkstelligt den Datentransfer, indem es die Befehle und Nutzdaten in Pakete des<br />

AX.25 Protokoll einbettet. Das AX.25 Protokoll ist eine für den Amateurfunk modifizierte<br />

Variante des kommerziellen X.25 Übertragungsprotokolls. Es sorgt für eine sichere<br />

und fehlerfreie Datenübertragung Statt des Modems und der Software (FlexNet) kann<br />

auch ein TNC (Terminal Node Controller) eingesetzt werden.<br />

5.3 Terminalprogramm Paxon<br />

Dem Nutzer steht mit einem Terminalprogramm wie Paxon eine leicht zu bedienende<br />

Oberfläche für die Betriebsart Packet Radio auf modernen Windows PCs zur Verfügung.<br />

Paxon ist aber nicht - wie andere Terminalprogramm unter DOS (z.B. SP) - fähig<br />

andere Programme aufzurufen bzw. fernzusteuern. Um auf einem modernen Windows<br />

PC dennoch die ermittelten Wetterparameter zu übertragen, muss meine Software die<br />

Übertragung selbst übernehmen. Glücklicherweise bietet Paxon eine COM- Programmierschnittstelle,<br />

mit der man auf wichtige Funktionen des Programms zugreifen kann,<br />

ohne sich um die eigentlichen Funktionsweise des Verbindungsaufbaus kümmern zu müssen.<br />

Dafür wird zunächst die Component Object Model (COM) Library mit CoInitialize initialisiert<br />

und anschließend mit CreateOleObject eine Referenz auf die COM-Schnittstelle<br />

von Paxon zurückgegeben. Mit dieser ist es nun möglich, Funktionen von Paxon wie<br />

FindConnection, Connect, SendTextLine, WaitForText oder Disconnect aufzurufen.<br />

If CoInitialize(NIL) S_OK then<br />

begin<br />

CoUninitialize;<br />

exit;<br />

end;<br />

// Paxon finden<br />

if FindWindow(’tHauptfenster’, NIL) > 0 then<br />

begin<br />

myPaxon := CreateOLEObject(’Paxon.Application’) as iApplication;


18 5 Übertragung<br />

Zu erwähnen bleibt, dass die Übertragung in einem eigenen Thread ausgeführt wird, so<br />

dass die Messwerterfassung ungestört von den Vorgängen der Übertragung stattfindet.<br />

Dieses Multithreading findet mittels einer abgeleiteten Standard TThread-Klasse statt.


19 5 Übertragung<br />

5.4 Übertragung in eine Mailbox<br />

Um die Daten nun z.B. alle 30 Minuten zu übertragen, ist es nur noch notwendig eine<br />

Verbindung mit dem nächsten User-Einstieg aufzubauen, sich mit einer Mailbox zu<br />

connecten und die Mail zu senden. Anschließend kann die Verbindung beendet werden.<br />

Dies geschieht bei meiner Software durch folgenden Code:<br />

procedure TPaxonThread.Connect(Call : WideString);<br />

begin<br />

Connection := myPaxon.FindConnection(Call);<br />

PaxonStr := ’Connection gefunden’;<br />

Synchronize(UpdateLabel);<br />

If Connection = Nil Then<br />

begin<br />

Connection := myPaxon.Connect(Call);<br />

PaxonStr := ’Neu verbunden’;<br />

Synchronize(UpdateLabel);<br />

end;<br />

end;<br />

procedure TPaxonThread.SendToMailbox(Einstieg : WideString; Board :<br />

WideString; Betreff : WideString);<br />

begin<br />

Connect(Einstieg);<br />

Connection.SendTextLine(’ ’);<br />

Connection.WaitForText(’=>’);<br />

Connection.SendTextLine(’m’);<br />

Connection.WaitForText(’-->’);<br />

Connection.SendTextLine(’ ’);<br />

Connection.WaitForText(’-->’);<br />

Connection.SendTextLine(’s’ + ’ ’ + Board + ’ ’ + Betreff);<br />

Connection.WaitForText(’:’);<br />

Connection.SendTextLine(’Diese Mail wurde automatisch generiert’);<br />

Synchronize(SendSensorData);<br />

Connection.SendTextLine(myString);<br />

Connection.SendTextLine(’NNNN’);<br />

Connection.WaitForText(’-->’);<br />

Connection.SendTextLine(’ ’);<br />

Connection.WaitForText(’-->’);<br />

Connection.SendTextLine(’q’);<br />

SendMailNext := False;<br />

end;


20 6 Schlussbetrachtung<br />

6 Schlussbetrachtung<br />

Diese Arbeit bedeutete für mich eine sehr große Herausforderung. Da zahlreiche Probleme<br />

zu lösen waren:<br />

• Entwicklung von Wettersensoren<br />

• Entwicklung der Hardware zur Messwerterfassung<br />

• Entwicklung und Programmierung von Software<br />

• Programmierung der Übertragung ins Funknetz<br />

Um all diese Probleme zu lösen, ging ich zunächst auf die Suche nach geeigneter Literatur.<br />

Ich stieß auf den TLC 549 und dessen Ansteuerung mithilfe des PCs in ”Messen,<br />

Steuern und Regeln mit Word und Excel” von H.J. Berndt und B. Kainka. Im gleichen<br />

Buch fand sich die Schaltung eines Temperatursensors.<br />

Für den ersten Aufbau benutzte ich ein Steckbrett, so dass ich die Schaltungen einfach<br />

ausprobieren und erweitern konnte. Da von vornherein klar war, das nicht nur ein Sensor<br />

abgefragt werden sollte, suchte ich Möglichkeiten, die Schaltung um Sensoren zu erweitern.<br />

So kam ich zu der Idee, einen Analog-Multiplexer zu benutzen. Ich baute darauf<br />

die Schaltung für den A/D-Wandler, den Multiplexer und den achtstufigen Binärzähler<br />

auf der Steckplatine auf.<br />

Neben dem Aufbau programmierte ich die grundlegenden Funktionen der Software und<br />

zeichnete den Schaltplan. Nachdem auf dem Steckbrett weitere Sensoren funktionierten,<br />

begann ich mit dem Aufbau der Station auf einer Streifenrasterplatine. Trotz einiger<br />

zu bewältigende Programmierprobleme und Hardwareschwierigkeiten, gelang es mir,<br />

schließlich einen Prototypen fertig zu stellen. Da dieser recht gut lief, kontrollierte ich<br />

die Schaltung auf Fehler und ließ eine Platine dieser Schaltung ätzen.<br />

Das hier vorgestellte Projekt bietet aus meiner Sicht vielfältige Anbindungsmöglichkeiten<br />

an den projektorientierten Physik- und Technikunterricht in der Schule. Dies ist eine gute<br />

Möglichkeit, den Unterricht in diesen Fächern interessant, anspruchsvoll und innovativ


21 6 Schlussbetrachtung<br />

zu gestalten, um so das Interesse und die Begeisterung von Schülerinnen und Schülern<br />

an der Technik zu wecken und zu fördern.<br />

Der Leser kann sich von der Funktionsfähigkeit der Station überzeugen, indem er unter<br />

http://www.db0res.de:8080/ den Befehl l wetter -100 in der Befehlsbox unter der Beschriftung<br />

”Commands” eingibt. Dort findet man unter meinem Rufzeichen, DO2YRB,<br />

mit dem Betreff ”Wx LH” die Wetterdaten aus Lüdinghausen. Anschließend einfach auf<br />

das Rufzeichen klicken und die Mail wird angezeigt.


22 7 Ausblick<br />

7 Ausblick<br />

Eigenartig und dunkel erscheint schon seit der Antike das Verhalten von Fledermäusen:<br />

So beschreibt der römische Dichter Ovid (43 v. Chr. bis 17 n. Chr.) das Ende der drei<br />

Töchter des Königs von Böotien, Minyas: Zur Strafe wurden sie in Fledermäuse verwandelt,<br />

weil sie es vorgezogen hatten, am Webstuhl zu arbeiten und sich Geschichten zu<br />

erzählen, statt an den Festlichkeiten zu Ehren des Weingottes Bacchus teilzunehmen.<br />

Tectaque, non silvas celebrant lucemque perosae<br />

Nocte volant seroque tenent a vespere nomen.<br />

(Häuser, nicht Wälder bewohnen sie, hassen das Licht<br />

fliegen in der Nacht und vom späten Abend haben sie ihren Namen.)<br />

(Ovid, Metamorphosen IV 414f.)<br />

Ein wenig Licht in das Verhalten dieser immer schon in unserem Kulturkreis suspekten<br />

und mit dunklem Odem behafteten Tiere, die sich in der Nähe von Häusern aufhalten<br />

und ihren lateinischen Namen durch ihre Nachtaktivität erhalten haben, war und ist das<br />

Ziel dieser Arbeit.<br />

Dafür ist die Wetterstation zunächst einmal auf ihre Zuverlässigkeit bei Wind und Wetter<br />

zu prüfen. Hat sie sich bewährt, dann soll sie in unmittelbarer Nahe zum Fledermausstollen<br />

dauerhaft installiert werden. Dazu müssen Kabel vom Standort des nun<br />

anzuschaffenden PC zu den Sensoren verlegt werden. Darüber hinaus ist der Erwerb von<br />

Funkgeräten notwendig. Hier empfehle ich das Projekt einer weiteren Förderung durch<br />

den VDE Rhein Ruhr e.V.<br />

Denkbar für die Zukunft ist die Erweiterung der Wetterstation für IR-Lichtschranken und<br />

eines Sensors für die Messung der Windgeschwindigkeit. Bei der Planung des Systems<br />

wurde diese Erweiterungsmöglichkeit berücksichtigt. Eine prinzipielle Weiterentwicklung<br />

wäre der Einsatz von Microcontrollern.<br />

Hat sich die Station in der Praxis als zuverlässig erwiesen, wird sie bestimmt auch für<br />

einen breiteren Nutzerkreis interessant sein.


23 Literatur<br />

Literatur<br />

[1] A. Wendt, “Computergestützte Wetterstation”, Praxisheft 3 für Amateurfunk und<br />

Elektronik in Schule und Freizeit, Heft 3 , Seite 4-19, o.J..<br />

[2] A. Schweizer, “ASYNOP-meterologischer Schlüssel für das WxNET”, Praxisheft 9<br />

für Amateurfunk und Elektronik in Schule und Freizeit, Heft 9 , Seite 4-9, 1999.<br />

[3] A. Schweizer, “Die AATiS-Wetterstation: Hardware”, Praxisheft 9 für Amateurfunk<br />

und Elektronik in Schule und Freizeit, Heft 9 , Seite 10-14, 1999.<br />

[4] A. Schweizer, “Die AATis-Wetterstation: Software”, Praxisheft 9 für Amateurfunk<br />

und Elektronik in Schule und Freizeit, Heft 9 , Seite 15-17, 1999.<br />

[5] A. Schweizer, “Schritte ins WxNET”, Praxisheft 9 für Amateurfunk und Elektronik<br />

in Schule und Freizeit, Heft 9 , Seite 18-23, 1999.<br />

[6] H.J. Berndt/B. Kainka, Messen, Steuern und Regeln mit Word und Excel, Poing,<br />

Francis-Verlag, 2001 3 .<br />

[7] K. Block/H.-J. Hölzel/L. Wölfing/P. Zachert, Kontaktlose Signalverarbeitung, Köln-<br />

Porz, Verlag H. Stam GmbH, 1979 3 .<br />

[8] W.-D. Schmidt, Sensorschaltungstechnik, Würzburg, Vogel Verlag, 2002 2 .<br />

[9] DISCRETE SEMICONDUCTORS, KTY81-2 series. Silicon temperature sensors,<br />

DATA SHEET, 16 Seiten, 1996<br />

[10] STMicroelectronics, NE555 SA555 SE555. GENERAL PURPOSE SINGLE BIPO-<br />

LAR TIMERS, DATA SHEET, 10 Seiten, 1998<br />

[11] National Semiconductor, LM2907/LM2917 Frequency to Voltage Converter, DATA<br />

SHEET, 18 Seiten, 1995<br />

[12] Texas Instruments, CD4051B, CD4052B, CD4053B, DATA SHEET, 20 Seiten, 2003<br />

[13] Fairchild Semiconductor, CD4027BC Dual J-K Master/Slave Flip-Flop with Set and<br />

Reset, DATA SHEET,6 Seiten, 2002<br />

[14] Philips Components, Moisture control with Philips’humidity sensor, DATA SHEET,<br />

7 Seiten, 1997<br />

[15] Motorola, MPX4115A MPXA4115A SERIES, SEMICONDUCTOR TECHNICAL<br />

DATA, 9 Seiten, 2001


24 Literatur<br />

[16] Texas Instruments, TLC548C, TLC548I, TLC549C, TLC549I 8-BIT ANALOG-<br />

TO-DIGITAL CONVERTERS WITH SERIAL CONTROL DATA SHEET, 12 Seiten,<br />

1996<br />

[17] Texas Instruments, µA741, µA741Y GENERAL-PURPOSE OPERATIONAL AM-<br />

PLIFIERS, DATA SHEET, 11 Seiten, 2000<br />

[18] Michael Puff, Thread Programmierung unter Windows mit Delphi, Version 2.4,<br />

http://www.luckie-online.de, 2005


A Schaltpläne<br />

25 A Schaltpläne


26 A Schaltpläne<br />

Abbildung A.1: Schaltplan für Wettermessstation


27 A Schaltpläne<br />

Abbildung A.2: Schaltplan für Temperatursensoren, Lichtsensoren und Drucksensor


B Fotos<br />

28 B Fotos


29 B Fotos<br />

Abbildung B.1: Messschaltung auf Streifenrasterplatine, Schrägansicht<br />

Abbildung B.2: Messschaltung auf Streifenrasterplatine, Draufsicht


30 B Fotos<br />

Abbildung B.3: Sensoren auf Streifenrasterplatine<br />

Abbildung B.4: Geätzte Platine, Schrägansicht


31 B Fotos<br />

Abbildung B.5: Geätzte Platine, Draufsicht<br />

Abbildung B.6: Geätzte Sensorplatine für Luftfeuchigkeit


C Stückliste<br />

32 C Stückliste


33 C Stückliste<br />

Tabelle C.1: Stückliste für Messstation (Preise: Reichelt Elektronik, 07.06.06)<br />

Artikel Beschreibung Preis Anzahl<br />

(inkl. MWSt.)<br />

MOS 4051 CD4051BE Multiplexer 0.23 1<br />

MOS 4027 Dual-JK Master-Slave Flip-Flop 0.23 1<br />

TLC 549 CP A/D-Converter, DIP-8 1.95 1<br />

µA 7805 Spannungsregler 1A positiv, TO-220 0.17 1<br />

µA 7905 Spannungsregler 1A negativ, TO-220 0.17 1<br />

LED 5MM LED, 5mm 0.05 4<br />

1N 4001 DIODE 0.02 3<br />

BC 107A TRANSISTOR 0.23 2<br />

Schalter Kippschalter 1.15 2<br />

D-SUB BU 09 D-SUB-Buchse, 9-polig, Lötkelch 0.10 1<br />

BB 4 Bananenbuchse 4mm, vollisoliert 0.25 4<br />

µA 741 DIP Op-Amp, DIP-8 0.14 4<br />

64W-1,0K Präzisionspoti. 25 Gänge, stehend, 1,0 K-Ohm 0.64 2<br />

1,0K Metalloxidschicht-Widerstand 1,0 K-Ohm 0.09 22<br />

4,7K Metalloxidschicht-Widerstand 4,7 K-Ohm 0.09 1<br />

NE 555 DIP Timer, DIP-8 0.12 1<br />

LM 2907 DIL Converter, DIL-14 (LM 2907-8) 1.20 1<br />

1,0M Metalloxidschicht-Widerstand 1 M-Ohm 0.09 1<br />

560K Metalloxidschicht-Widerstand 560 K-Ohm 0.09 1<br />

47K Metalloxidschicht-Widerstand 47 K-Ohm 0.09 1<br />

KERKO 22N KERAMIK-KONDENSATOR 0.07 1<br />

KERKO 470P KERAMIK-KONDENSATOR 0.04 1<br />

100K Metalloxidschicht-Widerstand 100 K-Ohm 0.09 1<br />

10K Metalloxidschicht-Widerstand 10 K-Ohm 0.09 6<br />

2,2K Metalloxidschicht-Widerstand 2,2 K-Ohm 0.09 2<br />

64W-10K Präzisionspoti. 25 Gänge, stehend, 10 K-Ohm 0.64 7<br />

KERKO 100N KERAMIK-KONDENSATOR 0.07 15<br />

H25SR160 Streifenrasterplatine, Hartpapier, 160x100mm 1.30 2<br />

Warenwert: 21.42<br />

MPX 4115A Motorola-Drucksensor 24.30 1<br />

KTY 81-210 Temperatursensor, -55...+150 ◦ C 0.59 2<br />

LDR 03 Fotowiderstand 1.60 2<br />

FEUCHTES. Sensor für Feuchtigkeit 11.60 1<br />

Warenwert: Sensoren 40.28<br />

Warenwert: gesamt 61.70


34 D Quellcode<br />

D Quellcode<br />

program Wetherstation;<br />

uses<br />

Forms,<br />

Main in ’Main.pas’ {frmMain},<br />

Thread in ’Thread.pas’,<br />

Speichern in ’Speichern.pas’,<br />

Paxon in ’Paxon.pas’,<br />

CalibSensor in ’CalibSensor.pas’ {frmCalibSensor};<br />

{$R *.res}<br />

begin<br />

Application.Initialize;<br />

Application.CreateForm(TfrmMain, frmMain);<br />

Application.CreateForm(TfrmCalibSensor, frmCalibSensor);<br />

MySerialThread := TSerialThread.Create(True);<br />

MyPaxonThread := TPaxonThread.Create(@mySendMailNext, @mySensorString,frmMain.lblPaxon,True);<br />

Application.Run;<br />

end.<br />

unit Main;<br />

interface<br />

uses<br />

Windows, Messages, Variants, Classes, Graphics, Controls, Forms,<br />

Dialogs, StdCtrls, SysUtils, Thread, ExtCtrls, Speichern, Math, Paxon,<br />

CalibSensor,Paxon_TLB,ActiveX,ComObj;<br />

type<br />

TfrmMain = class(TForm)<br />

btnOpen: TButton;<br />

lblStatus: TLabel;<br />

btnCloseCom: TButton;<br />

Label1: TLabel;<br />

Label2: TLabel;<br />

Label3: TLabel;<br />

Label4: TLabel;<br />

Label5: TLabel;<br />

Label6: TLabel;<br />

Label7: TLabel;<br />

Label8: TLabel;<br />

Label9: TLabel;<br />

lblSensor1: TLabel;<br />

lblSensor2: TLabel;<br />

lblSensor3: TLabel;<br />

lblSensor4: TLabel;<br />

lblSensor5: TLabel;<br />

lblSensor6: TLabel;<br />

lblSensor7: TLabel;<br />

lblSensor8: TLabel;


35 D Quellcode<br />

tmrSensorabfrage: TTimer;<br />

chbSensoren: TCheckBox;<br />

chbSaveSensor: TCheckBox;<br />

lblUhr: TLabel;<br />

btnStartThread: TButton;<br />

lblPaxon: TLabel;<br />

btnStopThread: TButton;<br />

btnCalibSensor: TButton;<br />

chbSendMail: TCheckBox;<br />

tmrMail: TTimer;<br />

Label10: TLabel;<br />

txtSensorTime: TEdit;<br />

Label11: TLabel;<br />

Label12: TLabel;<br />

txtSendTime: TEdit;<br />

Label13: TLabel;<br />

txtEinstieg: TEdit;<br />

Label14: TLabel;<br />

lbl: TLabel;<br />

Label15: TLabel;<br />

txtBoard: TEdit;<br />

txtBetreff: TEdit;<br />

Label16: TLabel;<br />

btnSendEinstellungen: TButton;<br />

procedure btnOpenClick(Sender: TObject);<br />

procedure btnCloseComClick(Sender: TObject);<br />

procedure tmrSensorabfrageTimer(Sender: TObject);<br />

procedure btnStartThreadClick(Sender: TObject);<br />

procedure btnStopThreadClick(Sender: TObject);<br />

procedure btnCalibSensorClick(Sender: TObject);<br />

procedure tmrMailTimer(Sender: TObject);<br />

procedure txtSensorTimeChange(Sender: TObject);<br />

procedure txtSendTimeChange(Sender: TObject);<br />

procedure btnSendEinstellungenClick(Sender: TObject);<br />

private<br />

public<br />

end;<br />

var<br />

frmMain: TfrmMain;<br />

var mySerialThread: TSerialThread;<br />

var mySaveSensor: TSaveSensor;<br />

var myPaxonThread: TPaxonThread;<br />

myTimeString : String;<br />

mySensorString : WideString;<br />

mySendMailNext : Boolean;<br />

implementation<br />

{$R *.dfm}<br />

procedure TfrmMain.btnOpenClick(Sender: TObject);<br />

begin<br />

if mySerialThread.OpenCOM(1)= False then<br />

lblStatus.Caption := ’Fehler beim Öffnen’<br />

else<br />

lblStatus.Caption := ’Erfolgreich geöffnet’;<br />

end;<br />

procedure TfrmMain.btnCloseComClick(Sender: TObject);<br />

begin<br />

if mySerialThread.CloseCOM = true then lblStatus.Caption := ’COM geschlossen’;<br />

end;<br />

procedure TfrmMain.tmrSensorabfrageTimer(Sender: TObject);


36 D Quellcode<br />

var ByteWert, SenNr, i, ByteSumme : Integer;<br />

Sensor: array[0..7] of Extended;<br />

str, myTimeStr, appendstr: string;<br />

myTime : TDateTime;<br />

const Zahler = 1000;<br />

begin<br />

if chbSensoren.Checked = True then<br />

begin<br />

myTime := Date + Time;<br />

myTimeStr := DateToStr(Date) + ’;’ + TimeToStr(Time);<br />

str := myTimeStr + ’;’;<br />

mySensorString := ’PC Uhrzeit: ’ + myTimeStr + #13;<br />

for SenNr := 0 to 7 do<br />

begin<br />

if mySerialThread.StatTXD = True then mySerialThread.ClearTXD<br />

else if mySerialThread.StatTXD = False then mySerialThread.SetzeTXD;<br />

ByteWert:=0;<br />

ByteSumme:=0;<br />

for i := 0 to Zahler do<br />

begin<br />

ByteWert := mySerialThread.ByteRead;<br />

ByteSumme := ByteSumme + ByteWert;<br />

end;<br />

ByteWert := Round(ByteSumme / Zahler);<br />

Sensor[SenNr] := RoundTo(frmCalibSensor.CalibArray[SenNr,ByteWert],-2);<br />

appendstr := IntToStr(SenNr)+ ’;’ + FloatToStr(Sensor[SenNr]) +<br />

frmCalibSensor.EinheitArray[SenNr] + ’;’;<br />

str := str + appendstr;<br />

mySensorString := mySensorString + ’SensorNr ’ + IntToStr(SenNr) + ’: ’ +<br />

FloatToStr(Sensor[SenNr]) + frmCalibSensor.EinheitArray[SenNr]<br />

+ #13;<br />

end;<br />

str := str + #13;<br />

if chbSaveSensor.Checked = True then WriteMyData(’SensorData.txt’,str);<br />

lblSensor1.Caption := FloattoStr(Sensor[0]);<br />

lblSensor2.Caption := FloattoStr(Sensor[1]);<br />

lblSensor3.Caption := Floattostr(Sensor[2]);<br />

lblSensor4.Caption := FloattoStr(Sensor[3]);<br />

lblSensor5.Caption := FloattoStr(Sensor[4]);<br />

lblSensor6.Caption := Floattostr(Sensor[5]);<br />

lblSensor7.Caption := FloattoStr(Sensor[6]);<br />

lblSensor8.Caption := Floattostr(Sensor[7]);<br />

lblUhr.Caption := DateTimeToStr(myTime);<br />

end;<br />

mySaveSensor.Free;<br />

end;<br />

procedure TfrmMain.btnStartThreadClick(Sender: TObject);<br />

begin<br />

tmrMail.Interval := StrToInt(txtSendTime.Text) * 60000;<br />

myPaxonThread.Resume;<br />

end;<br />

procedure TfrmMain.btnStopThreadClick(Sender: TObject);<br />

begin<br />

myPaxonThread.Terminate;<br />

end;<br />

procedure TfrmMain.btnCalibSensorClick(Sender: TObject);<br />

begin<br />

frmCalibSensor.lblSensorNr.Caption := inttostr(frmCalibSensor.SensorNr);<br />

frmCalibSensor.Show;<br />

end;<br />

procedure TfrmMain.tmrMailTimer(Sender: TObject);


37 D Quellcode<br />

begin<br />

if chbSendMail.Checked = True Then myPaxonThread.SendMailNext := True<br />

else myPaxonThread.SendMailNext := False;<br />

end;<br />

procedure TfrmMain.txtSensorTimeChange(Sender: TObject);<br />

begin<br />

tmrSensorabfrage.Interval := StrToInt(txtSensorTime.Text) * 1000;<br />

end;<br />

procedure TfrmMain.txtSendTimeChange(Sender: TObject);<br />

begin<br />

tmrMail.Interval := StrToInt(txtSendTime.Text) * 60000;<br />

end;<br />

procedure TfrmMain.btnSendEinstellungenClick(Sender: TObject);<br />

var save : boolean;<br />

begin<br />

save := myPaxonThread.SendMailNext;<br />

myPaxonThread.SendMailNext := False;<br />

myPaxonThread.myEinstieg := txtEinstieg.Text;<br />

myPaxonThread.myBoard := txtBoard.Text;<br />

myPaxonThread.myBetreff := txtBetreff.Text;<br />

myPaxonThread.SendMailNext := save;<br />

end;<br />

end.<br />

unit Thread;<br />

interface<br />

uses<br />

Classes, Windows, SysUtils;<br />

type<br />

TSerialThread = class(TThread)<br />

private<br />

PortTimeout : _COMMTIMEOUTS;<br />

PortHandle : Integer;<br />

PortDCB : TDCB;<br />

PortNr : Integer;<br />

PortState : Cardinal;<br />

WriteOverlapped,ReadOverlapped,StatusOs: TOverlapped; { Private-Deklarationen }<br />

protected<br />

fComEvent: cardinal;<br />

fStatCTS: boolean;<br />

fStatDCD: boolean;<br />

fStatDSR : Boolean;<br />

fStatRing : Boolean;<br />

procedure Execute; override;<br />

public<br />

StatDTR : boolean;<br />

StatRTS : boolean;<br />

StatTXD : boolean;<br />

constructor Create(CreateSuspended: Boolean);<br />

property ComEvent: cardinal read fComEvent;<br />

property StatCTS: boolean read fStatCTS;<br />

property StatDCD: boolean read fStatDCD;<br />

property StatDSR: boolean read fStatDSR;<br />

property StatRing: boolean read fStatRing;<br />

function ClearDTR : boolean; stdcall;<br />

function ClearRTS : boolean; stdcall;<br />

function ClearTXD : boolean; stdcall;<br />

function SetzeDTR : boolean; stdcall;


38 D Quellcode<br />

function SetzeRTS : boolean; stdcall;<br />

function SetzeTXD : boolean; stdcall;<br />

function ComAvailable(ComNr: byte): boolean; stdcall;<br />

function CTS : boolean; stdcall;<br />

function DCD : boolean; stdcall;<br />

function DSR : boolean; stdcall;<br />

function RING : boolean; stdcall;<br />

function ByteRead : Integer; stdcall;<br />

function OpenCOM(Port: byte): boolean; stdcall;<br />

function CloseCOM : boolean; stdcall;<br />

procedure InitOverlapped(var Overlapped : TOverlapped);<br />

procedure ReleaseEvent(Event : Cardinal);<br />

function SetBaudRate(baud: cardinal): boolean; stdcall;<br />

end;<br />

implementation<br />

constructor TSerialThread.Create(CreateSuspended: Boolean);<br />

begin<br />

FreeOnTerminate:= True;<br />

inherited Create(CreateSuspended);<br />

Priority := tpNormal;<br />

end;<br />

procedure TSerialThread.ReleaseEvent(Event : Cardinal);<br />

begin<br />

fStatCTS := CTS;<br />

fStatDSR := DSR;<br />

fStatDCD := DCD;<br />

fStatRING := RING;<br />

end;<br />

procedure TSerialThread.Execute;<br />

var<br />

SerialEvent, WaitResult, BytesRead: Cardinal;<br />

begin<br />

SetCommMask(PortHandle,EV_CTS or EV_DSR or<br />

EV_RING or EV_RLSD);<br />

if not WaitCommEvent(PortHandle,SerialEvent,@StatusOs) then<br />

begin<br />

if (GetLastError = ERROR_IO_PENDING) then<br />

begin<br />

WaitResult := WaitForSingleObject(StatusOs.hEvent,INFINITE);<br />

case WaitResult of<br />

WAIT_OBJECT_0:<br />

begin<br />

if GetOverlappedResult(PortHandle,StatusOs,BytesRead,false) then<br />

ReleaseEvent(SerialEvent);<br />

end;<br />

end;<br />

end;<br />

end else ReleaseEvent(SerialEvent);<br />

end;<br />

procedure TSerialThread.InitOverlapped(var Overlapped : TOverlapped);<br />

begin<br />

Overlapped.Offset := 0;<br />

Overlapped.OffsetHigh := 0;<br />

Overlapped.Internal := 0;<br />

Overlapped.InternalHigh := 0;<br />

Overlapped.hEvent := CreateEvent(nil,True,False,’’);<br />

end;


39 D Quellcode<br />

function TSerialThread.OpenCOM(Port: byte): boolean; stdcall;<br />

begin<br />

PortHandle :=<br />

CreateFile(PChar(’\\.\COM’+IntToStr(Port)),GENERIC_READ or GENERIC_WRITE,0,<br />

nil,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,LongInt(0));<br />

if PortHandle > 0 then<br />

begin<br />

Result := true;<br />

InitOverlapped(WriteOverlapped);<br />

InitOverlapped(ReadOverlapped);<br />

InitOverlapped(StatusOs);<br />

end else Result := false;<br />

end;<br />

function TSerialThread.CloseCOM : boolean; stdcall;<br />

begin<br />

PurgeComm(PortHandle, PURGE_RXABORT or PURGE_RXCLEAR or PURGE_TXABORT or PURGE_TXCLEAR);<br />

SetCommMask(PortHandle,0); //unterbricht WaitCommEvent im Polling thread<br />

result:= CloseHandle(PortHandle);<br />

PortHandle := 0;<br />

end;<br />

function TSerialThread.ComAvailable(ComNr: byte): boolean; stdcall;<br />

var<br />

TestHandle : integer;<br />

begin<br />

TestHandle :=<br />

CreateFile(PChar(’\\.\COM’+IntToStr(ComNr)),GENERIC_READ or GENERIC_WRITE,0,<br />

nil,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,LongInt(0));<br />

if (TestHandle


40 D Quellcode<br />

begin<br />

if (PortHandle 0) then Result := EscapeCommFunction(PortHandle,CLRDTR);<br />

StatDTR := False;<br />

end;<br />

function TSerialThread.ClearRTS : boolean; stdcall;<br />

begin<br />

if (PortHandle 0) then Result := EscapeCommFunction(PortHandle,CLRRTS);<br />

StatRTS := False;<br />

end;<br />

function TSerialThread.ClearTXD : boolean; stdcall;<br />

begin<br />

if (PortHandle 0) then Result := EscapeCommFunction(PortHandle,CLRBREAK);<br />

StatTXD := False;<br />

end;<br />

function TSerialThread.DSR : boolean; stdcall;<br />

begin<br />

GetCommModemStatus(PortHandle,PortState);<br />

if ((Portstate and MS_DSR_ON) 0) then Result := true<br />

else Result := false;<br />

end;<br />

function TSerialThread.CTS : boolean; stdcall;<br />

begin<br />

GetCommModemStatus(PortHandle,PortState);<br />

if ((Portstate and MS_CTS_ON) 0) then Result := true<br />

else Result := false;<br />

end;<br />

function TSerialThread.DCD : boolean; stdcall;<br />

begin<br />

GetCommModemStatus(PortHandle,PortState);<br />

if ((Portstate and MS_RLSD_ON) 0) then Result := true<br />

else Result := false;<br />

end;<br />

function TSerialThread.RING : boolean; stdcall;<br />

begin<br />

GetCommModemStatus(PortHandle,PortState);<br />

if ((Portstate and MS_RING_ON) 0) then Result := true<br />

else Result := false;<br />

end;<br />

function TSerialThread.ByteRead : Integer; stdcall;<br />

var BitWert, b, i : Integer;<br />

begin<br />

BitWert := 128;<br />

b := 0;<br />

//Chipselect ein und ausschalten<br />

SetzeRTS;<br />

ClearRTS;<br />

//Am Dataout liegt jetzt das 1. Bit<br />

for i := 0 to 7 do // 8 mal weiterschalten<br />

begin<br />

if CTS = True then<br />

b := b + BitWert;<br />

//I/O-Clock weiterschalten<br />

SetzeDTR;<br />

ClearDTR;<br />

//nächstes Bit nur noch halbwertig<br />

BitWert := BitWert div 2;<br />

end;<br />

result := b;<br />

end;<br />

end.


41 D Quellcode<br />

unit Speichern;<br />

interface<br />

uses<br />

Classes, Windows, SysUtils;<br />

procedure WriteMyData(FileName: OpenString; Data : OpenString);<br />

type<br />

TSaveSensor = class(TFileStream)<br />

private<br />

protected<br />

public<br />

end;<br />

const<br />

fmCreate = $FFFF;<br />

fmOpenRead = $0000;<br />

fmOpenWrite = $0001;<br />

fmOpenReadWrite = $0002;<br />

fmShareCompat = $0000 platform;<br />

fmShareExclusive = $0010;<br />

fmShareDenyWrite = $0020;<br />

fmShareDenyRead = $0030 platform;<br />

fmShareDenyNone = $0040;<br />

implementation<br />

procedure WriteMyData(FileName: OpenString; Data : OpenString);<br />

var myFile : TextFile;<br />

begin<br />

AssignFile(myFile,FileName);<br />

try<br />

if FileExists(FileName) = True then Append(myFile) else Rewrite(myFile);<br />

writeln(myFile,Data);<br />

finally<br />

CloseFile(myFile);<br />

end;<br />

end;<br />

end.<br />

unit Paxon;<br />

interface<br />

uses Windows, Paxon_TLB, ComObj, ActiveX, Dialogs, Classes, StdCtrls;<br />

type PBoolean = ^Boolean;<br />

type<br />

TPaxonThread = class(TThread)<br />

private<br />

lblCaption : TLabel;<br />

myStringPointer :PWideString;<br />

myString : WideString;<br />

SendMailNextPointer : PBoolean;<br />

procedure Connect(Call : WideString);<br />

procedure SendSensorData();<br />

protected<br />

PaxonStr : string;<br />

procedure Execute; override;<br />

procedure UpdateLabel;


42 D Quellcode<br />

public<br />

Connection : iConnection;<br />

myPaxon : iApplication;<br />

SendMailNext : Boolean;<br />

myEinstieg: WideString;<br />

myBoard: WideString;<br />

myBetreff: WideString;<br />

procedure SendToMailbox(Einstieg : WideString;<br />

Board : WideString; Betreff : WideString);<br />

constructor Create(SendMailPointer : PBoolean; StringPointer:PWideString ;<br />

myLabel : TLabel; CreateSuspended : Boolean);<br />

end;<br />

implementation<br />

constructor TPaxonThread.Create(SendMailPointer : PBoolean; StringPointer :PWideString;<br />

myLabel : TLabel; CreateSuspended : Boolean);<br />

begin<br />

FreeOnTerminate := False;<br />

lblCaption := myLabel;<br />

myStringPointer := StringPointer;<br />

SendMailNextPointer := SendMailPointer;<br />

myEinstieg:= ’DB0EA’;<br />

myBoard:= ’Wetter @ DB0RES.#NRW.DEU.EU’;<br />

myBetreff:= ’Wx LH’;<br />

inherited Create(CreateSuspended);<br />

end;<br />

procedure TPaxonThread.Execute();<br />

begin<br />

Connection := nil;<br />

myPaxon := Nil;<br />

SendMailNext := True ;<br />

try<br />

If CoInitialize(NIL) S_OK then<br />

begin<br />

CoUninitialize;<br />

PaxonStr :=’Fehler’;<br />

Synchronize(UpdateLabel);<br />

exit;<br />

end;<br />

// Paxon finden<br />

if FindWindow(’tHauptfenster’, NIL) > 0 then<br />

begin<br />

myPaxon := CreateOLEObject(’Paxon.Application’) as iApplication;<br />

PaxonStr := ’Paxon-Objekt erzeugt’;<br />

Synchronize(UpdateLabel);<br />

Connect(myEinstieg);<br />

while (not Terminated) do<br />

begin<br />

if SendMailNext = True then SendToMailbox(myEinstieg,myBoard,myBetreff);<br />

Synchronize(UpdateLabel);<br />

end;<br />

end<br />

else PaxonStr := ’Application nicht erzeugt’; Synchronize(UpdateLabel);<br />

finally<br />

Connection.Disconnect;<br />

CoUninitialize;<br />

PaxonStr := ’Verbindung beendet’;<br />

Synchronize(UpdateLabel);<br />

end;<br />

end;<br />

procedure TPaxonThread.UpdateLabel;


43 D Quellcode<br />

begin<br />

lblCaption.Caption := PaxonStr;<br />

end;<br />

procedure TPaxonThread.SendSensorData();<br />

begin<br />

myString := myStringPointer^;<br />

end;<br />

procedure TPaxonThread.Connect(Call : WideString);<br />

begin<br />

Connection := myPaxon.FindConnection(Call);<br />

PaxonStr := ’Connection gefunden’;<br />

Synchronize(UpdateLabel);<br />

If Connection = Nil Then<br />

begin<br />

Connection := myPaxon.Connect(Call);<br />

PaxonStr := ’Neu verbunden’;<br />

Synchronize(UpdateLabel);<br />

end;<br />

end;<br />

procedure TPaxonThread.SendToMailbox(Einstieg : WideString; Board :<br />

WideString; Betreff : WideString);<br />

begin<br />

Connect(Einstieg);<br />

Connection.SendTextLine(’ ’);<br />

Connection.WaitForText(’=>’);<br />

Connection.SendTextLine(’m’);<br />

Connection.WaitForText(’-->’);<br />

Connection.SendTextLine(’ ’);<br />

Connection.WaitForText(’-->’);<br />

Connection.SendTextLine(’s’ + ’ ’ + Board + ’ ’ + Betreff);<br />

Connection.WaitForText(’:’);<br />

Connection.SendTextLine(’Diese Mail wurde automatisch generiert’);<br />

Synchronize(SendSensorData);<br />

Connection.SendTextLine(myString);<br />

Connection.SendTextLine(’NNNN’);<br />

Connection.WaitForText(’-->’);<br />

Connection.SendTextLine(’ ’);<br />

Connection.WaitForText(’-->’);<br />

Connection.SendTextLine(’q’);<br />

SendMailNext := False;<br />

end;<br />

end.<br />

unit CalibSensor;<br />

interface<br />

uses<br />

SysUtils, Windows, Messages, Classes, Graphics, Controls,<br />

StdCtrls, ExtCtrls, Forms, Dialogs;<br />

type TCalibArray = Array[0..7,0..255] of Single;<br />

type TEinheitArray = Array[0..7] of ShortString;<br />

type<br />

TfrmCalibSensor = class(TForm)<br />

btnOk: TButton;<br />

btnCancel: TButton;<br />

Label1: TLabel;<br />

lblSensorNr: TLabel;<br />

Label2: TLabel;<br />

Label3: TLabel;


44 D Quellcode<br />

Label4: TLabel;<br />

txt0: TEdit;<br />

txt127: TEdit;<br />

txt255: TEdit;<br />

txtEinheit: TEdit;<br />

lblEinheit: TLabel;<br />

btnSpeichern: TButton;<br />

btnLaden: TButton;<br />

txtSensorNr: TEdit;<br />

lstArray: TListBox;<br />

rdbLinear: TRadioButton;<br />

rdbEinzelauswahl: TRadioButton;<br />

btnUebernehmen: TButton;<br />

procedure btnOkClick(Sender: TObject);<br />

procedure btnSpeichernClick(Sender: TObject);<br />

procedure btnLadenClick(Sender: TObject);<br />

procedure ArrayFuellen();<br />

procedure btnCancelClick(Sender: TObject);<br />

procedure ListBoxFuellen();<br />

procedure txtSensorNrChange(Sender: TObject);<br />

procedure btnUebernehmenClick(Sender: TObject);<br />

procedure Aktualisieren();<br />

procedure lstArrayClick(Sender: TObject);<br />

public SensorNr: Byte;<br />

public CalibArray: TCalibArray;//Array[0..7,0..255] of Single;<br />

public EinheitArray: TEinheitArray;<br />

end;<br />

const DAT_PFAD = ’CalibSensor.dat’;<br />

const Einheit_PFAD = ’Einheit.dat’;<br />

var<br />

frmCalibSensor: TfrmCalibSensor;<br />

implementation<br />

{$R *.DFM}<br />

procedure TfrmCalibSensor.btnOkClick(Sender: TObject);<br />

begin<br />

Aktualisieren;<br />

frmCalibSensor.Hide;<br />

end;<br />

procedure TfrmCalibSensor.btnSpeichernClick(Sender: TObject);<br />

var f: file of TCalibArray;<br />

f1 : file of TEinheitArray;<br />

begin<br />

ArrayFuellen;<br />

AssignFile(f, DAT_PFAD);<br />

ReWrite(f);<br />

Write(f, CalibArray);<br />

CloseFile(f);<br />

AssignFile(f1, Einheit_PFAD);<br />

ReWrite(f1);<br />

Write(f1, EinheitArray);<br />

CloseFile(f1);<br />

end;<br />

procedure TfrmCalibSensor.btnLadenClick(Sender: TObject);<br />

var f: file of TCalibArray;<br />

f1 : file of TEinheitArray;<br />

begin<br />

// Array laden<br />

AssignFile(f, DAT_PFAD);<br />

Reset(f);


45 D Quellcode<br />

Read(f, CalibArray);<br />

CloseFile(f);<br />

AssignFile(f1, Einheit_PFAD);<br />

Reset(f1);<br />

Read(f1, EinheitArray);<br />

CloseFile(f1);<br />

SensorNr := StrToInt(txtSensorNr.Text);<br />

txt0.Text := FloattoStr(CalibArray[SensorNr,0]);<br />

txt127.Text := FloattoStr(CalibArray[SensorNr,127]);<br />

txt255.Text := FloattoStr(CalibArray[SensorNr,255]);<br />

txtEinheit.Text:=EinheitArray[SensorNr];<br />

ListBoxFuellen;<br />

end;<br />

procedure TfrmCalibSensor.ArrayFuellen();<br />

var klWert, miWert, hoWert, Differenz, Schritt : Single;<br />

var n : Byte;<br />

begin<br />

klWert := StrToFloat(txt0.Text);<br />

miWert := StrToFloat(txt127.Text);<br />

hoWert := StrToFloat(txt255.Text);<br />

CalibArray[SensorNr,0] := klWert;<br />

CalibArray[SensorNr,127] := miWert;<br />

CalibArray[SensorNr,255] := hoWert;<br />

EinheitArray[SensorNr] := txtEinheit.Text;<br />

if rdbLinear.Checked = True then<br />

begin<br />

Differenz := hoWert - klWert;<br />

Schritt := Differenz / 255;<br />

for n := 0 to 255 do<br />

begin<br />

CalibArray[SensorNr,n] := klWert + Schritt*n<br />

end;<br />

end;<br />

end;<br />

procedure TfrmCalibSensor.btnCancelClick(Sender: TObject);<br />

begin<br />

Hide;<br />

end;<br />

procedure TfrmCalibSensor.ListBoxFuellen();<br />

var n : Byte;<br />

begin<br />

lstArray.Items.BeginUpdate;<br />

lstArray.Items.Clear;<br />

For n := 0 to 255 do<br />

begin<br />

lstArray.Items.Add(Floattostr(CalibArray[SensorNr,n]));<br />

end;<br />

lstArray.Items.EndUpdate;<br />

end;<br />

procedure TfrmCalibSensor.txtSensorNrChange(Sender: TObject);<br />

begin<br />

SensorNr := StrToInt(txtSensorNr.Text);<br />

lblSensorNr.Caption := txtSensorNr.Text;<br />

end;<br />

procedure TfrmCalibSensor.btnUebernehmenClick(Sender: TObject);<br />

begin<br />

Aktualisieren();<br />

end;<br />

procedure TfrmCalibSensor.Aktualisieren();


46 D Quellcode<br />

begin<br />

SensorNr := StrToInt(txtSensorNr.Text);<br />

ArrayFuellen;<br />

txt0.Text := FloattoStr(CalibArray[SensorNr,0]);<br />

txt127.Text := FloattoStr(CalibArray[SensorNr,127]);<br />

txt255.Text := FloattoStr(CalibArray[SensorNr,255]);<br />

txtEinheit.Text:=EinheitArray[SensorNr];<br />

ListBoxFuellen;<br />

end;<br />

procedure TfrmCalibSensor.lstArrayClick(Sender: TObject);<br />

var AktIndex : integer;<br />

begin<br />

if rdbEinzelauswahl.Checked = true then<br />

begin<br />

AktIndex := lstArray.ItemIndex;<br />

CalibArray[SensorNr,AktIndex] := StrtoFloat(InputBox(’Bitte geben Sie einen Wert ein’,<br />

Inttostr(AktIndex) + ’ entspricht:’,<br />

lstArray.Items.Strings [AktIndex]));<br />

Aktualisieren;<br />

end;<br />

end;<br />

end.

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!