1-Wire Feuchte-Sensor

Erste Überlegungen

2010 habe ich für unser Haus eine günstige günstige Möglichkeit gesucht, Temperatur und Luftfeuchte in jedem Raum zu messen und mit dem Computer zu erfassen.

S300THDie günstigste Variante war damals der Funksensor S300TH mit der WS300PC. Dieser kostete bei dem ELV-Elektronikversand etwa 15 € und baugleich bei Conrad-Elektronik sogar (als S555TH) sogar nur 5 €!!!!  Leider gibts bei Conrad den Sensor nicht mehr (Stand 06.06.2012). Die Batterien der Sensoren halten nun schon über 2 Jahre. Das ist Ok.

Nachteile:

An den Funksensoren können nur 8 verschiedene Codes eingestellt werden. Ich brauche mehr Sensoren. Mit unter gibt es Empfangsprobleme, aber nachdem ich das Funkmodul der WS300PC außerhalb des Gehäuses angebracht habe geht es ganz gut.

Vorteile:

Sehr günstig, Batterien halten sehr lang (habe sie z.T. schon über 2 Jahre und noch kein Batteriewechsel war notwendig).


1-Wire Bus

Was genau der 1-Wire Bus ist liest man für den Einstieg am besten bei Wikipedia nach.

Ich habe schon vorher ein bisschen mit dem 1-Wire Bus rumgespielt. Einen Feuchtesensor fand ich beim Googeln für um die 70 €, das ist viel zu teuer!!!

Aber ich fande auch eine sehr interessante Abhandlung über eine Lösung mit dem 1-Wire Chip DS2438 und den HIHXXXX Sensoren von Honywell (z.B. Link).  Der DS2438 ist eigentlich als Batteriemonitor gedacht aber hat alle wichtigen Komponenten: Einen A/D-Wandler und einen Temperatursensor. Die Feuchte Sensoren von Honywell sind sehr linear, d.h. die Spannung am Ausgang ist proportional zur Feuchtigkeit. Als zusätzliche Beschaltung benötigt man nur einen Widerstand.

Bei Conrad sind die Sensoren "sehr teuer" aber ich fand sie günstiger bei meinem inzwischen liebsten Elektronik-Versand Mouser Electronics mit etwa 10 € pro Stück für den HIH4030 und 7,90 € für den HIH5030 (inzwischen ist der nicht mehr ganz so günstig stand 2012). Der DS2438 kostet etwa 3 €. Als Bausatz können die Bautele mit Leiterplatte für 21 € bei mir bestellt werden. Bin noch auf der Suche nach einer Webshop Software. Wer jetzt schon Bedarf hat kann einfach per Mail bestellen.

Alternativen:

Es gibt auch den 4-fach D/A-Wandler DS2450 für den 1-Wire Bus, der hat aber Übertragungprobleme. Das hatte ich schon irgendwo mal gelesen aber auch bei eigenen Versuchen feststellen können.

Schaltung und Layout

Schaltung 1-Wire Feuchtesensor

Die Schaltung ist recht einfach. Die HIHXXXX Sensoren benötigen einen Widerstand am Ausgang. Der Ausgang selbst ist direkt auf den A/D-Eingang des DS2438 gelegt. In meinem Sensoren habe ich zusätzlich einen DS18B20 zur Temperaturmessung eingebaut. Der ist noch ein bisschen genauer als der interne Sensor des DS2438 und kostet auch nur 1 €. Außerdem habe ich einige Sensoren in einem nicht mehr zugänglichen Bereich installiert (Dachdämmung) und so gibt es wenigstens für die Messung der Temperatur eine höher Ausfallsicherheit. 5V liegen an meinem 1-Wire Bus immer mit an, so dass ich die Stromversorgung nicht aus dem Bus selbst nehmen muss.

Eigentlich wollte ich die ganze Sache auf einem SIOC-DIP Adapter aufbauen. Aufgrund der hohen Anzahl: 30 im Betrieb (stand 2012) 30 in Planung lohnte sich aber doch der Conrad-Leiterplatten-Service. Es ist erheblich weniger Aufwand, wenn nur die Komponenten zu löten sind und nicht zusätzlich noch eine Verdrahtung.

Hier ist mal ein Bild von den Leiterplatten der 2. Generation. Diese Leiterplatten können bei mir für 2,50 € käuflich erworben werden. Einen Bausatz mit allen Bauteilen biete ich für 21 € an. Bitte einfach eine E-Mail an mich schreiben.

PCB Feuchtesensor


Eine gelötet Variante habe ich leider gerade nicht zum Fotografieren aber im fertigen Einbau in der Dachdämmung sieht das ganze so aus:

1-Wire Feuchtesensor in Dachdämmung

Software und Anwendung

Hier noch ein Beispiel für eine Abfrage-Prozedur basierend auf den 1-Wire Public Domain Kit. Der Umweg über die Integer-Werte kommt daher, dass in meinem Haussystem die Abfrage der Sensoren irgendwann einmal ein Mikrocontroller übernehmen soll. Dieser liefert dann die gesammelten Daten über LAN an den Zentralrechner und Datenbank. Der Typ des Feuchtesensors (HIH5030 oder HIH4030) ist aber nur dem Zentralrechner aus der Datenbank bekannt.

Die Abfrage der Spannung kann eventuell auch wegfallen. Im Betrieb, wenn keine neuen Sensoren angebaut werden ändert sich die Spannung kaum.

//reading the DS2438 chip as Humidity and Thermo Sensor 
//
//Copyright (C) 2012  Tobias Mueller mail (at) tobynet.de
//
//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
// any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
//
//


#include <ownet.h>

#define OW_DS2438_CONV_TIME 10
#define OW_DS2438_MESS_COUNT 3


#define OWHUM_HIH4030 0
#define OWHUM_HIH5030 1

#define OW_TRY_COUNT 3


inline int16_t ow_fconvert(uchar b1, uchar b2) {
  int tsht;
  tsht=b1  |((int)b2<<8);
  if (b2 & 0x080)
	tsht |= 0xFFFFF0000;
  return tsht;
}

//Auslesen und als integer ausgeben.
bool ow_readDS2438i(int portnum, uchar *SerialNum, int16_t *VDD, int16_t *VAD, int16_t *Temp) {
	uchar send_block[12],lastcrc8;
	int send_cnt,  i,k;
	bool rt=FALSE;
//Anzahl der Versuche 	
	for(k=0;k<OW_TRY_COUNT;k++) {
//Auslesen der Spannung
		owSerialNum(portnum,SerialNum,FALSE);
		if (owAccess(portnum)) {
			send_cnt = 0;
			send_block[send_cnt++] = 0x4E;
			send_block[send_cnt++] = 0x00;
			send_block[send_cnt++] = 0x0F; 
			if (!owBlock(portnum,FALSE,send_block,send_cnt)) continue;
		} else continue;
		if (owAccess(portnum)) {
			// Senden des Befehls zu Konvertieung
			if (!owWriteByte(portnum,0xB4)) continue;
		} else continue;
		msDelay(OW_DS2438_CONV_TIME);
		//Notwendig?
		if (owAccess(portnum)) {
			if (owLevel(portnum,MODE_NORMAL) != MODE_NORMAL) continue;
		} else continue;
		//Recall memory
		if (owAccess(portnum))  {
			//Copy page 0 to scratchpad
			send_cnt = 0;
			send_block[send_cnt++] = 0xB8;
			send_block[send_cnt++] = 0x00;
			if (!owBlock(portnum,FALSE,send_block,2)) continue;
		} else continue;

		if (owAccess(portnum))  {
			// scratchpad lesen
			send_cnt = 0;
			send_block[send_cnt++] = 0xBE;
			send_block[send_cnt++] = 0x00;
			// Bytes zu Lesen sind am Array hinten drann
			for (i = 0; i < 9; i++)
				send_block[send_cnt++] = 0xFF;
			if (owBlock(portnum,FALSE,send_block,send_cnt)) {
				setcrc8(portnum,0);
				// CRC8 Berechnung
				for (i = send_cnt - 9; i < send_cnt; i++)
					lastcrc8 = docrc8(portnum,send_block[i]);
				if (lastcrc8 == 0x00) {
					*VDD=ow_fconvert(send_block[5],send_block[6]);
					if (*VDD!=0) {rt=TRUE; break;}
				}
			}
		}
	} //try
	if (!rt) return FALSE;
	rt=FALSE;
       //Einstellung zum Auslesen des AD-Wandlers
	for( k=0;k<OW_TRY_COUNT ;k++) {
		owSerialNum(portnum,SerialNum,FALSE);
		if (owAccess(portnum)) {
			send_cnt = 0;
			send_block[send_cnt++] = 0x4E;
			send_block[send_cnt++] = 0x00;
			send_block[send_cnt++] = 0x00; //0x08;
			if (!owBlock(portnum,FALSE,send_block,3)) continue;
			rt=TRUE;break;
		}
	}

	if (!rt) return FALSE;
	rt=FALSE;
	int mn;
	uint32_t VAD_sum=0;
	uint32_t Temp_sum=0;
       //Messwerte Auslesen
	for(mn=0;mn<OW_DS2438_MESS_COUNT;mn++) {
		for( k=0;k<OW_TRY_COUNT ;k++) {
			owSerialNum(portnum,SerialNum,FALSE);
			if (owAccess(portnum)) {
				send_cnt = 0;
				send_block[send_cnt++] = 0x4E;
				send_block[send_cnt++] = 0x00;
				send_block[send_cnt++] = 0x00; //0x08;
				if (!owBlock(portnum,FALSE,send_block,3)) continue;
			} else continue;
			if (owAccess(portnum)) {
				if (!owWriteByte(portnum,0x44)) continue;
			} else continue;
			msDelay(OW_DS2438_CONV_TIME);
			if (!owAccess(portnum)) continue;
			if (owLevel(portnum,MODE_NORMAL) != MODE_NORMAL) continue;
			if (!owWriteByte(portnum,0xB4)) continue;
			msDelay(OW_DS2438_CONV_TIME);
			if (owLevel(portnum,MODE_NORMAL) != MODE_NORMAL) continue;
			if (owAccess(portnum))  {
				send_cnt = 0;
				send_block[send_cnt++] = 0xB8;
				send_block[send_cnt++] = 0x00;
				if (!owBlock(portnum,FALSE,send_block,send_cnt)) continue;
			} else continue;
			if (owAccess(portnum))  {
				// Array zum Lesen von Temperatur und Feuchte vorbereiten
				// und lesen
				send_cnt = 0;
				send_block[send_cnt++] = 0xBE;
				send_block[send_cnt++] = 0x00;
				for (i = 0; i < 9; i++)
					send_block[send_cnt++] = 0xFF;
				// Array senden
				if (!owBlock(portnum,FALSE,send_block,send_cnt)) continue;
				setcrc8(portnum,0);
				// CRC berechnen und Pruefen
				for (i = send_cnt - 9; i < send_cnt; i++)
					lastcrc8 = docrc8(portnum,send_block[i]);
				if (lastcrc8 == 0x00) {
					Temp_sum+=ow_fconvert(send_block[3],send_block[4]);
								// OK

					*VAD=ow_fconvert(send_block[5],send_block[6]);
					VAD_sum+=(*VAD);
					if(*VAD!=0) {rt=TRUE;break;}
				}
				printf("Retry...  \n");
			}
		}
		if (!rt) return FALSE;

	}
	*Temp=(uint16_t)(Temp_sum/OW_DS2438_MESS_COUNT);
	*VAD=(uint16_t)(VAD_sum/OW_DS2438_MESS_COUNT);
	return rt;

}




//Alle integer werde in float Konvertieren
inline bool ow_readDS2438f(int portnum, uchar *SerialNum, float *VDD, float *VAD, float *Temp){
	int16_t _VDD,_VAD,_Temp;
	if (!ow_readDS2438i(portnum,SerialNum,&_VDD,&_VAD,&_Temp)) return FALSE;
	*VDD=ow_ConvVoltageDS2438(_VDD);
	*VAD=ow_ConvVoltageDS2438(_VAD);
	*Temp=ow_ConvTempDS2438(_Temp);
	return TRUE;


}

inline bool ow_readDS2438h(int portnum, uchar *SerialNum, int sensor, float *VDD, float *Hum, float *Temp) {
	int16_t _VDD,_VAD,_Temp;
	if (!ow_readDS2438i(portnum,SerialNum,&_VDD,&_VAD,&_Temp)) return FALSE;
	*VDD=ow_ConvVoltageDS2438(_VDD);
	*Temp=ow_ConvTempDS2438(_Temp);
	*Hum=ow_ConvHumDS2438(sensor,_VDD,_VAD,_Temp);

	return TRUE;
}

//Konvertieren der Temperatur
inline float ow_ConvTempDS2438(int16_t v) {
   return (float)v/256.0f;
}
//Konvertieren der Spannung
inline float ow_ConvVoltageDS2438(int16_t v) {
	return (float)v/100.0f;
}
//Konvertieren der Feuchtigkeit
inline float ow_ConvHumDS2438(int sensor, int16_t VDD, int16_t VAD, int16_t Temp) {
	float fVAD=ow_ConvVoltageDS2438(VAD);
	float fVDD=ow_ConvVoltageDS2438(VDD);
	float fTemp=ow_ConvTempDS2438(Temp);
	float Hum;
	if (sensor==OWHUM_HIH4030) {
		Hum=(float)(fVAD/fVDD-0.16f)/0.0062f;
		Hum=(float)(Hum)/(1.0546f-0.00216f*(fTemp));
	}
	if (sensor==OWHUM_HIH5030) {
		Hum=(float)(fVAD/fVDD-0.1515f)/0.00636f;
		Hum=(float)(Hum)/(1.0546f-0.00216f*(fTemp));
	}
	return Hum;
}

 Wenn alles funktioniert und man schon viele Sensoren verbaut hat, kann es dann so aussehen:

Sensoren im Dach

Kommentare  

-1 #2 RE: 1-Wire FeuchtesensorAndreas 2015-02-04 14:35
Hallo, ich messe an bisher 8 verschiedenen Stellen mit dieser Schaltung http://www.kompf.de/weather/pionewire.html erfolgreich Temperaturen. Nun muss ich noch einen PT1000 irgendwie an den 1 Wire dranbekommen mit einem D/A Wandler. Haben sie da noch eine Idee?
#1 Heiko Siekrt 2013-04-24 22:41
Hallo,
ich wollte mich hiermit nochmals herzlichst für die Bausätze bedanken.
Diese Funktionieren mit einem USB9097 Adapter unter OWFS auf einem kleinem Miniserver hervorragend.

Gruß
Heiko

You have no rights to post comments

Zum Seitenanfang