3. Steuerungstechnik
(Grundlagen und Vorgehensweise) Stand: 16.01.2008
Struktur_Steuerungsprogramm , Struktur_Hauptprogramm
Retten_von_Variablen remanente und nicht-remanente Variable, Variable EEPROM
Retten von Daten bei
Spannungsausfall Wann war der
letzte Spannungsausfall? NEU
Automatischer Start_bei_Spannungswiederkehr (z.B. mit Kondensator)
Parallele_und_serielle_Abläufe
, Ablauf- und Verknüpfungssteuerung
Flanken Flanken-Ersatz ,
Zähler NEU
Aufrufbit
Melden und Befehlen, Verriegelungsbit, Meldebit und Meldenummer
Wartezeit und Überwachungszeit sowie
Einschaltverzögerung, Ausschaltverzögerung, Zeitbegrenzung
Schrittsteuerung (Ablaufsteuerung)
Schrittregister_mit_Wartezeit Verzweigung der
Schrittsteuerung ,
Bedienung Taster_mit_Flanke Taster_ohne_Flanke Prellen von
Schaltern, Stromstoßschalter
Gegenseitige_Verriegelung und
Ansteuerverriegelung
Sollwerte_eingeben Takten
mit steigender Geschwindigkeit
Begrenzungen für Eingaben, Zähler und Rechenergebnisse NEU
Datenregister Bit-Register, Byte-Register, Word-Register
Ordnung und Übersichtlichkeit
sparen Zeit und ersparen Fehler.
3.0.1) Struktur eines Steuerungsprogramms
(1) Definitionen Variable
für
Ports, Word, Byte, Bit usw.
Define Sollwert Byte
' Liste der Belegung EEPROM-Variable
' 4 = Betiebsstundenzähler (Minuten)
' 6 = Uhrzeit Start Stunde , Minute
(2) a) Definition Festwerte
Define Obergrenze 70
b) Definition
Pseudo-Variable
#Grenzwert RETURN Sollwert + 3
(3) Vorbesetzung von Variablen
bei Start
und Spannungswiederkehr
Sollwert = 40
(4)
Hauptprogramm
(Grobstruktur)
#Anfang Schleife
if Istwert < Sollwert then goto Ein
if Istwert >
Grenzwert then goto ....
gosub
xyz
#Ein
K1 = ON
Goto
weiter
#Aus
K1 = OFF
#weiter
(weitere
Programmteile)
Goto Anfang Schleife
(5) Unterprogramme für gosub
#xyz
if Istwert > Obergrenze then K2 = OFF
RETURN
3.0.2) Feinstruktur
des Hauptprogramms (4)
(0) Retten bei Spannungsausfall
Falls
notwendig
Abfrage Analogport 8 bzw. 7
(1)
Zeittakte bilden
SekundenImpuls
(2)
Messwerte erfassen
Istwert =
T1 / 2 -25
(3)
Schrittregister mit Wartezeit
Schritte weiterschalten
Wartezeiten
setzen
(4)
Bedienung
Tastatur
Schalter
(5)
Anzeigen
LED, LCD
(6) Schnittstelle
PC – Anzeige und Eingabe
3.0.3) Retten von Variablen-Werten
In der Steuerungstechnik unterscheidet man nicht-remanente, teil-remanente und voll-remanente Variable.
(1) Nicht-remanente Variable werden vom Betriebssystem nach einem Reset oder nach Spannungsausfall auf Null gesetzt.
Das sind die Variablen Byte 1 bis 24 und bei Erweiterung (siehe Solpersteine) Byte 25 bis 28 sowie Datum und Uhr.
(2) Teil-remanente Variable behalten ihren letzten Wert auch nach Reset und Start.
Jedoch bei einem Spannungsausfall können sie ihren Wert nur bei Batterie-Pufferung der c-contol retten.
Remanente Variable sind Byte 59 und 60 sowie 69 bis 72.
Erweiterung des Bereichs siehe Stolpersteine „mehr Variable“.
Remanente Variable sind notwendig, wenn bei Wiederanlauf bei Reset oder nach einem Spannungsausfall das Programm mit letztem Sollwert oder Richtungsbit Vorwärts/Rückwärts fortgesetzt werden soll.
Auch bei Neu-Laden des geänderten Programms behalten sie ihren Wert. So bleibt z.B. der Wert des Betriebsstundenzählers erhalten.
Sie können natürlich auch bei Reset und Wiederanlauf durch die Vorbesetzung (siehe 3.0.1) auf Null gesetzt werden.
(3) Voll-remanente Variable sind Speicherwerte im EEPROM .
Sie behalten ihren Wert bei Reset und bei Spannungsausfall, auch wenn keine Pufferbatterie verwendet wird.
Bei Neuladen des Programms werden sie jedoch überschrieben, wenn nicht besondere Vorkehrungen getroffen werden. Deshalb werden sie am Ende des EEPROMs abgelegt.
Wenn man Datum und Uhrzeit in EEPROM-Variable sichert, kann man z.B. nach Reset die Werte bei Wiederanlauf rückladen und hat sofort Werte bevor die Funkuhr synchronisiert. Jede Minute darf nicht gespeichert werden, weil die Lebensdauer des EEPROMs begrenzt ist. Weitere Nutzung siehe Softwarebausteine und das folgende Beispiel.
3.0.4) Retten von Daten bei Spannungsausfall
(Netzausfall)
Die Station meldet den Ausfall der Netzspannung an einem intern angeschlossenen Analogport.
Dadurch kann man Daten retten, sofern eine Batteriepufferung vorhanden ist. Außerdem kann man die Steuerung abschalten, um nicht die Batterie durch eingeschaltete Relais, LCD, usw. unnötig zu belasten.
Speichert man jeweils die Uhrzeit bei Spannungsausfall und bei Spannungswiederkehr, kann auf diese Weise die Ausfallzeit bestimmt werden.
Vor Neu-Laden eines Programms unterbreche ich die Netzversorgung und erzwinge damit die Speicherung der Uhrzeit. Beim Start des Programms habe ich dadurch die Uhrzeit mit nur geringer Abweichung, selbst wenn die Synchronisation mit der Funkuhr noch nicht erfolgt ist.
Mit dem folgenden Beispiel kann auch Datum und Uhrzeit des letzten Spannungsausfalls auf dem Bildschirm angezeigt werden.
Definition
Define Spg230V AD[8] ' Wert 255 bei vorhandener Netzspannung
weitere Definitionen siehe Softwarebausteine Teil EEPROM-Variable
Vorbesetzung, Rückladen der geretteten Daten bei Start
if year < 90 then goto UhrGesetzt ' year ist 97 ohne Funkuhr
' In diesem Beispiel wurde das Jahr nicht gespeichert.
year = 1 ' Vorbesetzung, wenn Funkuhr nicht gestellt
Zeiger = 76 : input# wert12 ' Datum holen letzte Speicherung (Platz 76)
day = wert1 : month = wert2 ' Datum setzen
input# wert12 ' Uhrzeit holen letzte Speicherung (Platz 78)
hour = wert1 : minute = wert2 ' Uhrzeit setzen
#UhrGesetzt
Hauptprogramm
'Datum und Uhrzeit retten bei Spannungsausfall
if Spg230V > 100 then goto SpannungOK
' Spannungsausfall
wert1 = day : wert2 = month 'Retten Datum letzter Spannungsausfall
Zeiger = 76 : print# wert12 'in EEPROM-Variable 76
wert1 = hour : wert2 = minute 'Retten Uhrzeit
print# wert12 ' in EEPROM-Variable 78
Abschalten bei Spannungsausfall
#Ausfall 'Schleife bei Spannungsausfall
K1 = OFF : K2 = OFF 'Brenner aus , Pumpe aus
if Spg230V < 200 then goto Ausfall 'Festhalten in Schleife (keine Bildschirmanzeige)
#SpannungOK
Anzeige des letzten Spannungsausfalls
Zeiger = 76 : input# wert12 ' Datum holen letzte Speicherung (Platz 76)
print "Letzter Spannungsausfall: ";wert1;".";wert2;
input# wert12 ' Uhrzeit holen letzte Speicherung (Platz 78)
print ". Uhr ";wert1;":";wert2;" "
Weitere Informationen siehe Kapitel Softwarebausteine Teil EEPROM
3.0.5) Start der Station bei
Spannungswiederkehr nach Netzausfall
Es gibt es mehrere Lösungen für einen automatischen Start:
(1) 12 Volt-Batterie mit
Abfrage Analogport 8 (siehe vorhergehenden Punkt 3.0.4)
Die folgenden
Lösungen bewirken auch einen automatischen Start, wenn die c-control nicht von
Hand gestartet war. Die Funktion der Starttaste als Einschalt-Taste ist also
aufgehoben. Der Programmierer muss für ein sicheres Verhalten sorgen.
(2) Drahtbügel mit
Pappplättchen und damit Starttaste
dauernd gedrückt halten
(3) Schalter einbauen, der
die Starttaste überbrückt (Abschalten vor Laden eines Programms)
(4) Kondensator einlöten
(die Seite von Conrad ist wieder erreichbar, siehe Linkliste)
3.0.6) Parallele und serielle Abläufe
Die Steuerung mehrerer Rollladenantriebe sind parallele Abläufe. Sie können unabhängig von einander die Rollladen öffnen oder schließen.
Dagegen ist eine Heizungssteuerung ein serieller Ablauf, da erst die Pumpe und danach der Brenner eingeschaltet wird.
Abläufe werden mit Schritten strukturiert. Man spricht dann von einer Ablaufsteuerung.
Bei einer Verknüpfungssteuerung wird die Ausführung von Befehlen vorwiegend mit AND, OR, usw. verknüpft ist. Diese Vorgehensweise stammt von der Projektierung von Schützen- und Relaissteuerungen sowie der Hardware-Elektronik.
Nach Einführung der Software-Steuerungen etwa ab Jahr 1970 setzten sich die Ablaufsteuerungen mit ihrer Schritt-Struktur durch.
Die Aufgabenstellung liegt immer in Klartext vor (Pflichtenheft). Durch Unterteilung der Aufgabe in Schritte gelangt man direkt zur Schrittsteuerung.
In der Steuerungstechnik gibt es nicht nur die Zustände „EIN“ und „AUS“ , sondern auch die Änderung von „EIN“ nach „AUS“ und umgekehrt.
Die Änderung nennt
man Flanke. Es gibt als Flankenmerker die Ein-Flanke (auch positive Flanke oder
steigende Flanke genannt), die Aus-Flanke und Doppelflanke (beide).
define
Zaehler byte
define
Anzahl byte
define
Bit81_88 byte[11] ' byte 11 (statische Bits 81 bis 88)
define
Flanke1 Bit[81] 'Flankenbit
define
FlankeSekpuls Bit[82] 'Flankenbit für Sek-Takt
define
Flanke2 Bit[83] 'Flankenbit
define
Aufrufbit Bit[86]
define
Heizung Bit[87]
define
Motor Bit[88]
3.1.1) Ein-Flanke (Aus-Flanke sinngemäß)
if Motor = ON then goto setz ' Motor Ein? Ja, dann setze EIN-Flanke
Flanke1 = OFF ' Reset Ein-Flanke (bei Motor Aus)
Goto Ende
#setz
if Flanke1 = ON then goto Ende ' Ein-Flanke gesetzt? Ja, dann Ende
Flanke1 = ON ' Setze Ein-Flanke (Sperre für weiteres Setzen)
Zaehler = Zaehler +1 ' Beispiel: zählt die Anzahl Motor-Einschaltungen
Aufrufbit = ON ' Beispiel: Aufruf einer Funktion
(siehe 3.2)
#Ende
3.1.2) Doppelflanke
(Ein und Aus)
meldet, dass ein Wechsel von EIN
nach AUS oder AUS nach EIN stattfand.
if Motor = Flanke2 then goto Ende2' Wenn Motor (Ein-Aus) gleich Flanke, dann „nichts tun“
Flanke2 = Motor ' andernfalls
setze Flanke = Motor (Ein-Aus) setzen
Anzahl = Anzahl +1 ' Beispiel: zählt die Anzahl Ein- und Ausschaltungen
#Ende2
3.1.3) Indirekte Flanke (Flanken-Ersatz)
Man kann auch ohne Flankenbit auskommen.
(1) Relais als Flanke
If
K1 = ON then goto weiter
K1 = ON
Zaehler = Zaehler + 1 ' Anzahl Ein
#weiter
(2) Relais als Flanke (Selbstmordschaltung)
If
K1 = OFF then goto weiter
K1 = OFF
Zaehler = Zaehler + 1 ' Anzahl Aus
#weiter
(3) Wert als Flanke
Im folgenden Beispiel sollen Mitternacht der Betriebsstundenzähler und Zähler der Brennerstarts auf Null gesetzt werden.
If
Brennerstarts = 0 then goto
ende3
if hour >< 0 or minute >< 0 or year > 90 then goto ende3
Brennerstarts = 0
wert12 =0 : Zeiger = 4 : print# wert12 ' Betriebstundenzähler Null setzen
#ende3
Ohne Abfrage Brennerstarts würde Mitternacht 1 Minute lang auf das EEPROM geschrieben (schädlich wegen begrenzter Lebensdauer).
Indem die Variable Brennerstarts auf Null gesetzt und ausgewertet wird, kann auf das EEPROM nur einmal geschrieben werden.
Die Abfrage „Year > 90“ verhindert, dass bei Neustart eines Programms die Zähler Null gesetzt werden. Bei Neustart steht year auf 97.
Die Abfrage „Brennerstarts“ kann natürlich mit „OR“ in der Zeile der Zeitabfrage eingebunden werden.
(4) Zeit als Flanke
If
MinutenImpuls = OFF then goto
ende4
if hour >< 0 or minute
>< 0 or year > 90 then goto
ende3
Brennerstarts = 0
wert12 =0 : Zeiger = 4 : print# wert12 ' Betriebstundenzähler Null setzen
#ende4
Durch den Minuten-Impuls wird bei Minute = 0 nur einmal je Tag bearbeitet.
Soll der Baustein zu einer Funktion gezwungen werden z.B. „Parkposition anfahren“, dann handelt es sich um ein Aufrufbit (aktives Befehlsbit).
Meldet es den Vollzug, dann spricht man von einem Meldebit. Dies kann wiederum als Verriegelungsbit im aufrufenden Baustein verwendet werden.
Das Verriegelungsbit ist auch ein Befehlsbit (passiv) und verhindert den Start eines Vorgangs in einem anderen Softwarebaustein.
3.2.1) Aufrufbit (Aufruf einer Funktion)
In einem Softwarebaustein (siehe 3.1.1) wird ein Aufrufbit gesetzt, das hier in diesem Baustein ausgewertet wird.
Das Aufrufbit veranlasst einen Vorgang in einem anderen Softwareteil (Softwarebaustein).
if Aufrufbit = OFF then goto Ende321 ' Wenn „Aus“, dann „nichts tun“
Heizung = ON ' Wenn Aufrufbit gesetzt, dann Funktion ausführen
if T1 < 50 then goto Ende321 ' Wenn Temperatur
kleiner Abschaltwert, dann ..
Aufrufbit = OFF ' Wenn Funktion erledigt , dann
Aufrufbit ausschalten, usw.
Heizung = OFF
#Ende321
In diesem Beispiel schaltet der aufrufende Baustein nur ein. Der ausführende Baustein wickelt den Vorgang einschließlich dem Ausschalten ab.
Natürlich kann der aufrufende Baustein auch die volle Befehlsgewalt haben, z.B.
Heizung = Aufrufbit AND T1 < 50 ' Aufrufbit schaltet ein (abhängig von der Temperatur) und aus.
3.2.2) Aufruf durch Ereignis (Beispiel schneller
Zähler)
In dem Beispiel sollen schnelle Zähl-Impulse am Frequenz-Eingang während einer Einschaltdauer oder Zeitdauer erfasst werden.
Am Frequenz-Eingang freq oder freq2 werden während der sogenannten Torzeit 1 sec lang die Impulse gezählt.
if Ereignis = OFF then goto Ende 322 ' Wenn „Aus“, dann „nichts tun“
if second >< oldsec then goto Ende 322 ' Wenn „Sekunde ausgewertet“, dann „nichts tun“
oldsec = second ' (Altwert als Flanke)
Zaehler = Zaehler + Freq2 ' Wert der vergangenen Sekunde dazu addieren
#Ende 322
3.2.3) Meldebit
und Meldenummer
Ein Byte kann nur 8 Meldebits haben, aber 256 Meldenummern (0 bis 255).
Während die Meldebits gleichzeitig melden können, kann es gleichzeitig nur eine Meldenummer geben.
In folgender Software wird jeweils der letzte Vorgang gemeldet. Vorteilhaft ist dabei, dass Bits nicht rückgesetzt werden müssen.
MeldeNr = 0
If HandAus then goto Markise_zurück
MeldeNr = 1
If Wind > 49 then goto Markise_zurück
MeldeNr = 2
If Sonne < 99 then goto Markise_zurück
MeldeNr = 10
If HandEin then goto Markise_vor
MeldeNr = 11
If Sonne > 150 then goto Markise_vor
goto ...
#Markise_zurück
goto..
#Markise_vor
goto
Auf einfache Weise kann der zugehörige Text ausgegeben werden.
On MeldeNr goto
print „Text0“, print „Text1“, print „Text2“, ... usw
3.3)
Wartezeit und Überwachungszeit
In der Steuerungstechnik unterscheidet man
nur diese zwei Zeittypen.
Die Wartezeit läuft im Normalfall immer zu Ende. Hierzu gehören die Zeitverzögerung unterschieden in Einschaltverzögerung und Ausschaltverzögerung sowie die Zeitbegrenzung und die Zeitverlängerung (Impulsverlängerung).
Dagegen läuft die Überwachungszeit im Normalfall nicht zu Ende. Mit ihr wird ein Vorgang überwacht, z.B. eine Rolllade muss in einer bestimmten Zeit auf oder geschlossen sein.
Läuft die Überwachungszeit ab, dann wird ein anderer
Steuerungsschritt z.B. Meldung des Fehlers eingeleitet. Der Fehler wird also
erst nach Ablauf der Überwachungszeit von der Steuerung erkannt; so gesehen ist
die Überwachungszeit eine Notlösung. Im Fall der Rolllade könnte die Hemmung
sofort durch Messung der Stromaufnahme oder durch einen Drehzahlwächter
festgestellt werden. Dieser Aufwand ist meist zu groß und bringt weitere
Fehlermöglichkeiten mit sich, deshalb ist die Überwachungszeit eine weit
verbreitete Lösung.
Wartezeit und Überwachungszeit werden
zweckmäßig in Verbindung mit dem Schrittregister_mit_Wartezeit
angewendet, dadurch werden nur zwei Byte für die Zeiten benötigt, weil in jedem
Schritt beide Zeiten mit neuen Zeitwerten gesetzt werden können.
define
Wert1 byte [7] '
Zwischenspeicher 1 (Rechenwerte und Zahlenübergabe)Bit 49-56
define
Sekpuls Bit[6] ' Bit 4-Sekunden Impuls
define
FlankeSekpuls Bit[82] ' Flankenbit für 4-Sek-Takt
define
wert1Bit0 Bit [49] ' Wert = 1
(für Bit-Handling des Byte wert1)
define
wert1Bit1 Bit [50] ' Wert = 2
define
wert1Bit2 Bit [51] ' Wert = 4
Als Zeittakt
werden Zeit-Impulse benötigt. Die Impulse stehen z.B. im Abstand von 4 Sekunden
nur während eines Programmdurchlaufs.
Zeittakt mit
TIMER siehe Kapitel Tipps
Sekpuls = OFF' Reset Sekunden-Impuls nach einem
Programmdurchlauf
wert1 = second 'Uhrzeit wird nach Byte geladen (Bit 2 wechselt alle 4 Sekunden)
if wert1Bit2 = FlankeSekpuls then goto EndeSekpuls'
wenn Wert1 Bit 2 gleich Flankenmerker , dann „nichts
tun“
FlankeSekpuls = wert1Bit2 ' andernfalls
Flankenmerker = Bitwert setzen
Sekpuls = ON ' Aufrufbit alle 4 sec als Zeittakt für
Wartezeit und Überwachungszeit
#EndeSekpuls
(1) Beispiel:
Zeitbegrenzung, Relais K1 wird nach Zeitablauf ausgeschaltet.
If K1 = ON then goto AUS
If
... then goto EIN
Goto weiter
#EIN
K1 = ON
Wartezeit = 21
Goto weiter
#AUS
if Sekpuls = OFF then goto weiter
if Wartezeit = 0 then K1 = OFF else Wartezeit
= Wartezeit –1
#weiter
(2) Beispiel: Zeitbegrenzung mit
einem byte Wartezeit für mehrere Relais, die nicht gleichzeitig benutzt werden.
if Sekpuls = OFF then goto weiter1
if Wartezeit = 0 then goto weiter1
Wartezeit = Wartezeit –1
#weiter1
If K1 = ON then goto AUS1
If
K2 = ON then goto AUS2
If
... then goto EIN1
If ... then goto EIN2
Goto weiter2
#EIN1
K1 = ON
Wartezeit = 21
Goto weiter2
#AUS1
if Wartezeit = 0 then K1 = OFF
goto weiter2
#EIN2
K2 = ON
Wartezeit = 47
Goto weiter2
#AUS2
if Wartezeit = 0 then K2 = OFF
#weiter2
(3) Beispiele für Wartezeit (Ein- bzw. Ausschaltverzögerung) und Überwachungszeit siehe weiter unten.
3.4) Schrittsteuerung (Ablaufsteuerung)
„Teile und herrsche“ war ein alter römischer Grundsatz.
In der Steuerungstechnik teilt man die Aufgabe in Teile,
um sie besser zu beherrschen.
if Lüfter = ON then goto Ausschalten ' Wenn der Lüfter läuft, wird nur das Ausschalten bearbeitet
if Temperatur > Sollwert then Lüfter = ON ' Vorteil: evt. Änderungen gelten nur für das Einschalten
goto EndeX
#Ausschalten
if Temperatur < (Sollwert + Diff) then Lüfter = OFF ' Vorteil: evt. Änderungen gelten nur für das Ausschalten
#EndeX
3.4.1)
Schrittregister Größere Abläufe werden in Schritte unterteilt.
'Die Steuerung wird in Ablaufschritte
strukturiert.
Dies hat den Vorteil, dass vom Programm nur das
bearbeitet wird, was im aktuellen Steuerungsschritt programmiert ist. Man kann
im Schritt gezielt ergänzen, ohne dass dies Auswirkungen in anderen Schritten
hat.
Die Programmteile der anderen Schritte können nicht
stören, weil sie nicht bearbeitet werden.
In einem Schritt wird man niemals Relais EIN und Relais
AUS programmieren, sondern dies in verschiedene Schritte legen.
if
(Schritt = 1) then goto Schritt1 ' Heizen
einschalten?
if
(Schritt = 2) then goto Schritt2 ' Pumpe ein
if
(Schritt = 3) then goto Schritt3 ' Heizen
einschalten
if (Schritt = 4) then goto Schritt4 ' Heizen ausschalten?
Schritt = 1 ' Neustart der Ablaufkette (wird die Schrittabfrage durchlaufen, wird Schritt 1 gesetzt )
Goto Ende12 '----------------->>>
#Schritt1 ' Heizen einschalten?
if (Istwert > Sollwert) then goto Ende12' Istwert größer als Sollwert ---- > nicht einschalten
Goto
Schrittweiter ' dort wird die Schritt-Nr um 1
erhöht
#Schritt2 'Pumpe ein
K2 = ON ' Pumpe Ein (Relais K2)
Goto Schrittweiter
#Schritt3 ' Heizen ein
K1 = ON ' (Brenner ein)
Goto Schrittweiter
#Schritt4 ' Heizen ausschalten? Heizen aus
Ausschaltwert (mindestens 5 Grad Differenz)
if (Istwert < Sollwert +5 ) then goto Ende12' Istwert kleiner als Sollwert +5 ---- > nicht ausschalten
K1 =
OFF 'Brenner Aus
#Schrittweiter
Schritt = Schritt + 1 ' Schritt-Nummer um 1 erhöhen
#Ende12
3.4.2) ***
Schrittsteuerung mit Wartezeiten ***
'In jedem Schritt kann eine Wartezeit gesetzt
werden, die rückwärts gegen Null läuft.
Ein Vorteil besteht darin, dass nur ein Byte für die
Wartezeit gebraucht wird, die in jedem Schritt mit neuem Zeitwert gesetzt werden
kann.
Nach Ablauf der
Wartezeit wird der eingeschaltete Schritt bearbeitet.
if
(Wartezeit = 0) then goto Schritt 'Wartezeit
abgelaufen? ja ---> geh zu Schritt
if (sekpuls = OFF) then goto Ende12
Wartezeit = Wartezeit -1 'Wartezeit
minus 1 x 4 sek (Zeittakt siehe oben)
goto
Ende12
#Schritt '
Schrittregister bei Wartezeit NULL (Beispiele)
if
(Schritt = 2) then goto Schritt2 ' Pumpe ein,
Wartezeit
if (Schritt = 3) then goto Schritt3 ' Heizen einschalten
goto Ende12
#Schritt2 'Pumpe ein
K2 = ON ' Pumpe Ein (Relais K2)
Einschaltverzögerung
für K1 in Schritt 3
Wartezeit = 10 'x 4 sec Wartezeit setzen
Goto Schrittweiter
#Schritt3 ' Heizen ein
K1 = ON ' (Brenner ein)
If T1 < 60 then goto Ende 12 ' Temperatur nicht erreicht
K1 = OFF
Ausschaltverzögerung
für K2 in Schritt 4
Wartezeit = 7'x4 sec Wartezeit setzen
Goto Schrittweiter
#Schritt4 ' Pumpe aus
K2 = OFF ' (Pumpe aus)
3.4.3) Verzweigung der Schrittsteuerung mit Wartezeiten
Während die Wartezeit läuft, wird in einem eigenen
Schrittregister gearbeitet, z.B. weil bei bestimmten Bedingungen die Wartezeit
abgebrochen werden soll.
Nach Ablauf oder Abbruch wird der eingeschaltete Schritt
bearbeitet.
Die Wartezeit kann auch vor Ablauf neu gesetzt werden
(nachtriggern).
if (Wartezeit = 0)
then goto Schritt 'Wartezeit abgelaufen? (Verzweigung)
if
(sekpuls = OFF) then goto SchrittWartezeit
Wartezeit = Wartezeit -1 'Wartezeit
minus 1 x 4 sek (siehe Zeittakt 4 sec)
#SchrittWartezeit '
Schrittregister bei Wartezeit läuft (Zweig 1)
if
(Schritt = 1) then goto Schritt1w ' Wartezeit
abbrechen?
Goto
Ende12
#Schritt1w 'Schritt 1
bei Wartezeit läuft
if .... then Wartezeit
= 23 ' Wartezeit neu setzen
(nachtriggern)!
if
(Istwert > 38) or (NachtSenkung = ON) then goto Ende12
wartezeit
= 0 ' Wartezeit abbrechen!
Goto Ende12
#Schritt '
Schrittregister bei Wartezeit NULL (Zweig
2)
if
(Schritt = 0) then goto Schritt0
if
(Schritt = 1) then goto Schritt1 ' Heizen
einschalten? (usw. siehe vorhergehende Abschnitte)
3.4.4) Schrittsteuerung ergänzt mit Überwachungszeit
#Schritt0
Überwachungszeit = 0 ' Reset
im Schritt vor der Nutzung
#Schritt1 ' Heizen einschalten?
if
Überwachungszeit > 240 then Pumpe = OFF ' Abfrage
Überwachungszeit (kein Heizbedarf)
GOSUB Üzeit '
Überwachungszeit läuft vorwärts
if (Istwert >
Sollwert) then goto Ende12' Istwert größer als
Sollwert ---- > nicht einschalten
Goto Schrittweiter ' dort wird die Schritt-Nr um 1 erhöht
------------------------------------------------------------------------
#Üzeit ' Unterprogramm Überwachungszeit
if sekpuls = OFF then RETURN
if Überwachungszeit > 254 then RETURN' 1 Byte, Zeit bleibt bei 255 stehen !
Überwachungszeit = Überwachungszeit +1 : RETURN
3.4.5) Schrittregister mit On .. goto..
Alternativ zum Schrittregister if ... then goto... kann die Verzweigung auch mit on... goto .. erfolgen.
On Schritt goto Schritt0, Schritt1, Schritt2, Schritt3, Schritt4,
Schritt5, Schritt6
Der zeilenmäßige Aufbau des if-Registers kann jedoch besser kommentiert werden.
Vorteilhaft ist es für Text-Zuordnung zum Schritt oder DOW:
On Schritt goto Text0, Text1, Text2,
Text3, Text4, Text5, Text6
#Text0
print „xyz“ : goto
EndeText
#Text1
print „abc“ : goto EndeText
3.5)
Bedienung mit Tast-Schaltern
define Sollwert byte [6]
define Wert1 byte [7] ' Zwischenspeicher 1 und Bit 49-56
define Bit81_88 byte [11] ' (statische Bits)<<(Bit 81 bis 88)<<
define wert1Bit0 Bit [49] ' für bit-Handling des byte wert1 (Zwischenspeicher)
define wert1Bit2 Bit [51]
define wert1Bit4 Bit [53]
define Flanke1 Bit [81] 'Flankenbit
define FlankeZeitpuls Bit [82] 'Flankenbit für Zeittakt
define AbfrageImpuls Bit [87] 'z.B. Bit HalbSekundenImpuls (ca. 0,6 sec)
Leichte Bedienung kann zweckmäßig mit Zeit-Impulsen erfolgen.
AbfrageImpuls = OFF :
wert1 = TIMER '(max 255 x 20 ms = 5,1 SEK)
if wert1bit4 = ON then goto weiter21 ' bzw. wert1Bit2
FlankeZeitpuls = OFF : goto Ende2
#weiter21
if FlankeZeitpuls = ON then goto Ende2
FlankeZeitpuls = ON : AbfrageImpuls = ON ' für Bedienung der Tasten
#Ende2
3.5.1) Taster mit Flanke Jeder Tasten-Druck schaltet einmalig.
Mechanische Schalter prellen, d.h. beim Schließen des Schalters öffnet er noch mehrmals während einer Zeit von z.B. 100 Millisekunden.
Ist die Zykluszeit des Programms größer (Messung siehe Tipps), sind keine Probleme zu erwarten.
if
not F1 then goto setz ' Taste
gedrückt? Ja, dann setze EIN-Flanke
Flanke1 = OFF ' Reset
Ein-Flanke
Goto Ende
#setz
if Flanke1 = ON then goto Ende3 ' Ein-Flanke gesetzt? Ja, dann Ende
Flanke1 = ON ' Setze Ein-Flanke (Sperre für weiteres Setzen)
Sollwert = Sollwert + 1 '(Beispiel für Sollwert erhöhen)
Relais = not Relais '(Beispiel für Funktion Stromstoßschalter)
#Ende3
3.5.2) Taster mit Flanke Jeder Tasten-Druck schaltet einmalig mit Maßnahme gegen Prellen.
Ist die Zykluszeit des Programms kleiner als der Prellvorgang, kann dies zu Problemen führen z.B. ein Zähler zählt mehrmals.
Fragt man Schalter nur bei gesetztem Bit Abfrage-Impuls ab, dann wird nur ein Schaltvorgang ausgewertet.
If
AbfrageImpuls = OFF then goto
Ende3 ' Impuls aus? Ja, dann keine
Schalterabfrage
Diese Befehlszeile wird vor obige Schalterabfrage 3.5.1) eingefügt.
Grenzschalter (Endschalter) mit sehr kurzer Betätigung können so nicht abgefragt werden.
3.5.3) Taster ohne Flanke (Takten)
Festhalten der Taste bewirkt taktweißes Hochschalten.
Außerdem spart man durch dieses Verfahren viele Flanken-Impulse.
Wenn das gesamte Programm lang ist, ergibt sich auch ohne Abfrage-Impuls eine Taktzeit.
Dann wird direkt gosub Schalter verwendet.
if AbfrageImpuls = ON then gosub Schalter
Goto Ende
#Schalter
if F1 then goto weiterF2' F 1 frei -->
Sollwert = Sollwert + 1
Return
#weiterF2
if F2 then return' F 2 frei -->
Sollwert = Sollwert - 1
Return
3.5.4) Mehrfache Nutzung
von Tastern
(5)
Bedienungsmenue
Mit einem eigenen Schrittregister baut man ein Bedienmenue auf, indem z.B. mit Taste 1 die Schritt-Nr hoch getaktet wird.
Die Schritt-Nr nennt man Anzeige-Nr, damit der Bediener informiert ist, welches Menue wirksam ist.
Die Tasten 2 bis 4 schalten je nach Anzeige-Nr andere Funktionen.
Zum Beispiel bei Anzeige-Nr = 1 wird mit Taste 3 bzw. 4 ein Sollwert höher bzw. niedriger gestellt, bei Anzeige-Nr = 2 ein anderer Sollwert und bei „3“ wird ein- bzw. ausgeschaltet.
(6)
Bedienungszeit
Das Schrittregister mit Wartezeit gestattet die Abfrage, ob eine Taste lange oder kurz betätigt wurde. Nach Ablauf der Wartezeit wird in Schritt 2 lediglich abgefragt, ob der Taster noch gedrückt ist. Bei „Ja“ wird nach Schritt 3 geschaltet bzw. bei „Nein“ nach Schritt 4.
(7)
Gleichzeitige Tastenbetätigung
Zum Beispiel kann man mit 2 Tasten 3 Funktionen schalten. Wenn beide Tasten gleichzeitig gedrückt werden, erhält man die zusätzliche Funktion.
In einfachen Fällen reicht der Vorrang beider Tasten.
If Taste1 and Taste2 then goto
AUSSCHALTEN
If Taste1 then goto LINKSLAUF
If Taste2 then goto RECHTSLAUF
Sicherheitshalber nutzt man wie bei Bedienzeit ein Zeitfenster. Taste 1 schaltet auf Schritt 1 und Taste 2 auf Schritt 2. In beiden Schritten wird nun verzweigt, je nachdem, ob der andere Taster nach Ablauf der Wartezeit betätigt ist.
Sogar 4 Funktionen kann man erreichen. Je nach Reihenfolge von Taste 1 und 2 wird ja Schritt 1 oder 2 eingeschaltet und dort wird nun unterschiedlich reagiert.
3.6) Gegenseitige Verriegelung
Werden zwei gleichrangige Funktionen verriegelt z.B. vorwärts und rückwärts oder Linkslauf und Rechtslauf, dann spricht man von „Gegenseitiger Verriegelung“.
Gegen gleichzeitige Bedienung (Tastendrücken) muss verriegelt werden. Der Bedienungsfehler muss vom Programm „abgefangen“ werden.
If
LinksTaster AND not RechtsTaster then gosub Linkslauf
If RechtsTaster AND
not LinksTaster then gosub Rechtslauf
Werden beide Tasten betätigt, wird keine Funktion ausgeführt.
Auch wenn der LinksTaster betätigt wird, fragt das Programm den RechtsTaster ab, was unsinnig ist.
Besser als der Befehl
gosub ist hier die Verwendung des Befehles goto, da er direkt das Programm
strukturiert.
If
LinksTaster then goto Linkslauf
If RechtsTaster then
goto Rechtslauf
Bei Betätigung LinksTaster wird RechtsTaster nicht mehr abgefragt.
Werden beide Tasten
betätigt, hat Linkslauf Vorrang. Wird dies nicht gewünscht, wird die
Ansteuerverriegelung angewendet.
If
LinksTaster AND not RechtsTaster then goto Linkslauf
If RechtsTaster AND not LinksTaster then goto
Rechtslauf
Die Schütze (Relais) müssen wegen ihrer Ein- bzw. Abschaltzeit (30 bis 100 msec) zusätzlich gegenseitig verriegelt sein, d.h. jeweils die Ansteuerung (Spule) wird über einen Öffner des anderen Schützes geführt.
3.7)
Folgeverriegelung, Plausibilitätsprüfung
siehe Kapitel Hardware
3.8) Sollwerte eingeben (Takten mit steigender Geschwindigkeit)
Muss der Sollwert um eine größere Zahl erhöht werden, ist zweckmäßig nicht nur mit +1 zu erhöhen sondern variabel.
Je länger die Taste gedrückt wird, desto größer werden die Sprünge.
Kurzes Drücken bewirkt nach wie vor Erhöhung +1.
Define x
byte
if not F1
then goto PlusVar
' Taste gedrückt? Ja, dann Takte
x = 1 ' Reset
Geschwindigkeit
Goto Ende37
#PlusVar
Sollwert = Sollwert + x ' Erhöhung Sollwert
if x > 200 then goto Ende4 ' Begrenzung
x = x + 1 ' Erhöhung der Geschwindigkeit
#Ende37
3.9) Begrenzungen für Eingaben,
Zähler und Rechenergebnisse
(1) Byte +1
If Zaehler = 255 then goto ... (bzw. Return)
Zaehler = Zaehler + 1 : goto... (bzw Return)
Alternativ Zaehler = MIN (255 , Zaehler +1)
(2) Byte – 1
If Zaehler = 0 then goto ... (bzw. Return)
Zaehler = Zaehler – 1 : goto... (bzw Return)
Alternativ Zaehler = MAX (0 , Zaehler – 1)
(3)
Byte + x
If Zaehler + x < 255 then Zaehler = Zaehler + x else Zaehler = 255
Alternativ Zaehler = MIN (255 , Zaehler + x)
(4)
Byte – x
If Zaehler – x > 0 then Zaehler = Zaehler – x else Zaehler = 0
Alternativ Zaehler = MAX (0 , Zaehler – x)
(5) Word +1
If Zaehler = 32767 then goto ...(bzw. Return)
Zaehler = Zaehler + 1 : goto ... (bzw. Return)
(6)
Word + x (für x
= 0 bis 32767)
Vorsicht: Die folgende Abfrage ist fehlerhaft, denn wird 32 767 überschritten, wird die Zahl negativ und ist dadurch kleiner.
If Zaehler + x <= 32767 then Zaehler = Zaehler + x else Zaehler = 32767
Richtig ist folgende Abfrage:
If Zaehler + x – 32767 < 0 then Zaehler = Zaehler + x else Zaehler = 32767
Oder man prüft, ob das Vorzeichen plus bleibt, wenn der Befehl ausgeführt wird:
If SGN (Zaehler + x) >= 0 then Zaehler = Zaehler + x else Zaehler = 32767
Oder anschließende Korrektur, wenn das Ergebnis kleiner 0 (= negativ) ist.
Zaehler = Zaehler + x
If Zaehler < 0 then Zaehler = 32767
Oder anschließende Korrektur bei negativem Vorzeichen der ausgeführten Rechnung:
Zaehler = Zaehler + x
If SGN (Zaehler) = -1 then Zaehler = 32767
(7)
Word – x (für x
= 0 bis 32767)
If Zaehler – x >= 0 then Zaehler = Zaehler – x else Zaehler = 0
Alternativen sinngemäß wie vor.
(8) Word + x (für x = -32767 bis +32767)
If x < 0 then goto negativ else goto positiv
Vorgeschaltet wird die Entscheidung, welcher Rechenweg gegangen werden muss.
Hier werden „echte“ Variable (byte oder word ) benutzt. Im Kapitel Softwarebausteine werden EEPROM-Variable behandelt.
(1) Byte-Register (für Historie)
Zur Darstellung vergangener Daten nimmt man für einfache Fälle mehrere Bytes.
Define R1 byte
Define R2 byte
Define R3 byte
Define R4 byte
Define Temperatur byte
Define Status byte [6]
Define StatusBit0 bit [41] ' (byte 6 *8 – 7 = BitNR)
Bei einem Ereignis (z.B. Einschaltung) oder zeitlich werden die Daten weitergeschoben.
R4 = R3 : R3 = R2 : R2 = R1 : R1 = Temperatur 1' Erst schieben, dann neue Temperatur speichern.
So einfach kann dieses Programmteil in den Schritt eines Schrittregisters eingefügt werden.
Andernfalls muss ein Zeitimpuls oder das Ereignis mit Flankenauswertung verwendet werden.
If
not ZeitImpuls then goto Ende38
R4 = R3 : R3 = R2 : R2 = R1 : R1 = Temperatur
#Ende38
(2) Bit-Register
(für Historie)
Beispielsweise kann zusätzlich der Status des Lüfters (EIN-AUS) gespeichert werden.
Hierzu reicht jeweils ein Bit (Ein-Bit-Register).
Status = Status SHL 1' Erst schieben (Historie)
StatusBit0 = Lüfter ' dann 1. Statusbit setzen
Da das Byte 8 Bit hat, können auch 4 Zustände (Lüfter1-2)
Status = Status SHL 2' 2 Bit schieben (Historie)
StatusBit0 = Lüfter1 : StatusBit1 =
Lüfter2 ' dann beide Statusbits setzen
Abfrage Bit 3 der Historie (Beispiel) weitere Abfragen
siehe „Tipps und Tricks“
Man teilt durch 8 (oder verständlicher durch &B 0000 1000 <- Bit 3 gesetzt)
Anschließend wird mit Modulo-Division festgestellt, ob ein Rest (=1, also ON) bleibt.
AnzeigeBit =
Wert / &B 0000 1000 MOD 2
oder alternativ schiebt man nach rechts um drei Bit
AnzeigeBit = Wert SHR 3 MOD 2
Danach kann abgefragt werde:
If
AnzeigeBit = ON then ... ' Achtung Bit-Abfrage (OFF/ON bzw. 0/–1)
Bei direkter Abfrage ist das Ergebnis eine Zahl 0 bzw. 1.
If Wert SHR 3 MOD 2 = 1 then .. ' Achtung Wert-Abfrage (0/1)
(3) Wordregister
unterteilt in Nibble (4 Bit)
Register schieben und Neuwert einlesen (für Historie)
Das Register hat 3 Word (RW1,usw.) unterteilt in 4 Nibble, also 12 Speicherstellen.
Es kann sinngemäß erweitert werden mit mehr words.
RW3 = RW3 SHL 4 ' Erst schieben um 4 Bit
Dann Übernahme des maskierten Nibble vom anderen Word.
Dabei wird erst das Nibble maskiert (vorrangig durch
Klammer),
dann 12 Bit geschoben und zusätzlich noch mal maskiert
wegen evt. Bit-Fehler
und dann mit Word zusammen gefügt.
RW3
=(RW2 and &HF000)SHR 12 and &H000F or RW3
RW2 = RW2 SHL 4 ' Erst schieben um 4 Bit
RW2 =(RW1 and
&HF000)SHR 12 and &H000F or RW2 ' Übernahme
Nibble vom anderen word
RW1 = RW1 SHL 4 ' Erst schieben um 4 Bit
wert1 = Sollwert – TG
' Bildung Neuwert 4 Bit (Sollwert abzüglich Festwert
TG)
if sollwert < TG then wert1 = 0 ' Begrenzung auf 0 bis 15 (4 Bit)
if wert1 > 15 then wert1 = 15
RW1 = RW1 or wert1 ' Übernahme Neuwert 0 - 15 (Nibble)
Registerwerte (Nibble) auslesen für Anzeige der Historie
#sp11 return RW1 and &H000F
#sp12 return RW1 SHR 4 and &H000F
#sp13 return RW1 SHR 8 and
&H000F
#sp14 return
RW1 SHR 12 and &H000F
#sp21 return RW2 and &H000F
#sp22 return RW2 SHR 4 and &H000F
#sp23 return RW2 SHR 8 and &H000F
#sp24 return
RW2 SHR 12 and &H000F
#sp31 return RW3 and &H000F
#sp32 return RW3 SHR 4 and &H000F
#sp33 return RW3 SHR 8 and &H000F
#sp34 return
RW3 SHR 12 and &H000F
Vorteilhaft wird hier Pseudo-Variable benutzt (hierzu siehe Tipps und Tricks).
Für die Anzeige wird einfach programmiert:
Anzeige = sp13 ' Anzeige von Speicher Registerwort 1 Nibble 3
Im vorliegendem Beispiel hat man sich auf den Temperaturbereich 30 bis 55 Grad für die gespeicherten Sollwerte beschränkt.
Die Konstante TG muss
also wieder hinzugefügt werden (define TG 30).
Anzeige = TG + sp13 '
Festwert TG plus Speicher Registerwort 1 Nibble 3
Im Kapitel Softwarebausteine werden Schieberegister mit EEPROM-Variable behandelt.
--------- ENDE Kapitel Steuerungstechnik ----------- nach_oben
------------------------- zurück zur Startseite