werte in ein db schreiben über indirekte adressierung

aleXandroW

Level-2
Beiträge
59
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
hi,
möchte jede sekunde mein db mit werten füllen. db ist ein array mit real platzhaltern. möchte das erstmal mit einem schieberegler in wincc flex simulieren. habe mir folgenden code überlegt

AUF DB 1
L 0
T #index
b001: NOP 0
U M 1.0 // immer 1 merker
FP M 0.5 // taktmerker mit 1s periode
SPBN a001
L #index
L 4
*I
SLD 3
LAR1
L MD 10
T DBB [AR1,P#0.0]
L #index
L 1
+I
T #index
L #index
L 20
<D
SPB b001
SPA a001
a001: NOP 0

problem ist das der index sich nicht erhöht, wo ist mein denkfehler
 
Also deine Flankenauswertung ist etwas seltsam...

Probier mal...

Code:
U M0.5
FP Mx.y //freier Merker
SPBN a001
AUF DB1
L 0
T #index
b001: NOP 0

Rest
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
falls #Index eine TEMP-Variable ist ... die merkt die Steuerung sich nicht.

Das Skript darfst du natürlich auch nicht als Schleife durchlaufen - dann ändert sich der M1.0 auch nicht.

Ansonsten wäre der OB35 auch noch eine Möglichkeit an Stelle des Taktgebers. Den OB35 kannst du so parametrieren, dass er jede Sekunde (oder auch sehr viel schneller) aufgerufen wird.

Gruß
Larry
 
genau

versuchs mal so
Code:
U M 0.5 // taktmerker mit 1s periode
FP M 1.0 // flankenspeicher
SPBN a001
 
AUF DB 1
L #index
L 4
*I 
SLD 3
LAR1 
L MD 10
T DB[COLOR=red][B]D[/B][/COLOR] [AR1,P#0.0]
L #index
L 1
+I 
T #index
b001: nop 0
 
L #index
L 20
>D
spbn m001
L 0
T #index
m001: nop 0
 
Zuletzt bearbeitet:
Wenn man deinen Kommentar hinter dem Flankenmerker richtig interpretiert, dann belgst du eines von den Taktmerkerbits mit ner positiven Flanke von M1.0.
Deshalb das nicht so machen, sondern für die Flanke einen freien Merker nehmen.

Läuft dein Programm denn und nur der Index wird nicht hochgezählt ?
beim Überfliegen hätte ich jetzt, bei dem Programm, getippt dass die CPU in Stop geht.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
programm läuft aber index zählt nicht hoch
Hmm, dann hast Du hier wohl was anderes gepostet, als das Programm, was bei Dir "läuft". :confused: ;)

Außer dem Haupt-Problem mit dem fehlerhaften FP (was schon hinreichend beanwortet wurde) gibt es noch weitere "Probleme" und "Unschönheiten" in dem geposteten Code.
Z.B. schreibst Du immer nur den Wert des MB13 (konstante! Quelladresse MD10) in jedes erste Byte (DBB [AR1,P#0.0]) eines Elements des REAL-Arrays in DB1 ab DBB0 (also in DBB0, DBB4, ... DBB76) - macht das irgendeinen Sinn?
#index soll ein INT (0..20) sein - mal rechnest Du *I und +I, dann vergleichst Du <D - unschön.
"SPA a001" ist überflüssig.

Ich würde Dein Programm etwa so umformen:
Code:
      U    M 0.5    // taktmerker mit 1s periode
      FP   M 2.0    // oder anderer freier Merker
      SPBN a001

      L    0
      T    #index

b001: L    #index
      SLD  5        // *4 wegen REAL-Array + SLD 3 für P#
      L    P#0.0    // bzw. Anfangsadresse des Array in DB1
      +D
      LAR1

//hier noch die zu schreibenden Werte in MD10 zur Verfügung stellen
//dabei AR1 nicht verändern!
//    ...

      L    MD 10
      AUF  DB 1
      T    DBD [AR1,P#0.0]

      L    #index
      +    1
      T    #index
      L    20
      <I
      SPB  b001

a001: NOP  0
Am Ende des Codes wird nach dem ersten Durchlaufen immer #index=20 sein (IN_OUT), ein Hochlaufen des #index wirst Du normal nicht beobachten können.

Harald
 
Ähh ... vielleicht nur so als Anmerkung :
Die Mittelwertbildung in einem (langen) Zyklus bringt nichts. Wie ich schon schrieb muss die Schleife so geändert werden, dass sie erst mit jeder Flanke einen Wert aufzeichnet und (erst) bei Erreichen von Index-Max. die Auswertung erfolgt.
Das wäre eine schöne Aufgabe für einen FB ...

@TE:
Wenn das Ganze aber einen Bezug zu deinem anderen Thread hat, dann wird dir das auch nicht helfen. Dafür bräuchtest du einen "gleitenden Mittelwert" - das heißt, du müßtest dir eigentlich nur den vorhergehenden Wert merken und ihn mit der entsprechenden Gewichtung mit dem neuen Wert in den Ausgabewert umrechnen. Also vielleicht so :
Code:
Ausgabewert := (Einlesewert + (alterWert * Gewichtung)) / (Gewichtung + 1) ;
alterWert := Ausgabewert ;
Gruß
Larry

Nachsatz:
Es wundert mich allerdings, dass die Siwarex das angeblich nicht kann. Ich hatte das Ding auch mal am Start und ich hatte dalediglich das Problem, dass ich den Rohwert da nicht rausbekam - ge-Mittelwert-et war kein Thema ...
 
hi pn/dp
kling logisch was du sagst, nur in deinem code schreibt er die werte nicht jede sekunde rein. da er in der schleife bleibt spielt der taktmerker ja keine rolle mehr
und warum schiebst du um 5 nach links? verstehe nicht wie du das meinst
 
Zuviel Werbung?
-> Hier kostenlos registrieren
hi pn/dp
kling logisch was du sagst, nur in deinem code schreibt er die werte nicht jede sekunde rein. da er in der schleife bleibt spielt der taktmerker ja keine rolle mehr
In der Tat.
Ich habe Harald's Code mal schnell angepasst:
Code:
      U    M 0.5    // taktmerker mit 1s periode
      FP   M 2.0    // oder anderer freier Merker
      SPBN a001
 
 
      L    #index
      SLD  5        // *4 wegen REAL-Array + SLD 3 für P#
      L    P#0.0    // bzw. Anfangsadresse des Array in DB1
      +D
      LAR1
 
//hier noch die zu schreibenden Werte in MD10 zur Verfügung stellen
//dabei AR1 nicht verändern!
//    ...
 
      L    MD 10
      AUF  DB 1
      T    DBD [AR1,P#0.0]
 
      L    #index
      +    1
      T    #index
      L    20
      <I
      SPB  a001
      L    0
      T    #index
a001: NOP  0
Die Variable #index muss jetzt allerdings irgendeine statische Variable sein.
Larry hat es ja schon erwähnt, könnte was für einen FB sein.
Oder du nimmst einfach ein freies Merkerwort.
und warum schiebst du um 5 nach links? verstehe nicht wie du das meinst
Steht doch schon im Kommentar. ;)
Um 3 schieben für das Pointerformat (3 Bit-Stellen)
und nochmals um 2 schieben für das Real-Format (index * 4 = 4 Byte)
 
in die indirekte adressierung muss ich mich noch reinfuchsen, habe eigentlich damit fast nie gearbeitet, kenne das nur mit
L #index
L 4
*I
SLD 3

das es mit SLD 5 genauso geht wusste ich net

@larry: Ausgabewert := (Einlesewert + (alterWert * Gewichtung)) / (Gewichtung + 1) ;
alterWert := Ausgabewert ;

mein Einlesewert ist doch das gewicht, ist ja das gleiche wie Gewichtung wenn ich das richtig sehe
 
Mit Gewichtung meinte ich das Verhältnis mit dem der alte Wert zum neuen steht. Wenn du für meine Gewichtung z.B. den Wert 10 als Betrag annimmst dann würde der neuste eingelesene Wert nur im Verhältnis 1:11 den letzten Wert beeinflussen, was dann etwas Ähnliches ist wie das, was du mit deinem Werte-Speicher wahrscheinlich vorhast ...
 
nur in deinem code schreibt er die werte nicht jede sekunde rein. da er in der schleife bleibt spielt der taktmerker ja keine rolle mehr
Macht Dein Code ja auch nicht. Wenn Dein im EP geposteter Code "laufen" würde, dann würde er ebenfalls bei jedem Sekundenpuls alle 20 Array-Elemente beschreiben.
Ich habe Deinen Code nur so verändert, daß er korrekt mit dem von Dir vorgegebenen Ablauf funktioniert.
Der Taktmerker spielt schon noch eine Rolle, er gibt ja vor, daß nur jede volle Sekunde der Code 1x durchlaufen wird und die ~ 400 anderen Programm-Zyklen dazwischen nicht. Bedenke: ein SPS-Programm wird zyklisch abgearbeitet - daher wohl auch Deine falsche Vorstellung, wie eine Schleife funktioniert.

Wenn Du aber eigentlich jede Sekunde die selbe eine Variable in das nächste Array-Element schreiben wolltest (sowas nennt sich Ringpuffer mit Überschreiben der ältesten Einträge, nur Schreib-Pointer), dann solltest Du das deutlicher schreiben. (Programmieren ist ein "exaktes" Handwerk, wo es sehr darauf ankommt, eine Aufgabe und dann das Programm exakt zu formulieren.)

In dem Fall darf es natürlich keine Schleife geben, sondern von Durchlauf zu Durchlauf (von Sekundenpuls zu Sekundenpuls) wird nur der Index erhöht und nur auf das eine Array-Element Array[Index] geschrieben. Das könntest Du so wie von Paule geändert machen. Da ich bei indirekter Adressierung grundsätzlich den Index VOR Verwendung prüfe, würde ich etwa so schreiben:
Code:
      U    M 0.5    // taktmerker mit 1s periode
      FP   M 2.0    // oder anderer freier Merker
      SPBN a001

      L    #index
      +    1        // index weiterstellen und auf
      L    20       // Anzahl Array-Elemente
      MOD           // (0..19) begrenzen
      T    #index

      SLD  5        // *4 wegen REAL-Array + SLD 3 für P#
      L    P#0.0    // bzw. Anfangsadresse des Array in DB1
      +D
      LAR1

      L    MD 10    // der einzuspeichernde REAL-Wert
      AUF  DB 1
      T    DBD [AR1,P#0.0]

a001: NOP  0
#index muß eine Variable mit "Gedächtnis" sein (STAT, IN_OUT oder globale Variable).
Der Code erhöht zuerst den Index und schreibt danach auf das indizierte Array-Element, schreibt also beim ersten Durchlauf in das zweite Array-Element Array[1]. Es füllt also das Array in dieser Reihenfolge: Array[1], Array[2], ... Array[19], Array[0], Array[1] ...
Bei Ringpuffern ist dieser Umstand aber meistens unerheblich.
Wenn Dein Ringpuffer unbedingt beim ersten Durchlauf auf das erste Array-Element Array[0] schreiben soll, dann müßtest Du lediglich den Index vor der ersten Verwendung mit -1 (oder 19) initialisieren.

warum schiebst du um 5 nach links?
Das ist ein altes Programmierer-Geheimnis, daß *4 einem SLD 2 entspricht ;), und SLD 2 und SLD 3 kann man dann gleich zu SLD 5 zusammenfassen.

Harald
 
ah ok

hab nochmal in die bedinungsanleitung der siwarex cs geguckt, finde da nichts mit gemittelter wert

Habe ich jetzt auch mal gerade gemacht.
Mit sind da die Parameter :
- Grenzfrequenz für Tiefpassfilter [5Hz ... 0.05 Hz]
- Filtertiefe Mittelwertfilter [0 ... 255]
aufgefallen. Ohne groß danach zu suchen !!!
Vielleicht beschäftigst du dich auch einmal damit. Die Schleifengeschichte ist natürlich auch toll - kannst du m.E. mit den Parametern der CS auch komplett umgehen ...

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
danke an alle

@larry die idee mit dem array war ja auf halbwegs auf mein reglerthema bezogen, wollte ja so mein istwert öfters aktualisieren damit ich keine große totzeit habe
wie ich das richtig verstehe ist der mittelwert hauptsächlich dafür da, damit er bei vibration gleich ausschlägt
 
... die beschriebenen Parameter der CS würden das Gleiche bewirken, wie du es mit dem Ringpuffer vorhast.

Die CS würde dir aber (so oder so) in einem schnelleren Zyklus ihren "Istwert" abliefern auf den du dann reagieren kannst. Da ist für mich der Zusammenhang zu deinem Regler-Thema ein bißchen "auf der Strecke" geblieben ...

Gruß
Larry
 
Zurück
Oben