Gleich gehts los...

Erklärungen zum 1-Wire Emulator bis 2014

Einige Erklärungen zum grundsätzlichen Ablauf:

Reset-Impuls erkennen

Eine 1-Wire-Sequenz beginnt immer mit einem Reset-Impuls. Dies ist der längste Low-Pegel im ganzen Protokoll. Im "Ruhezustand" (OWM_SLEEP) wird bei jeder fallenden Flanke ein Interrupt ausgelöst. Gleichzeitig wird ein Timer gestartet der nach der angegebenen minimalen Länge des Reset-Impulses eine Leitungsanfrage auslöst. Ist die Leitung dann immer noch auf Low, so wird der Pegel-Interrupt auf die Detektion einer steigenden Flanke umgestellt und sozusagen auf das Ende des Reset-Impulses gewartet.

Was passiert, wenn das 1-Wire Device im Ruhezustand ist, weil der 1-Wire Master mit einem anderem Gerät kommuniziert?
Jede fallende Flanke löst einen Interrupt aus. Der Timer wird immer wieder zurückgesetzt, oder am Ende der Kommunikation wird ein High-Pegel detektiert.

UML des Kommunikationsbeginns 
UML für den Kommunikationsbeginn (pdf)

Presence-Impuls

Nach dem Reset-Impuls mus jedes angeschlossene Gerät den 1-Wire Bus eine bestimmte Zeit auch Low ziehen. So erkennt der Master, ob überhaupt Geräte angeschlossen sind. Dieser Vorgang ist komplett über den Timer-Interrupt gesteuert. Der Interrupt für den 1-Wire Eingang ist dabei deaktiviert.

1-Wire Sequenz und Ablauf im Programm
Zeitlicher Ablauf und Zustände im Mikrocontroller (pdf)

Empfangen von Bits und Bytes

Die Übertragung eines Bits im 1-Wire-Bus geht immer mit einer fallenden Flanke einher, die vom Master vorgegeben wird. Damit wird der Bus synchronisiert. Diese Flanke löst den Interrupt aus und stellt den Timer entsprechen ein für die Überprüfung ob das entsprechende Bit eine 1 (High-Pegel) oder eine 0 (Low-Pegel) ist. Der Interupt für das Bus-Pin wird dann deaktiviert und auf den Timer-Interupt gewartet. Die Timer-ISR list dann das Bit aus Speichert es und aktiviert wieder den Pin-Change-Interrupt. Das gleiche wiederholt sich für alle 8 Bits. Danach wird in der Timer-ISR der Befehl geprüft und die Zustandsvariable entsprechen gesetzt.

1-Wire Timing

Fünf Zeiten müssen für das Protokoll eingestellt werden:

Name Beschreibung Vorgegebene Zeit Wert bei 8 MHz/64 Erklärungen
OWT_MIN_RESET Minimale Dauer des Reset-Impulses 480 µs normal Wert Annahme 440 µm 55  
OWT_RESET
_PRESENCE
Minimale Dauer des Reset-Impulses Master samples den Presence-Impuls nach
70 µs
4 (32µs) Basierent auf Messwerte
OWT_PRESENCE Pause zwischen Reset Presence-Impuls 410 µs bis Master fallende sendet 20 (80µs) Bei Problemen erhöhen
OWT_READLINE Zeit zwischen fallander Flanke vom Master und dem Auslesen 15 µs 3-4 (24-32 µs) Für lange Leitungen sind längere Zeiten sinnvoll
OWT_LOWTIME Dauer des Slave Low-Pegels 60 µs 3-4 (24-32 µs) Schnelle Master (z.B. DS9490) funktionieren nur mit 24 µs korrekt, da der AVR für die Berechnungen für das nächste Bit Zeit braucht (DS2423 read, Countercopy, CRC16...)

 

Zu Problemen kam es bei der DS2423-Emulation bei zu langer LOW-TIME. Offensichtlich ist der AVR dann noch nicht fertig mit der Berechnung, die erst nach dem Ende des Low-Signals erfolgt. Mit 24 µs funktionierte es aber bisher ganz gut. Es besteht aber noch die Möglichkeit, Berechnungen oder das Kopieren der Zählervariablen in die PIN_INT Funktion zu verschieben.  Weiterhin gibt es auch die Möglichkeit die LOW-TIME zu splitten, so dass die Berechnungen wärend des Low-Signals ausgeführt werden. Wer Probleme hat, soll sich bitte melden, dann pflege ich die Änderungen ein.

 

Einleitung

Nach dem nun schon hunderte solcher Platinen im Einsatz sind gibt es dieses Jahr wieder eine neue Version. Zur vorhergehenden Version gibt es zwei Unterschiede:

  • Zusätzlicher Glättungskondensator vor dem A/D-Eingang
  • Ein Loch zur Schraubbefestigung

Dafür ist die Platine jetzt mit 23x15mm etwas größer. Sie ist weiterhin mit konventionellen oder SMD Bauteilen bestückbar, zumindest was die passiven Bauteile betrifft.

Mit SMD-Bauteilen bestückt sieht das ganze dan so aus:

1-Wire Feuchtesensor Version 4 (2015) mit SMD-Bauteilen 1-Wire Feuchtesensor Version 4 (2015) mit SMD-Bauteilen

Schaltung

Die Schaltungen sollen auch nicht fehlen:

Schaltung aktiv mit 5V Anschluss
Schaltung aktiv mit 5V Anschluss

Schaltung parasitär
Schaltung parasitär (ohne zusätlichen 5V Anschluss)

Die parasitäre Variante Funktioniert nicht besonders gut bei vielen Sensoren, weil der gesamte Strom über den Bus fließen muss, der oft nur mit einem Pullup-Widerstand an die Versorgungsspannung angeschlossen ist. Besonders der HIH5030/31 macht da Probleme, weil bei 5V etwas mehr Strom verbraucht.

Mit einem HIH5030/31 lässt sich der Sensor aber auch mit 3,3V betreiben, z.B. an einem GPIO am Raspberry PI. Der HIH4030/31 benötigt mindestens 4V um zu funktionieren.

 

 

 

Verbesserung für die CUNO (CUL) von Busware

Für die Haussteuerung mit dem 868 MHz Band (FS20, FHT, WS300, HomeMatic ...) sind die Sende/Empfangs Geräte von Busware sehr interessant. Ich habe eine CUNO im Betrieb und sie leistet mir treue Dienste. Leider war der Empfang besonders von S300TH und KS300 nicht besonders gut. Da brachte auch der Test mit verschiedenen Frequenzen uns Bandbreiten nicht viel. Also musste eine bessere Antenne her! Zunächst versuchte ich es mit einer Groundplane-Antenne:

Groundplane

Leider brachte es nicht den gewünschten Erfolg. Der Empfang war noch schlechter als mit der mitgelieferten Stab-Antenne. Ich bin kein Antennenfachmann und habe keinen sinnvollen Grund dafür gefunden.

Eine wirkliche Verbesserung brachte eine kleine Modifikation der Stab-Antenne zu einer L-Antenne mit einem Draht zur Seite:

CUNO Antenne

Jetzt stimmt zwar glaube ich die Impedanz nicht mehr mit der ursprünglichen überein, aber der Empfang war und ist deutlich besser.



Empfangsverbesserung WS300PC

Vor einigen Jahren habe ich mir mal so einen WS300PC Bausatz von ELV zugelegt, um die Wetterstation KS300 und einige andere passende Sensoren auszulesen. Leider war der Empfang trotz Wände ohne Metall (Altbaus) sehr schlecht. Eine erhebliche Verbesserung brachte das Anbringen des Empfangsmoduls außerhalb des Gehäuses wie folgendes Bild zeigt:

WS300pc Antenne

Nun funktioniert es in unserem neuem Haus sogar bis ins Nachbargebäude (3 Wände + 12m Luftlinie). Meine Vermutung ist, dass das mit Metall beschichtete Kunststoffgehäuse ein großteil der Radiowellen abhält

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

Einführung

Übersicht Haustechnik

Zunächst erst einmal ein kleiner Überblick über die Haustechnik in unserem Haus. Sie besteht im großen und ganzen aus 1-Wire Sensoren und Aktoren sowie aus Sensoren und Aktoren die über das 868MHz Funknetz angesprochen werden. Alle Sensorabfragen und Verknüpfungen mit Aktoren werden in einer Datenbank (MySQL/Postgresql) abgespeichert und sind über ein PHP-Webinterface auslesbar/steuerbar. Auf dem Home-Server übernimmt ein Programm in C/C++ die Abfrage der Sensoren und die Ansteuerung der Aktoren.

Haustechnikuebersicht

Im Obergeschoss/Dachgeschoss übernimmt ein "1-Wire Relaisstation" die Kommunikation mit den 1-Wire Sensoren. Diese ist über das LAN-Netzwerk mit dem Home-Server verbunden. Bisher hat ein MiniITX Board mit dem AMD Prozessor EM-350 die Aufgabe des Home-Servers, zusätzlich ist auch der Touchscreen-Monitor zur Verwaltung, Wettervorhersage, E-Mail  und 1000 andere Sachen angeschlossen. Dieser Rechner bötigt etwa 20 W für den Betrieb.

Einsaz von ARM-Boards

Den Homeserver würde ich gerne ganz oder Teilweise durch ein ARM-Board ersetzen. Damit müsste sich der Stromverbrauch erheblich reduzieren lassen. Ich habe immer mal nach ARM-Boards ausschau gehalten, aber die waren meist sehr teuer. Mit dem Raspberry Pi kam ein recht günstiges Board auf dem Markt. Ein Grund sich die ganze Sache mal näher anzuschauen.

Was mit dem Raspberry Pi seinen Anfang nahm, setzt sich durch weitere, nicht ganz so billige, aber leistungsfähigere Boards fort. Zunächst wollte ich nur über den Raspberry schreiben aber mitlerweile sind zwei weitere Boards unterwegs zu mir. In diesen Blog werde ich allso nach und nach über alle schreiben. Also über

Unterkategorien

Neu Schutzlack

Für einen Aufpreis von 3 € können alle Module mit Schutzlack versiegelt werden. (abgesehen von den Sensoröffnungen 😉)

Option Schutzlack

Neue Artikel im Shop

Zum Seitenanfang