/*************************************
* Solaranlagensteuerung *
* 18.05.2002 *
* *
/*************************************/
// 4.2.2002 Abfrage ob notentladen > als Boiler aus
// 10.02.2002 Nachts absenken, um Puffer zu leeren / getestet, ok!
// 24.02.2002 Boiler laden von Speicher ?
// 05.05.2002 Lesen mit 11 Bit Genauigkeit
// 10.05.2002 Fehler bei hochz. / Umsch. Boiler /Speicher
// 18.05.2002 Uhrzeit geändert
// 19.05.2002 Uhrzeit einstellbar

// Betriebsarten :
// Wenn Modus 1 eingegeben ist : Nachts Speicher leeren 2:00-3:00 Uhr
// Wenn Modus 2 eingegeben ist : Alle Zähler werden bei EEPROMWRITE gelöscht.
// Wenn Modus 4 eingegeben ist : Ausgänge können manipuliert werden !
// Wenn Modus 8 : Temperatur Kollektor von Analogport 3 sonst 2
// Wenn Modus16 : Morgens immer heizen
// geplant :

// ------------- Globale Variablen ----------------------
// string r ; //
string s,t,i ; // String für LCD Ausgabe (W)
// string t ; // Fehlerstring Sensoren (W)
// i für Datum auf Minidisplay

byte Merker ; // Betriebsart LCD
byte Read ; // Merker Temp. gelesen
byte Read1 ; //
byte Index ; // Index im Auswahlmenue
byte ti ; // Zähler im Auswahlmenue
byte Byte_in ; // Eingabebyte vom WSO_Board
byte Byte_Outx ; // Ausgabebyte fuer Relais_Board 1
byte Byte_Outy ; // Ausgabebyte fuer Relais_WSO_Board
byte Speicher[64] ; // Erst mal Platz für 16 Long-Werte machen
byte d[32] ; // Korrektur / Einstellungen 32 Korrekturwerte

byte Zeit_Mzu ; // Zeit Mischer Pause
byte Zeit_Mauf ; // Zeit Mischer auf
byte Zeit_MPause ; // Pausenzeit des Mischers
byte M_Temp ; //
byte Z_Sekunde ; // Zeit zum Zählen

int M_Korr ; // Korrekturwert für Mischer
int M_Zeit ; // Zeit für das zufahren nach Boilerladen

//------------------------------------------------------------
// byte Byte_Out2 ; // für Ausgabe an WSO Board

const Modus1 = 1; // Leeren Speicher 10.02.2002
const Modus2 = 2; // Löschen Zähler (W)
const Modus4 = 4; // Ausgänge manipuliren
const Modus8 = 8; // Temp Kollektor Analogport 3 sonst 2 (W)
const Modus16 = 16; // Morgens heizen
// const Modus32 = 32; // Mischer_auf

//------------------------------------------------------------
byte Status1 ; // Status der Heizungsanlage

const Boiler_laden = 1; // Boiler will geladen werden (W)
const Restentleeren = 2; // Kessel Restentleeren (W)
const Boilerpumpe_ein = 4; // Boilerpumpe an (W)
const Kessel_kalt = 8; // Kessel im Temperaturbereich (W)
const Ruecklaufanhebung = 16; // Merker Rücklauferwärmung (W)
const Kessel_heiss = 32; // Kessel läuft & heiss (W)
const Heizen_ein = 64; // Abfrage, ob geheizt werden will (W)
const Speicher_leeren =128; // Temperatur

//const Kessel_ein = 16; // Kessel ein
//const Boilerladebetrieb = 16; // Abfrage, ob Boiler geladen werden will
//------------------------------------------------------------
byte Status2 ; // Status der Solaranlage

const B_laden = 1; // Boiler will geladen werden (W)
const Sp_laden = 2; // Speicher will geladen werden (W)
const B_zu_heiss = 4; // Boiler zu heiss (W)
const Sp_zu_heiss = 8; // Speicher zu heiss (W)
const Boi_laden_2 = 16; // Boiler kann vom Speicher geladen werden(24.2)

//------------------------------------------------------------
int Zeit_bis_Speicher ; // (W)

int T_Aussen ;
int T_Kollektor ;
int T_Kessel ;
int T_Rezirkulation ;
int T_Speicher_Oben ;
int T_Speicher_Unten ;
int T_Boiler_Oben ;
int T_Boiler_Unten ;
int T_Heizungs_Vorlauf ;
int T_Heizungs_Ruecklauf;

long Zeit_Zaehler [20] ; // Zeit Zaehler -12 werden gespeichert

//float Trend ; // Trend der Vorlauftemperatur Heizung
float Temp_Sensor[10] ; // Temp. der Sensoren
float Temp_Korr ; // Änderung Kollektortemp.
float ADC1 ; // Analogwerteingabe PT 500
//float ADC2 ; // Analogwerteingabe KTY 10-6

/* - Bits als Konstanten deklarieren für PCF Ausgabeport - */

const Mischer_aus = 1; // Relaisausgang Mischer_aus
const Boiler_Speicher = 2; // Relais Boiler / Speicher (W)
const Rezirkulation = 4; // Relais Ventil zur Rezirkulation (W)
const Mischer_ein = 8; // Relaisausgang Mischer_ein
const Kollektor_Pumpe = 16; // Relais Solarpumpe (W)
const Kessel = 32; // Gummistecker
const Boilerlade_Pumpe = 64; // Relais Heisswasserladepumpe
const Heizungs_Pumpe = 128; // Relais

/* - Bits als Konstanten deklarieren für Ausgabeport WSO - */
const Spannung_Sensoren = 1; // o.k
const Relais_1 = 4; // o.k
const Relais_2 = 2; // o.k
const Spannung_PCF_Board = 16; // o.k
const LCD_Beleuchtung = 32; // o.k.

/* - Bits als Konstanten deklarieren für Eingabeport - */
// Bits 0-2 für 3 Tasten
const Taster_E0 = 1; // Bit 0
const Taster_E1 = 2; // Bit 1
const Taster_E2 = 4; // Bit 2
const Heizungsbetrieb3 = 8; // Abfrage, ob OG heizen will
const Heizungsbetrieb2 = 16; // Schalter Schornsteinfeger / EG !
const Heizungsbetrieb1 = 32; // Abfrage, og DG heizen will
const Mischer_zu = 64; // ok.
// const Mischer_auf = 128; // Bit 3 noch frei

const x[] = "dT aus ","dT in Boiler ","dT Speicher ",
"max.T Boiler ","max.Speicher ","aus Boiler ",
"ein Boiler ","Zeit *30 Sek ","Kessel aus ",
"Kessel ein ","Modus ","Or Wert .... ",
"and ","Notentladen ","Nachl.Bo v.Sp",
"Ladetemp. Bo ","Mischer Vorl.","Steig. MV ", //d[15]...
"dT Mischer ","T Mischer zu ","Regelzeit ", //
"Nachtenl.bis ","Heizen von h ","Heizen bis h "; // Texte Auswahl

const y[] = "Kol=>Spei ","Kol=>Boil ","Rezir.Zeit",
"Boil.Pumpe","Heiz.Pumpe","Kessel an ",
"Dach heizt","Mitt.heizt","Erdg.heizt",
"Fehler RZ ","Fehler 0C ","Rueckl.anh",
"Spe_heute ","Boi_heute ","B.P_heute ",
"H.P_heute ","Kes heute ","Notentl. B",
"Notentl.Sp","Ruck.heute"; // für Zeitzähler


//Texte f. Temp.anz
const z[] = "Bo"," Bu"," MV","So"," Su"," Ko","Ke"," RZ"," HR";

const T0 = 154; // Boiler oben (W) ok
const T1 = 144; // Boiler unten (W) ok
const T2 = 152; // Mischer (W) ok
const T3 = 148; // Speicher oben (W) ok
const T4 = 150; // Speicher unten(W) ok
// T5 = // KollektorPT500(W) ok
const T6 = 156; // Kessel (W) ok
const T7 = 146; // Rezirkulation (W) ok
const T8 = 158; // Heizungsrückl (W) ok
// T9 = // T_Aussen PT 500

//--------------------------------------------------
// inline function sqrt ( float value ) returns float
//--------------------------------------------------
//{ inline vmcodes.VM_MATH_FUNCTION | (vmcodes.MATH_SQRT << 8);
//}

//------------------------------------------------------------
inline function getlong ( byte src[], int pos ) returns long
//------------------------------------------------------------
{ inline vmcodes.VM_GET_LONG;
}

//------------------------------------------------------------
inline function putlong ( byte dest[], int pos, long value )
//------------------------------------------------------------
{ inline vmcodes.VM_PUT_LONG;
}

/******************************************************************/
/* Treiberbibliothek fuer externes LC-Display mit HD44780 */
/* Controller konfiguriert für 4x20 Zeichen */
/******************************************************************/

const LOW = 0;
const HIGH = -1;
const LCD_E = 10; // P1H2 Start Enable signal
const LCD_RW = 9; // P1H1 HIGH Readmode, LOW Writemode
const LCD_RS = 8; // P1H0 HIGH Datamode, LOW Kommandomode
const LCD_DATA = 3; // P1H4-P1H7 vier Datenleitungen
/******************************************************************/
/* schreibt ein Byte im 4 Bit Mode zum LCD-Kontroller */
/******************************************************************/
function put(byte a )
{ ports.setn (LCD_DATA,a>>4); // High Nibble auf P1L
ports.pulse (LCD_E); // Enable Data
ports.setn (LCD_DATA,a); // Low Nibble auf P1L
ports.pulse (LCD_E); // Enable Data
}
/*****************************************************************/
/* sendet ein Kommando zum LCD-Kontroller */
/*****************************************************************/
function LCD_WriteCommand ( byte command )
{ ports.set(LCD_RS,LOW); // Kommando Mode
put(command);
ports.set(LCD_RS,HIGH); // Data Mode
}
/*****************************************************************/
/* Initialisierung des Kontrollers für 4 Bit Mode */
/*****************************************************************/
function init ()
{ ports.set(LCD_E,LOW); // Enable Port initialisieren
ports.set(LCD_RS,LOW); // Kommando Mode
ports.set(LCD_RW,LOW); // Write Mode
ports.setn(LCD_DATA,0b0011); // Function Set 8 bit Interface
ports.pulse(LCD_E); // Enable Data
sleep (15); // mindestens 4.1 millisec. warten (P 5
ports.pulse(LCD_E); // Enable Data
sleep (5); // mindestens 0.1 millisec. warten (Sleep 1
ports.pulse(LCD_E); // Enable Data
ports.setn(LCD_DATA,0b0010); // Function Set 4 bit Interface
ports.pulse(LCD_E); // Enable Data
LCD_WriteCommand(0b00101000);// Function Set, 2 Zeilen Display, 5x7 Font
LCD_WriteCommand(0b00001100);// Display an, Cursor sichtbar, blinken aus
LCD_WriteCommand(0b00000001);// Clear Display
}
/*****************************************************************/
/* sendet einen kompletten String zum Kontroller */
/*****************************************************************/
//--------------------------------------------------------
function getchar ( byte s[], int position ) returns byte
//--------------------------------------------------------
{ return s[position];
}

function print ( string s )
{ byte a;
for a=0...str.length(s)-1
put(getchar(s,a)); // siehe Zeilen drüber !!
}

/****************************************************************/
/* positioniert den Cursor an Zeile (0..3), Spalte (0...19) */
/****************************************************************/
function goto(byte zeile,byte spalte)
{ if zeile == 0 LCD_WriteCommand(128 + spalte);
if zeile == 1 LCD_WriteCommand(192 + spalte);
if zeile == 2 LCD_WriteCommand(148 + spalte);
if zeile == 3 LCD_WriteCommand(212 + spalte);
}
function clear() /* Clear Display */
{ LCD_WriteCommand(0x01);
sleep(2); //bis 1.64 ms Dieser sleep ist neu
}
function home() /* Cursor to home position */
{ LCD_WriteCommand(2);
sleep(2); //bis 1.64 ms ! Dieser sleep ist neu
}
function cursorleft() /* Moves cursor left */
{ LCD_WriteCommand(0x10);
}
function cursorright() /* Moves cursor right */
{ LCD_WriteCommand(0X14);
}
function showcursor() /* Switch Cursor on */
{ LCD_WriteCommand(0X0F);
}
function hidecursor() /* Switch Cursor off */
{ LCD_WriteCommand(0x0C);
}
function scrollleft() /* Shift Display left */
{ LCD_WriteCommand(0x18);
}
function scrollright() /* Shift Display right */
{ LCD_WriteCommand(0x1C);
}
//###################################################################


/**********************/
function EEprom_Write()
/**********************/
{ byte i,j;
long k;

plm.beep(plm.TONE_A2); // Piepen zum Speichern
sleep 300;
plm.beep(plm.TONE_OFF);

if d[10] and Modus2 // Modusbit 1 gesetzt ?
{ for i = 0 ... 11
Zeit_Zaehler[i]=0; // Alle Zeitzähler löschen
}

// Tageszähler löschen
for i = 12 ... 19
{Zeit_Zaehler[i]=0;
}

// Daten in Daten-Speicher (EEPROM) übertragen
for i = 0 ... 11
{ putlong(Speicher,i*4,Zeit_Zaehler[i]);
}
/* ab Adresse $1f00 schreiben */
i2c.start(160) ; // Addressbits : A0-A3=GND
// weg i2c.write(0x1f); // Byte-Addr. : high-byte bei 24C65
i2c.write(0x00); // Byte-Addr. : low-byte

// Erst Korrekturwerte schreiben ab $1f00
/* i2c.write(d[0]); // dT aus: mindeste Temp. sonst aus (W)
i2c.write(d[1]); // dT Boiler minimale höhere Temp. zum Laden (W)
i2c.write(d[2]); // dT Speicher minimale höhere Temp. z Laden (W)
i2c.write(d[3]); // max. Boiler (W)
i2c.write(d[4]); // max. Speicher ???
i2c.write(d[5]); // min. Boiler nachheizen (W)
i2c.write(d[6]); // max. Boiler nachheizen (W)
i2c.write(d[7]); // dt Zeit Kollektor erwärmen (W)
i2c.write(d[8]); // Kessel ein bei (W)
i2c.write(d[9]); // Kessel aus bei (W)
i2c.write(d[10]); // Modus (W)
i2c.write(d[11]); // or (W)
i2c.write(d[12]); // and (W)
i2c.write(d[13]); // Sicherheitstemp Start Pumpe Notentladen (W)
i2c.write(d[14]); // Boiler laden von Speicher
i2c.write(d[15]); // Ladetemp. des Heizungswasserswasser (W)
i2c.write(d[16]); // Mischertemp. im Normalfall (W)
i2c.write(d[17]); // Mischertemp. Steigung (W)
d[18] dT Mischer //
d[19] T-Mischer zufahren // Beim Umschalten von Boiler auf heizen (W)
d[20] Mischer Regelgeschwindigkeit
d[21] Temperatur zum Entladen in der Nacht
*/

for i = 0 ... 15
{i2c.write(d[i]); // Korrekturwerte 0-15 schreiben
} // beim 24C04
i2c.stop(); // max. 16 Werte am Stück schreiben !!
sleep 100; // beim 24C65 max. 64 Werte


i2c.start(160) ; // Addressbits : A0-A3=GND
i2c.write(0x10); // Byte-Addr. : low-byte

for i = 16 ... 31
{i2c.write(d[i]); // 16-31 Korrekturwerte schreiben
}
i2c.stop(); // max. 16 Werte am Stück schreiben !!
sleep 100; // beim 24C65 dann max. 64 Werte

i2c.start(160) ; // Addressbits : A0-A3=GND
i2c.write(0x20); // Byte-Addr. : low-byte

for i = 0 ... 15
i2c.write(Speicher[i]); // Byte-schreiben
i2c.stop(); // max. 16 Werte am Stück schreiben !!
sleep 100;

i2c.start(160) ; // Addressbits : A0-A3=GND
i2c.write(0x30); // Byte-Addr. : low-byte
for i = 16 ... 31
i2c.write(Speicher[i]); // Byte-schreiben
i2c.stop(); // max. 16 Werte am Stück schreiben !!
sleep 100;


i2c.start(160) ; // Addressbits : A0-A3=GND
i2c.write(0x40); // Byte-Addr. : low-byte

for i = 32 ... 47
{ i2c.write(Speicher[i]); // Byte-schreiben
}
i2c.stop(); // max. 16 Werte am Stück schreiben !!
plm.beep(plm.TONE_E2); // Piepen zum Speichern
sleep 300;
plm.beep(plm.TONE_OFF);

// Temp_Sensor[4]=98; // Signalisieren das gespeichert !
}

/**********************/
function EEprom_Read()
/**********************/
{ byte i;

i2c.start(160); // Schreibzugriff
// i2c.write(0x1f); // zum Adresse übermitteln (1f = last page bei 2465)
i2c.write(0x00); // High Endurance Block bis 100.000 x schreiben
i2c.start(161); // Lesezugriff

/* Korrekturwerte/ Einstellungen lesen (16 Stück) */
for i = 0 ... 31
{d[i] = i2c.read(); //
}

/* Zeit_Zaehler lesen */
for i = 0 ... 47 // zur Zeit 32+16 Bytes Lesen / hier 48 Bytes
{ Speicher[i] = i2c.read(); //
}
Speicher[63] = i2c.readlast(); // und letztes Byte lesen
i2c.stop();

// Tageszähler löschen
for i = 12 ... 19
{Zeit_Zaehler[i]=0;
}


for i = 0 ... <12 // 12 Longveriable aus Speicher[] holen
{ Zeit_Zaehler[i] = getlong(Speicher,i*4);
}
if d[10] == 255 // Defaultwerte laden
{ d[0] = 0; // dT aus W
d[1] = 1; // dT Boiler W
d[2] = 2; // dT Speicher W
d[3] = 60; // max. Boiler W
d[4] = 90; // max. Speicher ?????
d[5] = 48; // Boiler aus ( von Heizung ) W
d[6] = 42; // Boiler ein ( von Heizung ) W
d[7] = 2; // Zeit * 30 ! W
d[8] = 76; // Kesseltemperatur aus W
d[9] = 70; // Kesseltemperatur ein W
d[10]= 9; // Modus W
d[11]= 0; // Or
d[12]=255; // And
d[13]= 62; // Pumpen starten wegen B/Speicher zu heiss / Notenladen
d[14]= 45; // Boiler vom Speicher nachladen vom Puffer
d[15]= 57; // Ladetemp. Boiler ( Mischer !)
d[16]= 45; // Mischertemperatur im Notfall
d[17]= 1; // Steigung Mischertemp.
d[18]= 2; // Mischertemperatur bevor geregelt wird
d[19]= 10; // Mischer zufahren beim Umschalten
d[20]= 10; // Regelzeit 10 sec.
d[21]= 25; // Temperatur zum Entladen
d[22]= 04; // Heizung ein um 3:59
d[23]= 08; // Heizen aus um 7:59
for i = 0 ... 19 // 19 Variable löschen
{ Zeit_Zaehler[i] = 0;
}
}
}

/********************************************************************
Diese Routine ist jetzt für das WSO Board (aus ds1621.c2)
C-Control II User Lib sample
release : 2000/12/26
author : Willi Haferkemper
requires : contents : tested
********************************************************************/
/* alte Anlage
const SDA3 = 8; // SDA ist P1H1 mit 5 Kohm nach (+) gezogen !
const SCL3 = 9; // SCL ist P1H2 mit 5 Kohm nach (+) gezogen !
const PAUSE3 = 0; // Wartezeiten nach toggle etc. püfen !!
*/
const SDA3 = 4; // SDA ist P1H0 mit 5 Kohm nach (+) gezogen !
const SCL3 = 6; // SCL ist P1H2 mit 5 Kohm nach (+) gezogen !
const PAUSE3 = 1; // Wartezeiten nach toggle etc. püfen !!

const LOW3 = 0;
const HIGH3 = -1;


//----------------------
function i3c_start()
//----------------------
{ ports.set(SDA3,LOW3); sleep(PAUSE3);
ports.set(SCL3,LOW3); sleep(PAUSE3);
}

//---------------------
function i3c_stop()
//---------------------
{ports.set(SDA3,LOW3); sleep(PAUSE3);
ports.set(SCL3,HIGH3);sleep(PAUSE3);
ports.set(SDA3,HIGH3);sleep(PAUSE3);
}

//---------------------
function i3c_pulse()
//---------------------
{ ports.toggle(SCL3);
ports.toggle(SCL3);
}

//----------------------------
function i3c_send(byte wert)
//----------------------------
{ byte r;

for r = 0 ... 7
{ if(wert and 128)
{ ports.set(SDA3,HIGH3);
}
else
{ ports.set(SDA3,LOW3);
}

i3c_pulse();
wert = wert shl 1;
}
ports.deact (SDA3); // SDA auf Eingang
ports.toggle(SCL3); //

if ports.get(SDA3) /* Ackn. vom Slave prüfen! */
{plm.beep (50); // Hier qiekt es, wenn kein Ackn. kommt !
str.clear(t); str.putstring(t,"WSO Fehler ! "); str.putintf (t,99,2);
}
ports.toggle(SCL3); //
}

//----------------------------
function i3c_read() returns byte
//----------------------------
{ byte r;
byte wert;
wert=0;
ports.deact (SDA3); /* muss das sein wenn man Bit-Abfrage macht ? */

for r = 0 ... 7
{wert = wert shl 1;
if ports.get(SDA3)
wert=wert+1; /* wenn SDA HIGH3 ist */
i3c_pulse();
}
return wert;
}

//--------------------------------------
function IO_Write(byte wert)
//--------------------------------------
{ i3c_start(); /* send start and */
i3c_send(70); /* adress PCF */
i3c_send(wert); /* send value to port */
i3c_stop();
}

//--------------------------------------
function WSO_init()
//--------------------------------------
{ i3c_start(); /* send start and */
i3c_send(64); /* adress Statusport */
i3c_send(255-16); /* send 255-16 to Statusport */
i3c_stop();
}
//--------------------------------------
function WSO_write( byte Wert )
//--------------------------------------
{ i3c_start(); // Send start and
i3c_send(66); // adress of WSO Port
i3c_send(Wert); // Send Data
i3c_stop();
}

//--------------------------------------
function WSO_read() returns byte
//--------------------------------------
{ byte Wert;
i3c_start(); // Send start and
i3c_send(69); // Adress of WSO Port
Wert = i3c_read(); // Get byte
i3c_pulse(); // Ackn. vom Slave ??muss??
i3c_stop();
return Wert;
}

//--------------------------------------
// ds1621.c2
// C-Control II User Lib sample
// release : 2001/3/25
// author : Willi Haferkemper
// requires : // contents : tested
//--------------------------------------



/******************************************************************/
/* DS Commands (Refer to datasheet of Dallas DS1621 */
/******************************************************************/
const command1 = 0xac; /* 2 Byte command */
const command2 = 0xee; /* 1 Byte command Start T DS1621 */
const command3 = 0x51; /* 1 Byte command Start T DS1631 */
const cont_read = 0x00; /* continuous temp. read */
const cont_read1 = 0x08; /* continuous temp. read ( 11 bit ) */
const temp_read = 0xaa; /* command temp. read */
/* */
/******************************************************************/

// Für die unteren Klemmen auf Platine ( zwischen +/- und 12/13 )
// für den Notfall, falls die Ports defekt !
//const SDA4 = 15; // SDA4 ist P1H8 mit 10 Kohm nach + gezogen !
//const SCL4 = 14; // SCL4 ist P1H7 mit 10 Kohm nach + gezogen !


// Neu am Bus
const SDA4 = 0; // SDA ist P1H0 mit 5 Kohm nach (+) gezogen !
const SCL4 = 2; // SCL ist P1H2 mit 5 Kohm nach (+) gezogen !



// Für die oberen Klemmen auf Platine ( falls die anderen defekt
//const SDA4 = 13; // SDA4 ist P1H6 mit 5? Kohm nach + gezogen !
//const SCL4 = 12; // SCL4 ist P1H5 mit 5? Kohm nach + gezogen !

const pause4 = 0; // Wartezeiten nach toggle etc. püfen !!
const LOW4 = 0;
const HIGH4 = -1;

//----------------------
function i4c_start()
//----------------------
{ ports.set(SDA4,LOW4); sleep(pause4);
ports.set(SCL4,LOW4); sleep(pause4);
}

//---------------------
function i4c_stop()
//---------------------
{ ports.set(SDA4,LOW4); sleep(pause4);
ports.set(SCL4,HIGH4);sleep(pause4);
ports.set(SDA4,HIGH4);sleep(pause4);
}

//---------------------
function i4c_rep_start()
//---------------------
{ ports.set(SCL4,HIGH4);sleep(pause4);
ports.set(SDA4,LOW4); sleep(pause4);
ports.set(SCL4,LOW4); sleep(pause4);
}

//---------------------
function i4c_pulse()
//---------------------
{ ports.toggle(SCL4); sleep(pause4);
ports.toggle(SCL4); sleep(pause4);
}

//---------------------
function i4c_ackn()
//---------------------
{ ports.set(SDA4,LOW4);sleep(pause4);i4c_pulse();
}

//---------------------
function i4c_not_ackn()
//---------------------
{ ports.set(SDA4,HIGH4);sleep(pause4);i4c_pulse();
}

//----------------------------
function i4c_send(byte wert)
//----------------------------
{ byte r;

for r = 0 ... 7
{ if wert and 128
{ ports.set(SDA4,HIGH4);sleep(pause4);
}
else
{ ports.set(SDA4,LOW4);sleep(pause4);
}
i4c_pulse();
wert = wert shl 1;
}
ports.deact (SDA4); // SDA4 auf Eingang
ports.toggle(SCL4); // hier wird Ackn. geprüft
sleep(pause4); // nur beim senden der Adresse prüfen
// Ackn. des adressierten DS 1621 prüfen
if ports.get(SDA4) // SDA4 muss vom Slave auf LOW4 gez.werden
{ plm.beep(plm.TONE_F2); // Piepen wenn Fehler !!
sleep 50;
Zeit_Zaehler[11] = Zeit_Zaehler[11]+1; // Fehler zählen !!
str.clear(t); str.putstring(t,"DS Ackn. Err. !");
str.putintf (t,wert,3); ; // Adresse speichern
plm.beep(plm.TONE_OFF);
}
ports.toggle(SCL4);sleep(pause4);
}

//----------------------------
function i4c_read() returns byte
//----------------------------
{ byte i;
byte wert;

wert=0;
ports.deact (SDA4); // das muss sein, wenn man Bit-Abfrage macht !
// wenn nicht, geht 0,5 °C nicht !!
for i = 0 ... 7
{
wert = wert shl 1;
if ports.get(SDA4)
wert=wert+1; // wenn SDA4 HIGH4 ist
i4c_pulse();
}

return wert;
}

//--------------------------------------
function ds_init ( byte I2C_Adresse )
//--------------------------------------
{ byte x;

// Configuration Byte lesen und teste Bit 1
i4c_start() ; // send start and
i4c_send(I2C_Adresse) ; // adress of DS 1621
i4c_send(command1) ; // send command $AC
i4c_rep_start() ; // I²C repeated start
i4c_send(I2C_Adresse+1) ; // Adress+1 of DS 1621
x = i4c_read() ; // Liest das Configurationbyte
i4c_not_ackn() ; // No ackn. by busmaster d.h. beenden
i4c_stop() ; //

if (x and 1) == 1 // Wenn Bit 1 auf "1" ist, erneut cont. Wandeln setzen

{Zeit_Zaehler[9] = Zeit_Zaehler[9]+1; // RZ-Fehler zählen
str.clear(t); str.putstring(t,"DS cont. weg Err. !");
str.putintf (t,I2C_Adresse,3); ; // Adresse speichern
i4c_start() ; // send start and
i4c_send(I2C_Adresse); // adress of DS 1621
i4c_send(command1) ; // send command $AC
i4c_send(14); // (cont_read 12 bit !)*************************
i4c_stop() ; // Sequenz ok


plm.beep(plm.TONE_E2) ; /* Piepen wenn Fehler !!*/
sleep 100 ;
plm.beep(plm.TONE_OFF) ;
}

if (x and 14) == 10 // Wenn DS 1621, ( Bit 3=1 und Bit2 =0 zeigt DS 1621 )
{
i4c_start(); // send start and
i4c_send(I2C_Adresse); // adress of DS 1621
i4c_send(command2); // send command $ee / Start für DS 1621
i4c_stop(); // (Start Conversions)
}
else
{ // hier
i4c_start(); // send start and
i4c_send(I2C_Adresse); // adress of DS 16"3"1
i4c_send(command3); // send command Start T DS 1631
i4c_stop(); // (Start Conversions)
} // ende else DS1621
}

//----------------------------------------------------------------
function ds_read( byte I2C_Adresse) returns float
//----------------------------------------------------------------
{ byte x; //
float z; //
x=0; z=0; // x & z löschen

i4c_start(); // send start and
i4c_send(I2C_Adresse); // adress of DS 1621
i4c_send(temp_read); // send $AA / Temp holen
i4c_rep_start(); // I²C repeated start
// i4c_start(); // send start and // Über !!
i4c_send(I2C_Adresse+1); // adress+1 of DS 1621
x = i4c_read(); // get HIGH-byte temperature
i4c_ackn(); // ackn. by Busmaster also des Moduls
z = x and 127 ; // HIGH4 bit = +/- bit / Z=Temp-Wert!

// dieser Test kann eigentlich entfallen,
// da Temp immer positiv sein sollten !
if x and 128 // testen auf neg. Temperaturen
{z = -256+x; // wenn ja, dann ist Temp -256+x
} //
/* ------- das 0,5 °C Bit holen ----- */
ports.deact (SDA4); /* muss sein, wenn man Bit-Abfrage macht */
if ports.get(SDA4) /* wenn SDA4 HIGH4 ist */
z = z + 0.5; /* ja, dann 0,5 °C addieren */

i4c_pulse();
if ports.get(SDA4) /* wenn SDA4 HIGH4 ist */
z = z + 0.25; /* ja, dann 0,25 °C addieren */

i4c_pulse();
if ports.get(SDA4) /* wenn SDA4 HIGH4 ist */
z = z + 0.125; /* ja, dann 0,125 °C addieren */

// vorher 0 ... 7
for x = 0 ... 5 /* x ist jetzt Hilfsbyte */
i4c_pulse(); /* die nächsten Bits überlesen */

i4c_not_ackn() ; /* No ackn. by busmaster */
i4c_stop() ; /* */
/* */
// Spezielle Routine für Absturz !!
if z == 0 // Sensor abgestürzt !
{ ds_init(I2C_Adresse) ; // Temp. Wandlung dauert 0,4-1 Sek.
// also ca. 1 Sekunde warten
plm.beep(plm.TONE_E2) ; /* Piepen wenn Fehler !!*/
sleep 300 ;
plm.beep(plm.TONE_OFF) ;

Zeit_Zaehler[10] = Zeit_Zaehler[10]+1 ; // Fehler zählen !!
str.clear(t); str.putstring(t,"0 Grad Fehler ! .");

str.putintf (t,I2C_Adresse,3); ; // Adresse speichern

if (I2C_Adresse > 143) and (I2C_Adresse < 160)
{ plm.beep(plm.TONE_D2) ; /* Piepen wenn Fehler !!*/
str.clear(t); str.putstring(t,"Adresse ist ok. !");
sleep 100 ;
plm.beep(plm.TONE_OFF) ;
plm.beep(plm.TONE_E2) ; /* Piepen wenn Fehler !!*/
sleep 100 ;
plm.beep(plm.TONE_OFF) ;
ds_read(I2C_Adresse); // nochmal lesen
if z==0
{z=177;
}
}
else
{str.clear(t); str.putstring(t,"Ill. Adressfehler");
str.putintf (t,I2C_Adresse,3); ; // Adresse speichern
z=188;
}
} // das kann bei mehrfachen Fehlern problematisch werden.
// Stacküberlauf

return z;
}


// ***************************************************************
function DS_reset_all() // Messstelle initialisieren
{
// WSO_write(Byte_Outy or Spannung_Sensoren); // Sensor Spannung aus
ports.set(7,-1); // Schaltet das NAIS Relais ein d.h. Sensor aus
sleep (150);
ports.set(7,0); // Schaltet das NAIS Relais aus d.h. Sensor ein
// WSO_write(Byte_Outy and (255-Spannung_Sensoren));// Spannung einschalten
sleep (150);
ds_init(T0);
ds_init(T1);
ds_init(T2);
ds_init(T3);
ds_init(T4);
// T5 = analog Kollektor
ds_init(T6); // Kessel
ds_init(T7); // Rezirkulation
ds_init(T8); // Heizungsrücklauf
// T9 = analog Außenfühler
}

//--------------------------------------------------------
function DS_read_all() // Messstellen lesen
{
Temp_Sensor[0] = ds_read(T0); // Boiler oben (W)
T_Boiler_Oben = Temp_Sensor[0];

Temp_Sensor[1] = ds_read(T1); // Boiler unten (W)
T_Boiler_Unten = Temp_Sensor[1];

Temp_Sensor[2] = ds_read(T2); // Mischer_Vorl. (W)
T_Heizungs_Vorlauf = Temp_Sensor[2];

Temp_Sensor[3] = ds_read(T3); // Speicher oben (W)
T_Speicher_Oben = Temp_Sensor[3];

Temp_Sensor[4] = ds_read(T4); // Speicher unten(W)
T_Speicher_Unten = Temp_Sensor[4];

// 5 = PT 500 // Kollektor analog

Temp_Sensor[6] = ds_read(T6); // Kessel (W)
T_Kessel = Temp_Sensor[6];

Temp_Sensor[7] = ds_read(T7); // Rezirkulation (W)
T_Rezirkulation = Temp_Sensor[7];

Temp_Sensor[8] = ds_read(T8); // Heizungsrücklauf (W)
T_Heizungs_Ruecklauf = Temp_Sensor[8];

// T9 = analog Außenfühler // T_Aussen ist analog
}


/* ------------------------------------------ */
/* ------ Zähler hochzählen --------------- */
/* ------------------------------------------ */
function count()
{
if ( Z_Sekunde != system.second()) // ungleich, d.h. Sek.-Takt
{

Read = 0 ; // Beim nächsten mal wieder Temperaturen lesen
Read1 = 0 ;

if Byte_Outx and Kollektor_Pumpe // Kollektorpumpe läuft
{
if (not Byte_Outx) and Rezirkulation // Rezirkulieren ein
Zeit_Zaehler[2] = Zeit_Zaehler[2]+1;
else
{
if Byte_Outx and Boiler_Speicher
{ Zeit_Zaehler[0] = Zeit_Zaehler[0]+1; // Kollektor lädt Boiler (S)
Zeit_Zaehler[12] = Zeit_Zaehler[12]+1;// Koll./ Boiler Tageszähler
}
else
{ Zeit_Zaehler[1] = Zeit_Zaehler[1]+1; // Kollektor lädt Speicher !!
Zeit_Zaehler[13] = Zeit_Zaehler[13]+1; // Koll./Speicher Tageszähler
}
} // ende else
}
if Byte_Outy and Relais_1 // Rücklaufanhebung
{Zeit_Zaehler[11] = Zeit_Zaehler[11]+1;
Zeit_Zaehler[19] = Zeit_Zaehler[19]+1;
}
if Byte_Outx and Boilerlade_Pumpe // Boilerladepumpe
{Zeit_Zaehler[3] = Zeit_Zaehler[3]+1;
Zeit_Zaehler[14] = Zeit_Zaehler[14]+1; // Tageszähler
}
if Byte_Outx and Heizungs_Pumpe // Heizpumpe läuft
{Zeit_Zaehler[4] = Zeit_Zaehler[4]+1;
Zeit_Zaehler[15] = Zeit_Zaehler[15]+1;
}
if Byte_Outx and Kessel // Kessel läuft
{Zeit_Zaehler[5] = Zeit_Zaehler[5]+1;
Zeit_Zaehler[16] = Zeit_Zaehler[16]+1;
}
if (Status2 and B_zu_heiss) == B_zu_heiss // Notentladen Boiler
{Zeit_Zaehler[17] = Zeit_Zaehler[17]+1;
}

if (Status2 and Sp_zu_heiss) == Sp_zu_heiss // Notentladen Speicher
{Zeit_Zaehler[18] = Zeit_Zaehler[18]+1; //
}

if (not Byte_in) and Heizungsbetrieb1 // DG fordert Heizung
Zeit_Zaehler[6] = Zeit_Zaehler[6]+1 ; // Gesamtzähler

if (not Byte_in) and Heizungsbetrieb3 // OG fordert Heizung
Zeit_Zaehler[7] = Zeit_Zaehler[7]+1 ; // Gesamtzähler

if ( not Byte_in)and Heizungsbetrieb2 // EG fordert Heizung
Zeit_Zaehler[8] = Zeit_Zaehler[8]+1; // Gesamtzähler

Z_Sekunde = system.second(); // Jetzt muss wieder gewartet werden

// -----------------------
// Ausgabe auf Minidisplay
//------------------------
if system.hour() == 0 /* Datum nur nachts neu! */
{
lcd.goto (0,0);
str.clear(i);
str.putintf(i,(system.day()),2); /* Tag ausgeben*/
str.putstring(i,".");
str.putintf(i,(system.month()),2); /* Monat ausgeben*/
str.putstring(i,".");
str.putintf(i,(system.year()-2000),2);
lcd.print(i,8);
}

lcd.goto (1,0);
str.clear(i);
str.putintf(i,(system.hour()),2); /* Stunde ausgeben*/
str.putstring(i,":");
str.putintf(i,(system.minute()),2);/* Minute ausgeben*/
str.putstring(i,":");
str.putintf(i,(system.second()),2); /*Sek. ausgeben*/
lcd.print(i,8);
}
}


//##############################################################
function Write_Zaehler(byte i) // Messstelle + Wert ausgeben
{ str.clear(s); print(y[i]); str.putlongf(s,(Zeit_Zaehler[i]/3600),4);
str.putstring(s,":"); str.putintf (s,((Zeit_Zaehler[i] % 3600)/60),2);
str.putstring(s,"."); str.putintf(s,(Zeit_Zaehler[i]%60),2);print(s);
}

function Write_Temp(byte i)
{ str.clear(s); print (z[i]); // Meßstellenbez. ausgeben
if Temp_Sensor[i] >99.9
{str.putfloatf(s,Temp_Sensor[i],0);print (" "); // Wert ausgeben
}
else
{
if Temp_Sensor[i] >9.9
str.putfloatf(s,Temp_Sensor[i],1); // Wert ausgeben
else
{if Temp_Sensor[i] <=0
str.putfloatf(s,Temp_Sensor[i],0); // Wert ausgeben
else
str.putfloatf(s,Temp_Sensor[i],2); // Wert ausgeben

}
}
print(s);
}

function Ausgabe_Temp(byte Index)
{ if Merker == 0
{ // ---- In den Zeilen 1.-3. Temperatur anzeigen ----
goto (0,0);Write_Temp(0);Write_Temp(1);Write_Temp(5); // 1. Zeile LCD
goto (1,0);Write_Temp(3);Write_Temp(4);Write_Temp(7); // 2. Zeile LCD
goto (2,0);Write_Temp(6);Write_Temp(2);Write_Temp(8); // 3. Zeile LCD
// print (" "); // 3. Zeile LCD
// jetzt noch die Zeit, bis zun Speicher gefahren wird
// goto (2,15); str.clear(s); str.putintf(s,Zeit_bis_Speicher,4); print(s);
// goto (2,15); str.clear(s); str.putintf(s,M_Zeit,4); print(s);
}
else
{ // Laufzeiten anzeigen
if Index == 0
{ goto (0,0); Write_Zaehler(0); // 1. Zeile Kollektor lädt Boiler
goto (1,0); Write_Zaehler(1); // 2. Zeile Kollektor lädt Speicher
goto (2,0); Write_Zaehler(2); // 3. Zeile Rezirkulationszeit
}
else
{
if Index == 3
{
goto (0,0); Write_Zaehler(3); // 1. Zeile Boilerladepumpe gesamt
goto (1,0); Write_Zaehler(4); // 2. Zeile Heizungspumpe gesamt
goto (2,0); Write_Zaehler(5); // 3. Zeile Kesselstunden gesamt
}
else
{
if Index == 5
{ goto (0,0); Write_Zaehler(6); // Dach heizt
goto (1,0); Write_Zaehler(7); // Mitte heizt
goto (2,0); Write_Zaehler(8); // Erdgesch.heizt


}
else
if Index == 1 // 9,10,11 sind Fehlerzähler
{ goto (0,0); Write_Zaehler(12); // 1. Z. Tagesz. Kol->Boiler
goto (1,0); Write_Zaehler(13); // 2. Z. Tagesz. Kol->Speicher
goto (2,0); Write_Zaehler(14); // 3. Z. Tagesz. Boilerpumpe
}
else

if Index == 4
{ goto (0,0); Write_Zaehler(18); // Tageszähler Notentl. Speicher
goto (1,0); Write_Zaehler(19); // Tageszähler Rücklaufanh. Tag
goto (2,0); Write_Zaehler(17); // Tageszähler Notentladen
}
else
if Index == 2
{ goto (0,0); Write_Zaehler(15); // Tageszähler Heizpumpe
goto (1,0); Write_Zaehler(16); // Tageszähler Kessel
goto (2,0); Write_Zaehler(17); // Tageszähler Notentladen Boiler
}
else
if Index == 6
{ goto (0,0); str.clear(s); print(y[9]); // Err-Text0 ausg.
str.putlongf(s,Zeit_Zaehler[9], 10); print(s); // Wert ausgeben
goto (1,0); str.clear(s); print (y[10]); // Err-Text1 ausg.
str.putlongf(s,Zeit_Zaehler[10],10); print(s); // Wert ausgeben
// goto (2,0); str.clear(s); print (y[11]); // Err-Text1 ausg.
// str.putlongf(s,Zeit_Zaehler[11],10); print(s); // Wert ausgeben
// goto (2,0); Write_Zaehler(11); // 3. Z. Tagesz. Rücklaufanhebung
goto (2,0); print(t); // Fehlerstring / wert ausgeben
}
else
if Index == 7
{ goto(0,0);str.clear(s); str.putstring(s,"Status_1....");// LCD Z_1
str.putmask(s,Status1,'1','0');print(s);
goto(1,0);str.clear(s); str.putstring(s,"Status_2....");// LCD Z_2
str.putmask(s,Status2,'1','0');print(s);
goto (2,0); str.clear(s);str.putstring(s,"Byte_Outx...");
str.putmask(s,Byte_Outx,'1','0');print(s);
}
else

{ goto (0,0); str.clear(s);str.putstring(s,"Mischer zu Zeit ");
str.putintf(s,M_Zeit,4); print(s);
goto (1,0); str.clear(s);str.putstring(s,"Mischerkorr.Cel ");
str.putintf(s,M_Korr,4); print(s);
goto (2,0); Write_Zaehler(11); // 3. Z. Tagesz. Rücklaufanhebung
// goto (2,0); print(t); // Fehlerstring / wert ausgeben
}
}
}
}
}

function Ausgabe_Datum() // LCD auf Zeile 4 des Displays / Spalte 0
{ goto(3,0); str.clear(s); str.putintf(s,(system.day()),2); /* Tag ausgeben*/
// str.putstring(s,".");
str.putintf(s,(system.month()),2); /* Monat ausgeben*/
//str.putstring(s,".");str.putintf(s,(system.year()-2000),2);/*Jahr ausgeben*/
str.putstring(s,"-");str.putintf(s,(system.hour()),2); /* Stunde ausgeben*/
str.putstring(s,":");str.putintf(s,(system.minute()),2);/* Minute ausgeben*/
str.putstring(s,":");str.putintf(s,(system.second()),2); /*Sek. ausgeben*/
// str.putstring(s," ");str.putlongf(s, M_Zeit,-3)
str.putstring(s," ");str.putintf(s,(M_Temp),2); // 14.11.2001
str.putstring(s," ");
// str.putintf(s, Byte_in,-2);print(s); /* Eingabebyte vom WSO anzeigen */
str.putintf(s, Zeit_bis_Speicher,3);print(s); /* Zeit anzeigen */
}

/*---------------------------------------*/
/* -- Werte Auswahl im LCD -----*/
/*---------------------------------------*/
function Eingabe_Werte(byte i)
{ byte Taste;

Taste = ( Byte_in and 7 ); //

if Taste > 6 /* Wenn keine Taste gedrückt ist */
{ ti = ti+1; /* Zeit hochzählen */
}
else
{ ti = 0; /* Wenn eine Taste gedrückt ist ti= 0 */

if Taste == 2 /* Rote + Grün ? Speichern */
EEprom_Write(); /* der eingest. Werte */

if Taste == 4 /* Rote Taste gedrückt ? Ende */
{ Merker = 0;
Index = 0; /* Wenn rote Taste, dann Index 0*/
clear (); /* Display löschen */
}
if Taste == 6 /* Grüne Taste gedrückt ? */
Index = Index+1; /* Index hochzählen */
if Index == 24 /* Index darf max. 31! werden */
Index = 0; /* bis 21 möglich !! */

if Taste == 3 /* Blaue rechte Taste */
d[Index] = d[Index]+1;
if Taste == 5 /* Blaue linke Taste */
d[Index] = d[Index]-1;

plm.beep(plm.TONE_E2); sleep 100;

// Sicherheitsabfragen :
// Wenn Nachladetemperatur fast so groß wie notentladen
if (d[5]+2) > d[13 ]
{d[13] = d[13]+1;
}

plm.beep(plm.TONE_OFF);
}

if ti >100 /* Zeit abgelaufen ? */
{ ti = 0;
clear (); /* Display löschen */
Merker=0; /* nach 100 Durchläufen auf Normalanzeige */
}
goto (3,0); print(x[Index]); /* Text des Indizes angeben */
str.clear(s); str.putintf(s,(d[Index]),3);
str.putstring (s," "); str.putintf(s,ti,3); print(s);
}

//--------------------------------------------
thread main

{ byte i;
byte Alt_Sekunde; /* Zeit für LCD Eingabe */
byte Alt_Minute; /* Zeit für Spannung von Sensoren */
byte Alt_Tag; /* Zeit fürs Abspeichern */

Byte_Outx = 0;
Byte_Outy = 0;// Byte_Outy and (255-Spannung_Sensoren); // Sensor Sp. einsch
Alt_Tag = 1; // Wird beim Speichern benötigt
t = "Kein Fehler ";
M_Zeit = d[19]; // für Mischer zufahren
M_Korr = 0; // Korrekturwert Mischer

/* --------------------------------------------------------------*/
/* ---- Programminitalisierungen --------------------------*/
/* --------------------------------------------------------------*/

// system.setdate(2002,01,1); // Defaultdatum setzen
system.settime(0,3,00);
// lcd.init(); // internes LCD initialisieren

IO_Write (0); // Ausgabeplatine löschen
WSO_write(0); //
WSO_init(); // WSO Board initialisieren
init(); // externes LCD1 initialisieren
i2c.init(); // I²C Bus initialisieren

clear(); /* Display löschen */
goto(0,0); print ("Solarsteuerung V 0.9");
goto(1,0); print ("(C) by W.xxxxxxxxxxx");
goto(2,0); print ("mobil. 01xxxxxxxxxxx");
goto(3,0); print ("Stand : 18.05.2002");
sleep (1000);
// ports.set(7,0);
i2c.init();
EEprom_Read(); /* gespeicherte Werte einlesen */
DS_reset_all(); // DS-Sensoren initalisiern
sleep (500);
count();
sleep (500);
DS_read_all(); // alle Temperaturen lesen
clear(); // Display löschen

// Testroutine für Temperatursensoren
Byte_in = WSO_read(); // beim RESETTEN / Einschalten :

if (Byte_in and 7 ) == 6 // nur grüne Taste gedrückt 6 !!!!!
{ Merker = 0;clear(); sleep(100); // Display löschen */
Ausgabe_Temp(i); // Alle Temperaturen anzeigen
goto(3,0);str.clear(s); // LCD auf Zeile 4 des Displays
str.putmask(s,Byte_in,'0','1');print(s);

WSO_write(Spannung_PCF_Board);
sleep(500) ; // 24 Volt auf Ausgabegruppe geben
IO_Write(128); sleep(1000); // Daten auf neuen Port ausgeben
IO_Write(64) ; sleep(1000); // Daten auf neuen Port ausgeben
IO_Write(32) ; sleep(1000); // Daten auf neuen Port ausgeben
IO_Write(16) ; sleep(1000); // Daten auf neuen Port ausgeben
IO_Write(2) ; sleep(1000); // Daten auf neuen Port ausgeben
IO_Write(4) ; sleep(1000); // Daten auf neuen Port ausgeben
IO_Write(8) ; sleep(1000); // Daten auf neuen Port ausgeben
IO_Write(1) ; sleep(1000); // Daten auf neuen Port ausgeben
IO_Write(0) ; // Alles "Aus"

WSO_write(Relais_1) ; sleep(1000); // Relais
WSO_write(Relais_2) ; sleep(1000); // Relais
WSO_write(Spannung_Sensoren) ; sleep(1000); // Relais
//WSO_write(8) ; sleep (1000); // frei
//WSO_write(128) ; sleep (1000); // frei
//WSO_write(64) ; sleep (1000); // frei
ports.set(7,-1); sleep(2000); // Minirelais für Spannung !
ports.set(7,0);
WSO_write(LCD_Beleuchtung) ; sleep(5000); // LCD Beleuchtung
WSO_write(0); // Alles "Aus"

Zeit_Zaehler[9] =0; // Fehlerzähler löschen
Zeit_Zaehler[10]=0; //
// Zeit_Zaehler[11]=0; // Rücklaufanhebung

/* Test, um andere Betriebsart im DS 1621 zu setzen
i4c_start(); // send start and
i4c_send(150); // adress of DS 16"3"1
i4c_send(command1); // send command $AC
i4c_send(255); // send command $FF
i4c_stop();
*/
quit(1);
}

// ################################################################

Byte_Outy= Byte_Outy or Spannung_PCF_Board; // 24 Volt auf Ausgabegruppe geben
WSO_write(Byte_Outy); sleep(300);
// Zeit_bis_Speicher = 0; // Wenn in Boiler, dann Zeit 0
Zeit_bis_Speicher = d[7]*30;
Alt_Minute = system.minute();
M_Zeit = d[19];
Status1 = (Status1 or Heizen_ein); //Setze Bit heizen wegen Restentleern

ADC1 = ports.adc(1)*0.004; // Analogport lesen
Temp_Sensor[5] =((1800/(4.96-ADC1)*ADC1)-500)/1.96; // Kollektor berechn.

// --------------------------------------------
// Hauptschleife Heizung
// --------------------------------------------
loop
{

/* ------------------------------------------ */
/* --- Einlesen des WSO-Ports ----------- */
/* ------------------------------------------ */
Byte_in = WSO_read(); // Tasten und Meldungen vom WS-Board lesen

/* ----------------------------------------------*/
/* ------ Umrangieren der Temperaturen -------*/
/* ------ und evtl. Korrekturwerte der Sensoren */
/* ----------------------------------------------*/
// $90=144, $92=146, $94=148, $96=150
// $98=152, $9A=154, $9C=156, $9E=158

// Nur alle 27 Sekunden die Speichertemperaturen abfragen !

if ((system.second()%24) == 3) and ( Read == 0 )
{
Temp_Sensor[0] = ds_read(T0); // Boiler oben
Temp_Sensor[1] = ds_read(T1); // Boiler unten
Temp_Sensor[3] = ds_read(T3); // Speicher oben
Temp_Sensor[4] = ds_read(T4); // Speicher unten

T_Boiler_Oben = Temp_Sensor[0];
T_Boiler_Unten = Temp_Sensor[1];
T_Speicher_Oben = Temp_Sensor[3];
T_Speicher_Unten = Temp_Sensor[4];

Read = 1; // Dieser Merker soll doppeltes Lesen verhindern
// Wird bei count zurückgesetzt !

// Wenn Werte nicht logisch erscheinen : Spannung aus und neu einlesen!
if Temp_Sensor[0] < 5 or Temp_Sensor[0] > 99 // Boiler oben (W)
or Temp_Sensor[1] < 5 or Temp_Sensor[1] > 99 // Boiler unten (W)
or Temp_Sensor[3] < 5 or Temp_Sensor[3] > 110 // Speicher Oben (W)
or Temp_Sensor[4] < 5 or Temp_Sensor[4] > 110 // Speicher Unten (W)

{ Zeit_Zaehler[9] = Zeit_Zaehler[9]+1000; // Fehler hochzählen !!
DS_reset_all(); // Re-Setten und neu einlesen
count(); // evtl. Zeit-Zähler hochzählen
sleep (800);
count(); // evtl. Zeit-Zähler hochzählen
DS_read_all();
count();
str.clear(t); str.putstring(t,"DS1621 <5 oder >99 z");
} // Ende Test Temperauren
} // Ende 27 sec.

else
{

/* ----------------------------------------------*/
/* ------- Einlesen der Temperaturen Analogport */
/* ----------------------------------------------*/
// NUR der PT 500 / KTY 10-6 für Kollektor !!!
if d[10] and Modus8
{ ADC1 = ports.adc(1)*0.004; // zur Zeit immer Analogport 1 !
Temp_Sensor[5] =(((1791/(4.96-ADC1)*ADC1)-500)/1.96+Temp_Sensor[5])/2;
}
else
{ ADC1 = ports.adc(1)*0.004;
Temp_Korr = (((1800/(4.96-ADC1)*ADC1)-500)/1.96-Temp_Sensor[5])/20;
Temp_Sensor[5] = Temp_Korr+Temp_Sensor[5];
}

// Leitung 1,6 Ohm
// Kollektor PT 500
// Temp_Sensor[5] = math.sqrt((ADC1*1793/(5.02-ADC1)-16)/0.027931)-241.52;
// // Kollektor KTY 10-6

if ((system.second()%10) == 2) and ( Read1 == 0 )
// Alle 10 sec. diese Temp. lesen
{
Read1 = 1 ;

// T0 und T1 sind Boiler
Temp_Sensor[2] = ds_read(T2); //Heizungs_Vorlauf (W)
// T2 und T3 sind Speicher
Temp_Sensor[6] = ds_read(T6); //Kessel (W)
Temp_Sensor[7] = ds_read(T7); //22mm Rohr Rezirk.(W)
Temp_Sensor[8] = ds_read(T8); //Heizungsrücklauf (W)

// T0 & T1 = Boiler oben / unten !
T_Heizungs_Vorlauf = Temp_Sensor[2];
// T2 und T3 sind Speicher
T_Kollektor = Temp_Sensor[5];
T_Kessel = Temp_Sensor[6];
T_Rezirkulation = Temp_Sensor[7];
T_Heizungs_Ruecklauf = Temp_Sensor[8];
T_Aussen = 15;

// ____________________________________________________________________
// Wenn Werte nicht logisch erscheinen : Spannung aus und neu einlesen !

if Temp_Sensor[2] < 5 or Temp_Sensor[2] > 110 // Mischer (W)
or Temp_Sensor[6] < 5 or Temp_Sensor[6] > 110 // Kessel (W)
or Temp_Sensor[7] < 5 or Temp_Sensor[7] > 110 // Rezirkulation (W)
or Temp_Sensor[8] < 5 or Temp_Sensor[8] > 90 // Heizungsrückl. (W)

{ Zeit_Zaehler[9] = Zeit_Zaehler[9]+1; // Fehler hochzählen !!
DS_reset_all(); // Re-Setten und neu einlesen
count();
sleep (500);
count();
sleep (500);
count();
DS_read_all();
str.clear(t); str.putstring(t,"DS1621 <5 oder >99 y");
}
}
}

Ausgabe_Temp(Index); // Ausgabe der Temp. + Zaehler

if Merker == 0
{ Ausgabe_Datum(); // wird
if (Byte_in and 7 ) == 6 // nur grüne Taste gedrückt
{ Merker =1;
clear (); // Display löschen
}
}
else
{ Eingabe_Werte(1);
}

// ---------------------------------------- //
// -- Laderoutine für Boiler nachheizen // tested 1.7.01
// ---------------------------------------- //
if (T_Boiler_Oben < d[6]) // Boiler zu kalt
{ if (system.hour() > 4 ) // Zwischen 22:59- 4:59 Uhr tiefer!
and (system.hour() < 23 ) //
{Status1 = Status1 or Boiler_laden; // Setze Bit Boiler heizen
}
else
{if T_Boiler_Oben < (d[6]-5) // Nachts 5 Grad tiefer
Status1 = Status1 or Boiler_laden; // Setze Bit Boiler heizen
}
}

else
{ if (T_Boiler_Oben > d[5]) // Boiler hat Temp erreicht
{Status1=Status1 and (255-Boiler_laden);// Lösche Bit Boiler heizen
}
}

// ---------------------------------------- // ungetestet !!
// Boiler nachheizen von Puffer 24.2.2002
// Bit zeigt, ob Speicher heißer als Boiler
// damit Kessel nicht gestarted werden muß
// Bit sperrt im Sommerbetrieb den Brennerstart
// ---------------------------------------- //
if (T_Boiler_Oben < (T_Speicher_Oben-10)) // Boiler kälter als Pufffer
{ Status2 = Status2 or Boi_laden_2; // Setze Bit Boiler kälter
} // als Speicher

else
{if T_Boiler_Oben > (T_Speicher_Oben-5) // Wenn Boiler zu warm
Status2 = Status2 and (255-Boi_laden_2);// Lösche Bit Boiler / Puffer
}

// ---------------------------------------- //
// -- Test, ob "Rest"-entleeren des Kessels // getested 1.7.01
// ---------------------------------------- //
if (T_Boiler_Oben + 10 ) < T_Kessel // Restentleeren 30.3.2002
//if (T_Boiler_Oben + d[0]) < T_Kessel // Restentleeren
{ Status1 = (Status1 or Restentleeren); // Setze Bit
}
else
{
// if ((T_Boiler_Oben + d[0]) > T_Kessel) // Restentleeren
if ((T_Boiler_Oben + 5 ) > T_Kessel) // Restentleeren
Status1=Status1 and (255-Restentleeren);// Lösche Bit
}

// ----------------------------------------
// -- Bit zum Starten der Boilerladepumpe getested 1.7.01
// ----------------------------------------
if (Status1 and Boiler_laden)==Boiler_laden // Boiler noch zu kalt
or
( (Status1 and Restentleeren)==Restentleeren // oder Restentleeren
and (not Status1 and Heizen_ein)==Heizen_ein) // bei Sommerbetrieb

{ Status1 = Status1 or Boilerpumpe_ein; // Setze Bit
}
else
{ Status1=Status1 and (255-Boilerpumpe_ein);// Lösche Bit
}

// ----------------------------------------
// -- Routine für Kessel heizen / tested --
// ----------------------------------------
if ( T_Kessel < d[9] ) // Kessel zu kalt
{ Status1 = (Status1 or Kessel_kalt); // Setze Bit Kessel heizen
}
else
{ if (T_Kessel > d[8]) // Kessel hat Temp erreicht
{ Status1=Status1 and (255-Kessel_kalt); // Lösche Bit
}
}

// ----------------------------------------
// -------- Heizung angefordert -----------
// ---------------------------------------- Irgendein ( 8,16,32 )
if ((((not Byte_in )and 56) > 1 ) // Thermostatschalter ein ?
and ( T_Aussen < 21 )) // und aussen < 21

{ Status1 = (Status1 or Heizen_ein); // Setze Bit heizen
}
else
{ if (((not Byte_in) and 56 ) < 8 ) // Alle Thermostatsch. aus
or (T_Aussen > 22) // oder draussen warm
{ Status1=Status1 and (255-Heizen_ein); // Lösche Bit heizen
}
}

// ----------------------------------------
// ------- Morgens immer heizen ----------- oder Notentladen Speicher
// ----------------------------------------
if ((system.hour() and (system.hour()>d[22]) // Zwischen 5:00-7:59 Hzg. ein
and ( d[10] and Modus16 == Modus16 )
)
or ((Status2 and Sp_zu_heiss)==Sp_zu_heiss) //

{ Status1 = (Status1 or Heizen_ein); // Setze Bit heizen
}

// ----------------------------------------
// --------- Bit für Kessel heiss --------
// ----------------------------------------
if T_Kessel > (d[9]-3) // Kessel heiss
{ Status1 = (Status1 or Kessel_heiss); // Setze Bit Kessel heiss
}
else
{ if T_Kessel < (d[9]-5) //
{ Status1=Status1 and (255-Kessel_heiss);// Lösche Bit
}
}

// -------------------------------------------
// ------------ Rücklaufanhebung ------------ 19.1.2002
// -------------------------------------------
if ((T_Heizungs_Ruecklauf+1) < T_Speicher_Oben)
// and
{ Status1 = Status1 or Ruecklaufanhebung;
}
else
{if (T_Heizungs_Ruecklauf +1 ) > T_Speicher_Oben
Status1 = Status1 and (255-Ruecklaufanhebung);
}
// ------------------------------------------

// -------------------------------------------
// ------------ Speicherentleeren ----------- 10.2.2002
// -------------------------------------------
if (T_Speicher_Oben) > d[21]
{ Status1 = Status1 or Speicher_leeren;
}
else
{if T_Speicher_Oben < d[21]
Status1 = Status1 and (255-Speicher_leeren);
}
// ------------------------------------------


// --------------------------------------------------------------------- (W)
// - Hier Temperatur Mischer manipulieren, wenn Boiler geladen wird ----
// ---------------------------------------------------------------------
if (Status1 and Boilerpumpe_ein)
{ M_Temp=d[15]; // Temp = Heizungswassertemp. zum Laden
M_Zeit=0;
}
else

{ if Status1 and Heizen_ein
{ M_Temp=d[16]+M_Korr ; // Temperatur = Setpoint + Korrekturwert

if (not Byte_in and Heizungsbetrieb1) == Heizungsbetrieb1
{M_Temp=M_Temp+3;
}
if (not Byte_in and Heizungsbetrieb2) == Heizungsbetrieb2 // EG heizt
{M_Temp=M_Temp+3;
}
if (not Byte_in and Heizungsbetrieb3) == Heizungsbetrieb3
{M_Temp=M_Temp+3;
}

if ((Status1 and Speicher_leeren) == Speicher_leeren )
and (( d[10] and Modus1 ) == Modus1 )
and (system.hour() > 2) // Zwischen 2:59- 3:59 Uhr tiefer!
and (system.hour() < 4) //
{M_Zeit=d[19]-2; // Zeit = < d[19] heißt : Setze M_Temp. herunter
}

if M_Zeit < d[19] // Wärend gezählt wird :
{ M_Zeit=M_Zeit+1;
M_Temp=0; // Mischer soll saukalt sein
if (Byte_in and Mischer_zu) == Mischer_zu
{ M_Zeit = d[19];
}
}
else // Wenn Aussen/ z.Zeit Koll. < 20 Grad
{ if T_Kollektor < 20 // Steigung Mischertemmp einstellen
M_Korr = (20-T_Kollektor)*d[17]/10; // d.h. 0 Grad = 10 Grad höher
} // Ende else // bei d[15] = 5 !!
} //Ende "if Status1 and Heizen_ein"

else
M_Temp=0; // Dieses sagt, der Mischer soll saukalt sein !!
}

// ---------------------------------------- (W)
// -------- Mischer zufahren -------------
// ----------------------------------------
if ( T_Heizungs_Vorlauf > (M_Temp+d[18])) // d[18] Regelabw.
and (system.second()%d[20])<((T_Heizungs_Vorlauf-M_Temp))
and ((not Byte_in ) and Mischer_zu)

{ Byte_Outx = Byte_Outx or Mischer_aus; //
}
else
{ Byte_Outx = Byte_Outx and (255-Mischer_aus);
}

// ---------------------------------------- (W)
// -------- Mischer auffahren -------------
// ----------------------------------------
// bei "Heizen aus" wird M_Temp auf 0 gesetzt, um Mischer zu schließen

// Wenn Brenner startet, nur bei großer Abweichung auffahren
// Temperatur wird eh bald ansteigen ( nur wenn Heiz_Pumpe läuft !)

if (((Byte_Outx and Kessel) == Kessel ) // neu : Stop wenn
// and (T_Heizungs_Vorlauf < M_Temp) // beim sinken ?
and ((Byte_Outx and Heizungs_Pumpe) == Heizungs_Pumpe)) // Kessel started
and ( M_Temp != 0 )
{ M_Temp = M_Temp-2; // Soll_Temperatur um 2 Grad senken
}

// -----------------------------------------
if (T_Heizungs_Vorlauf < (M_Temp)) and // -1 ???
(system.second()%d[20]) < (M_Temp-T_Heizungs_Vorlauf)
{
Byte_Outx = Byte_Outx or Mischer_ein; // ?????????!!
}
else
{ Byte_Outx = Byte_Outx and (255-Mischer_ein);
} // Ende else Mischer auf


// ----------------------------------------
// Umrangieren und Ausgabe auf die Ausgänge
// ----------------------------------------

// Wenn Boilerpumpe laufen soll, dann ein !
if (Status1 and Boilerpumpe_ein) == Boilerpumpe_ein

{ Byte_Outx = Byte_Outx or Boilerlade_Pumpe;
}

else // sonst aus
{ Byte_Outx = Byte_Outx and (255-Boilerlade_Pumpe);
}

// Heizungspumpe einschalten
if ((Status1 and Boilerpumpe_ein) // Heizungspumpe beim laden aus !!!
or ((not Status1) and Heizen_ein) ) // oder wenn nicht geheizt werden soll

{ Byte_Outx = Byte_Outx and (255-Heizungs_Pumpe);
}
else
{
if ((M_Zeit >= d[19]) // Hat der Mischer die Zeit gehabt zuzufahren ?
and (Status1 and Heizen_ein ))
{ Byte_Outx = Byte_Outx or Heizungs_Pumpe;
}
}

// -------------------------------------------- NICHT getested !!!!!
// Hier noch Heizungspumpe an, zum NOTENTLADEN Speicher
// --------------------------------------------
if (Status2 and Sp_zu_heiss) == Sp_zu_heiss //
{Byte_Outx = Byte_Outx or Heizungs_Pumpe;
// Byte_Outx = Byte_Outx or Ruecklaufanhebung; //
}

// -------------------------------------------- NICHT getested !!!!!
// Hier noch beide Pumpen an, zum NOTENTLADEN Boiler
// --------------------------------------------
if (Status2 and B_zu_heiss) == B_zu_heiss
{Byte_Outx = Byte_Outx or Heizungs_Pumpe;
Byte_Outx = Byte_Outx or Boilerlade_Pumpe;
}

// ----------------------------------------
// ------ Routine für Kessel ein --------
// ----------------------------------------
if (Status1 and Kessel_kalt)== Kessel_kalt // Wenn K_Temperatur zu niedrig
and // und
(
((Status1 and Heizen_ein)== Heizen_ein // Heizen ein
and ((not Byte_in ) and Mischer_zu)
)
or // oder
(
(Status1 and Boiler_laden)== Boiler_laden // Boiler will geladen werden
and
(Status2 and Boi_laden_2) != Boi_laden_2 // und Speicher NICHT heiß
) // das funktioniert noch nicht ???? Kann B zu heiß werden ?
)
// and Mischer ist auf

// or // falsch ??
// (
// (Byte_Outx and Boilerpumpe_ein)==Boilerpumpe_ein // Laden des Boilers
// and not // und
// ( Status1 and Restentleeren)==Restentleeren )) // & nicht Restentleeren

{Byte_Outx = Byte_Outx or Kessel ; // Kessel heizen
}
else
{Byte_Outx = Byte_Outx and (255-Kessel); // Kessel aus !
}


count();

// ------------------------------------------------------------
// ----------- Laderoutine für Boiler oder Speicher -----------
// Boiler nicht voll und Kollektor Einschalttemperatur : Bit 0
// ------------------------------------------------------------

if ((T_Kollektor - d[1])> T_Boiler_Unten) // Kollektor wärmer als Boiler
and (T_Boiler_Unten < d[3]-d[0]) // Boiler unter max.-dT Grad

{Status2 = Status2 or B_laden; // Boilerbit setzen
}
else
{if (T_Kollektor-d[0]) < T_Boiler_Unten // Kollektor-3 <= Boiler
or T_Boiler_Unten > d[3] // oder wenn Boiler voll!

{ Status2 = Status2 and (255-B_laden);// Boilerbit löschen
// Zeit_bis_Speicher = 0; // Wie mache ich das ????
// nur beim ausschalten
if T_Boiler_Unten > d[3] // Nur wenn Boiler zu heiss,
{Zeit_bis_Speicher = d[7]*30+5; // dann auf Zeitendwert,um direkt
} // auf Speicher zu gehen
}
} // Ende else

// -------------------------------------------------------
// ---- Immer beim/während des Boilerladen Zeit auf 0 ----
// -------------------------------------------------------
if ( Status2 and B_laden) == B_laden
{Zeit_bis_Speicher = 0; // ????
}

else // also nicht mehr Boiler
{
// -------------------------------------------------------
// Testen, ob Kollektor warm genug ist für Speicher : Bit 1
// -------------------------------------------------------
if (T_Kollektor - d[2]) > T_Speicher_Unten // Speicher ist kälter,
{
// Hochzaehlen, wenn Speicher kälter als Kollektor und die Pumpe aus ist!
if ((Alt_Sekunde != system.second()) // ungleich, d.h. Sek.-Takt
and (Zeit_bis_Speicher < (d[7]*30)+3)) // und nicht zu hoch zählen

{Zeit_bis_Speicher = Zeit_bis_Speicher +1;// Zeit hochzählen
Alt_Sekunde = system.second();
} // Ende if - Sekunden zählen

else // else Zeit abgelaufen
{ Status2 = Status2 or Sp_laden; // Wenn T abgelaufen, Speicher ein
}

} // Ende Kollektor wärmer
else
{ if (T_Kollektor - d[0]) <= (T_Speicher_Unten )// minus Ausschalthyst.
{ // Status2 = Status2 and (255-Sp_laden); siehe unten !
Zeit_bis_Speicher = (0); // Zeit auf -99 fürs Anwärmen. Man
} // könnte auch negative Werte vorgeben,
// um längere Zeiten zu bekommen
} // Ende else
// ----------------------------------------
} // Ende "Else" Boiler laden

// -----------------------------------------------------------
// -------------Stromlos geht es in den Boiler ! -------------
// ------------ Boiler-Speicher Ventil schalten --------------
// Wenn Zeit nicht abgelaufen ist, nicht in Speicher fahren !
// -----------------------------------------------------------
if Zeit_bis_Speicher < (d[7]*30+2) // Zeit warten,ob sich Kol.-Temp. erhöht
// war am 1.5.02 noch < Problem wenn T = 0 x 30 !
{Status2 = Status2 and (255-Sp_laden); // Statusbit für Speicher loeschen
Byte_Outx=Byte_Outx and (255-Boiler_Speicher); // Ventil zum SP zu
}
else
{Byte_Outx = Byte_Outx or Boiler_Speicher; // Ventil zum Speicher auf
}

// ----------------------------------------
// Kollektorpumpe starten, wenn Speicher
// oder Boiler kälter als Kollektor
// evtl. Rezirkulationsventil schalten
// ----------------------------------------
if ( Status2 and B_laden) == B_laden // Setzen der Kollektorpumpe
or (Status2 and Sp_laden)== Sp_laden // oder
or ( Byte_in and 7 ) == 1 // wenn beide vorderen Tasten

{Byte_Outx = Byte_Outx or (Kollektor_Pumpe);

//----------------------------------------------- 18.2.2002 neu
//- Schalten des Rezirkulationsventils / nur wenn Pumpe an !
//-----------------------------------------------
if (Byte_Outx and Boiler_Speicher)==Boiler_Speicher // Kollektor lädt SP
{ // Rezirkulierung bei Speicherladen
if T_Rezirkulation < T_Speicher_Unten // Leitung kälter ?
{ Byte_Outx=Byte_Outx and (255-Rezirkulation); // Rezirkulation ein
} // d.h. Strom aus
else
{ if T_Rezirkulation > T_Speicher_Unten
Byte_Outx = Byte_Outx or Rezirkulation; // Rezirkulation aus
} // d.h. Strom an !
}
else // Wenn nicht der Speicher geladen wird
{ // Rezirkulierung bei Boilerladen
if T_Rezirkulation < T_Boiler_Unten // Leitung kälter ?
Byte_Outx=Byte_Outx and (255-Rezirkulation); // Rezirkulation ein
else
{ // Rezirkulieren aus für Boiler laden !
if T_Rezirkulation > T_Boiler_Unten
Byte_Outx=Byte_Outx or Rezirkulation; // Rezirkulation aus
} // d.h. Strom an !
}

} // Ende "if" Boiler oder Speicher laden
else // else B_laden oder SP_laden
{ Byte_Outx = Byte_Outx and (255-Kollektor_Pumpe);
Byte_Outx = Byte_Outx and (255-Rezirkulation); // Rezirkulation ein
} // Ende "Else" // Ventil & Strom aus

// -------------------------------------------------
// ---- Ende der Laderoutine Boiler / Speicher ----
// -------------------------------------------------

// -------------------------------------------
// --------------- Boiler zu heiss --------- 26.10.2001
// -------------------------------------------
if T_Boiler_Oben>d[13] // Wenn Notentladen, beide Pumpen an !
{ Status2=Status2 or B_zu_heiss;
}
else
{ if T_Boiler_Oben { Status2 = Status2 and (255-B_zu_heiss);
}
}

// -------------------------------------------
// -------------Speicher zu heiss ----------- 19.1.2002
// -------------------------------------------
if T_Speicher_Unten>d[4] // Wenn Notentladen, Heiz-Pumpe an !
{ Status2=Status2 or Sp_zu_heiss;
}
else
{ if T_Speicher_Unten { Status2 = Status2 and (255-Sp_zu_heiss);
}
}
// ----------------------------------------------- Nicht fertig Byte_outx?
// -------- Speicher + Boiler zu heiss ---------
// -----------------------------------------------
if (T_Speicher_Unten>(d[4])+10)and(T_Boiler_Oben>d[13]) // Alles zu heiß,
{Byte_Outx = Byte_Outx and (255-Kollektor_Pumpe) ; // Kollektorpumpe aus !
Byte_Outx = Byte_Outx and (255-Rezirkulation) ; // Rezirkulation aus !
Byte_Outx = Byte_Outx and (255-Boiler_Speicher) ; // Ventil zum Speicher zu
}
//
/* ------------------------------------------ */
/* ----- Ausgänge manipuliern ------------- */
/* ------------------------------------------ */
if d[10] and Modus4 // Ist Modusbit 2 gesetzt ?
{ Byte_Outx = Byte_Outx or d[11]; // Bits evtl. setzen
Byte_Outx = Byte_Outx and d[12]; // Bits evtl. löschen
}

// ----------------------------------------
// Schreiben auf den Ausgabeport (Eigenbau)
// ----------------------------------------
IO_Write(Byte_Outx);
//-----------------------------------------


// ---------------------------------------- nicht wirklich getestet !!
// --- Rücklaufanhebung / Relais1 ---------
// --- Testen der Pumpenrelais --------
// ----------------------------------------
if ((Status1 and Ruecklaufanhebung)==Ruecklaufanhebung) // Speicher heißer
and // als Rücklauf ?
(((Byte_Outx and Boilerlade_Pumpe) == Boilerlade_Pumpe) // Testen, ob
or ((Byte_Outx and Heizungs_Pumpe) == Heizungs_Pumpe)) // Pumpen laufen

{ Byte_Outy = Byte_Outy or Relais_1; // Wenn ja, Ventil auf
}

else
{ Byte_Outy = Byte_Outy and (255-Relais_1); // sonst zu
}
// ----------------------------------------

// ----------------------------------------
// Beleuchtung ein / Ausgabeport WSO
// ----------------------------------------
if Merker != 0 // Wenn Zaehler läuft, dann Beleuchtung ein
or ( (not Byte_in ) and 2 ) // oder Taste vorne links
{ Byte_Outy = Byte_Outy or LCD_Beleuchtung;
}

else
{ Byte_Outy = Byte_Outy and (255-LCD_Beleuchtung);
}
// ----------------------------------------

// ------------------------------------------
// ------ Ausgabe auf WS-Board -------
// ------------------------------------------
WSO_write(Byte_Outy);


// ------------------------------------------
// ------ Spannung aus der Sensoren -------
// ------------------------------------------
if Alt_Minute != system.minute() // Wenn 5 min um,
{
if system.minute()%5 ==0

{ DS_reset_all();
count();
sleep(800);
count();
Alt_Minute = system.minute(); // jetzt wird beides gleich !
}
}

/* ------------------------------------------ */
/* ------ Speichern bei Tageswechsel ------- */ // am 16.4. von "<" auf "!="
/* ------------------------------------------ */ // geändert
if Alt_Tag != system.day() // Wenn neuer Tag dann speichern
{ if Alt_Tag > 1 // Nicht beim Einschalten
EEprom_Write(); // sonst jedesmal bei Neustart!
Alt_Tag = system.day(); // jetzt wird beides gleich !
}

/* ------------------------------------------ */
count (); // evtl. Zeiten hochzählen
/* ------------------------------------------ */

} // Ende Loop
} // Ende Thread