Hallo,
ich habe mal mit ein bisschen interessanter Hardware herumgespielt und herausgekommen ist ein Schimmelwarner.
Die Idee kam mir schon beim Testsketch zum DHT22. Aus Lufttemperatur und Luftfeuchte läßt sich der Taupunkt berechnen. Hintergrund ist, das kalte Luft weniger Feuchtigkeit aufnehmen kann. Der Taupunkt ist die Temperatur, wo sich aus den gemessenen Werten dann Sättigung ergibt. Die Formel hatte bereits ein netter Mensch bereits in Code "gegossen"
Wenn nun eine Außenwand kälter ist, als der Taupunkt, dann kondensiert dort die Luftfeuchtigkeit. Die Folge sind feuchte Wände und Schimmel! Durch Stoßlüften kann man die Luftfeuchte verringern und so aus dem gefährlichen Bereich herauskommen. Ein herkömmlicher Temperaturfühler, um die Wand zu messen ginge auch, wäre aber uncool 8)
Zufällig las ich hier im Forum von den berührungslosen IR Sensoren von Melexis. In einem Ebayshop in Amerika gibts die Dinger für ca. 11,50€, samt Link auf einen Testsketch.
Auf einem 20x4 LCD ließ sich alles nur abkürzen und nicht sinnvoll darstellen. Glücklicherweise hat Pollin 40x4 LCD Displays für 12,95€ - sogar billiger, als der freundliche Chinse liefern kann
Das Problem ist, das 40x4 Display elektrisch eigentlich zwei 40x2 Displays sind und 2 Enable Pins besitzt. Die LiquidCrystalFast Lib kann damit umgehen.
Nun noch ein bisschen die einzelnen Libs und Codeschnipsel miteinander verwursten und heraus kommt dann ein Schimmelwarner.
// Einbinden des DHT22
#include <i2cmaster.h>
#include "DHT.h" // Library für DHT Sensor aufgerufen
#define DHTPIN 7 // DHT Sensor wird aus PIN 9 ausgelesen
#define DHTTYPE DHT22 // DHT Type wird auf DHT22 festgelegt
DHT dht22(DHTPIN, DHTTYPE); // DHTPIN und DHTTYE in dht22 definiert
#include <LiquidCrystalFast.h>
LiquidCrystalFast lcd(12, 11, 10, 9, 5, 4, 3, 2);
// LCD pins: RS RW EN1 EN2 D4 D5 D6 D7
// make some custom characters:
byte ue[8] = { // 0 off, 1 set pixel
0b00000, // in 5x7 caracter 8. row is unused
0b01010,
0b00000,
0b10001,
0b10001,
0b10011,
0b01101,
0b00000
};
void setup(){
// create a new character
lcd.createChar(0, ue);
i2c_init(); //Initialise the i2c bus
PORTC = (1 << PORTC4) | (1 << PORTC5);//enable pullups
lcd.begin(40, 4);
dht22.begin(); // Auslesen des DHT22 beginnt
}
void loop()
{
float t = dht22.readTemperature(); // Die Temperatur wird vom DHT22 ausgelesen, Wert in "t" schreiben
float h = dht22.readHumidity(); // Die Luftfeuchte wird vom DHT22 ausgelesen, Wert in "h" schreiben
float a = 17.271;
float b = 237.7;
float taupunktTemp = (a * t) / (b + t) + log(h/100);
float p = (b * taupunktTemp) / (a - taupunktTemp);
int dev = 0x5A<<1;
int data_low = 0;
int data_high = 0;
int pec = 0;
i2c_start_wait(dev+I2C_WRITE);
i2c_write(0x07);
// read
i2c_rep_start(dev+I2C_READ);
data_low = i2c_readAck(); //Read 1 byte and then send ack
data_high = i2c_readAck(); //Read 1 byte and then send ack
pec = i2c_readNak();
i2c_stop();
//This converts high and low bytes together and processes temperature, MSB is a error bit and is ignored for temps
double tempFactor = 0.02; // 0.02 degrees per LSB (measurement resolution of the MLX90614)
double tempData = 0x0000; // zero out the data
int frac; // data past the decimal point
// This masks off the error bit of the high byte, then moves it left 8 bits and adds the low byte.
tempData = (double)(((data_high & 0x007F) << 8) + data_low);
tempData = (tempData * tempFactor)-0.01;
float celcius = 1.38*(tempData - 273.15);
float fahrenheit = (celcius*1.8) + 32;
lcd.setCursor(0, 0); // Anfang auf Stelle 0, Zeile 0 setzen
lcd.print("Lufttemp. :"); // Temp. : auf LCD ausgeben
lcd.setCursor(13, 0); // Anfang auf Stelle 9, Zeile 0 setzen
lcd.print(t ,1); // Wert aus "t" ausgeben (Temperatur)
lcd.setCursor(17, 0); // Anfang auf Stelle 15, Zeile 0 setzen
lcd.write(0xD0 + 15); // Grad-Zeichen (Arduino 1.00)
lcd.print("C Wandtermp.: "); // C auf LCD ausgeben
lcd.print(celcius ,1);
lcd.write(0xD0 + 15); // Grad-Zeichen (Arduino 1.00)
lcd.setCursor(39, 0);
lcd.print("C");
lcd.setCursor(0, 1); // Anfang auf Stelle 0, Zeile 1 setzen
lcd.print("Luftfeuchte:"); // Luft.: auf LCD ausgeben
lcd.setCursor(13, 1); // Anfang auf Stelle 9, Zeile 1 setzen
lcd.print(h ,1); // Wert aus "h" ausgeben (Luftfeuchtigkeit)
lcd.setCursor(18, 1); // Anfang auf Stelle 15, Zeile 1 setzen
lcd.print("% Taupunkt : "); // % auf LCD ausgeben
lcd.print(p ,1);
lcd.write(0xD0 + 15);
lcd.print("C");
lcd.setCursor(1, 3);
// if(celcius - taupunktTemp < 0) // richtige Formel
if(celcius - taupunktTemp > 0) // zum Testen
{
lcd.print("!!! Achtung L");
lcd.write(0);
lcd.print("ften, Schimmelgefahr !!!");
delay(1500);
lcd.setCursor(1, 3);
lcd.print(" ");
//delay(500);
}}
Das nächste Problem war, das kein "ü" für Lüften im Zeichensatz des Displays enthalten ist. Also suchte ich mir raus, wie man Sonderzeichen generieren kann.
Ok, es ginge vielleicht noch ein wenig übersichtlicher, indem ich mehr von set Cursor Gebrauch gemacht hätte, aber mit Leerzeichen weiterschreiben geht auch, bis zur Darstellung der nächsten Variablen ]
Da es für das Blinken der Warnung in Zeile 4 keinen extra Befehl gibt, habe ich mal auf die Schnelle zum ungeliebten Delay gegriffen. Nach dem Überschreiben mit Leerzeichen ist kein weiteres Delay notwendig, da die Schleife ohnehin eine beachtliche Laufzeit besitzt. Außerdem beruhigt das Delay eine zu hektische Anzeige bei den Messwerten
Ich habe um den Warntext sichtbar zu machen und das Blinken implementieren zu können aus dem kleiner ein größer gemacht. Für das echte Gerät dann einfach die Auskommentierung tauschen.
Werde das Ganze batteriebetrieben zu einem handlichen Messgerät aufbauen. Allerdings werde ich das Pollin Display gegen ein anderes Modell austauschen, da es ein schlecht ablesbares Stromschwein ist. Die Hintergrundbeleuchtung säuft satte 500mA und die Lesbarkeit ist trotzdem nur semigut. Ein normales grünliches Display mit schwarzer Schrift ist besser lesbar und ohne Backlight wesentlich stromsparender.
Gruß Gerald