'##############################################################################
' ZisterneFuellstandsanzeige.BAS                               Stand 10.05.2009
' ------------------------------                               (C) Markus Fulde
'
' Gesamtsoftware Steuerprogramm für Zisternen-Füllstandsanzeige
'
' Das Projekt verfügt über die folgenden einzelnen Funktions- und
' Teilkomponenten:
'     - Spannungsversorgung für +5V
'     - Mikrocontroller ATmega16 (inkl. ISP, RS232 und Reset)
'     - LCD-Display 1x16
'     - 3 Taster und Schalter
'     - LED-Anzeigen für Funktionsanzeige
'     - I2C Ultraschall-Modul für Füllstandsmessung
'     - 1-Wire Temperatursensor für Wassertemperatur
'
'     - Funktions- und Debug-Steuerung über RS232
'
'##############################################################################

'------------------------------------------------------------------------------
' Compilerinstruktionen und Compilerdirektiven
'------------------------------------------------------------------------------
$regfile = "m16def.dat"                                     ' Definitionsdatei für ATmega128 laden
$crystal = 16000000                                         ' Quarzfrequenz für 16 MHz festlegen
$hwstack = 128                                              ' HW-Stack auf 128 Bytes erweitern
$swstack = 64                                               ' SW-Stack auf 64 Bytes erweitern
$framesize = 80                                             ' Framesize auf 80 Byte festlegen

' Serielle Schnittstelle wird für Tracedatenausgabe verwendet
' $baud = 38400                                               ' Baudrate für RS232 auf 38400 Bauf festlegen
' Hinweis: Direktive nicht notwendig da Konfiguration über CONFIG

'------------------------------------------------------------------------------
' Allgemeine Zusatzinformatonen zu Programmbeginn
'------------------------------------------------------------------------------

' ASCII Table (Incomplete)
' Decimal  Hex    Binary       Value   Beschreibung
' -------  ---    --------     -----   ------------------
' 000      000    00000000     NUL     (Null char.)
' 008      008    00001000     BS      (Backspace)
' 009      009    00001001     HT      (Horizontal Tab)
' 010      00A    00001010     LF      (Line Feed)
' 012      00C    00001100     FF      (Form Feed)
' 013      00D    00001101     CR      (Carriage Return)
' 032      020    00100000     SPACE   (Leerzeichen)
' 048      030    00110000     0       (Beginn der Ziffern)
' 049      031    00110001     1       (..)
' 052      034    00110100     4       (..)
' 065      041    01000001     A       (Beginn der Zeichen)
' 066      042    01000010     B       (..)
' 067      043    01000011     C       (..)

'------------------------------------------------------------------------------
' Definition von Ressourcen
'------------------------------------------------------------------------------

' ----- KEY: Tasten -----

' Tastenport
Tastenport Alias Pind

' Taste 1
Taste1_pin Alias Pind.5                                     ' GPIO für KEY1 (für DDR oder Input)
Taste1 Alias Portd.5                                        ' GPIO für KEY1 (für Output oder PullUp)

' Taste 2
Taste2_pin Alias Pind.6                                     ' GPIO für KEY2 (für DDR oder Input)
Taste2 Alias Portd.6                                        ' GPIO für KEY2 (für Output oder PullUp)

' Taste 3
Taste3_pin Alias Pind.7                                     ' GPIO für KEY3 (für DDR oder Input)
Taste3 Alias Portd.7                                        ' GPIO für KEY3 (für Output oder PullUp)

' ----- LED: Anzeige-LED's -----
' LED1 = Wasserstandsmessung
Led1_pin Alias Pinc.5                                       ' GPIO für LED1 (für DDR oder Input)
Led1 Alias Portc.5                                          ' GPIO für LED1 (für Output oder PullUp)

' LED2 = Temperaturmessung
Led2_pin Alias Pinc.4                                       ' GPIO für LED2 (für DDR oder Input)
Led2 Alias Portc.4                                          ' GPIO für LED2 (für Output oder PullUp)

' ----- LCD: Display -----
' Port und Pin für LCD Hintergrundbeleuchtung
Lcd_light_pin Alias Pina.7                                  ' um Hintergrundbeleuchtung einzuschalten (für DDR oder Input)
Lcd_light_dataout Alias Porta.7                             ' um LCD einzuschalten einzuschalten (für Output oder PullUp)

'------------------------------------------------------------------------------
' Definition von Konstaten
'------------------------------------------------------------------------------

' ----- Für Testumgebung bzw. Traceausgaben -----
Const Main_testmodus = 0                                    ' Flag für Testmodus Allgemeinsystem
Const Lcd_testmodus = 0                                     ' Flag für Testmodus LCD-Dispaly
Const Sectick_testmodus = 0                                 ' Flag für Testmodus Sekunden-Tick
Const Key_testmodus = 0                                     ' Flag für Testmodus Tastensteuerung
Const Vol_testmodus = 1                                     ' Flag für Testmodus Volumenberechnung
Const Konvert_testmodus = 0                                 ' Flag für Konvertierungstestmodus
Const Temp_testmodus = 0                                    ' Flag für Testmodus Temperaturmessung

' ----- LCD:  Für LCD-Display -----
' LCD: Konstanten für LCD-Kontrast (Range 0-63 / 6 Bit)
Const Lcd_kontrast_default = 20                             ' Default Kontrast empirisch ermittelt
Const Lcd_abschaltzeit = 10                                 ' Defaultwert auf 10 Sekunden festgelegt

' ----- KEY: Tasten -----
Const Key_mask = &B11100000                                 ' Maskierung für Tastenbits auf Portbyte
Const Tastenentprellung = 50                                ' Entprellung in ms

' ----- Allgemeine Konstanten -----
' Boolsche Variablen
Const True = 1                                              ' Boolsche Variable TRUE
Const False = 0                                             ' Boolsche Variable FALSE

' ----- Füllstandsanzeige -----
Const Vol_luftstrecke = 25                                  ' Luftstrecke von Sensor zu Wasseroberfläche
Const Vol_konvertierungswerte = 130                         ' Anzahl an Konvertierungswerten
Const Fuellstand_data = 140                                 ' Anzahl der Datenwerte in Konvertierungstabelle

' ----- Slave -----
Const Slave_responde_delay = 5                              ' Timeout bs Slave antworten muss

'------------------------------------------------------------------------------
' Definition von Variablen und Datentypen
'------------------------------------------------------------------------------

' ----- KEY: Tasten -----
Dim Key_released_flag As Bit                                ' Variable zur Entprellung

' ----- LCD:  Für LCD-Display -----

' Variablen für Lcd_kontrastwerte deklarieren und mit Default laden
Dim Lcd_kontrastwert As Byte                                ' Kontrastwert für LCD-Display
Dim Lcd_abschaltcounter As Word                             ' Variable für Abschaltzeitpunkt

' ----- VOL: Füllstand -----
Dim Vol_result_string_liter As String * 9                   ' Globaler Ergebnisstring für Literangabe
Dim Vol_result_string_prozent As String * 9                 ' Globaler Ergebnisstring für Prozent

' ----- MENUE: Anzeigemenü -----
Dim Anzeige_flag As Bit                                     ' Steuervariable für Anzeige
' 0 bedeutet Prozentangabe
' 1 bedeutet Literangabe

' ----- TEMP: Temperatur -----
Dim Temp_result_string As String * 9                        ' Globaler Ergebnisstring für Temperatur
Dim Temp_error_flag As Byte                                 ' Errorflag für Temperaturmessung
Dim Temp_messwert As Integer                                ' Globaler Rohwert für Temperatur

' ----- SRF: Ultraschallsensor -----
Dim Srf_result_struct(17) As Word                           ' Array für Echo-Daten
Dim Srf_error_flag As Byte                                  ' Errorflag für Wasserstandsmessung

' ----- Sekundentakt für System -----
Dim Sectick_counter As Word                                 ' Globaler Sekundenzähler

' ggf. Tracedaten ausgeben um Timer zu testen
#if Sectick_testmodus
   Dim Sectick_counter_old As Word
   Sectick_counter = 0
#endif

' ----- Allgemeine systembedingte globale Variablen -----

' temporäre globale Arbeitsvariablen
Dim Temp_byte_1 As Byte                                     ' Temporäre Byte-Variable 1
Dim Temp_byte_2 As Byte                                     ' Temporäre Byte-Variable 2
Dim Temp_byte_3 As Byte                                     ' Temporäre Byte-Variable 3

Dim Temp_word_1 As Word                                     ' Temporäre Word-Variable 1
Dim Temp_word_2 As Word                                     ' Temporäre Word-Variable 2
Dim Temp_word_3 As Word                                     ' Temporäre Word-Variable 3

Dim Temp_string_1 As String * 20                            ' Temporäre String Variable 1

Dim Temp_single_1 As Single                                 ' Temporäre Single Variable 1

'------------------------------------------------------------------------------
' Prototyping
'------------------------------------------------------------------------------

' ========== Funktionen ==========

' ----- Allgemeine Funktionen -----
Declare Function Byte2string(byval Value As Byte , Byval Character As Byte) As String
Declare Function Word2string(byval Value As Word , Byval Character As Byte , Byval Length As Byte) As String

'------------------------------------------------------------------------------
' Konfiguration und Basiseinstellungen (Projekt und Testumgebung)
'------------------------------------------------------------------------------

' ----- Variablen und Werte -----

' Globaler Sekundenzähler initialisieren
Sectick_counter = 0

' Flag für Tastensteuerung initialisieren
Key_released_flag = False

' Messwerte vorinitialisieren bzw. Ergebnisstring vorbelegen
Temp_result_string = " ----{223}"
Vol_result_string_liter = "----l"
Vol_result_string_prozent = "----%"

' Menueeinstellungen
Anzeige_flag = 0                                            ' Anzeige erfolgt bei Start in Prozent

' Ultraschallsensor
Srf_error_flag = False                                      ' Fehlerflag auf NO-ERROR

' Temperatursensor
Temp_error_flag = False                                     ' Fehlerflag auf NO-ERROR

' ----- CONFIG -----

' Hardware RS232 Kanal 1 konfigurieren = interne RS232
Config Com1 = 38400 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Config Serialin = Buffered , Size = 128
Open "com1:" For Binary As #1

' Software RS232 Kanal 2 und 3 konfigurieren = externe RS232
' Anschluss an Mega16 über PORTB.0 für RxD und PORTB.1 für TxD.

' Achtung: Tracesausgaben zum PC erfolgen über SW-RS232. Die HW-RS232 wird zur
' Kommunikation mit dem Slave verwendet

' Öffnen eines Transmit-Kanals (#2) für Ausgaben
Open "comb.1:38400,8,n,1" For Output As #2

' Öffnen eines Receive-Kanals (#3) für Eingaben
Open "comb.0:38400,8,n,1" For Input As #3

' ggf. Traceausgaben ausgeben
#if Main_testmodus
   ' Systemstart auf RS232 ausgeben
   Print #2 , "** Iginiton sequence start **"
#endif

' LCD-Display konfigurieren
' Ausgang definieren und Displaybeleuchtung einschalten
Config Lcd_light_pin = Output
Gosub Lcd_beleuchtung_an

' Konfiguration LCD Display
Config Lcdpin = Pin , Db4 = Porta.0 , Db5 = Porta.1 , Db6 = Porta.2 , Db7 = Porta.3 , E = Porta.4 , Rs = Porta.5
Config Lcd = 16 * 3 , Chipset = Dogm163v5                   ' DOG-M Treiber laden
Config Lcdbus = 4                                           ' LCD arbeitet über 4-Bit
Initlcd                                                     ' LCD initialisieren
Waitms 100                                                  ' 100ms nach Init warten
Cursor Off Noblink                                          ' Blinkenden Cursor abschalten
Cls                                                         ' Clear Screen

' Erstes Lebenszeichen auf Display schreiben
Locate 1 , 3 : Lcd "INIT"
Waitms 500

' Konfiguration des 1 Sekunden-Timers für LED-Toggle-Funktion
Config Timer1 = Timer , Prescale = 256
On Timer1 Sekunden_tick

' Timer aktivieren und Interrupts freigeben
Enable Timer1
Enable Interrupts

' ----- Port's und Pin's -----

' LCD:  LCD-Display
Lcd_kontrastwert = Lcd_kontrast_default                     ' Kontrastwert

' LED: LED's
Config Led1_pin = Output                                    ' Ausgang konfigurieren
Config Led2_pin = Output                                    ' Ausgang konfigurieren

' KEY: Tasten
Config Taste1_pin = Input                                   ' Eingang konfigurieren
Config Taste2_pin = Input                                   ' Eingang konfigurieren
Config Taste3_pin = Input                                   ' Eingang konfigurieren

' PullUps werden via default aktiviert. PullUp sind in Beschaltung vorgesehen
' darum hier PullUp deaktivieren
Taste1 = 0 : Taste2 = 0 : Taste3 = 0

' ----- Gosub's -----

' LCD: Routinen und Einstellungen
Gosub Lcd_kontrastset                                       ' Kontrast noch einstellen

' #############################################################################
'
'                             Hauptprogramm ConvCtrl
'
' #############################################################################

' Controll-Output schreiben und los's gehts
#if Main_testmodus                                          ' Trace
   Print #2 , ""
   Print #2 , "** Enter MainLoop **"
   Print #2 , ""
#endif                                                      ' Trace

' Menü-LED's kurz blinken lassen
For Temp_byte_1 = 1 To 3
   Led1 = 1 : Led2 = 1
   Waitms 100
   Led1 = 0 : Led2 = 0
   Waitms 100
Next Temp_byte_1                                            ' LED's blinken lassen

' Display löschen und Startposition ausgeben
Cls                                                         ' Clear Screen
Lcd "Bereit !"

Lcd_abschaltcounter = Sectick_counter + Lcd_abschaltzeit

' ----------------------------------------------
' ----- Hier ist die Programmhauptschleife -----
' ----------------------------------------------

Do

   ' ----- Tastenauswertung -----
   ' Taste 1: Umschalten auf Wasserstandsmessung und Messung durchführen
   ' Taste 2: Umschalten auf Temperaturmessung und Messung durchführen
   ' Taste 3: Umschalten zwischen Anzeigemodus Liter und Prozent
   ' Taste 1+2+3: Ausgabe der Versionsinfo

   ' Debounce Taste1_pin , 0 , Key_taste1_request , Sub
   ' Abfrage Taste 2 und Ansprung Auswerteroutine für Taste 2
   ' Debounce Taste2_pin , 0 , Key_taste2_request , Sub
   ' Abfrage Taste 3 und Ansprung Auswerteroutine für Taste 3
   ' Debounce Taste3_pin , 0 , Key_taste3_request , Sub

   ' Gesamten Port an dem die Tasten hängen einlesen
   Temp_byte_1 = Tastenport
   ' Bits zur sauberen Auswertung drehen
   Temp_byte_1 = Temp_byte_1 Xor Key_mask
   ' Relevante Tasten maskieren
   Temp_byte_1 = Temp_byte_1 And Key_mask

   ' Prüfen ob Taste betätig und ggf. Released-Flag zurücksetzen
   If Temp_byte_1 <> 0 Then

      ' Prüfen ob Tasten in der Zwischenzeit losgelassen
      If Key_released_flag = False Then
         ' Ja, Tasten wurden zwischenzeitlich losgelassen

         ' Es wurde eine Taste betätigt, damit Entprellung und Kontrolle
         Waitms Tastenentprellung

         ' Tasten erneut einlesen und Kontrolle

         ' Gesamten Port an dem die Tasten hängen einlesen
         Temp_byte_2 = Tastenport
         ' Bits zur sauberen Auswertung drehen
         Temp_byte_2 = Temp_byte_2 Xor Key_mask
         ' Relevante Tasten maskieren
         Temp_byte_2 = Temp_byte_2 And Key_mask

         ' Prüfen ob immer noch Tasten betätigt

         If Temp_byte_2 <> 0 Then
            ' Ja, es sind immer noch Tasten betätigt

            ' Flag setzen
            Key_released_flag = True

            ' Taste auswerten

            Select Case Temp_byte_2

               ' Taste 1 = Wasserstand
               Case 32:
                  Gosub Key_taste1_request

               ' Taste 2 = Temperatur
               Case 64:
                  Gosub Key_taste2_request

               ' Taste 3 = Wasserstandmodus Liter/Prozent
               Case 128:
                  Gosub Key_taste3_request

               ' Taste 1+2+3 = Versionsinfo
               Case 224:
                  Gosub Version_output

            End Select                                      ' Temp_byte_2
         End If                                             ' Tastendruck nach Wartezeit
      End If                                                ' Released Flag
   Else                                                     ' Keine Taste
      ' Flag zurücksetzen
      Key_released_flag = False
   End If                                                   ' Initialer Tastendruck

   ' ----- Virtuelle Steuerung über RS232 -----
   #if Main_testmodus
      ' Tastaturabfrage und Auswertung

      ' Mit Inkey SW-UART nach Zeichen abfragen
      Temp_byte_1 = Inkey(#3)

      ' Ist ein Zeichen vorhanden?
      If Temp_byte_1 > 0 Then
         ' JA, dann Zeichen auswerten

         Select Case Temp_byte_1:
            '--- LCD Testpunkt ---

            ' Taste 'a'
            Case 97 :
               Print #2 , "Funktion: LCD Beleuchtung einschalten"
               Gosub Lcd_beleuchtung_an

            ' Taste 'b'
            Case 98 :
               Print #2 , "Funktion: LCD Beleuchtung ausschalten"
               Gosub Lcd_beleuchtung_aus

            ' Taste 'c'
            Case 99 :
               Print #2 , "Funktion: LCD Display einschalten"
               Gosub Lcd_display_on

            ' Taste 'd'
            Case 100 :
               Print #2 , "Funktion: LCD Display ausschalten"
               Gosub Lcd_display_off

            ' Taste 'e'
            Case 101 :
               Print #2 , "Funktion: Messkommando Fuellstand an Slave senden"
               Print #1 , "{001}"                           ' Füllstand messen

            ' Taste 'f'
            Case 102 :
               Print #2 , "Funktion: Messkommando Temperatur an Slave senden"
               Print #1 , "{002}"                           ' Temperatur messen

            ' Taste 'g'
            Case 103:
               Print #2 , "Funktion: Konvertierungstabelle einlesen und ausgeben"
               Gosub Vol_konvertierungstabelle

            ' Taste 'h'
            Case 104:
               Print #2 , "Funktion: Füllstand messen und Ergebnisstring berechnen"
               Gosub Vol_measurement

            ' Taste 'i'
            Case 105:
               Print #2 , "Funktion: Temperatur messen und Ergebnisstring berechnen"
               Gosub Temp_measurement

         End Select                                         ' Eingelesene Funktion über Temp_byte_2
         Print #2 , ""                                      ' Leerzeile ausgeben
      End If                                                ' Wurde ein Zeichen erkannt?
   #endif

   ' ----- Sectick Auswertung -----
   #if Sectick_testmodus
      Temp_word_1 = Sectick_counter_old + 1
      If Sectick_counter = Temp_word_1 Then
            Print #2 , "Sectick: " ; Sectick_counter
         Sectick_counter_old = Sectick_counter
      End If                                                ' Sekunden-Tick Update
   #endif

   If Lcd_abschaltcounter = Sectick_counter Then
      Gosub Lcd_beleuchtung_aus
      Gosub Lcd_display_off
   End If                                                   ' LCD Abschaltzeitpunkt erreicht
Loop

'## End Hauptprogramm #########################################################

'******************************************************************************
' Interruptroutinen
'******************************************************************************

'------------------------------------------------------------------------------
' Interrupt-Service-Routine (Timer1): Sekunden_tick
' Routine zur Auswertung des Timer Interrupts
'------------------------------------------------------------------------------
Sekunden_tick:

   ' Timervariable erhöhen
   Incr Sectick_counter

Return
'-- End Sekunden_tick ---------------------------------------------------------

'******************************************************************************
' Funktionen
'******************************************************************************

'------------------------------------------------------------------------------
' Function: Byte2string
' Funktion liefert als Ergebnis eine "rechtsbündig" formatierten String einer
' übergebenen Byte-Variablen. Der String ist max. 3 Zeichen groß und beinhaltet
' ggf. bei kleineren Zahlen das übergebene Character als Füllzeichen von links
' führend aufgefüllt.
'
' Parameter:    Value     = Byte das als SString formatiert werden soll
'               Character = ASCII-Wert des Zeichens mit dem ggf. aufgefüllt
'               werden soll.
' Rückgabewert: String der Byte-Variablen inkl. Füllzeichen
'------------------------------------------------------------------------------
Function Byte2string(byval Value As Byte , Byval Character As Byte) As String

   ' ----- lokale Variablen -----
   Local String_length As Byte
   Local Process_string As String * 4

   ' ----- Programmcode -----

   #if Konvert_testmodus
      Print #2 , "Enter Byte2string"
   #endif

   ' Basis-String anlegen
   Process_string = Str(value)
   ' Länge ermitteln
   String_length = Len(process_string)

   ' Abhängig von Länge Füllzeichen ergänzen
   Select Case String_length
      Case 1:
         ' Wenn Länge 1 müssen zwei Füllzeichen links ergänzt werden
         Process_string = Chr(character) + Process_string
         Process_string = Chr(character) + Process_string
      Case 2:
         ' Wenn Länge 2 muss ein Füllzeichen links ergänzt werden
         Process_string = Chr(character) + Process_string
   End Select                                               ' Stringlänge

   ' Bearbeiteter String an Übergabeparameter übergeben
   Byte2string = Process_string

End Function
'-- End Byte2string -----------------------------------------------------------

'------------------------------------------------------------------------------
' Function: Word2string
' Funktion liefert als Ergebnis eine "rechtsbündig" formatierten String einer
' übergebenen Word-Variablen. Der String ist max. n Zeichen groß und beinhaltet
' ggf. bei kleineren Zahlen das übergebene Character als Füllzeichen von links
' führend aufgefüllt.
'
' Parameter:    Value     = Byte das als String formatiert werden soll
'               Character = ASCII-Wert des Zeichens mit dem ggf. aufgefüllt
'               werden soll.
'               Length    = Länge des String der mit dem Word gefüllt werden soll
' Rückgabewert: String der Byte-Variablen inkl. Füllzeichen
'------------------------------------------------------------------------------
Function Word2string(byval Value As Word , Byval Character As Byte , Byval Length As Byte) As String

   ' ----- lokale Variablen -----
   Local String_length As Byte
   Local Process_string As String * 6
   Local Index As Byte

   ' ----- Programmcode -----

   #if Konvert_testmodus
      Print #2 , "Enter Word2string"
   #endif

   ' Basis-String anlegen
   Process_string = Str(value)
   ' Länge ermitteln
   String_length = Len(process_string)

   ' Abhängig von Länge Füllzeichen ergänzen
   If String_length < 5 Then
      ' JA, Länge muss korrigiert werden
      String_length = 5 - String_length
      For Index = 1 To String_length
         Process_string = Chr(character) + Process_string
      Next Index
   End If

   ' Ergebnisstring beschneiden
   Process_string = Right(process_string , Length)

   ' Bearbeiteter String an Übergabeparameter übergeben
   Word2string = Process_string

End Function
'-- End Word2string -----------------------------------------------------------

'******************************************************************************
' GOSubroutinen
'******************************************************************************

' ********************
' * KEY: Tasten      *
' ********************

'------------------------------------------------------------------------------
' KEY - Gosub-Routine: Key_taste1_request
' Routine wird bei Betätigung von Taste 1 angesprungen und steuern Ablauf
'------------------------------------------------------------------------------
Key_taste1_request:

   ' Wenn Konstante gesetzt Trace Output schreiben
   #if Key_testmodus                                        ' Trace
      Print #2 , "Enter Key_taste1_request"
   #endif                                                   ' Trace

   ' LCD-Display wieder einschalten und Abschaltzeit neu setzen
   Lcd_abschaltcounter = Sectick_counter + Lcd_abschaltzeit
   Gosub Lcd_beleuchtung_an
   Gosub Lcd_display_on

   ' Status aus LED ausgeben
   Led1 = 1 : Led2 = 0                                      ' Menümodus ist Wasserstand messen

   ' Display löschen und Wartezeile ausgeben
   Cls
   '    12345678
   ' Lcd "T: wait!" ' Messung geht sehr schnell daher keine Anzeige notwendig!!

   ' Wasserstandsmessung beginnen und Ergebnis ausgeben
   Gosub Vol_measurement

   ' Ergebnis aus globalem String ausgeben
   Cls

   ' Abhängig von Anzeige Messwert in Liter oder Prozent ausgeben
   Select Case Anzeige_flag
      Case 0:
         ' Anzeige erfolgt in Prozent
         Lcd "W: " ; Vol_result_string_prozent
      Case 1:
         ' Anzeige erfolgt in Liter
         Lcd "W: " ; Vol_result_string_liter
   End Select                                               ' Anzeige_flag

Return
'-- End Key_taste1_request ----------------------------------------------------

'------------------------------------------------------------------------------
' KEY - Gosub-Routine: Key_taste2_request
' Routine wird bei Betätigung von Taste 2 angesprungen und steuern Ablauf
'------------------------------------------------------------------------------
Key_taste2_request:

   ' Wenn Konstante gesetzt Trace Output schreiben
   #if Key_testmodus                                        ' Trace
      Print #2 , "Enter Key_taste2_request"
   #endif                                                   ' Trace

   ' LCD-Display wieder einschalten und Abschaltzeit neu setzen
   Lcd_abschaltcounter = Sectick_counter + Lcd_abschaltzeit
   Gosub Lcd_beleuchtung_an
   Gosub Lcd_display_on

   ' Status aus LED ausgeben
   Led1 = 0 : Led2 = 1                                      ' Menümodus ist Temperatur erfassen

   ' Display löschen und Wartezeile ausgeben
   Cls
   Lcd "T: wait!"

   ' Temperaturmessung beginnen und Ergebnis ausgeben
   Gosub Temp_measurement

   ' Ergebnis aus globalem String ausgeben
   Cls
   Lcd "T:" ; Temp_result_string

Return
'-- End Key_taste2_request ----------------------------------------------------

'------------------------------------------------------------------------------
' KEY - Gosub-Routine: Key_taste3_request
' Routine wird bei Betätigung von Taste 3 angesprungen und steuern Ablauf
'------------------------------------------------------------------------------
Key_taste3_request:

   ' Wenn Konstante gesetzt Trace Output schreiben
   #if Key_testmodus                                        ' Trace
      Print #2 , "Enter Key_taste3_request"
   #endif                                                   ' Trace

   ' LCD-Display wieder einschalten und Abschaltzeit neu setzen
   Lcd_abschaltcounter = Sectick_counter + Lcd_abschaltzeit
   Gosub Lcd_beleuchtung_an
   Gosub Lcd_display_on

   ' Status aus LED ausgeben
   Led1 = 1 : Led2 = 0                                      ' Menümodus ist Wasserstand anzeigen

   ' Anzeigemodus Wassersstandmessung umschalten und letztes Messergebnis ausgeben

   ' Anzeige umschalten und Bildschirm löschen
   Toggle Anzeige_flag
   Cls

   ' Abhängig von Anzeige Messwert in Liter oder Prozent ausgeben
   Select Case Anzeige_flag
      Case 0:
         ' Anzeige erfolgt in Prozent
         Lcd "W: " ; Vol_result_string_prozent
      Case 1:
         ' Anzeige erfolgt in Liter
         Lcd "W: " ; Vol_result_string_liter
   End Select                                               ' Anzeige_flag

Return
'-- End Key_taste3_request ----------------------------------------------------

' ********************
' * LCD:  Display    *
' ********************

'------------------------------------------------------------------------------
' LCD - Gosub-Routine: Lcd_display_ein
' Routine schaltet das gesamte Display ein
'------------------------------------------------------------------------------
Lcd_display_on:

   ' Wenn Konstante gesetzt Trace Output schreiben
   #if Lcd_testmodus                                        ' Trace
      Print #2 , "Enter Lcd_display_ein"
   #endif                                                   ' Trace

   ' Instruction Display ON/OFF gemäß LCD Befehlskatalog
   _temp1 = &B00001100
   !Call _Lcd_control

Return
'-- End Lcd_display_ein -------------------------------------------------------

'------------------------------------------------------------------------------
' LCD - Gosub-Routine: Lcd_display_aus
' Routine schaltet das gesamte Display aus
'------------------------------------------------------------------------------
Lcd_display_off:

   ' Wenn Konstante gesetzt Trace Output schreiben
   #if Lcd_testmodus                                        ' Trace
      Print #2 , "Enter Lcd_display_aus"
   #endif                                                   ' Trace

   ' Instruction Display ON/OFF gemäß LCD Befehlskatalog
   _temp1 = &B00001000
   !Call _Lcd_control

Return
'-- End Lcd_display_ein -------------------------------------------------------

'------------------------------------------------------------------------------
' LCD - Gosub-Routine: Lcd_beleuchtung_an
' Routine schaltet die Hintergrundbeleuchtung für das Display an
'------------------------------------------------------------------------------
Lcd_beleuchtung_an:

   ' Wenn Konstante gesetzt Trace Output schreiben
   #if Lcd_testmodus                                        ' Trace
      Print #2 , "Enter Lcd_beleuchtung_an"
   #endif                                                   ' Trace

   Lcd_light_dataout = 1

Return
'-- End Lcd_beleuchtung_an ----------------------------------------------------

'------------------------------------------------------------------------------
' LCD - Gosub-Routine: Lcd_beleuchtung_aus
' Routine schaltet die Hintergrundbeleuchtung für das Display aus
'------------------------------------------------------------------------------
Lcd_beleuchtung_aus:

   ' Wenn Konstante gesetzt Trace Output schreiben
   #if Lcd_testmodus                                        ' Trace
      Print #2 , "Enter Lcd_beleuchtung_aus"
   #endif                                                   ' Trace

   Lcd_light_dataout = 0

Return
'-- End Lcd_beleuchtung_aus ---------------------------------------------------

'------------------------------------------------------------------------------
' LCD - Gosub-Routine: Lcd_contrastset
' Routine berechnen neue Kontrastwerte und steuert direkt den
' Kontroller des Display an.
'------------------------------------------------------------------------------
Lcd_kontrastset:                                            ' Kontrasteinstellung Display

   ' Wenn Konstante gesetzt Trace Output schreiben
   #if Lcd_testmodus                                        ' Trace
      Print #2 , "Enter Lcd_kontrastset" ; Lcd_kontrastwert
   #endif                                                   ' Trace

   ' Verarbeitung des Kontrastwertes für High-Byte und Low-Byte
   Temp_byte_1 = Lcd_kontrastwert And &B00001111
   Temp_byte_1 = Temp_byte_1 + &B01110000

   Temp_byte_2 = Lcd_kontrastwert
   Shift Temp_byte_2 , Right , 4
   Temp_byte_2 = Temp_byte_2 And &B00000011
   Temp_byte_2 = Temp_byte_2 + &B01010100

   ' Achtung: rCall muss durch Call ersetzen werden. rCall ist ein relavtiver
   ' Sprung welcher nur über 2kByte Zeilen geht. Die LCD-Lib liegt aber Auf-
   ' grund der Code-Größe außerhalb des Bereichs und kann deshalb nicht mehr
   ' angesprungen werden.
   ' Error 220: Forward jump out of range

   ' Instruction Table 1 einstellen [0,1]
   _temp1 = &B00101001
   '!rCall _Lcd_control
   !Call _Lcd_control

   ' Tempvar_1 = &B0111xxxx für Kontrast Set Instruction Table 1 - Low Byte
   _temp1 = Temp_byte_1
   '!rCall _Lcd_control
   !Call _Lcd_control

   ' Temovar_2 = &B010101xx für Kontrast Set Instruction Table 1 - High Byte
   _temp1 = Temp_byte_2
   '!rCall _Lcd_control
   !Call _Lcd_control

   ' Zurückschalten auf Instruction Table 0 [0,0]
   _temp1 = &B00101000
   '!rCall _Lcd_control
   !Call _Lcd_control

Return
'-- End Lcd_kontrastset -------------------------------------------------------

' *********************
' * Füllstandsanzeige *
' *********************

'------------------------------------------------------------------------------
' Gosub-Routine: Vol_konvertierungstabelle
' Routine liest Konvertierungstabelle für Volumenrechnung ein und gibt diese
' aus
'------------------------------------------------------------------------------
Vol_konvertierungstabelle:

   ' Wenn Konstante gesetzt Trace Output schreiben
   #if Vol_testmodus                                        ' Trace
      Print #2 , "Enter Vol_konvertierungstabelle"
   #endif                                                   ' Trace

   ' Überschrift ausgeben
   Print #2 , "Konvertierungstabelle:"
   Print #2 , "=====================:"
   Print #2 , ""

   Restore Fuellstand

   ' Werte einlesen
   For Temp_byte_1 = 1 To Fuellstand_data

      Read Temp_byte_2
      Read Temp_word_1
      Read Temp_byte_3

      Print #2 , "Wert " ; Temp_byte_1 ; " :" ;
      Print #2 , "  Abstand=" ; Temp_byte_2 ;
      Print #2 , "  Volumen=" ; Temp_word_1 ;
      Print #2 , "  Prozent=" ; Temp_byte_3
   Next Temp_byte_1                                         ' Zähler Konvertierungswerte
Return
'-- End Vol_konvertierungstabelle ---------------------------------------------

'------------------------------------------------------------------------------
' Gosub-Routine: Vol_measurement
' Routine sendet Messkommando an Slave und liest Messwerte ein. Messwerte
' werden verrechnet und entsprechender Füllstand ermittelt
'------------------------------------------------------------------------------
Vol_measurement:

   ' Wenn Konstante gesetzt Trace Output schreiben
   #if Vol_testmodus                                        ' Trace
      Print #2 , "Enter Vol_measurement"
   #endif                                                   ' Trace

   ' Ergebnisstrings vorbereiten
   Vol_result_string_liter = "----l"
   Vol_result_string_prozent = "----%"

   ' Fehlerflag zurücksetzen
   Srf_error_flag = False

   ' Messkommando an Slave senden
   ' Wenn Konstante gesetzt Trace Output schreiben
   #if Vol_testmodus                                        ' Trace
      Print #2 , "Funktion: Messkommando Fuellstand an Slave senden"
   #endif                                                   ' Trace
   Print "{001}"                                            ' Füllstand messen

   Temp_word_1 = Sectick_counter + Slave_responde_delay     ' Timeout aufziehen
   ' Daten von Slave lesen

   ' Arbeitsstring vorbereiten
   Temp_string_1 = ""

   Do
      ' RS232 Buffer lesen
      Temp_byte_1 = Ischarwaiting(#1)

      ' Prüfen ob Zeichen wartet
      If Temp_byte_1 <> 0 Then
         ' JA es wartet ein Zeichen

         ' Wenn Konstante gesetzt Trace Output schreiben
         #if Vol_testmodus                                  ' Trace
            Print #2 , "Zeichen wartet"
         #endif

         ' Flag auf Erfolgreich setzen und Do-Loop schon verlassen
         Srf_error_flag = True
         Exit Do
      End If                                                ' Pürfung ob Zeichen wartet
   Loop Until Temp_word_1 = Sectick_counter                 ' Timeout

   ' Prüfen ob Fehler aufgetreten
   If Srf_error_flag = False Then
      ' JA, es ist ein Fehler aufgetreten

      ' Wenn Konstante gesetzt Trace Output schreiben
      #if Vol_testmodus                                     ' Trace
         Print #2 , "Fehler erkannt, Leerstring bleibt gesetzt"
      #endif

   Else                                                     ' Fehlerüberprüfung
      ' Kein Fehler, also alle 17 Datenwerte lesen

      ' Anmerkung:
      ' Die Übertragung der Daten vom Slave zum Master wird über eine normale
      ' Printfunktion ausgeführt damit die Daten lesbar / tracebar sind.
      ' Die Printfunktion fügt am Ende immer <CR><LF> ein welches ein direktes
      ' Einlesen des Datenstromg mittels Input usw. in eine Variable WORD
      ' verhindert. Das automatische Einlesen des trings und das Konvertieren wird
      ' durch <CR><LF> gestört. Damit muss der Datenstrom über RS232 manuell
      ' geparsed werden.

      ' Schleife über 17 Datenwerte
      For Temp_byte_1 = 1 To 17
         Do                                                 ' Zeichen-Schleife
            Temp_byte_2 = Waitkey(#1)                       ' Zeichen von Kanal #1 lesen

            ' Ist Zeichen <CR> oder <LF>
            If Temp_byte_2 <> 10 And Temp_byte_2 <> 13 Then ' Auf CR und LF prüfen
               ' NEIN, Zeichen ist normales Zeichen

               ' Damit kann Zeichen dem Ergebisstring angehängt werden
               Temp_string_1 = Temp_string_1 + Chr(temp_byte_2)

            Else                                            ' CR / LF Prüfung
               ' CR wird mit diesem Konstrukt überlesen und bei LF wird Datenübernahme
               ' gestartet

               ' Wurde <LF> erkannt?
               If Temp_byte_2 = 10 Then
                  ' JA

                  ' Ergebnisstring in Word-Variable wandeln und in Datenstruktur schreiben
                  Srf_result_struct(temp_byte_1) = Val(temp_string_1)
                  ' Ergebnisstring zurücksetzen
                  Temp_string_1 = ""

               End If                                       ' LF Prüfung
            End If                                          ' Cr / Lf Prüfung
         Loop Until Temp_byte_2 = 10                        ' Zeichenschleife wiederholen bis LF
      Next Temp_byte_1                                      ' nächster Datenwert

      ' Alle noch im Buffer befindlichen Zeichen und Störungen löschen und Buffer
      ' auf den nächsten Empfang vorbereiten
      Clear Serialin

      ' Wenn Traceausgabe eingeschaltet dann eingelesene Daten wieder ausgeben
      #if Vol_testmodus                                     ' Trace
         For Temp_byte_1 = 1 To 17
            Print #2 , Temp_byte_1 ; " - " ; Srf_result_struct(temp_byte_1)
         Next Temp_byte_1                                   ' Struktur einlesen
      #endif                                                ' Trace

      ' 1. Echowert auslesen und korrespondierendes Intervall aus Konvertierungstabelle
      ' auslesen. Ergebnisstring für Literangabe und Prozenz füllen

      ' Zunächste Echowert 1 in Arbeitsvariable laden
      Temp_word_1 = Srf_result_struct(1)

      ' Korrektur für kleinere Werte aufgrund Schwankungen in der Zisterne
      If Temp_word_1 > 20 And Temp_word_1 < 25 Then
         ' Wasserspiegel Befindet sich zwischen 20 und 25 cm -> OK
         Temp_word_1 = 25
      End If

      ' Prüfen ob gemessene Wasseroberfläche in gültigem Bereich liegt.
      If Temp_word_1 >= Vol_luftstrecke Then
         ' JA, Messwert ist >= der Luftstrecke in der sich kein Wasser befinden
         ' kann

         ' Also kann fester Differenzbetrag (SRF <-> Wasseroberfläche) abgezogen
         ' werden
         Temp_word_1 = Temp_word_1 - Vol_luftstrecke        ' Luftstrecke kürzen

         ' Konvertierungstabellenzeiger zurücksetzen
         Restore Fuellstand

         ' Werte einlesen
         For Temp_byte_1 = 1 To Fuellstand_data

            Read Temp_byte_2                                ' Abstand
            Read Temp_word_2                                ' Volumen
            Read Temp_byte_3                                ' Prozent

            ' Ergebnisbyte aus Tabelle in Word casten
            Temp_word_3 = Temp_byte_2

            ' Prüfen ob Entfernundangabe in cm in Konvertierungstabelle gefunden wird
            If Temp_word_3 = Temp_word_1 Then
               ' Ja, dann FOR Schleife abbrechen damit Wert gerechnet werden kann

               ' Ggf. Traceausgaben schreiben
               #if Vol_testmodus                            ' Trace
                  Print #2 , "Wert gefunden" ; Temp_byte_1 ; " :" ;
                  Print #2 , "  Abstand=" ; Temp_byte_2 ;
                  Print #2 , "  Volumen=" ; Temp_word_2 ;
                  Print #2 , "  Prozent=" ; Temp_byte_3
               #endif

               ' FOR-Schleife beenden
               Exit For
            End If
         Next Temp_byte_1                                   ' Zähler Konvertierungswerte

         ' Ggf. Traceausgaben schreiben
         #if Vol_testmodus                                  ' Trace
            Print #2 , "FOR-Schleife beendet!"
         #endif

         ' Messergebnisse in Ergebnisstring umrechnen
         Vol_result_string_liter = Word2string(temp_word_2 , &H30 , 4)
         Vol_result_string_liter = Vol_result_string_liter + "l"

         Vol_result_string_prozent = Byte2string(temp_byte_3 , &H30 )       ' 0 als Auffüllzeichen verwenden
         Vol_result_string_prozent = " " + Vol_result_string_prozent + "%"

      End If                                                ' Messwert zu klein

      ' Ggf. Traceausgaben schreiben
      #if Vol_testmodus                                     ' Trace
         Print #2 , "12345678"
         Print #2 , "L: " ; Vol_result_string_liter
         Print #2 , "W: " ; Vol_result_string_prozent
      #endif

   End If                                                   ' Fehlerüberprüfung
Return
'-- End Vol_measurement -------------------------------------------------------

' *********************
' * Temperaturmessung *
' *********************

'------------------------------------------------------------------------------
' Gosub-Routine: Temp_measurement
' Routine sendet Messkommando an Slave und liest Messwerte ein. Messwerte
' werden verrechnet und Temperaturwert berechnet
'------------------------------------------------------------------------------
Temp_measurement:

   ' Wenn Konstante gesetzt Trace Output schreiben
   #if Temp_testmodus                                       ' Trace
      Print #2 , "Enter Temp_measurement"
   #endif                                                   ' Trace

   ' Ergebnisstrings vorbereiten
   Temp_result_string = " ----{223}"

   ' Fehlerflag zurücksetzen
   Temp_error_flag = False

   ' Messkommando an Slave senden
   ' Wenn Konstante gesetzt Trace Output schreiben
   #if Temp_testmodus                                       ' Trace
      Print #2 , "Funktion: Messkommando Temperatur an Slave senden"
   #endif                                                   ' Trace
   Print "{002}"                                            ' Füllstand messen

   Temp_word_1 = Sectick_counter + Slave_responde_delay     ' Timeout aufziehen
   ' Daten von Slave lesen

   ' Arbeitsstring vorbereiten
   Temp_string_1 = ""

   Do
      ' RS232 Buffer lesen
      Temp_byte_1 = Ischarwaiting(#1)

      ' Prüfen ob Zeichen wartet
      If Temp_byte_1 <> 0 Then
         ' JA es wartet ein Zeichen

         ' Wenn Konstante gesetzt Trace Output schreiben
         #if Temp_testmodus                                 ' Trace
            Print #2 , "Zeichen wartet"
         #endif

         ' Flag auf Erfolgreich setzen und Do-Loop schon verlassen
         Temp_error_flag = True
         Exit Do
      End If                                                ' Pürfung ob Zeichen wartet
   Loop Until Temp_word_1 = Sectick_counter                 ' Timeout

   ' Prüfen ob Fehler aufgetreten
   If Temp_error_flag = False Then
      ' JA, es ist ein Fehler aufgetreten

      ' Wenn Konstante gesetzt Trace Output schreiben
      #if Temp_testmodus                                    ' Trace
         Print #2 , "Fehler erkannt, Leerstring bleibt gesetzt"
      #endif

   Else                                                     ' Fehlerüberprüfung
      ' Kein Fehler, also Messwert einlesen

      ' Anmerkung:
      ' Die Übertragung der Daten vom Slave zum Master wird über eine normale
      ' Printfunktion ausgeführt damit die Daten lesbar / tracebar sind.
      ' Die Printfunktion fügt am Ende immer <CR><LF> ein welches ein direktes
      ' Einlesen des Datenstromg mittels Input usw. in eine Variable WORD
      ' verhindert. Das automatische Einlesen des trings und das Konvertieren wird
      ' durch <CR><LF> gestört. Damit muss der Datenstrom über RS232 manuell
      ' geparsed werden.

      Do                                                    ' Zeichen-Schleife
         Temp_byte_2 = Waitkey(#1)                          ' Zeichen von Kanal #1 lesen

         ' Ist Zeichen <CR> oder <LF>
         If Temp_byte_2 <> 10 And Temp_byte_2 <> 13 Then    ' Auf CR und LF prüfen
            ' NEIN, Zeichen ist normales Zeichen

            ' Damit kann Zeichen dem Ergebisstring angehängt werden
            Temp_string_1 = Temp_string_1 + Chr(temp_byte_2)

         Else                                               ' CR / LF Prüfung
            ' CR wird mit diesem Konstrukt überlesen und bei LF wird Datenübernahme
            ' gestartet

            ' Wurde <LF> erkannt?
            If Temp_byte_2 = 10 Then
               ' JA

               ' Ergebnisstring in Integer-Variable wandeln und speichern
               Temp_messwert = Val(temp_string_1)
               ' Ergebnisstring zurücksetzen
               Temp_string_1 = ""

            End If                                          ' LF Prüfung
         End If                                             ' Cr / Lf Prüfung
      Loop Until Temp_byte_2 = 10                           ' Zeichenschleife wiederholen bis LF

      ' Alle noch im Buffer befindlichen Zeichen und Störungen löschen und Buffer
      ' auf den nächsten Empfang vorbereiten
      Clear Serialin

      ' Wenn Traceausgabe eingeschaltet dann eingelesene Daten wieder ausgeben
      #if Temp_testmodus                                    ' Trace
         Print #2 , "Temperaturrohwert : " ; Temp_messwert
      #endif                                                ' Trace

      ' Rohwert umrechnen
      Temp_single_1 = Temp_messwert
      Temp_single_1 = Temp_single_1 * 0.5

      ' Ggf. Traceausgaben schreiben
      #if Temp_testmodus                                    ' Trace
          Print #2 , "Gemessene Temperatur : " ; Temp_single_1
      #endif                                                ' Trace

      ' Aus Single sauberen String herstellen

      ' Hinweis:
      ' Obwohl im Zisternenwasser keine negativen Temperaturen vorkommen können
      ' wird die Umsetzung so ausgeführt, dass auch bei negativen Zahlen eine
      ' saubere Stringkonvertierung unter Berücksichtigung eines eventuellen
      ' Leerzeichenausgleichs durchgeführt wird.

      ' Ist die Temperatur >?= 10°C?
      If Temp_single_1 >= 10.0 Then
         ' JA, es wird eine Vorkommastelle mehr benötigt, damit eine Nachkommastelle weniger

         Temp_result_string = Fusing(temp_single_1 , "#.#")

         ' Leerzeichenausgleich
         Temp_result_string = Chr(32) + Temp_result_string  ' SPACE einfügen

      Else                                                  ' Anzahl Ziffern in Ausgabe
         ' Nein, es können zwei Nachkommastelle ausgegeben werden
         Temp_result_string = Fusing(temp_single_1 , "#.##")

         ' Prüfen ob negative Zahl
         If Temp_single_1 >= 0 Then
            ' NEIN, keine negative Zahl, dann Leerzeichen einfügen

            Temp_result_string = Chr(32) + Temp_result_string       ' SPACE einfügen

         End If                                             ' Negative Zahl?
      End If                                                ' Anzahl Ziffern in Ausgabe

      ' Auf jeden Fall Gradzeichen anhängen und fertig!
      Temp_result_string = Temp_result_string + Chr(223)    ' °

      ' Ggf. Traceausgaben schreiben
      #if Temp_testmodus                                    ' Trace
         Print #2 , "12345678"
         Print #2 , "T: " ; Temp_result_string
      #endif

   End If                                                   ' Fehlerüberprüfung
Return
'-- End Vol_measurement -------------------------------------------------------

' ********************
' * Sonstiges        *
' ********************

'------------------------------------------------------------------------------
' Gosub-Routine: Version_output
' Routine gibt aktuelle Programmversion und Jahr aus
'------------------------------------------------------------------------------
Version_output:

   ' Wenn Konstante gesetzt Trace Output schreiben
   #if Key_testmodus                                        ' Trace
      Print #2 , "Enter Version_output"
   #endif                                                   ' Trace

   ' LCD-Display wieder einschalten und Abschaltzeit neu setzen
   Lcd_abschaltcounter = Sectick_counter + Lcd_abschaltzeit
   Gosub Lcd_beleuchtung_an
   Gosub Lcd_display_on

   ' Status aus LED ausgeben
   Led1 = 0 : Led2 = 0                                      ' Menümodus ist Version ausgeben

   ' Programmversion ausgeben
   Cls
   Lcd "V1.2 '09"

Return
'-- End Version_output --------------------------------------------------------

'------------------------------------------------------------------------------
' Devices schließend und ggf. "Terminate Programm execution"
'------------------------------------------------------------------------------

Close #3                                                    ' Close SW-RS232 Input
Close #2                                                    ' Close SW-RS232 Output
Close #1                                                    ' Close HW-RS232

End                                                         'end program

'------------------------------------------------------------------------------
' Definition von globalen Konstantenfeldern
'------------------------------------------------------------------------------

'------------------------------------------------------------------------------
' DATA:           Konvertierungstabelle gemessener Abstand zu Volumen und
'                 Pozent
' Rückgabewerte:  Zeiger Volument und Prozent
'------------------------------------------------------------------------------

Fuellstand:
Data 0 , 3000% , 100
Data 1 , 2986% , 100
Data 2 , 2971% , 100
Data 3 , 2956% , 99
Data 4 , 2940% , 98
Data 5 , 2924% , 98
Data 6 , 2907% , 97
Data 7 , 2889% , 97
Data 8 , 2871% , 96
Data 9 , 2853% , 96
Data 10 , 2834% , 95
Data 11 , 2814% , 94
Data 12 , 2794% , 94
Data 13 , 2774% , 93
Data 14 , 2753% , 92
Data 15 , 2732% , 91
Data 16 , 2710% , 91
Data 17 , 2689% , 90
Data 18 , 2666% , 89
Data 19 , 2644% , 89
Data 20 , 2621% , 88
Data 21 , 2598% , 87
Data 22 , 2574% , 86
Data 23 , 2550% , 85
Data 24 , 2526% , 85
Data 25 , 2502% , 84
Data 26 , 2478% , 83
Data 27 , 2453% , 82
Data 28 , 2428% , 81
Data 29 , 2403% , 80
Data 30 , 2377% , 80
Data 31 , 2351% , 79
Data 32 , 2326% , 78
Data 33 , 2300% , 77
Data 34 , 2273% , 76
Data 35 , 2247% , 75
Data 36 , 2220% , 74
Data 37 , 2194% , 73
Data 38 , 2167% , 73
Data 39 , 2140% , 72
Data 40 , 2112% , 71
Data 41 , 2085% , 70
Data 42 , 2058% , 69
Data 43 , 2030% , 68
Data 44 , 2003% , 67
Data 45 , 1975% , 66
Data 46 , 1947% , 65
Data 47 , 1919% , 64
Data 48 , 1891% , 63
Data 49 , 1863% , 62
Data 50 , 1835% , 61
Data 51 , 1806% , 60
Data 52 , 1778% , 60
Data 53 , 1750% , 59
Data 54 , 1721% , 58
Data 55 , 1693% , 57
Data 56 , 1664% , 56
Data 57 , 1636% , 55
Data 58 , 1607% , 54
Data 59 , 1579% , 53
Data 60 , 1550% , 52
Data 61 , 1522% , 51
Data 62 , 1493% , 50
Data 63 , 1465% , 49
Data 64 , 1436% , 48
Data 65 , 1408% , 47
Data 66 , 1379% , 46
Data 67 , 1351% , 45
Data 68 , 1322% , 44
Data 69 , 1294% , 43
Data 70 , 1266% , 42
Data 71 , 1237% , 41
Data 72 , 1209% , 40
Data 73 , 1181% , 40
Data 74 , 1153% , 39
Data 75 , 1125% , 38
Data 76 , 1097% , 37
Data 77 , 1070% , 36
Data 78 , 1042% , 35
Data 79 , 1014% , 34
Data 80 , 987% , 33
Data 81 , 960% , 32
Data 82 , 932% , 31
Data 83 , 905% , 30
Data 84 , 878% , 29
Data 85 , 852% , 29
Data 86 , 825% , 28
Data 87 , 799% , 27
Data 88 , 773% , 26
Data 89 , 746% , 25
Data 90 , 721% , 24
Data 91 , 695% , 23
Data 92 , 669% , 22
Data 93 , 644% , 22
Data 94 , 619% , 21
Data 95 , 594% , 20
Data 96 , 570% , 19
Data 97 , 546% , 18
Data 98 , 522% , 17
Data 99 , 498% , 17
Data 100 , 474% , 16
Data 101 , 451% , 15
Data 102 , 428% , 14
Data 103 , 406% , 14
Data 104 , 384% , 13
Data 105 , 362% , 12
Data 106 , 340% , 11
Data 107 , 319% , 11
Data 108 , 298% , 10
Data 109 , 278% , 9
Data 110 , 258% , 9
Data 111 , 238% , 8
Data 112 , 219% , 7
Data 113 , 201% , 7
Data 114 , 183% , 6
Data 115 , 165% , 6
Data 116 , 148% , 5
Data 117 , 132% , 4
Data 118 , 116% , 4
Data 119 , 101% , 3
Data 120 , 86% , 3
Data 121 , 72% , 2
Data 122 , 59% , 2
Data 123 , 47% , 2
Data 124 , 36% , 1
Data 125 , 26% , 1
Data 126 , 17% , 1
Data 127 , 9% , 0
Data 128 , 3% , 0
Data 129 , 0% , 0
Data 130 , 0% , 0
' zur Sicherheit noch weitere Datenfelder definert!
Data 131 , 0% , 0
Data 132 , 0% , 0
Data 133 , 0% , 0
Data 134 , 0% , 0
Data 135 , 0% , 0
Data 136 , 0% , 0
Data 137 , 0% , 0
Data 138 , 0% , 0
Data 139 , 0% , 0
Data 140 , 0% , 0

'###################################### END ###################################

'################################### Historie #################################
' 28.01.2009 : Version 1.0
'              Erste offizielle und vollständig umgesetzte Produktivsoftware
' 12.03.2009 : Version 1.1
'              - Led für Wasserstandmessung und Temperatur waren vertauscht.
'                Zuordnung im Define getauscht.
'              - LCD Abschaltung eingebaut
' 10.05.2009 : Version 1.2
'              - Nach Zisterneneinbau Abstand Sensor-Wasser korrigiert
'              - Sonderbehandlung für 20-25 cm Abstand wegen Schwankungen
'                eingebaut.
'##############################################################################