TIA High Speed zählen mit S7-1200

Yannick

New member
Beiträge
3
Punkte Reaktionen
0
Zuviel Werbung?
->Hier kostenlos registrieren
Hallo zusammen


Ich stehe zur Zeit vor einem Problem, das den ganzen Vortschritt des Projektes unglaublich verlangsamt.

Folgendes: an ca. 50 Orten auf unserer Anlage (Modelleisenbahnanlage im Massstab 1:11) werden die Anzahl Räder der Züge gezählt, welche durchfahren. Dies funktioniert bei uns mittels zwei Tastern, die direkt am Gleis montiert sind (siehe Bild).

IMG_1683.jpg

Wenn nun ein Zug darüber fährt, passiert ungefähr dies:

Sensor 1
0
0
1
1
0
Sensor 2
01
1
0
0

Jedes Mal, wenn dieses Muster auftaucht, soll ein Rad dazugezählt werden. (Umgekehrt soll ein Rad weggezählt werden.) - Soweit so gut :cool:

Nun zu meinem Problem :-?:
Da die Züge teilweise so schnell fahren (über 5km/h), dass die Signale von den Sensoren kürzer sind als die Programmzykluszeit, gehen einige Signale verloren. Folgendes habe ich schon versucht (und bin daran gescheitert):
  • HSC der CPU (übrigens 1215C DC/DC/Rly) verwenden: diese hat ja 6 integrierte HSCs mit A/B Counter (was ja ideal wäre). Jedoch hat sie nur sechs und dabei bleibt es (??) - wir brauchen 50 :-|
  • "SIMATIC ET 200SP, TM count 1x 24V Zählerbaugruppe" (6ES7138-6AA00-0BA0) (wir haben an verschiedenen Standorten auf der Anlage verteilt ET200SP zur dezentralen Peripherie) verwenden: kommt uns zu teuer, da wir ca. 50 Stück von denen brauchen würden (wir sind ein Verein und haben nicht Geld im Überschuss)
  • "DI 8x 24VDC High Speed" (6ES7131-6BF00-0DA0) mit Oversampling verwenden: 1200er unterstützen Oversampling nicht (??, OB6x fehlen??)

Hat jemand eine Idee, wie ich das sonst noch lösen könnte? Ist dieses Projekt überhaupt noch weiterrealisierbar mit einer 1215C und ET200SP oder empfiehlt es sich, einen Advanced Controller zu nehmen?


Vielen Dank im Voraus

Yannick
 

Fabpicard

Well-known member
Beiträge
753
Punkte Reaktionen
103
Für eine Modelleisenbahn und wenig Budget würde ich da an eurer Stelle die Zählstellen an Arduinos auslagern, welche mit Netzwerk ausgestattet sind und euch den Zählwert jede Sekunde mit "Settimino" (ist eine Snap7-Version für Arduino) in jeweilige DBs schreiben.

Damit ihr einen Ausfall erkennen könnt, kann der Arduino auch immer bei Zählwert 0 trotzdem einen Bool im DB auf 1 setzen. Wenn der kommt, wisst ihr das neue Daten da sind und setzt den ganzen DB auf 0 zurück für den nächsten Intervall... (vorher natürlich den Zähler verarbeiten ;) )

MfG Fabsi
 

M-Ott

Well-known member
Beiträge
1.771
Punkte Reaktionen
371
Noch eine andere Idee: Wenn es Euren finanziellen Rahmen nicht sprengt, ersetze einige der ET200 durch CPU 1211. Die kannst Du als intelligenten Slave verwenden, lässt sie die Zählung machen und den Zählerstand an die Haupt-CPU senden, alle anderen Signale schleifst Du softwaretechnisch nur darüber zur Haupt-CPU. Mit dieser minimalen Tätigkeit sollte die Zykluszeit der Zähl-CPUs so niedrig sein, dass Du ohne HSC auskommst.
 

buffi4711

Well-known member
Beiträge
288
Punkte Reaktionen
3
Hallo,

die Idee von M-Ott ist echt gut.
Machen wir auch gerne so. Auf der 1200er nutzen wir nur die E/A und verarbeiten dort vor.
Wir lesen A/B Drehgeber damit aus und „sammeln“ noch ein paar digitale Signale im Bedienpult ein bzw. schalten Hardwaresignalleuchten damit.
Abgesehen vom Platz ist das auch finanziell nicht uninteressant da man keine Kopfstation, Baseunit usw. braucht. Die 1200er läuft als I-Device.
Hallo,

die Idee von M-Ott ist echt gut.
Machen wir auch gerne so. Auf der 1200er nutzen wir nur die E/A und verarbeiten dort vor.
Wir lesen A/B Drehgeber damit aus und „sammeln“ noch ein paar digitale Signale im Bedienpult ein bzw. schalten Hardwaresignalleuchten damit.
Abgesehen vom Platz ist das auch finanziell nicht uninteressant da man keine Kopfstation, Baseunit usw. braucht. Die 1200er läuft als I-Device.
 

Heinileini

Well-known member
Beiträge
5.175
Punkte Reaktionen
1.113
Zuviel Werbung?
->Hier kostenlos registrieren
Sensor 100110
Sensor 201100
Wie lang [ms] sind denn die Phasen mit S1=0/S2=1, S1=1/S2=1 und S1=1/S2=0 bei "HöchstGeschwindigkeit"?
Wie lang [ms] ist die ZyklusZeit?
Jedes Mal, wenn dieses Muster auftaucht, soll ein Rad dazugezählt werden. (Umgekehrt soll ein Rad weggezählt werden.) - Soweit so gut
Sehr gut, wenn Du damit meinst, dass die Zähler immer in Abhängigkeit von der FahrtRichtung vorwärts bzw. rückwärts zählen sollen.
Die Kontakte könnten prellen und zu Störungen führen und die werden automatsch ausgebügelt, wenn man die Zähler nicht daran hindert, auch in einer nicht erwarteten Richtung zu zählen.
Sorry, das habe ich jetzt blöd formuliert. Was ich sagen will: nur auf den Verlauf der Signale S1 und S2 "gucken" und nicht eingreifen, wenn man meint, dass der Zähler zwischendurch mal in der falschen Richtung zählt.

Die Eingänge würde ich so belegen, dass Du 2 EingangsDoppelWorte mit den A-Signalen ("S1") und 2 EingangsDoppelWorte mit den B-Signalen ("S2") hast, damit Du die Verknüpfungen Wort- bzw. DoppelWort-weise ausführen kannst (statt Bit-weise).
 

maxder2te

Well-known member
Beiträge
763
Punkte Reaktionen
227
Suche mal nach den Stichwörtern "Alarmeingang" und "Prozessalarm".
Ich hab die Prozessalarm-Eingänge meist für genau sowas genutzt. Beim Flankenwechsel an einem Alarmeingang wird ein Prozessalarm-OB aufgerufen. Das Programm in diesem Prozessalarm-OB sieht dann in etwa so aus (Pseudocode):
Code:
CASE (AlarmQuelle) OF
  ALARM_QUELLE_SENSOR1:
    IF (Sensor1 AND Sensor2 AND (step = 1) THEN
      step := 2;
    ELSIF (Sensor1 AND (NOT Sensor2) AND (step = 0) THEN
      step := 3;
    ELSIF ((NOT Sensor1) AND (NOT Sensor2) AND (step = 3) THEN
      step := 0;
    ELSIF ((NOT Sensor1) AND Sensor2 AND (step = 2) THEN
      step := 1;
    ELSE
      ; // ungültiger Sequenzzustand -> Fehlerreaktion einbauen
    END_IF;
  ALARM_QUELLE_SENSOR2:
    IF (Sensor1 AND Sensor2 AND (step = 3) THEN
      step := 2;
    ELSIF (Sensor1 AND (NOT Sensor2) AND (step = 2) THEN
      step := 3;
    ELSIF ((NOT Sensor1) AND (NOT Sensor2) AND (step = 1) THEN
      step := 0;
    ELSIF ((NOT Sensor1) AND Sensor2 AND (step = 0) THEN
      step := 1;
    ELSE
      ; // ungültiger Sequenzzustand -> Fehlerreaktion einbauen
    END_IF;
Wo die Ausbaugrenzen an Alarmeingängen bei S7-1200 sind und mit welchen Eingängen das geht, hab ich jetzt nicht nachgeprüft.

Insgesamt wäre es in jedem Fall mal interessant, von welchen Signalzeiten wir hier sprechen. Wie lange dauert die Sequenz? Dann lassen sich auch vernünftige Alternativen aufzeigen.
 

PN/DP

User des Jahres 2011-2013; 2015-2017; 2020-2021
Beiträge
18.620
Punkte Reaktionen
5.552
Wichtig wenn man in einem Prozessalarm-OB auf die Hardware-Eingänge zugreifen will, daß man da auf die Peripherie zugreift und nicht auf das Prozessabbild der Eingänge.

Harald
 

Heinileini

Well-known member
Beiträge
5.175
Punkte Reaktionen
1.113
Zuviel Werbung?
->Hier kostenlos registrieren
Hallo? Lebt dieser Thread noch?
Ich versuch's einfach mal mit dieser "Provokation":
Code:
// GLOBALe Variablen :
aZhl : ARRAY[0..63] OF DINT;    // ARRAY für 62 Zähler (eigentlich 64 - Idx 31 und 63 werden jedoch nicht genutzt)
dwE1Aalt : DWORD;   // "FlankenMerker" für A-Signale (0..30)
dwE2Aalt : DWORD;   // "FlankenMerker" für A-Signale (32..62)

FUNCTION AXCNT62 : VOID     // - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - +
VAR_TEMP    
    iIdx : INT;     // Index für ARRAY
    dwTemp : DWORD;     // div.
    diTemp AT dwTemp : DINT;    // DINT für Bildung des ZweierKomplements
    dwBiMu : DWORD;     // BitMuster der REAL-Zahl für Extraktion des Exponenten (BitNummer)
    reTemp AT dwBiMu : REAL;    // REAL-Zahl für Ermittlung der BitNummer

    dwE1A : DWORD;      // Abbild der A-SignalEingänge 0..31 gelesen mit PED
    dwE1Aneg : DWORD;   // negative Flanken der A-SignalEingänge 0..31
    dwE1Apos : DWORD;   // positive Flanken der A-SignalEingänge 0..31
    dwE1B : DWORD;      // Abbild der B-SignalEingänge 0..31 gelesen mit PED

    dwE2A : DWORD;      // Abbild der A-SignalEingänge 32..63 gelesen mit PED
    dwE2Aneg : DWORD;   // negative Flanken der A-SignalEingänge 32..63
    dwE2Apos : DWORD;   // positive Flanken der A-SignalEingänge 32..63
    dwE2B : DWORD;      // Abbild der B-SignalEingänge 32..63 gelesen mit PED

    dwZIR1 : DWORD;     // ZählImpulse rückwärts für Zähler 0..30
    dwZIR2 : DWORD;     // ZählImpulse rückwärts für Zähler 32..62
    dwZIV1 : DWORD;     // ZählImpulse vorwärts für Zähler 0..30
    dwZIV2 : DWORD;     // ZählImpulse vorwärts für Zähler 32..62
END_VAR     

BEGIN   
dwE1A := PEDx+00 AND 16#7FFFFFFF;   // "PEDx+00" anpassen: A-Signale 00..30 <===<<<
dwE2A := PEDx+08 AND 16#7FFFFFFF;   // "PEDx+08" anpassen: A-Signale 32..62 <===<<<
dwE1B := PEDx+04 AND 16#7FFFFFFF;   // "PEDx+04" anpassen: B-Signale 00..30 <===<<<
dwE2B := PEDx+12 AND 16#7FFFFFFF;   // "PEDx+12" anpassen: B-Signale 32..62 <===<<<

dwE1Apos := dwE1A AND NOT dwE1Aalt;     // pos Flanken der A-Signale
dwE2Apos := dwE2A AND NOT dwE2Aalt;     
dwE1Aneg := dwE1Aalt AND NOT dwE1A;     // neg Flanken der A-Signale
dwE2Aneg := dwE2Aalt AND NOT dwE2A;     

dwZIV1 := dwE1Apos AND dwE1B OR dwE1Aneg AND NOT dwE1B;     // VorwärtsZählImpulse
dwZIV2 := dwE2Apos AND dwE2B OR dwE2Aneg AND NOT dwE2B;     
dwZIR1 := dwE1Apos AND NOT dwE1B OR dwE1Aneg AND dwE1B;     // RückwärtsZählImpulse
dwZIR2 := dwE2Apos AND NOT dwE2B OR dwE2Aneg AND dwE2B;     

dwE1Aalt := dwE1A;      // "FlankenMerker" speichern
dwE2Aalt := dwE2A;  

WHILE dwZIV1 <> 0 DO    // Inc Zähler 0 .. 30
    dwTemp := dwZIV1 AND DINT_TO_DWORD(-DWORD_TO_DINT(dwZIV1));     // niederwertigstes 1-Bit isolieren
    dwZIV1 := dwZIV1 XOR dwTemp;    // niederwertigstes 1-Bit löschen
    reTemp := DINT_TO_REAL(diTemp);     // reTemp AT dwBiMu ; diTemp AT dwTemp
    dwTemp := SHR (IN:=dwBiMu, N:=23);      // Exponent rechtsbündig schieben
    iIdx := DINT_TO_INT(DWORD_TO_DINT(dwTemp)) - 128;   // - BIAS - 1 für Indizes 0 .. 30
    aZhl[iIdx] := aZhl[iIdx] + 1;   // Zähler inkrementieren
END_WHILE;  

WHILE dwZIR1 <> 0 DO    // Dec Zähler 0 .. 30
    dwTemp := dwZIR1 AND DINT_TO_DWORD(-DWORD_TO_DINT(dwZIR1));     // niederwertigstes 1-Bit isolieren
    dwZIR1 := dwZIR1 XOR dwTemp;    // niederwertigstes 1-Bit löschen
    reTemp := DINT_TO_REAL(diTemp);     // reTemp AT dwBiMu ; diTemp AT dwTemp
    dwTemp := SHR (IN:=dwBiMu, N:=23);      // Exponent rechtsbündig schieben
    iIdx := DINT_TO_INT(DWORD_TO_DINT(dwTemp)) - 128;   // - BIAS - 1 für Indizes 0 .. 30
    aZhl[iIdx] := aZhl[iIdx] - 1;   // Zähler dekrementieren
END_WHILE;  

WHILE dwZIV2 <> 0 DO    // Inc Zähler 32 .. 62
    dwTemp := dwZIV2 AND DINT_TO_DWORD(-DWORD_TO_DINT(dwZIV2));     // niederwertigstes 1-Bit isolieren
    dwZIV2 := dwZIV2 XOR dwTemp;    // niederwertigstes 1-Bit löschen
    reTemp := DINT_TO_REAL(diTemp);     // reTemp AT dwBiMu ; diTemp AT dwTemp
    dwTemp := SHR (IN:=dwBiMu, N:=23);      // Exponent rechtsbündig schieben
    iIdx := DINT_TO_INT(DWORD_TO_DINT(dwTemp)) - 96;    // - BIAS - 1 + 32 für Indizes 32 .. 62
    aZhl[iIdx] := aZhl[iIdx] + 1;   // Zähler inkrementieren
END_WHILE;  

WHILE dwZIR2 <> 0 DO    // Dec Zähler 32 .. 62
    dwTemp := dwZIR2 AND DINT_TO_DWORD(-DWORD_TO_DINT(dwZIR2));     // niederwertigstes 1-Bit isolieren
    dwZIR2 := dwZIR2 XOR dwTemp;    // niederwertigstes 1-Bit löschen
    reTemp := DINT_TO_REAL(diTemp);     // reTemp AT dwBiMu ; diTemp AT dwTemp
    dwTemp := SHR (IN:=dwBiMu, N:=23);      // Exponent rechtsbündig schieben
    iIdx := DINT_TO_INT(DWORD_TO_DINT(dwTemp)) - 96;    // - BIAS - 1 + 32 für Indizes 32 .. 62
    aZhl[iIdx] := aZhl[iIdx] - 1;   // Zähler dekrementieren
END_WHILE;  
END_FUNCTION
AxZähler62.jpg

Ausgelegt für 16 EingangsBytes, wovon jeweils 4 Bytes zusammenhängend vergeben sind, also 4 ED (PED) für bis zu 62 AxZählStellen (KontaktPaare und "Zähler").
Das höchstwertige Bit jedes der 4 ED wird ignoriert bzw. ausgeblendet, um "SprachSchwierigkeiten" aus dem Wege zu gehen. Folglich liegen die "Zähler" 31 und 63 (im Array of DINT von 0 bis 63 insgesamt) brach.
Leider ist bisher nicht bekannt,
- wie kurz die A- bzw. B-Signale bzw. ihre Überschneidungen werden können,
- wie viele ZählStellen maximal "gleichzeitig" Impulse senden,
- wie lang die "OB1-ZyklusZeit" ist,
so dass dieser LösungsWeg und andere (z.B. ProzessAlarm à la #7) nicht wirklich abzuschätzen bzw. zu vergleichen sind.
Man könnte also zunächst den Aufruf im OB1 versuchen und ggfs auf einen WeckAlarm ausweichen.
Der Code wurde von einem absoluten SCL-Banausen gebastelt und ist garantiert ungetestet - ich bitte deshalb um Nachsicht bezüglich aller mir unterlaufenen Fehler ;)

Gruss, Heinileini
 

Heinileini

Well-known member
Beiträge
5.175
Punkte Reaktionen
1.113
Haaallooo? Lebt dieser Thread wirklich nicht mehr?
Ich versuch's einfach mal mit noch einer "Provokation":

Wie wär's mit einer kleinen Bastelei für 63 AxZählStellen mit
- 192 Dioden,
- 7 Widerständen und
- 7 SPS-Eingängen?
Vorausgesetzt allerdings, dass Signale nie von zwei oder mehr AxZählStellen gleichzeitig kommen können?

Gruss, Heinileini
 

Heinileini

Well-known member
Beiträge
5.175
Punkte Reaktionen
1.113
In deiner Provokation fehlt noch die übliche Excel Lösung :)
Tja, sooo heftig wollte ich doch eigentlich nicht provozieren ;)
Dass ich (noch) keine ExcelLösung habe, ist übrigens gut.
So fällt es mir leichter, zu meiner ursprünglichen Idee zurückzukehren, auf die mich übrigens ein gestern sehr lebhafter anderer Thread gebracht hatte.
Also, ich verdoppele hiermit (annähernd) den Einsatz:
- 384 Dioden,
- 12 Widerstände und
- 12 SPS-Eingänge
Damit müsste doch schon klar sein, was ich im Schilde führe und eine ExcelDarstellung dürfte sich erübrigen!?

Gruss, Heinileini

PS @Michael:
Danke für Deine tröstenden Worte!
 

Heinileini

Well-known member
Beiträge
5.175
Punkte Reaktionen
1.113
Ich stehe zur Zeit vor einem Problem, das den ganzen Fortschritt des Projektes unglaublich verlangsamt.
Moin Yannik!
HP0 oder neue Vorsätze für 2020?
Stehst Du denn immer noch vor dem Problem oder musstest Du das Handtuch werfen oder hättest Du mal Zeit, über Fortschritte (vllt auch kleinere, zeitweise Rückschritte) zu berichten?
Gruss, Heinileini
 
Oben