Hallo Forengemeinde,
ich stümper gerade eine Zweipunktregelung als Hygrostat zusammen. Dafür
benutze ich folgenden Feuchtesensor, der Spannungswerte ausgibt, die ich
mit dem ADC eines Mega48 einlese:
http://www.produktinfo.conrad.com/datenblaetter/1100000-1199999/001170518-da-01-en-FEUCHTIGKEITS_SENSOR_HMZ_333A1.pdf
Zusätzlich hängt noch ein DS18S20 Temperatursensor und ein LCD-Display
mit dran.
Auf S.3 in dem Pdf ist eine Tabelle mit den Spannungswerten und den bei
den entsprechenden Temperaturen erhaltenen relativen Luftfeuchtigkeiten.
Aber wie wertet man so eine Tabelle ordentlich aus? Da ich eher Anfänger
bin würde ich jetzt ganz furchtbare "if" Konstruktionen bauen (oder eine
switch-case):
if Temperatur >= 10°C && <15°C
if Spannung >= 0.76 && <0.73
print "20%RH"
...
Das ist natürlich zum einen mit einem bösen Fehler behaftet und zum
anderen ist das so ungenau, dass ich gleich auf das Messen verzichten
kann.
Bitte helft mir mit einem für einen Anfänger geeigneten Rat wie ich das
ordentlicher machen.
Danke!
Paul
Paul schrieb:> Bitte helft mir mit einem für einen Anfänger geeigneten Rat wie ich das> ordentlicher machen.
Auf S.2 gibts doch eine Kurve, welche Luftfeuchte zu welcher Spannung
führt, bei einer gegebenen Temperatur. Die Punkte wie sie in der Tabelle
sind, sind eingezeichnet (wenn auch nur schwach sichtbar) und dann durch
gerade Linien verbunden.
Liegt nun die Spannung zwischen zwei Punkten, liegt die Luftfeuchte auch
im selben Maße zwischen 20 und 30 bzw. 30 und 40 usw. Du musst also
interpolieren.
Da die Kurve von der Temperatur abhängt, nimmst du für eine gegebene
Temperatur die Spannungswerte aus der entsprechenden Spalte.
Liegt die Spannung z.B. zwischen 0.76 und 1.06 V, dann weißt du, dass RH
zwischen 20 und 30% liegt...
0.76 a + b = 20
1.06 a + b = 30
-> 0.3 a = 10 => a = 33.3333...
-> b = -5.3333....
nun kannst du den gemessenen Spannungswert U in U*33.33333 - 5.3333
einsetzen und erhältst einen Wert zwischen 20 und 30.
Wenn ich das in Code umwandeln würde, würde ich die Zahlen a und b für
jedes Intervall $RH0...$RH0+10 bei $Temperatur vorher berechnen und in
eine Tabelle legen, die ins Flash packen, und die dann nur noch abrufen
und daraus RH berechnen. Spart Rechenzeit aufm AVR.
Kommst du damit schon weiter?
Danke, das war richtig hilfreich!
Interpolieren war das wonach ich gesucht habe.
Ich erstelle gerade eine Tabelle mit den interpolierten Werten in Excel.
Diese Werte würde ich dann versuchen in einer Tabelle in C zu speichern
und darauf zuzugreifen. Mal sehen wie weit ich heute komme und wann es
wieder klemmt.
Paul schrieb:> Ich erstelle gerade eine Tabelle mit den interpolierten Werten in Excel.> Diese Werte würde ich dann versuchen in einer Tabelle in C zu speichern> und darauf zuzugreifen.
Vielleicht hast du es nur etwas unglücklich ausgedrückt, aber du
solltest eigentlich die Stützpunkte bzw. Intervalle speichern und dann
auf dem Mikrocontroller interpolieren, nicht die interpolierten Werte
selbst irgendwo ablegen.
R. Rebentrost schrieb:> Paul schrieb:>> Ich erstelle gerade eine Tabelle mit den interpolierten Werten in Excel.>> Diese Werte würde ich dann versuchen in einer Tabelle in C zu speichern>> und darauf zuzugreifen.>> Vielleicht hast du es nur etwas unglücklich ausgedrückt, aber du> solltest eigentlich die Stützpunkte bzw. Intervalle speichern und dann> auf dem Mikrocontroller interpolieren, nicht die interpolierten Werte> selbst irgendwo ablegen.
R. Rebentrost schrieb:> Paul schrieb:>> Ich erstelle gerade eine Tabelle mit den interpolierten Werten in Excel.>> Diese Werte würde ich dann versuchen in einer Tabelle in C zu speichern>> und darauf zuzugreifen.>> Vielleicht hast du es nur etwas unglücklich ausgedrückt, aber du> solltest eigentlich die Stützpunkte bzw. Intervalle speichern und dann> auf dem Mikrocontroller interpolieren, nicht die interpolierten Werte> selbst irgendwo ablegen.
(Oben versagt.)
Ich glaube auch dass er die Werte meint, mit denen er interpoliert.
Die interpolierten Werte sind ja die, die auf dem Messwert vom ADC
beruhen, und den kennt Excel auf dem Hostsystem natürlich nicht :-)
Wobei da natürlich auch nichts gegen spricht, in Excel mal zu testen, ob
die Formel, die man dann in C gießt, so stimmt.
Hmpf...
Zum Glück habe ich nochmal einen Blick ins Forum geworfen bevor ich seit
3 Stunden an der Tabelle sitze :-O
Ich habe jetzt alle a's und b's bzw. alle Geradengleichungen bestimmt.
Das sind nun für jede Temperatur 7 Geradengleichungen. Macht bei 7
Temperaturen 49 Geradengleichungen und entsprechend genau so viele a's
und b's.
Allerdings bekomme ich gerade wieder einen kleinen Hirnknoten wenn ich
das versuche nun in Code umzusetzen, zumal ich auch gern die
Zwischentemperaturen mit auswerten möchte. Dafür habe ich also auch
wieder die Möglichkeit des Interpolierens genutzt.
Ein Bsp: Temp ist 10°C, ADC_Val ist zwischen 0.76 und 1.06
Da kommt erst mal das von foo raus: m=33.3333, n=-5.3333
Die Gleichung für die Feuchte ist dann RH=33.3333*ADC_Val-5.3333
ob der ADC_Val zwischen 0.76 und 1.06 liegt würde ich mit "if" prüfen.
Aber was wenn ich nun RH bei 11°C wissen möchte? Dort gilt doch nicht
mehr die selbe Geradengleichung?!
Tut mir leid das es bei mir so hängt, aber bis zu den komplexen
Denkvorgängen eines geübten Programmierers brauch ich einfach noch ein
gutes Stück mehr Übung.
Paul schrieb:> Hmpf...> Aber was wenn ich nun RH bei 11°C wissen möchte? Dort gilt doch nicht> mehr die selbe Geradengleichung?!
Naja. Es gibt nicht nur die Regression bei einer abhängigen sondern auch
die für mehrere. Nennt sich multivariate Regression. Leider kann Excel
die, glaube ich, nicht. Ich habe eben mal geschaut, aber eine "einfache"
Darstellung davon finde ich auf die Schnelle nicht. Vielleicht suchst Du
selbst einmal. Falls Du dazu Fragen hast, kannst Du hier ja nochmal
posten.
Ich denke das naheliegendste, was man noch aus dem Schulbetrieb kennen
könnte, wäre das Lösen eines linearen Gleichungssystems mittels Gauss -
allg. lineare Algebra. Das lässt sich dann auch auf nicht-lineare
Gleichungen erweitern. Aber etwas Hirnschmalz muss man dann doch schon
reinlegen.
Paul schrieb:> Aber was wenn ich nun RH bei 11°C wissen möchte? Dort gilt doch nicht> mehr die selbe Geradengleichung?!
Theoretisch liegst du da richtig.
Aber guck doch mal, wie wenig die Spannungen für eine gegebene RH
zwischen den Temperaturen abweichen. Und dann guck mal unter die Tabelle
wie genau der Sensor ist: +- 5%. Drunter steht auch für einen bestimmten
Wertebereich um wie viel die Spannung dabei abweichen kann, in dem Fall
+- 0.15V.
Die maximal +- 0.02V die von der "falschen" Geradengleichung kommen
machen da wohl auch keinen großen Unterschied mehr...
Mir wär es jedenfalls zu kompliziert auch in die andere Richtung zu
interpolieren (also zwischen den Referenzspannungswerten für die zwei
Temperaturen, zwischen denen deine richtige Temperatur liegt), der
Gewinn dürfte minimal sein. Ich würde einfach bis 12,5 Grad die erste
Spalte nehmen, bis 17,5 Grad die zweite usw.
Paul schrieb:> Allerdings bekomme ich gerade wieder einen kleinen Hirnknoten wenn ich> das versuche nun in Code umzusetzen, zumal ich auch gern die> Zwischentemperaturen mit auswerten möchte.
Dann machst du meiner Meinung nach den Fehler, zu viel auf einmal zu
wollen.
> Dafür habe ich also auch> wieder die Möglichkeit des Interpolierens genutzt.>> Ein Bsp: Temp ist 10°C, ADC_Val ist zwischen 0.76 und 1.06> Da kommt erst mal das von foo raus: m=33.3333, n=-5.3333> Die Gleichung für die Feuchte ist dann RH=33.3333*ADC_Val-5.3333>> ob der ADC_Val zwischen 0.76 und 1.06 liegt würde ich mit "if" prüfen.
Ja. Aber die Grenzen legst du sinnigerweise ebenfalls in die Tabelle
rein. D.h. du wirst da nicht eine lange Latte von if's haben, sondern
eine Schleife, in der du nacheinander alle Tabellenzeilen durchgehst und
nachsiehst, ob der aktuelle Wert vom ADC in den Grenzen genau dieser
Tabellenzeile liegt. Wenn ja, dann hast du die richtige Zeile gefunden.
Wenn nein, dann eben (in der Schleife) die nächste Zeile.
Du möchtest ALLE Zahlenwerte in der Tabelle haben! Organisier dir
deine Tabelle als Tabellenzeile mit einem bestimmten Aufbau und denk
weniger darüber nach, dass du da eine 2 dimensionalen Matrix mit
Zahlenwerten an den Schnittpunkten hast.
Was, genau, benötigst du in jeder einzelnen Zeile an Werten, so dass
dort alles an Information gesammelt ist. Genau hier ist normalerweise
der Punkt erreicht, an dem die Stunde einer Struktur ('struct' in C)
schlägt.
> Aber was wenn ich nun RH bei 11°C wissen möchte? Dort gilt doch nicht> mehr die selbe Geradengleichung?!
Wie schon angesprochen: Man kann sich natürlich aus den Koeffizienten
bei 10° und bei 15° auch die entsprechenden Koeffizienten bei 11° durch
Interpolation der Koeffizienten ermitteln. Aber du solltest dir wirklich
ansehen, inwiefern das das Ergebnis tatsächlich verbessert.
Auf der anderen Seite: Wenn du das Programm sauber aufbaust und in
Einzelteile zerlegst, dann ist auch die Interpolation von Koeffizienten
kein Problem (Hinweis: man muss die Interpolationskoeffizienten nicht
vorausberechnen. Die Abfrage eines Feuchtesensors ist sehr
wahrscheinlich jetzt nicht so zeitkritisch, dass es dich gross juckt,
wenn der µC 2 Millisekunden mehr braucht).
> Tut mir leid das es bei mir so hängt, aber bis zu den komplexen> Denkvorgängen eines geübten Programmierers brauch ich einfach noch ein> gutes Stück mehr Übung.
Der Schlüssel besteht darin, komplexe Dinge in einen Haufen einfachere
Dinge zu zerlegen und sich dann jeden einfacheren Teil für sich alleine
vorzunehmen. Kein geübter Programmierer löst komplexe Probleme in einem
Zug, sondern immer schrittweise. Der Trick besteht darin, sich selbst
aus Funktionen einen "Baukasten" zu machen, der einzelne Teile kapselt.
Und ein weiterer Trick besteht darin, genau die Aufgabenstellung erst
mal selbst mit Papier und Bleistift zu lösen. Dabei kommt es darauf an,
sich selbst auf die Finger zu sehen und zu registrieren, was man da
eigentlich macht. Wie alle können intuitiv viel mehr, als uns bewusst
ist und wir alle lösen viele Problemstellungen mit Hilfe dieser
Intuition. Was einem Programmierer bewusst ist, das ist, das er erst mal
rauskriegen muss, wie er eigentlich dieses Problem löst und welche
Schritte er (mglw. aufgrund welcher Vorbedingungen) dazu macht. Wenn das
erst mal klar ist, dann kann man sich auch hinsetzen und ein Programm
dafür schreiben. Aber gleichzeitig rauskriegen was man tut UND
gleichzeitig das Programm dazu schreiben, das geht oft schief und man
verläuft sich sinnlos in Details, die einem nicht zum Ziel führen. Erst
mal muss die (mehr oder weniger) grobe Richtung stehen. Und genau dazu
ist es hilfreich, einfach mal mit angenommenen Werten selbst auf Papier
die Rechnung durchzuexerzieren.
Paul schrieb:> Aber was wenn ich nun RH bei 11°C wissen möchte?
bilinear Interpolation
1
Temp
2
10 15 20 25 30 35 40
3
0.5 +----+----+----+----+----+----+
4
| | | | | | |
5
| | | | | | |
6
1.0 +----+----+----+----+----+----+
7
| | | | | | |
8
| | | | | | |
9
1.5 +----+----+----+----+----+----+
10
ADC-val | | | | | | |
11
| | | | | | |
12
2.0 +----+----+----+----+----+----+
13
| | | | | | |
14
| | | | | | |
15
2.5 +----+----+----+----+----+----+
16
| | | | | | |
17
| | | | | | |
18
3.0 +----+----+----+----+----+----+ <- die Werte an + sind die RH
Du siehst die ---- Geradenstücken von + zu + ?
Deine relativer Feuchtewert liegt in einem der Quadrate.
An den Ecken der Quadrate sind die RH-Werte für Temp&ADC-Val
i der Tabelle gespeichert.
Um den RH-Wert an Punkt o auszurechnen, bestimmst du erst die
RH-Werte an den Punkten x und y in den querlaufenden Geraden,
die von Höhe A nach Höhe B laufen und von Höhe C nach Höhe D.
Dann hast du die Anfangs- und Endpunkte der hochlaufenden
Gerade von x nach y auf der o liegt.
1
A---------x----B
2
| | |
3
| o |
4
| | |
5
| | |
6
| | |
7
| | |
8
C---------y----D
Du siehst also, du musst die Tabelle umrechnen auf ein anderes
Gitternetz.
Du speicherst nicht die 4 Geradenwerte, sondern bloss die RH
Werte an den Eckpunkten. Die Geradengleichung rechnest du aus.