Sie sind hier: Home » Bewässerungssteuerung 2021 » Programm RST_2021

Link zu: Programm_RST2021

'*******************************************************************************
'************               Regnersteuerung20_V0.8A              ***************
'*** bei Version Anne schliesst das Motorventil zurst, dann das Magnetventil ***
'*******************************************************************************

'name                     : Regnersteuerung20A_V0.8.bas
'copyright                : (c) 15.02.2021 jep
'purpose                  : Steuert Rasenbewässerung bei Anne
'micro                    : Mega1284P-PU
'
'Changelog:               : V0.1: Intialversion ab Regnersteuerung18_V0.6.bas
'                         : V0.2: Zwischenversion bei Anne erstellt
'                         : V0.3: Süd und West Ausgang vertauscht, Doubletten entfernt
'                         : V0.4: WEB-Ausgabe erledigt, Funkanbindung erledigt
'                         : V0.4a:Adressen und Zeiten für Anne angepasst
'                         : B_V0.5:komplett überarbeitet; Zeiten anders programmiert
'                         : V0.6: neu
'                         : V0.7: Vereinfachungen
'                         : V0.8: Korrekturen, vorläufige Endversion
'_______________________________________________________________________________

$regfile = "m1284Pdef.dat"                                  'ATMEL Mega1284-PU
$crystal = 20000000                                         'mit 20 MHz-Clock
$hwstack = 200                                              'default use 32 for the hardware stack
$swstack = 200                                              'default use 10 for the SW stack
$framesize = 200                                            'default use 40 for the frame space
$baud = 115200                                              'serielle Schnittstelle
'_______________________________________________________________________________

Declare Sub Rfm12_init()
Declare Sub Rfm12_senden()
Declare Function Spitransfer(byval Dataout As Word) As Word
Declare Sub Mintic()
Declare Sub Display_on()
Declare Sub Normalanzeige()
Declare Sub Restbereich_loeschen()
Declare Sub Titelanzeige()
Declare Sub Zeitanzeige()
Declare Sub Datumanzeige()
Declare Sub Menueanzeige()
Declare Sub WEB_Anzeige()
Declare Sub RLZ_Sued_anzeigen()
Declare Sub RLZ_West_anzeigen()


'******************************  Grafikdisplay  ********************************
'Display hat 320 x 240 Pixel:  bei 12x16 ===> 26 x 15   =  Font 1
'                              bei 20x24 ===> 16 x 10   =  Font 2

Config Portd.5 = Output                                     'LCD D/C
Config Portd.6 = Output                                     'LCD Reset
Config PortB.4 = Output                                     'LCD CS
Lcd_reset Alias PortD.6
Lcd_dc Alias PortD.5
Lcd_cs Alias PortB.4
Lcd_reset = 1
Lcd_cs = 1

Config Portb.5 = Output                                     'MOSI ----> SDI (RFM12B)
Config portb.6 = Input                                      'MISO <---- SDO (RFM12B)
Config Portb.7 = Output                                     'SCK  ----> SCK (RFM12B)
Config portb.3 = Output                                     'Slave select für RFM12

Const Lcd_mode = 3                                          'LCD Mode 1=Portrait 2=Portrait 180° 3=landscape 4=landscape 180°

'*******************************************************************************
$include "..\TFTDriver\ILI9341_declarations_spi_Text.inc"
'*******************************************************************************

Mosi Alias Portb.5
Miso Alias Pinb.6
Sck Alias Portb.7
Ss Alias PortB.3
Ss = 1                                                      'RFM12B ausschalten

'*******************************************************************************

Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = High , Phase = 1 , Clockrate = 4 , Noss = 1
Spsr.0 = 1                                                  ' Double speed on ATMega128
Spiinit

'======================== Tastenkonfiguration ==================================
Config PortA.0 = Input                                      'Taste UP
PortA.0 = 1                                                 'Pullup
UP Alias PinA.0

Config PortA.1 = Input                                      'Taste Down
PortA.1 = 1                                                 'Pullup
Down Alias PinA.1

Config PortA.2 = Input                                      'Taste LEFT
PortA.2 = 1                                                 'Pullup
Links Alias PinA.2

Config PortA.3 = Input                                      'Taste RIGHT
Porta.3 = 1                                                 'Pullup
Rechts Alias Pina.3

Config PortA.4 = Input                                      'Taste OK / Enter
PortA.4 = 1                                                 'Pullup
OK Alias PinA.4

Config DEBOUNCE = 20                                        '20 ms entprellen


'************************  Ventilbezeichnungen  ********************************
Config Portc.7 = Output                                     'Relais K1
PortC.7 = 0                                                 'ausschalten
West_K1 Alias Portc.7

Config Portc.6 = Output                                     'Relais K2
PortC.6 = 0                                                 'ausschalten
Sued_K2 Alias Portc.6

Config Portc.5 = Output                                     'Relais K3, nicht montiert
PortC.5 = 1                                                 'einschalten
Displaybeleuchtung Alias PortC.5                            'schaltet Displaybeleuchtung

Config PortC.4 = Output                                     'Relais K4, nicht montiert
PortC.4 = 0                                                 'ausschalten

Config PortC.3 = Output                                     'Relais K5
Portc.3 = 0                                                 'ausschalten
Motor_K5 Alias PortC.3

Config PortC.2 = Output                                     'Relais K6
PortC.2 = 0                                                 'ausschalten
Power_K6 Alias PortC.2


'**************************  freie Eingänge  ***********************************
Config PortB.0 = Input
PortB.0 = 1                                                 'Pullup
In0 alias Pinb.0                                            'Eingang 0

Config PortB.1 = Input
PortB.1 = 1                                                 'Pullup
In1 Alias PinB.1                                            'Eingang 1

Config PortB.2 = Input
PortB.2 = 1                                                 'Pullup
FW Alias PinB.2                                             'Eingang 2 = Interrupt 2 = Flusswächter

Config Porta.7 = Input
Porta.7 = 1                                                 'Pullup
In3 Alias PinA.7                                            'Eingang 3

'----------------------------
Config PinA.5 = Input                                       'DIP Eingang 2
PortA.5 = 1                                                 'Pullup
Dip2 Alias Pina.5                                           'Summertick => 0 = aktiv

Config Pina.6 = Input                                       'DIP-Eingang 1, Debug
PortA.6 = 1                                                 'Pullup
Debuggen Alias PinA.6                                       'am Schalter => 1 = log. 0 => Debuggen

Config PortD.4 = Output                                     'blockiert RX-Eingang des ESP
ESP_disable Alias PortD.4                                   'und damit das Senden des ESP
ESP_disable = 0                                             'freigegeben

Config PortD.7 = Output                                     'Signalgeber
PortD.7 = 0
Summer alias Portd.7


'============================== Serielle Konfiguration =========================

Config Serialin = Buffered , Size = 10 , Bytematch = 13     'Carridge Return als Bytematch


'=============================== I2C/TWI Konfiguration =========================
$lib "I2C_TWI.LBX"                                          'Library für HW-I2C-Bus
Config Scl = Portc.0                                        'SCL pinname angeben
Config Sda = Portc.1                                        'SDA Pinname angeben                                                    'und initialisieren
Config Twi = 400000                                         'DS1307 läuft nur mit 100kHz
I2cinit                                                     'Port´s nicht konfigurieren,
                                                            'sie sind HW-mässig festgelegt
'address of ds1307
Config clock = user
Const Ds1307w = &HD0                                        ' Addresses of Ds1307 clock
Const Ds1307r = &HD1

Config Date = DMY , Separator = DOT

Config Int1 = Falling                                       ' 1 sec-Takt
on Int1 sectic
Enable Int1
Disable Interrupts

Config Int2 = Falling
On Int2 Flusswaechter
Disable Int2

Config Watchdog = 8192                                      ' 8 Sekunden-Watchdog


'======================= Timerinterupt für Summer ==============================

Config Timer2 = Timer , Prescale = 64
Const Timer2_preload = 1
On Timer2 Timer2_irq                                        'beim Interrupt Summer stoppen
Enable Timer2                                               'Timer0 Interrupt freigeben
Stop Timer2
Dim Summer_aktiv as Byte : Summer_aktiv = 1                 'Sekundentick einschalten
Dim Summerzustand as Byte : Summerzustand = 0


'################################## ADRESSEN  ##################################
'                                                                             ##
Const Regnersteuerungsadresse = 88                          'ist fix, Hex 58  ##
Const Handsenderadresse = 78                                'ist fix, Hex 4E  ##
'                                                                             ##
'###############################################################################


'========= Hier werden die zu empfangenen Bytes (9, max 50) abgelegt ==========

'   1    2    3    4    5    6    7    8    9
'+----+----+----+----+----+----+----+----+----+
'|               Empfangsbytes                |
'+----+----+----+----+----+----+----+----+----+
'|LENe|DABe|SABe|CDBe|Code|Batterie |CRC2|CRC1|
'+----+----+----+----+----+----+----+----+----+
'

Const Maxanzahlempfangsbytes = 9                            'zu empfangende Datenmenge (maximal total 66 Byte)
Dim Irq_empfangsbytes(Maxanzahlempfangsbytes + 2) As Byte   'Empfangspuffer während Empfang  (etwas grösser)
Dim Irq_anzahlbytemax as Byte                               'Anzahl zu erwartende Empfangsbytes gemäss Empfang
Dim Irq_Akt_byte As Byte                                    'Zähler für die empfangenen Bytes
Dim Funkdaten_vorhanden As Bit
Dim Empfangsbytes(Maxanzahlempfangsbytes + 2) As Byte       'Empfangspuffer nach Empfang
Dim SABe as Byte at Empfangsbytes(3) Overlay                'Quelladresse
Dim Code as Byte At Empfangsbytes(5) Overlay
Dim Crc_16e As Word At Empfangsbytes(8) Overlay             'CRC16 für Empfang
Dim PNe as Byte                                             'Paket-Nummer beim Empfang
Dim PNez as Byte
Dim SABez as Byte
Const max_Empfangslaenge = Maxanzahlempfangsbytes + 2
'
'die Quittung besteht aus 4 Bytes
'   1    2    3    4
'+----+----+----+----+
'|  Sendebytes( )    |
'+----+----+----+----+
'|LENs|DABs|SABs|CDBs|
'+----+----+----+----+
'
Dim Sendebytes(5) As Byte                                   'Anzahl ist fix da nur Quittung
Dim Anzahlbyte_s as Byte
Dim Paketzaehler As Byte                                    'Startwert ist 1
Paketzaehler = 1


'================== Interrupt für den Empfang aktivieren =======================

Config PinD.2 = Input                                       'Int0
PortD.2 = 1                                                 'Pullup
Config Int0 = Falling
On Int0 RFM_Funkirq
Enable Int0
Disable Interrupts                                          'alle Interrupts noch stoppen


'======== Timerinterupt für Zeitbegrenzung Interruptempfang einstellen ===========

Config Timer0 = Timer , Prescale = 1024
Const Timer0_preload = 255 -(8 * 20000000 / 1024 * 4800)    'für 2 Bytes: gilt für 20 MHz und 4800 Baud
On Timer0 Timer0_irq                                        'beim Interrupt Empfang stoppen
Enable Timer0                                               'Timer0 Interrupt freigeben
Stop Timer0


'_______________________________________________________________________________

Dim Weekday As Byte
dim bcd_day as Byte
Dim bcd_month as Byte
Dim bcd_year as Byte
Dim bcd_hour as Byte
Dim bcd_min as Byte
Dim bcd_sec as Byte
Dim Datum as string * 10
Dim Zeit as string * 10
Dim alte_minute as Byte
Dim Neue_Sekunde as Byte
Dim Block_Zeitanzeige as Byte : Block_Zeitanzeige = 0

Dim serCode_da as Byte : serCode_da = 0

Const max_Laufzeit = 25                                     'maximale Ventillaufzeit in Min.
Const Motorventillaufzeit = 20                              'Motorventillaufzeit, default 20 sec.
Dim Laufzeit_W as Byte : Laufzeit_W = 0                     'Laufzeitvorgabe in min, default 0
Dim Laufzeit_S as Byte : Laufzeit_S = 0                     'Laufzeitvorgabe in min, default 0
Dim akt_Laufzeit_W as Byte : akt_Laufzeit_W = 0             'aktuelle Laufzeit in min, default 0
Dim akt_Laufzeit_S as Byte : akt_Laufzeit_S = 0             'aktuelle Laufzeit in min, default 0
Dim Restlaufzeit_W as Byte : Restlaufzeit_W = 0             'default 0 min
Dim Restlaufzeit_S as Byte : Restlaufzeit_S = 0             'default 0 min
Const Magnet_Starttime = 5                                  'Zeit zwischen Start Motorv -> Start Magnetv
Dim Magnet_Starttimer as Byte : Magnet_Starttimer = 0       'Timer für Startverzögerung Magnetv
Const Magnet_Stoptime = 12                                  'Zeit zwischen Stop Motorv -> Stop Magnetv
Dim Magnet_Stoptimer as Byte : Magnet_Stoptimer = 0         'Timer für Ausschaltverzögerungs Magnetv
Const 230V_Nachlauf_time = 1                                'Nachlaufzeit für 230V, deault 1 min
Dim 230V_Nachlauf_timer as Byte : 230V_Nachlauf_timer = 1   'Timer für 230V Nachlaufzeit
Dim Notbremse as Byte : Notbremse = 0                       'Merker, ausgeschaltet
Const Notbremse_time =(max_Laufzeit + 3) * 60               'absolut max. Laufzeit, 28 min = 1680 sec.
Dim Notbremse_timer as Word : Notbremse_Timer = Notbremse_time       'Timer für max. Laufzeit
Dim Entwaesserungstimer as Word : Entwaesserungstimer = 300 'Timer für Entwässerungszeit
Const Entwaesserungstime = 300                              'Entwässerungszeit in Sekunden, default 5 Min.
Dim Beleuchtungstimer as Byte : Beleuchtungstimer = 0       'Timer für Beleuchtungsdauer
Const max_Beleuchtungsdauer = 2                             'Beleuchtungsdauer, default 2 Min.
Dim Sicherheit_min as Word                                  'Anzeige in Minuten
Dim West_aktiv as Byte : West_aktiv = 0                     'Merker
Dim West_verz as Byte : West_verz = 0
Dim Sued_aktiv as Byte : Sued_aktiv = 0                     'Merker
Dim Sued_verz as Byte : Sued_verz = 0
Dim Menue_aktiv as Byte : Menue_aktiv = 0                   'Merker
Dim Menue_Timeout as Byte : Menue_Timeout = 0

Dim Text as String * 70
Dim D as Word
Dim N as Byte
Dim R as Byte
Dim X as Byte
Dim Y as Byte
Dim LCD_war_aktiv as Byte : LCD_war_aktiv = 0
Dim WEB_Ausgabe_erledigt as Byte : WEB_Ausgabe_erledigt = 0
Dim Status_Power as string * 150
Dim Status_Motor as string * 100
Dim Status_West as string * 200
Dim Status_Sued as string * 200
Dim Status_NT as string * 150
Dim Befehl as string * 6
Dim Meldung as String * 100


$include "..\Unterprogramme\Regnersteuerung21A_Menue.inc"

'-------------------------------------------------------------------------------
'                                    **
'                              **************
'                     ********************************
'             ***************************************************
'      ******************************************************************
'*******************************************************************************
'***************************** PROGRAMMSTART ***********************************
'*******************************************************************************

if Debuggen = 0 then
   Meldung = "************************************************"
   gosub SWPrint
   Meldung = "************** Programmstart *******************"
   gosub SWPrint
   Meldung = "************************************************"
   gosub SWPrint
end if

Initialisierung:

Disable Interrupts                                          'sonst wird die Anzeige durcheinandergebracht
Call Set1307_1sec_tick                                      '1 sec-Takt auf DS1307 einschalten

if Debuggen = 0 then
   Meldung = "1sec-Tick initialisiert"
   gosub SWPrint
end if

Displaybeleuchtung = 0
Beleuchtungstimer = max_Beleuchtungsdauer
LCD_Init
LCD_Clear Black
Displaybeleuchtung = 1
LCD_Text "Regnersteuerung" , 10 , 30 , 2 , White , Black , 1       'Display löschen
LCD_Text "2021 Vers:V.08A" , 10 , 80 , 2 , White , Black , 1       'Version immer anpassen !!!!!!!!!!!!!!!!!!!!!

Wait 2                                                      '2 Sekunden warten
Displaybeleuchtung = 0
LCD_Clear Black
Displaybeleuchtung = 1

'Ventile in eine definierte Stellung bringen (geschlossen)

Motor_K5 = 0                                                'Motorventil zu
West_K1 = 0                                                 'West zu
Sued_K2 = 0                                                 'Süd zu
waitms 50
Power_K6 = 1                                                '220VAC auf die Ventile geben
Titelanzeige
LCD_Text "Ventile" , 72 , 100 , 1 , Red , Black , 2
LCD_Text "schliessen" , 36 , 140 , 1 , Red , Black , 2
wait 20                                                     '20sec warten
Power_K6 = 0                                                '220V für die Ventile abschalten

Call RFM12_init
IRQ_akt_Byte = 0
Funkdaten_vorhanden = 0
'Auf neue Anfangssequenz warten
r = Spitransfer(&H82c8)                                     'Empfänger aktivieren
r = Spitransfer(&Hca83)                                     'FIFO einstellen/aktivieren

Getdatetime                                                 'die aktuellen Zeiteinstellungen übernehmen
Normalanzeige                                               'und darstellen
Enable Int2                                                 'Flusswächter scharf stellen
Enable Interrupts                                           'und nun los
waitms 10
WEB_Anzeige

'Ende Inmitialisierung

'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'++++++++++++++++++++++++++++ Hauptschleife ++++++++++++++++++++++++++++++
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Start Watchdog
do
   If Neue_sekunde = 1 Then                                 'alles was pro Sekunde abläuft
      Neue_sekunde = 0
      If Magnet_Starttimer > 0 then
         if Debuggen = 0 then
            gosub CRLF
            Meldung = "Magnetstarttimer:  " + str(Magnet_Starttimer)
            gosub SWPrint
            Gosub CRLF
         end if
         Magnet_Starttimer = Magnet_Starttimer - 1
         If Magnet_Starttimer = 0 then
            If West_aktiv = 1 then
               West_K1 = 1                                  'Ventil West ein              ??????????????
               gosub Anzeige_West
            End if
            If Sued_aktiv = 1 then
               Sued_K2 = 1                                  'Ventil Süd ein               ???????????????????
               gosub Anzeige_Sued
            End if
         End if
      End if
      If Magnet_Stoptimer > 0 then
         if Debuggen = 0 then
            gosub CRLF
            Meldung = "Magnetstoptimer:  " + str(Magnet_Stoptimer)
            gosub SWPrint
            Gosub CRLF
         end if
         Magnet_Stoptimer = Magnet_Stoptimer - 1
         If Magnet_Stoptimer = 0 then
            If West_aktiv = 1 then
               West_K1 = 0                                  'Ventil West aus              ??????????????
               West_aktiv = 0                               'Merker Süd zurückstellen
               West_verz = 0
               Laufzeit_W = 0                               'alle Zeiten zurücksetzen
               akt_Laufzeit_W = 0
               Restlaufzeit_W = 0
               Call Restbereich_loeschen
               If Sued_aktiv = 0 then 230V_Nachlauf_timer = 1       'klemmt sonst Süd die 230V ab
            End if
            If Sued_aktiv = 1 then
               Sued_K2 = 0                                  'Ventil Süd schliessen
               Sued_aktiv = 0                               'Merker Süd zurückstellen
               Sued_verz = 0
               Laufzeit_S = 0                               'alle Zeiten zurücksetzen
               akt_Laufzeit_S = 0
               Restlaufzeit_S = 0
               Call Restbereich_loeschen
               If West_aktiv = 0 then 230V_Nachlauf_timer = 1       'klemmt sonst West die 230V ab
            End if
            Block_Zeitanzeige = 0                           'Zeitausgabe wieder freigeben
         End if
      End if
      if alte_minute <> _min then
         alte_minute = _min
         mintic
      end if
      If West_aktiv = 0 and Sued_aktiv = 0 and Menue_aktiv = 0 and Block_Zeitanzeige = 0 then       'nichts aktiv
         Getdatetime                                        'aktuelle Zeit holen
         Zeitanzeige                                        'führt die Zeit im Sekundentakt nach
         Datumanzeige
       else
         Getdatetime
         If West_aktiv = 1 or Sued_aktiv = 1 then
            Text = Hex(bcd_sec) + " sec"                    'wenn aktiv: Sekunden unten einblenden
            LCD_Text Text , 120 , 220 , 1 , White , Black , 1
         End if
      End if
   End If

   if _sec = 5 then gosub WEB_Ausgabe                       'WEB -Seite nachführen

   Debounce OK , 0 , Menue , sub
   Debounce Up , 0 , Sued_ea , sub
   Debounce Down , 0 , West_ea , sub
   Debounce Links , 0 , Display_on , sub
   Debounce Rechts , 0 , Display_on , sub

   if serCode_da = 1 then gosub Code_auswerten

   if Funkdaten_vorhanden = 1 then gosub RFM_auswerten

   Reset Watchdog
loop

'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

'=========================================================================
'============================ Sekundeninterrupt ==========================

Sectic:
'   Meldung = "*"                                            'Sekundentick auf Printer
'   gosub SWPrint
   Neue_sekunde = 1

   if Summer_aktiv = 1 then                                 'Summer über Timer2 starten
      Timer2 = Timer2_Preload                               'für 0.5 ms
      Summer = 1                                            'Summer einschalten
      Start Timer2
   end if

  If Menue_Timeout > 0 then decr Menue_Timeout

'Überwachung auf Maximalzeit; sollte (hoffentlich) nie auftreten
   if Notbremse = 1 then                                    'Notbremse ist aktiv
      decr Notbremse_timer
      if Notbremse_timer = 0 then
         Notbremse = 0                                      'Notbremse ausschalten
         Notbremse_timer = Notbremse_time                   'max. Zeit laden
         gosub Not_aus                                      'alles aus und GENERALRESET
      end if
   End if
Return

'=========================================================================
'=========================================================================

'#########################################################################
'################ Alles was einmal pro Minute abläuft ####################

Sub Mintic:
   if Debuggen = 0 then
      gosub CRLF
      Meldung = "West / Süd aktiv: " + str(West_aktiv) + " / " + str(Sued_aktiv)
      Gosub SWPrint
      Meldung = "West verz: " + str(West_verz)
      Gosub SWPrint
      Meldung = "Sued verz: " + str(Sued_verz)
      Gosub SWPrint
      Meldung = "Nottimer: " + str(Notbremse_timer)
      Gosub SWPrint
      Gosub CRLF
   end if

   WEB_Ausgabe_erledigt = 0                                 'zu jeder vollen Minute zurücksetzen

   Sicherheit_min = Notbremse_timer / 60                    'Notbremse, für Anzeige in Minuten

   If West_aktiv = 0 and Sued_aktiv = 0 then                'es fliesst kein Wasser
      decr 230V_Nachlauf_timer
      if 230V_Nachlauf_timer = 0 then
         Notbremse = 0                                      'Notbremse ausschalten
         Notbremse_timer = Notbremse_time
         Power_K6 = 0                                       '230V ausschalten
         Enable INT2                                        'Flusswächter aktivieren
         if Debuggen = 0 then
            Meldung = "Power off"
            gosub SWPrint
         end if
      End if
   End if
   if West_aktiv = 1 then                                   'West wurde zuerst gestartet
      gosub Anzeige_West
      goto Mintic_End
   end if
   if Sued_aktiv = 1 then                                   'Süd wurde zuerst gestartet
      gosub Anzeige_Sued
      goto Mintic_End
   end if

   If Beleuchtungstimer > 0 then
      decr Beleuchtungstimer
    else
      Displaybeleuchtung = 0
   End if

 Mintic_End:
End Sub

'##########################################################################
'##########################################################################

'--------------------------- Unterprogramme -------------------------------
'dies sind Unterprogramme die nach einem Tastendruck aufgerufen werden

Anzeige_West:
   If akt_Laufzeit_W < Laufzeit_W then
      akt_Laufzeit_W = akt_Laufzeit_W + 1
      if Debuggen = 0 then
         Meldung = "akt. LZW: " + str(akt_Laufzeit_W)
         gosub SWPrint
      end if
      Restlaufzeit_W = Laufzeit_W - akt_Laufzeit_W
      if akt_Laufzeit_W >= Laufzeit_W then
         gosub Stop_West
         Call Normalanzeige
         Call WEB_Anzeige
      Else
         Call RLZ_West_anzeigen
      End if
   End if
Return

Anzeige_Sued:
   If akt_Laufzeit_S < Laufzeit_S then
      akt_Laufzeit_S = akt_Laufzeit_S + 1
      if Debuggen = 0 then
         Meldung = "akt. LZS: " + str(akt_Laufzeit_S)
         gosub SWPrint
      end if
      Restlaufzeit_S = Laufzeit_S - akt_Laufzeit_S
      if akt_Laufzeit_S >= Laufzeit_S then
         gosub Stop_Sued
         Call Normalanzeige
         Call WEB_Anzeige
      Else
         Call RLZ_Sued_anzeigen
      End if
   End if
Return


West_ea:
   If Displaybeleuchtung = 0 then
      Call Display_on
      goto West_end
   End if
   if Debuggen = 0 then
      gosub CRLF
      Meldung = "West Start Anfang / West aktiv: " + str(West_aktiv) + " West verz.: " + str(West_verz) + "   Süd aktiv: " + str(Sued_aktiv) + " Süd verz.: " + str(Sued_verz) + " LZW: " + str(Laufzeit_W)
      gosub SWPrint
      Gosub CRLF
   end if
   Block_Zeitanzeige = 1                                    'Zeitausgabe verhindern
   If Laufzeit_W = 0 then                                   'Start, erster Tastendruck
      Laufzeit_W = 6                                        'Startwert 6 Min
 West_ea1:
      akt_Laufzeit_W = 0                                    'aktuelle Laufzeit ist 0
      Restlaufzeit_W = Laufzeit_W - akt_Laufzeit_W
      Call RLZ_West_anzeigen
      if Sued_aktiv = 0 then                                'Süd nicht aktiv
         gosub Start_West                                   'also Starten
      else
         West_verz = 1                                      'West startet nach Süd
      end if
      Call WEB_Anzeige                                      'und auf WEB darstellen
    else                                                    'für weitere Tastendrücke
      Laufzeit_W = Laufzeit_W + 5                           'Wert um 5 Min. erhöhen
      Restlaufzeit_W = Laufzeit_W - akt_Laufzeit_W
      if Laufzeit_W >= max_Laufzeit then                    'max. Laufzeit in min.
         Laufzeit_W = 0
         gosub Stop_West                                    'Relais ausschalten
         Call WEB_Anzeige
      else
         Call RLZ_West_anzeigen
      End if
   End if
 West_end:
   if Debuggen = 0 then
      gosub CRLF
      Meldung = "West Start Ende / West aktiv: " + str(West_aktiv) + " West verz.: " + str(West_verz) + "   Süd aktiv: " + str(Sued_aktiv) + " Süd verz.: " + str(Sued_verz) + " LZW: " + str(Laufzeit_W)
      gosub SWPrint
      Gosub CRLF
   end if
'   Block_Zeitanzeige = 0                                    'Zeitausgabe wieder freigeben
Return

Start_West:
   If West_aktiv = 0 then                                   'nur wenn nicht schon aktiv
      West_aktiv = 1                                        'West ist nun aktiv
      Disable Int2                                          'Flusswächter deaktivieren
      Notbremse = 1                                         'Notbremse aktivieren
      Notbremse_timer = Notbremse_time                      'und Timer mit Wert laden
      Power_K6 = 1                                          '230V einschalten
      waitms 10
      Motor_K5 = 1                                          'Motorventil einschalten
      Magnet_Starttimer = Magnet_Starttime                  'Verzögerungstimer starten
      if Debuggen = 0 then
         gosub CRLF
         Meldung = "Start W"
         gosub SWPrint
         Meldung = "Power on"
         gosub SWPrint
         Meldung = "Wasser ein"
         gosub SWPrint
      end if
   End if
Return

Stop_West:
   if Debuggen = 0 then
      gosub CRLF
      Meldung = "West Stop Anfang / West aktiv: " + str(West_aktiv) + " West verz.: " + str(West_verz) + "   Süd aktiv: " + str(Sued_aktiv) + " Süd verz.: " + str(Sued_verz)
      gosub SWPrint
      Gosub CRLF
   end if
   If Sued_aktiv = 0 then                                   'nur wenn Süd nicht schon läuft
      if Sued_verz = 1 then
         Sued_K2 = 1                                        'Ventil Süd ein
         Sued_verz = 0                                      'Vormerker Süd zurückstellen
         Sued_aktiv = 1                                     'Süd ist nun aktiv
         Call RLZ_Sued_anzeigen                             'und auf Display anzeigen
         West_K1 = 0                                        'Ventil West aus
         West_aktiv = 0                                     'Merker West zurückstellen
         West_verz = 0
         Laufzeit_W = 0                                     'alle Zeiten zurücksetzen
         akt_Laufzeit_W = 0
         Restlaufzeit_W = 0
        else
         Motor_K5 = 0                                       'Motorventil schliessen
         Magnet_Stoptimer = Magnet_Stoptime                 'Timer bis Magnetventil schliesst
         if Debuggen = 0 then
            gosub CRLF
            Meldung = "Stop West: Motorventil schliesst"
            gosub SWPrint
         end if
         Call Restbereich_loeschen
         LCD_Text "Motorventil" , 50 , 130 , 2 , Red , Black , 1
         LCD_Text " schliesst" , 50 , 170 , 2 , Red , Black , 1
      end if
    else
      West_K1 = 0                                           'zur Sicherheit Ventil West aus
      West_aktiv = 0                                        'Merker West zurückstellen
      West_verz = 0
      Laufzeit_W = 0                                        'alle Zeiten zurücksetzen
      akt_Laufzeit_W = 0
      Restlaufzeit_W = 0
      Call RLZ_Sued_anzeigen
   End if
   if Debuggen = 0 then
      gosub CRLF
      Meldung = "Stop West"
      gosub SWPrint
   end if
   if Debuggen = 0 then
      gosub CRLF
      Meldung = "West Stop Ende / West aktiv: " + str(West_aktiv) + " West verz.: " + str(West_verz) + "   Süd aktiv: " + str(Sued_aktiv) + " Süd verz.: " + str(Sued_verz)
      gosub SWPrint
      Gosub CRLF
   end if
Return

'_______________________________________________

Sued_ea:
   If Displaybeleuchtung = 0 then
      Call Display_on
      goto Sued_end
   End if
   if Debuggen = 0 then
      gosub CRLF
      Meldung = "Süd Start Anfang / West aktiv: " + str(West_aktiv) + " West verz.: " + str(West_verz) + "   Süd aktiv: " + str(Sued_aktiv) + " Süd verz.: " + str(Sued_verz) + " LZS: " + str(Laufzeit_S)
      gosub SWPrint
      Gosub CRLF
   end if
   Block_Zeitanzeige = 1                                    'Zeitausgabe verhindern
   If Laufzeit_S = 0 then                                   'Start, erster Tastendruck
      Laufzeit_S = Laufzeit_S + 6                           'Startwert 6 Min.
 Sued_ea1:
      akt_Laufzeit_S = 0                                    'aktuelle Laufzeit ist 0
      Restlaufzeit_S = Laufzeit_S - akt_Laufzeit_S
      Call RLZ_Sued_anzeigen
      if West_aktiv = 0 then                                'West nicht aktiv
         gosub Start_Sued                                   'also Starten
      else
         Sued_verz = 1                                      'Süd startet nach West
      end if
      Call WEB_Anzeige                                      'und auf WEB darstellen
    Else                                                    'für weitere Tastendrücke
      Laufzeit_S = Laufzeit_S + 5                           'Wert um 5 Min. erhöhen
      Restlaufzeit_S = Laufzeit_S - akt_Laufzeit_S
      if Laufzeit_S >= max_Laufzeit then                    'max. Laufzeit
         Laufzeit_S = 0
         gosub Stop_Sued                                    'Relais ausschalten
'         Call Normalanzeige
         Call WEB_Anzeige
      else
         Call RLZ_Sued_anzeigen
      End if
   End if
 Sued_end:
   if Debuggen = 0 then
      gosub CRLF
      Meldung = "Süd Start Ende / West aktiv: " + str(West_aktiv) + " West verz.: " + str(West_verz) + "   Süd aktiv: " + str(Sued_aktiv) + " Süd verz.: " + str(Sued_verz) + " LZS: " + str(Laufzeit_S)
      gosub SWPrint
      Gosub CRLF
   end if
'   Block_Zeitanzeige = 0                                    'Zeitausgabe wieder freigeben
Return

Start_Sued:
   If Sued_aktiv = 0 then                                   'nur wenn nicht schon aktiv
      Sued_aktiv = 1                                        'Merker Süd setzen
      Disable Int2                                          'Flusswächter deaktivieren
      Notbremse = 1                                         'Notbremse einschalten
      Notbremse_timer = Notbremse_time                      'und Timer mit Wert laden
      Power_K6 = 1                                          '230V einschalten
      waitms 10
      Motor_K5 = 1                                          'Wasser einschalten
      Magnet_Starttimer = Magnet_Starttime                  'Verzögerungstimer starten
      if Debuggen = 0 then
         gosub CRLF
         Meldung = "Start S"
         gosub SWPrint
         Meldung = "Power on"
         gosub SWPrint
         Meldung = "Wasser ein"
         gosub SWPrint
         gosub CRLF
      end if
   End if
Return

Stop_Sued:
   if Debuggen = 0 then
      gosub CRLF
      Meldung = "Süd Stop Anfang / West aktiv: " + str(West_aktiv) + " West verz.: " + str(West_verz) + "   Süd aktiv: " + str(Sued_aktiv) + " Süd verz.: " + str(Sued_verz)
      gosub SWPrint
      Gosub CRLF
   end if
   if West_aktiv = 0 then                                   'nur wenn West nicht schon läuft
      if West_verz = 1 then
         West_K1 = 1                                        'Ventil West öffnen
         West_verz = 0                                      'Vormerker West zurückstellen
         West_aktiv = 1                                     'West ist nun aktiv
         Call RLZ_West_anzeigen                             'und auf Display anzeigenWest akt=
         Sued_K2 = 0                                        'Ventil Süd schliessen
         Sued_aktiv = 0                                     'Merker Süd zurückstellen
         Sued_verz = 0
         Laufzeit_S = 0                                     'alle Zeiten zurücksetzen
         akt_Laufzeit_S = 0
         Restlaufzeit_s = 0
        else
         Motor_K5 = 0                                       'Motorventil schliessen
         Magnet_Stoptimer = Magnet_Stoptime                 'Timer bis Magnetventil schliesst
         if Debuggen = 0 then
            gosub CRLF
            Meldung = "Stop Sued: Motorventil schliesst"
            gosub SWPrint
         end if
         Call Restbereich_loeschen
         LCD_Text "Motorventil" , 50 , 130 , 2 , Red , Black , 1
         LCD_Text " schliesst" , 50 , 170 , 2 , Red , Black , 1
      end if
    else
      Sued_K2 = 0                                           'zur Vorsicht Ventil Süd schliessen
      Sued_aktiv = 0                                        'Merker Süd zurückstellen
      Sued_verz = 0
      Laufzeit_S = 0                                        'alle Zeiten zurücksetzen
      akt_Laufzeit_S = 0
      Restlaufzeit_s = 0
      Call RLZ_West_anzeigen
   end if
   if Debuggen = 0 then
      gosub CRLF
      Meldung = "Stop Süd"
      gosub SWPrint
   end if
   if Debuggen = 0 then
      gosub CRLF
      Meldung = "Süd Stop Ende / West aktiv: " + str(West_aktiv) + " West verz.: " + str(West_verz) + "   Süd aktiv: " + str(Sued_aktiv) + " Süd verz.: " + str(Sued_verz)
      gosub SWPrint
      Gosub CRLF
   end if
Return


Stop_S_W:
   Sued_verz = 0                                            'damit nicht Süd gestartet wird
   gosub Stop_West
   waitms 100
   West_verz = 0                                            'damit nicht West gestartet wird
   gosub Stop_Sued
Return

Not_aus:
   Disable Interrupts
   Displaybeleuchtung = 0
   LCD_Init
   LCD_Clear Black
   Displaybeleuchtung = 1
   LCD_Text "Not-AUS" , 0 , 100 , 2 , Red , Black , 1
   West_aktiv = 0                                           'Merker West zurückstellen
   Laufzeit_W = 0                                           'alle Zeiten zurücksetzen
   akt_Laufzeit_W = 0
   Restlaufzeit_W = 0
   Sued_aktiv = 0                                           'Merker Süd zurückstellen
   Laufzeit_S = 0                                           'alle Zeiten zurücksetzen
   akt_Laufzeit_S = 0
   Restlaufzeit_s = 0
   West_verz = 0
   Sued_verz = 0
   Motor_K5 = 0                                             'Motorventil schliessen
   wait 3
   West_K1 = 0                                              'Ventil West schliessen
   wait 1
   Sued_K2 = 0                                              'Ventil Süd schliessen
   Power_K6 = 1                                             'zur Vorsicht, sollte noch 1 sein
   wait Motorventillaufzeit                                 'Ventillaufzeit abwarten
   Power_K6 = 0
   wait 1
   if Debuggen = 0 then
      gosub CRLF
      Meldung = ">>>>> NOT-AUS <<<<<"
      gosub SWPrint
      gosub CRLF
   end if
   Enable Interrupts
   waitms 100
   goto 0                                                   'RESET
Return                                                      'da kommt er nie hin


'-------------------------------------------------------------------------------
'------------------    Unterprogramme für Anzeige-Ausgabe     ------------------
'-------------------------------------------------------------------------------

Sub Display_on:
   Call Normalanzeige
   Beleuchtungstimer = max_Beleuchtungsdauer
End Sub

Sub Normalanzeige:
   If Sued_aktiv = 0 and West_aktiv = 0 then
      Call Titelanzeige
      Call Zeitanzeige
      Call Datumanzeige
   End if
End Sub

'Sub Titelanzeige_loeschen:
'   LCD_Box 0 , 0 , 319 , 75 , 1 , Black , Black
'End Sub

Sub Restbereich_loeschen:
   LCD_Box 0 , 76 , 319 , 239 , 1 , Black , Black
End Sub

Sub Titelanzeige:
   Displaybeleuchtung = 0
   LCD_Init
   LCD_Clear Black
   Displaybeleuchtung = 1
   LCD_Text "Annes Rasen-" , 40 , 10 , 2 , Green , Black , 1
   LCD_Text "bewässerung " , 40 , 40 , 2 , Green , Black , 1
   LCD_Line 1 , 75 , 320 , 75 , 2 , White                   'make line
End Sub

Sub Zeitanzeige:
   Text = Hex(bcd_hour) + ":" + Hex(bcd_min) + ":" + Hex(bcd_sec)       'Uhrzeit
   Lcd_text Text , 60 , 100 , 1 , Blue , Black , 2          'Datum
End Sub

Sub Datumanzeige:
   Text = Hex(bcd_day) + "." + Hex(bcd_month) + "." + Hex(bcd_year)
   Lcd_text Text , 60 , 140 , 1 , Blue , Black , 2
End Sub

Sub RLZ_Sued_anzeigen:
   Call Restbereich_loeschen
   Text = "Laufzeit  S: " + str(Laufzeit_S) + "m"
   LCD_Text Text , 0 , 100 , 2 , Green , Black , 1
   Text = "Restlaufz S: " + str(Restlaufzeit_S) + "m"
   LCD_Text Text , 0 , 140 , 2 , Green , Black , 1
   Text = "Sicherheitstimer: " + str(Sicherheit_min) + " min"
   LCD_Text Text , 0 , 190 , 1 , Red , Black , 1
End Sub

Sub RLZ_West_anzeigen:
   Call Restbereich_loeschen
   Text = "Laufzeit  W: " + str(Laufzeit_W) + "m"
   LCD_Text Text , 0 , 100 , 2 , Green , Black , 1
   Text = "Restlaufz W: " + str(Restlaufzeit_W) + "m"
   LCD_Text Text , 0 , 140 , 2 , Green , Black , 1
   Text = "Sicherheitstimer: " + str(Sicherheit_min) + " min"
   LCD_Text Text , 0 , 190 , 1 , Red , Black , 1
End Sub


'-------------------------------------------------------------------------------
'------------------    Unterprogramme für SW-Print-Ausgabe     -----------------
'-------------------------------------------------------------------------------

SWPrint:                                                    'Ausgabe über die Serieschnittstelle mit
   ESP_disable = 1                                          'abgeschaltetem ESP8266
   Print Meldung
   ESP_disable = 0                                          'und wieder freigeben
Return

CRLF:                                                       'Ausgabe über die Serieschnittstelle mit
   ESP_disable = 1                                          'abgeschaltetem ESP8266
   Print
   ESP_disable = 0                                          'und wieder freigeben
Return


'-------------------------------------------------------------------------------
'------------------    Unterprogramme für Flusswächtertest     -----------------
'-------------------------------------------------------------------------------

Flusswaechter:                                              'nur aktiv im Ruhezustand
   Text = "Flusswächter"
   LCD_Text Text , 10 , 30 , 2 , Red , Black , 1
   Text = "hat angesprochen"
   LCD_Text Text , 10 , 80 , 2 , Red , Black , 1
   if Debuggen = 0 then
      gosub CRLF
      Meldung = ">>>> Flusswächter hat angesprochen <<<<"
      gosub SWPrint
      gosub CRLF
   end if
   wait 2
   goto Not_aus                                             'führt zu einem SW-Reset
Return


'-------------------------------------------------------------------------------
'-------------------    Unterprogramme für WEB-Auswertung     ------------------
'-------------------------------------------------------------------------------

Serial0charmatch:                                           'Interrupt vom seriellen Eingang
   dim charakter as string * 1

   Befehl = ""                                              'Puffer leeren
   While Ischarwaiting() = 1                                'Zeichen sind da
      charakter = inkey()                                   'abholen
      Befehl = Befehl + charakter
      If Len(Befehl) = 3 then                               'es werden nur 3 Zeichen empfangen
         Clear serialin
      end if
   WEND
   Clear serialin                                           'Empfangspuffer leeren
   if Befehl = "W05" or Befehl = "W10" or Befehl = "S05" or Befehl = "S10" or Befehl = "AUS" then serCode_da = 1
Return


Code_auswerten:
   if Debuggen = 0 then
      gosub CRLF
      Meldung = "vor Select Case WEB: " + Befehl + "  serCode_da: " + hex(serCode_da)
      gosub SWPrint
      gosub CRLF
   end if

'Auswerung mittels Select Case

   Select Case Befehl
      Case "W05" :
         Laufzeit_W = 5                                     'Startwert 5 Min
         gosub West_ea1
         Befehl = ""
      Case "W10"
         Laufzeit_W = 10                                    'Startwert 10 Min
         gosub West_ea1
         Befehl = ""
      Case "S05" :
         Laufzeit_S = 5                                     'Startwert 5 Min
         gosub Sued_ea1
         Befehl = ""
      Case "S10" :
         Laufzeit_S = 10                                    'Startwert 10 Min
         gosub Sued_ea1
         Befehl = ""
      Case "AUS" :
         gosub Stop_S_W
         Call Normalanzeige
         Call WEB_Anzeige
         Befehl = ""
      Case else :
'         gosub Stop_S_W
         Call Normalanzeige
         Call WEB_Anzeige
         Befehl = ""
   End Select

   serCode_da = 0

   if Debuggen = 0 then
      gosub CRLF
      Meldung = "nach Select Case WEB,  serCode_da: " + hex(serCode_da)
      gosub SWPrint
      gosub CRLF
   end if
Return


'-------------------------------------------------------------------------------
'-------------------    Unterprogramme für WEB-Ausgabe     ---------------------
'-------------------------------------------------------------------------------

WEB_Ausgabe:
   if WEB_Ausgabe_erledigt = 0 then Call WEB_Anzeige        'damit nicht mehrmals gesendet wird
   WEB_Ausgabe_erledigt = 1                                 'für diese Minute Ausgabe erledigt
Return


Sub WEB_Anzeige:
   Const Head1 = "<html><style>.td{color:black;font-family:Arial,sans-serif;font-size:26px;font-weight:bold;}</style>"
   Const Head2 = "<body><table border=1px cellspacing=0 cellpadding='5' style= width:100%>"
   Const Head3 = "<tr><td class = 'td' colspan=2>Zustand Steuerung:</Font></td></tr>"

   if Power_K6 = 1 then
      Status_Power = "<tr><td class = 'td' width=300 bgcolor=#00FF40>230V eingeschaltet</td>"
   else
      Status_Power = "<tr><td class = 'td' width=300 bgcolor=#F7819F>230V ausgeschaltet</td>"
   end if

   if Motor_K5 = 1 then
      Status_Motor = "<td class = 'td' width=300 bgcolor=#00FF40>Motorventil f&uumlr Wasser ist offen</td></tr>"
   else
      Status_Motor = "<td class = 'td' width=300 bgcolor=#F7819F>Motorventil f&uumlr Wasser ist geschlossen</td></tr>"
   end if

   if Sued_aktiv = 1 then
      Status_Sued = "<tr><td class = 'td' width=300 bgcolor=#00FF40><b>Bew&aumlsserung S&uumld l&aumluft noch " + str(Restlaufzeit_S) + " min.</b ></td>"
   else
      if Sued_verz = 1 then
         Status_Sued = "<tr><td class = 'td' width=300 bgcolor=#BBE094><b>Bew&aumlsserung S&uumld wartet auf Start</b></td>"
      else
         Status_Sued = "<tr><td class = 'td' width=300 bgcolor=#F2F2D9><b>Bew&aumlsserung S&uumld ausgeschaltet</b></td>"
      end if
   end if

   if West_aktiv = 1 then
      Status_West = "<td class = 'td' width=300 bgcolor=#00FF40><b>Bew&aumlsserung West l&aumluft noch " + str(Restlaufzeit_W) + " min.</b></td></tr>"
   else
      if West_verz = 1 then
         Status_West = "<td class = 'td' width=300 bgcolor=#BBE094><b>Bew&aumlsserung West wartet auf Start</b></td></tr>"
      else
         Status_West = "<td class = 'td' width=300 bgcolor=#F2F2D9><b>Bew&aumlsserung West ausgeschaltet</b></td></tr>"
      end if
   End if

   Status_NT = "<tr><td colspan=2 bgcolor=#E0F2F7><Font size='5'><b>Sicherheitstimer, Ausschalten erfolgt nach " + str(Sicherheit_min) + " min.</b></Font></td></tr>"

   print Head1 ; Head2 ; Head3 ; Status_Power ; Status_Motor ; Status_Sued ; Status_West ; Status_NT ; "</table>" ;
   print "<table><tr><td class = 'td'>.  </Font></td></tr></table></body></html>"       'schafft etwas Abstand zwischen den Tabellen
   waitus 20
End Sub


'-------------------------------------------------------------------------------
'-------------------    Unterprogramme für RFM-Auswertung     ------------------
'-------------------------------------------------------------------------------
RFM_auswerten:

   Y = Empfangsbytes(1) - 1                                 'Datenlänge über alles ohne CRC16
   if Y = 7 then                                            'nur diese Anzahl akzeptiert
      Crc_16e = Crc16(Empfangsbytes(1) , Y )
      If Debuggen = 0 then                                  'mit DIP.1 schaltbar
         Y = Empfangsbytes(1) + 1
         gosub CRLF
         Meldung = "RxD:  "
         For x = 1 to y
            Meldung = Meldung + Hex(Empfangsbytes(x)) + " "
         next x
         gosub SWPrint
         Meldung = "SABe: " + Hex(SABe)
         gosub SWPrint
         Meldung = "CRC gerechn.: " + hex(CRC_16e)          'CRC-Vergleich gerechnet
         gosub SWPrint
         Meldung = "CRC Empfang:  " + hex(Empfangsbytes(y)) + hex(Empfangsbytes(y -1))       'mit Empfang"
         gosub SWPrint
      End If
   else
      goto Ende                                             'alles andere kommentarlos überspringen
   end if

   If Empfangsbytes(Empfangsbytes(1)) <> Low(crc_16e) Then
      If SABe = Handsenderadresse then                      'Handsender?
         gosub neg_Quittung
         goto Ende
      End if
   End if
   If Empfangsbytes(Empfangsbytes(1) + 1) <> High(crc_16e) Then
      If SABe = Handsenderadresse then                      'Handsender?
         gosub neg_Quittung
         goto Ende
      End if
   End if
   If SABe = Handsenderadresse then                         'Handsender?
      PNe = Empfangsbytes(4) and &B00001111                 'PNe ausmaskieren
      'hier wird verhindert dass, wenn der Sender die Quittung nicht empfängt,
      'bei der Sendewiederholung das Relais wieder geschaltet wird.
      If SABe = SABez and PNe = PNez then                   'gleiche Adresse und Paketnummer wie zuvor
         gosub pos_Quittung                                 'pos. Quittung senden
         Goto Ende                                          'und ohne Relaisschalten weiter
      End if
      SABez = SABe                                          'Adresse zwischenspeichern
      PNez = PNe                                            'Paketnummer zwischenspeichern

      gosub pos_Quittung                                    'nur wenn erlaubte Sender

      if Debuggen = 0 then
         gosub CRLF
         Meldung = "vor Select Case Funk: " + Hex(Code)
         gosub SWPrint
         gosub CRLF
      end if

   'Auswerung mittels Select Case

      Select Case Code
         Case &h10 :
            Laufzeit_S = 10                                 'Startwert 10 Min
            gosub Sued_ea1
            Code = &h00
         Case &h20
            Laufzeit_S = 20                                 'Startwert 20 Min
            gosub Sued_ea1
            Code = &h00
         Case &h30 :
            Laufzeit_W = 10                                 'Startwert 10 Min
            gosub West_ea1
            Code = &h00
         Case &h40 :
            Laufzeit_W = 20                                 'Startwert 20 Min
            gosub West_ea1
            Code = &h00
         Case else :
            gosub Stop_S_W
            Call Normalanzeige
            Call WEB_Anzeige
            Code = &h00
      End Select
   End if
Ende:
   Funkdaten_vorhanden = 0
   Reset Watchdog                                           'Watchdog triggern
Return


'====================== Quittungen zusammenstellen und senden ==================

neg_Quittung:
   If Debuggen = 0 then                                     'mit DIP.1 schaltbar
      Meldung = "QN  "
      gosub SWprint
   End if
   Sendebytes(1) = 3                                        '= LEN
   Sendebytes(2) = Handsenderadresse                        'zuvor empfangene Adresse
   Sendebytes(3) = Regnersteuerungsadresse                  'eigene Adresse
   Sendebytes(4) = &B10100000                               '=NACK  (hA0)
   Call RFM12_senden
Return


pos_Quittung:
   If Debuggen = 0 then                                     'mit DIP.1 schaltbar
      Meldung = "QP  "
      gosub SWprint
   End if
   Sendebytes(1) = 3                                        '= LEN
   Sendebytes(2) = Handsenderadresse                        'zuvor empfangene Adresse
   Sendebytes(3) = Regnersteuerungsadresse                  'eigene Adresse
   Sendebytes(4) = &B11100000 or PNe                        '=ACK  (hEx)
   Call RFM12_senden
Return


'*******************************************************************************
'*****************  Empfangs-Interrupt des Funkmoduls RFM12  *******************
'*******************************************************************************

Rfm_funkirq:
   Disable Int0                                             'während Interruptbehandlung ausschalten

   If LCD_CS = 0 then                                       'Test ob gerade LCD bedient wird
      LCD_war_aktiv = 1                                     'wenn ja merken
      LCD_CS = 1
      Summerzustand = Summer_aktiv                          'Summerzustand speichern
   End if

   Timer0 = Timer0_preload
   Start Timer0                                             'Start Zeitüberwachung (Byteweise)
   Incr Irq_akt_byte                                        'aktueller Bytezähler erhöhen (Startwert ist 0)
   Irq_empfangsbytes(irq_akt_byte) = Spitransfer(&Hb000)    'Empfangsbyte holen und abspeichern
   If Irq_akt_byte = 1 Then
      Irq_anzahlbytemax = Irq_empfangsbytes(1) + 1          'im ersten Byte steht die Anzahl folgender Datenbytes
   End If
   If Irq_akt_byte = Irq_anzahlbytemax Then                 'max. Anzahl Bytes erreicht
      Stop Timer0
      If irq_empfangsbytes(1) <= max_Empfangslaenge then    'auf max. Länge prüfen
         R = Memcopy(irq_empfangsbytes(1) , Empfangsbytes(1) , Irq_anzahlbytemax)       'umkopieren
         Funkdaten_vorhanden = 1                            'Merker setzen
      End if
      Irq_akt_byte = 0                                      'Bytezähler löschen
      R = Spitransfer(&Hca81)                               'FIFO FILL zurücksetzen
      R = Spitransfer(&Hca83)                               'FIFO FILL aktivieren
      Eifr.intf0 = 1                                        'Eventuell anstehenden Interrupt löschen
   End If

   If LCD_war_aktiv = 1 then                                'Displayausgabe war aktiv
      LCD_war_aktiv = 0                                     'Merker zurücksetzen
      LCD_CS = 0                                            'und wieder freigeben
   End if
   Enable Int0

   if Summerzustand = 1 then                                'Summer über Timer2 neu starten
      Timer2 = Timer2_Preload                               'für 0.5 ms
      Summer = 1                                            'Summer einschalten
      Start Timer2
   end if

Return

Timer0_irq:
   Stop Timer0                                              'Interrupt-Ueberwachung abgelaufen --> Stop
   Irq_akt_byte = 0                                         'Bytezähler löschen
   Funkdaten_vorhanden = 0                                  'Eventuellen Merker löschen
   R = Spitransfer(&Hca81)                                  'FIFO FILL zurücksetzen
   R = Spitransfer(&Hca83)                                  'FIFO FILL aktivieren
   Eifr.intf0 = 1                                           'Eventuell anstehenden Interrupt löschen
   if Debuggen = 0 then
      Meldung = "Timeout"
      Gosub SWprint
   end if
Return


'========================== Sendet die Quittung ================================
'Die Senderoutine ist für Polling des Senders geschrieben,
'es wird gewartet bis ein Byte gesendet ist


Sub Rfm12_senden()
   Disable INT0                                             'Empfänger ist sowieso abgeschaltet

   If LCD_CS = 0 then                                       'Test ob gerade LCD bedient wird
      LCD_war_aktiv = 1                                     'wenn ja merken
      LCD_CS = 1
      Summerzustand = Summer_aktiv                          'Summerzustand speichern
   End if

   If Debuggen = 0 then                                     'mit DIP.1 schaltbar
      Meldung = "TxD: " + Hex(Sendebytes(1)) + " " + Hex(Sendebytes(2)) + " " + Hex(Sendebytes(3)) + " " + Hex(Sendebytes(4))
      Gosub SWPrint
      gosub CRLF
   End if

   Anzahlbyte_s = Sendebytes(1) + 1                         'damit alle Bytes übertragen werden (+ LEN)
   D = Spitransfer(&H8238)                                  'Enable Transmitter; enable Synthesizer ;enable Crystal Osc
   Gosub Rfm12_warten
   D = Spitransfer(&Hb8aa)
   Gosub Rfm12_warten
   D = Spitransfer(&Hb8aa)
   Gosub Rfm12_warten
   D = Spitransfer(&Hb82d)
   Gosub Rfm12_warten
   D = Spitransfer(&Hb8d4)
   For N = 1 To Anzahlbyte_s
      Gosub Rfm12_warten
      D = &HB800 + Sendebytes(n)
      D = Spitransfer(d)
   Next N
   Gosub Rfm12_warten
   D = Spitransfer(&Hb8aa)
   Gosub Rfm12_warten
   D = Spitransfer(&Hb8aa)
   Gosub Rfm12_warten

   D = Spitransfer(&H8281)                                  'Tx aus, Rx ein
   D = Spitransfer(&H0000)                                  'Tx-Interrupt löschen
   D = Spitransfer(&HCA83)                                  'FIFO und Reset Mode

   Eifr.intf0 = 1                                           'Eventuell anstehenden Interrupt löschen
   Enable INT0                                              'Empfänger-Interrupt freigeben

   If LCD_CS = 0 then                                       'Test ob gerade LCD bedient wird
      LCD_war_aktiv = 1                                     'wenn ja merken
      LCD_CS = 1
      Summerzustand = Summer_aktiv                          'Summerzustand speichern
   End if

End Sub


Rfm12_warten:
   Ss = 0
   Do
   Loop Until Miso = 1
Return


'===============================================================================

Function Spitransfer(byval Dataout As Word) As Word

   Local Nspi As Integer
   Local Dspi As Integer
   Local Dmiso As Word

   SPCR.6 = 0                                               'Hardware-SPI ausschalten
   Ss = 0
   Dmiso = 0
   For Nspi = 1 To 16
      Dspi = Dataout And &H8000
      If Dspi = 0 Then
         Mosi = 0
      Else
         Mosi = 1
      End If
      Dataout = Dataout * 2
      Dmiso = Dmiso * 2
      Dmiso = Dmiso + Miso
      Sck = 1
      Waitus 1
      Sck = 0
   Next Nspi
   Ss = 1
   SPIINIT                                                  'Hardware-SPI einschalten
   SPCR.6 = 1                                               'Hardware-SPI einschalten
   Spitransfer = Dmiso
End Function


'_______________________________________________________________________________

'RFM-Initialisierung

Sub Rfm12_init()
   Local Wert As Word

   X = 0
   Restore Datainit3                                        'Initialisierungsfolge
   Do
      Read Wert
      D = Spitransfer(wert)
      Incr X
   Loop Until Wert = 0
   Waitms 200
   R = Spitransfer(&H0000)
End Sub

'_______________________________________________________________________________

Timer2_irq:
   Stop Timer2
   Summer = 0                                               'Summer ausschalten
Return

'_______________________________________________________________________________

$include "..\TFTDriver\ILI9341_routines_spi_Text.inc"

End                                                         'Programmende

'*******************************************************************************

$include "..\Font\jep_Font12x16.font"                       'Font 1, 26 Zeichen
$include "..\Font\jep_crn20x24.font"                        'Font 2, 16 Zeichen

'---------------------------------------------------

'Funkmodul Initialisierungsdaten mit 9600 Baud
Datainit3:
   Data &H80E8%                                             ' Enable: 868 Mhz;XTAL cap=12pf; TX-Register; RX-Fifo
   Data &H82D9%                                             ' Enable: Receiver; Crystal Osc; Base Band Block; Synthesizer, Disable Low-bat Detector; Transmitter; Wake-Up-Timer; Clock output Pin
   Data &HA67C%                                             ' &Ha67c=frequenz 434,15 Mhz oder z.B. &HA538 für 433,34 Mhz
   Data &HC647%                                             ' &Hc647=Datenrate '4.8kbps; C623=9600kbps; C611 =19200
   Data &H95C0%                                             ' Vdi , Fast , 67 kHz , 0db , -79dbm           !!!!!!!!!!
   Data &HC2AD%                                             ' Fiter=Digital; Recover Mode=Auto; Quality Threshold=4; Recovery Speed=Slow
   Data &HCA81%                                             ' FIFO INT Level=8; Sync on=2;Fifo Fill Start=Sync; Reset Sensitivity=High; Disable:FIFO Fill Enabled
   Data &HC483%                                             ' Enable: AFC Mode; AFC; Frequency Offset Register Disable: High Accuracy; Strobe
   Data &H9820%                                             ' Frequenz Shift=POS; Power Out=0 dB; Deviation=45 khz
   Data &HE000%                                             ' WakeUp-Timer=0s
   Data &HC800%                                             ' Duty Cycle = Infinity % OFF
   Data &HC000%                                             ' Low batterie=2,2V; Clock Pin=1 Mhz
   Data &HCED4%                                             ' Synchron Pattern
   Data &HCC76%                                             ' PLL Settings
   Data &H0000%                                             ' Status lesen, irqs zurückstellen
   Data 0%                                                  ' Ende Initialisierung

'*******************************************************************************
'        *************************************************************
'                ********************************************
'                        *************************


 
besucherzaehler-kostenlos.de