Programmierhilfe für S7

Joe.Baer

Level-1
Beiträge
13
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
habe ein sehr großes Problem. Da ich in der Programmierung von SPS überhaupt nicht durchsteige aber ich ein Programm für SIMATIC, Typreihe S7-300 bzw. S7-400 benötige, bin ich auf eure Hilfe angewiesen. Vielleicht kann mir ja einer von euch weiterhelfen!

Es soll eine Regelstrecke höherer Ordnung (Analoger Wert) in bestimmten Messintervallen (100, 200, 500 und 1000 ms) eingelesen werden. Der gewünschte Messintervall soll vom Benutzer vorgegeben werden. Dies soll über einen Taktmerker … .0 (100ms) und einem Zähler bei dem der Messinterfall als Zählerwert gesetzt wird realisiert werden (z.B. für den Messinterfall 200 ms ist der Zählerwert 2; für 500 ms ist er 5). Der eingelesene INT-Wert soll in einen REAL-Wert gewandelt werden. Der REAL-Wert soll in einem DB als „Tabelle“ abgelegt werden.
Da es sein kann, dass die Regelstrecke am abklingen ist (vor beginn des 2. Durchlaufs), muss kontrolliert werden, ob eine Änderung stattfindet. Findet keine Änderung mehr statt, soll mit der Aufnahme in ein DB begonnen werden (Start der Aufnahme). Bei erreichen des Ausgleiches (keine Änderung mehr vorhanden) soll die Aufnahme gestoppt werden. Der DB soll max. 3000 Werte (Doppelwort) erfassen (3000*4 Byte=12.000 Byte). Bei erreichen dieser Grenze soll eine Fehlermeldung Ausgegeben werden und die Aufnahme gestoppt werden. Ebenfalls soll eine Meldung über „Aufnahme aktiv“ und „Aufnahme beendet“ erscheinen.
Bei der Aufgenommenen Regelstrecke (Werte im DB) soll nun der kleinste und größte Wert ermittelt werden (min. und max. Regelgröße). Zudem soll der Wendepunkt der Strecke über ein Steigungsdreieck ermittelt werden. Bei max. Steigung (letztes mal der max. Steigung verwenden) wird der Steigungswert, der REAL-Wert und die dazugehörende Zeit benötigt. Diese Werte sollen ausgegeben werden.

Für Anregungen und besonders Hilfen bin ich sehr Dankbar!
Joe.Baer
 
Hatten wir das meiste davon nicht schon diskutiert?
Eine zeitlich exakte Aufzeichnung machst du besser über den OB35 als über einen Zeitgeber. In deinem Beispiel sind alle Zeiten Vielfache von 100ms. Wenn das so ist, rufst du den OB35 im 100ms Takt auf. Für 200ms beendest du den Baustein bei jedem 2. Aufruf ohne Daten zu holen.
Das "Steigungsdreieck" kannst du IM PRINZIP aus den Werten im FIFO (aus dem vorigen Beitrag) berechnen. Es ist allerdings schlecht, Ableitungen bzw. Differenzen einzelner Werte zu verarbeiten. Wenn durch Rauschen 100,101,99,100 gemessen wird, wäre da ein "Wendepunkt".
Das kann man über Filter hinkriegen. Dauert aber ein bischen...
 
Joe.Baer schrieb:
Ja, theoretisch habe ich es auch verstanden, aber mit der Praxis habe ich so meine Propleme ....
Womit genau?
OB35:

L MW 20 // Zaehler der Aufrufe
L 1
-I
T MW20
L 0
<>I
BEB // Wenn nicht 0 dann Ende
L MW22 // die Zahl n, wenn der Rest bei jedem n-ten Aufruf ausgeführt werden soll
T MW20 // Zähler wieder auf n
//
A DB 20 // dein FIFO
//
// Den 1. Wert aus dem FIFO holen, wir brauchen ihn um die Summen für AVR und RMS
// zu korrigieren
//
L DBD0
T lokaleVariable
//
// FIFO aufrücken
//
L DBD 4 // jedes real ist 4 byte lang
T DBD 0
L DBD 8
T DBD 4
L DBD 12
T DBD 8
...u.s.w.
L DBD 36 // 10. Wort
T DBD 32
//
// Ja, das geht auch mit Schleifen und Index, aber hier lohnt es nicht.
//
//
// Zahl gültiger Einträge
//
L DBW 40 // der Zähler für neue Einträge
L 1
+I
T DBW 40
L 10
<=I
SPB ok
L 10
T DBW 40 // Zähler hat maximal 10
ok: NOP0
//
// Analogwert holen und nach real wandeln, in FIFO schreiben:
//
L PEW320
ITD // nach doppelwort..
DTR //... und dann nach real wandeln
T DBD36 // letzter Eintrag
//
// deine Summen um Wert des herausgefallenen Elements korrigieren
//
L summeWerte
L lokaleVariable
-R
T summeWerte

L lokaleVariable
L lokaleVariable
*R
L summeQuadrate
TAK
-R
T summeQuadrate
//
// deine Summen um Wert des neuen Elements korrigieren
// das schreib ich jetzt nicht hin.
Deine Rechnung bezüglich der Größe der Änderung durchführen.

u.s.w.

Alles ungetestet.
 
Ich kann hier keinen kompletten Einführungskurs geben. Das folgende sollte reichen, um dir eine Vorstellung zu geben, wie man etwas, daß man in C formulieren kann, auf der SPS formuliert.
Ansonsten würde ich dir raten, dein Problem zunächst in C oder VB (nicht C++) zu programmieren. Du kannst dabei Regler und Regelstrecke leicht simulieren und per Tastendruck "Störungen" oder Sollwertsprünge simulieren.
Nachher kannst du die Teile posten, von denen du nicht weißt, wie du sie auf der SPS umsetzen sollst.

Assembler ist gut. Dann stell dir die S7 als eine Akkumulator-orientierte CPU vor (wie ein 6502).
Um etwas aus dem Speicher zu bekommen, mußt du es in den Akku laden:
L MW0

Den Akku kannst du wieder in den Speicher schreiben:
T MW2

Speicher kannst du als Bytes, Worte und Doppelworte ansprechen.

Speicher gibt's als einen zusammenhängenden Bereich M und als viele Datenbausteine. Datenbausteine brauchen immer die Datenbausteinnummer, so ein bischen wie die Segmentregister des 8086. Allerdings muß man sie erst anlegen, ein bischen wie malloc oder getmem, aber eher wie die Memory Descriptors beim 80386. Angelegt werden sie am besten in passender Größe mit Step7

Angesprochen werden sie dann:
L DB1:DW0 //lädt das erste Datenwort aus DB1
L DB1:DW6 //lädt das 7. Datenwort aus DB1
L DB10:DW0 //lädt das erste Datenwort aus DB10

Oder
AUF DB10
//
// ab jetzt geht alles mit DB10
//
L DW0 //lädt das erste Datenwort aus DB10
L DW6 //lädt das 7. Datenwort aus DB10
Die Notation mit AUF ist kürzer und schneller, denn bei
L DB10:DW0 //lädt das erste Datenwort aus DB10
erzeugt Step7 die Befelsfolge:
AUF DB10
L DW0

Du kannst mit indizierter Adressierung arbeiten:
L MW[MD0] // lade das Merkerwort, dessen Adresse in Merker-Doppelwort MD0 steht.
Die Adresse ist gleich der Anzahl BITS, die du zu 0 dazuzählen müsstest
Wenn MD0 hier 64 ist, wird das MW8 geladen.
Das geht auch für DWs
L DW[MD0] // lade das Datenwort, dessen Adresse in Merker-Doppelwort MD0 steht.
Nicht geht:
L DB10:DW[MD0] // FALSCH!!
sondern:
AUF DB10
L DW[MD0]

Beim Rechnen wird
1. Etwas in den Akku geladen. Dabei wird immer der Inhalt vonAKKU1 nach AKKU2 geladen.
2. Etwas in den Akku geladen. Dabei wird immer der Inhalt vonAKKU1 nach AKKU2 geladen.
3. Eine Rechenoperation mit AKKU1 und 2 ausgeführt. Ergebnis in AKKU1.
Wenn also AKKU1 ein Ergebnis enthält, mit dem weitergerechnet werden soll, kannst du dir das 1.Laden sparen.

Ergebnisse können getestet und in Abhängigkeit davon bedingte Sprünge ausgeführt werden:
<=R // vergleicht die 32-Bit-Inhalte der Akkus, ob sie als Gleitpunkt (float) Zahlen kleiner gleich sind. Welcher mit welchem verglichen wird vergeß ich immer...
SPB MARKe // springt zu einer Marke, Marken haben bis zu 4 Zeichen

L MD 44 // dieser Befehl wird dann übersprungen
MARK: NOP 0 // An einer Marke muß immer auch eine Anweisung stehen. Nackte Marken (Labels) gibt`s nicht. Das NOP empfiehlt sich dafür, weil man nachherdie Programmstruktur leichter ändern kann.

Mit Rückwärtssprüngen kann man Schleifen bauen.
Das ist aber nicht unbedingt gesund und üblich, denn:

1. Wird die Ausführungszeit überwacht. Ein Steuerungsprogramm, daß auf äußere Ereignisse reagieren muß, darf nicht mal eben einen Endschalter überfahren, weil es in einer langen Schleife herumrechnet.
2. Sind Schleifen oft nicht nötig, da der OB1 eh in einer Endlosschleife ausgeführt wird. In dem man pro OB1-Durchlauf das tut, was ein Schleifendurchlauf täte, kann man viele Schleifen-Konstrukte ersetzen.
 
Zurück
Oben