autom. Absiebung bei geringer Gewichtsänderung und dadurch langsamer Istwertänderung

Zuviel Werbung?
-> Hier kostenlos registrieren
Wie groß sind denn die zu erwartenden Dosiermengen? Und wie genau muss dosiert werden?

Warum willst du alle x Minuten einen Wert abspeichern? Genauer wird es dadurch nicht. Im einfachsten Fall speicherst du beim Start das Startgewicht und berechnest das Stoppgewicht. Aus diesen beiden Werten bildest du die Differenz, multiplizierst diese mit einem Faktor x, begrenzt das Produkt auf einen MaxWert y und gibst das Ergebnis normiert auf dem Analogausgang aus. Geht dieser Wert gegen Null, nimmst du die Freigabe für die Rüttelrinne weg, falls diese ansonsten auf einem Minimalwert weiter läuft.

Das selbe Ergebnis erreichst du mit einem PID-Regler, welcher als P-Regler parametriert ist. Eine bleibende Regelabweichung kann man bei hinreichend großer Verstärkung vermutlich vernachlässigen. Beim PID-Regler kannst du aber anschließend vorsichtig mit dem I-Anteil spielen, um auf den Punkt genau zu dosieren. Es darf nur nicht über-schwingen.

Das ist ein echt guter Gedankenansatz. Den lasse ich mir bei einer Tasse Kaffee noch mal durch den Kopf gehen und werde das mal durchsimulieren. Danke für den Tipp.

Gruß raz
 
ich würde z.b. ein real array mit 60 messwerten im sekundentakt:
1. rotieren
2. aktuellen wert an die erste stelle schreiben
3. durchschnitt errechnen als istwert für pid-regler

pid regler mit startwert 60 sekunden auf hold beim start ...

für das rotieren des arrays mit beliebiger länge habe ich mir erst kürzlich eine funktion erstellt (mit dem tipp pointer zu verwenden hier aus dem forum)

Code:
FUNCTION rotateRealArray : BOOL // Rotate Real Array beliebiger Länge um eins nach oben 
VAR_INPUT
	pt: POINTER TO ARRAY [1..32000] OF REAL ;
	size: UINT;
	new:REAL; // Neuer Wert für array[1]
END_VAR
VAR
	i: UINT;
	ende: UINT;
END_VAR

ende:=size/4  ;
FOR i:=ende TO 2 BY -1 DO
 pt^[i]:=pt^[i-1];
END_FOR
pt^[1]:=new;
rotateRealArray:=TRUE;

somit kannst du mit aufruf von
fertig:=rotateRealArray(ADR(a),SIZEOF(a));
nachträglich problemlos abtastrate und zeit anpassen ... unabhängig wie sich die arraygröße ändert ...

mittelwert auch mit pointer ...
Code:
FUNCTION mittelArray: REAL; // gibt den errechneten mittelwert  des real-arrays zurück
// Aufruf mit mittelwert:=mittelArray(ADR(a),SIZEOF(a));
VAR_INPUT
	pt: POINTER TO ARRAY [1..32000] OF REAL ;
	size: UINT;
END_VAR


VAR
	i:UINT;
	summ: REAL;
	ende: UINT;


END_VAR
ende:=size/4;
summ:=0;
FOR i:= 1 TO ende DO
	summ:=summ+pt^[i];
END_FOR
mittelArray:=summ/UINT_TO_REAL(ende);

und dann würde ich erst einmal die istwerte ansehen, was sinnvolle messzyklen und dauer sind
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das ist ein echt guter Gedankenansatz. ...
Natürlich ist er das, passt aber leider nicht zu deiner Aufgabe :ROFLMAO: !

Ich war irgend wie auf "Dosierung" gekommen. Du aber willst den Materialfluss regeln. Hierfür benötigst du eine entsprechende Regelgröße. Deine Ableitung nach der Zeit ging schon in die richtige Richtung.

Da sich das Gewicht nur sehr langsam ändert, wäre eine hohe Auflösung und ein präziser, langzeitstabiler Verlauf der Messung für diese Regelung schon sehr wichtig. Ansonsten vielleicht besser mit dem Vorschlag von Frohnius (#17) anfreunden.
 
Da fällt mir noch etwas ein. Du könntest das Gesamtgewicht regeln und den Sollwert von Max bis Min über eine Rampe vorgeben. Ich stelle mir vor, eventuelle Messwertsprünge würden sich über eine vorgegebene Rampe besser ausgleichen, als wenn fortlaufend Differenzen über der Zeit berechnet und geregelt werden.
 
Ja, beides...Den Mittelwert aus Zeit x mit dem letzten Mittelwert... Gibt gewicht/Zeit... Als istwert...
Aber erst mal messen... Vll liefert ja eine Abtastung alle 500ms über 10s scho vernünftige Werte...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo, ich bin erst einmal ein Stück weiter beim probieren.Ich habe mir jetzt erst einmal einen Ringspeicher gebaut mit 60 Messwerten. Also einen DB „Gewichtwerte“ mit einem Array [0..59] im Realformat. Dann ein paar Zeilen im FB von YouTube abgeschrieben und das ganze in einen OB30 (Cyclic interrupt) (1000ms)geschoben. Das funktioniert schon mal gut.Alle Sekunde ein Messwert und das fortlaufend. Schon mal ein Teilerfolg da ich noch nie etwas mit SCL zu tun hatte.Dun habe ich das Problem-wie bekomme ich nun aus dem DB Array einen Mittelwert gebildet? Gibt es da einen fertigen Baustein oder kann man das ggf. in SCL mit ein paar Zeilen realisieren?

Gruss raz

SCL.JPGDB.JPG
 
Zuletzt bearbeitet:
Du baust dir eine Schleife und addierst damit die einzelnen Messwerte auf. Nach der Schleife dividierst du durch die Anzahl der Messwerte. Wenn dein Baustein nur jede Sekunde einmal durchlaufen wird kannst du das nach jedem Durchlauf machen - das wird dein System nicht über Gebühr belasten ...
Da dur natürlich irgendwann einmal anfängst, dein Array zu befüllen, würde ich mit nach dem "Init" des Bausteins (wo das Array ja alles Nullwerte beinhaltet) merken, wieviele Werte dort bereits hinein geschrieben worden sind und dann entsprechend halt nicht durch 60 sondern durch diue tatsächliche Anzahl von Werten dividieren ...
Brauchst du dafür ein Beispiel ?

Gruß
Larry
 
Das wäre schön, wenn du mir eines geben könntest.:D das ist natürlich ein anderer Ansatz. Alles addieren über 60sek und dann durch 60 teilen. Macht auch den Durchschnitt.
Ich dachte es gäbe einen fertigen Baustein Namens "Averager" der das für mich komfortabel macht.
Auf der Siemens Seite gibt es eine Anleitung für Step 7 wie man so einem FB man sich basteln kann. Werde dort auch noch mal nachsehen.

raz
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Naja ... du kannst dir natürlich überall so etwas wegkopieren - der Code dafür ist ja kein Hexenwerk. Du kannst dir selbstverständlich auch einen Baustein (so quasi als Universal-Baustein) dafür bauen - alles denkbare ist machbar - der einfachst Code kommt aber dabei heraus wenn du es einfach integrierst ...
Code:
Array_Gesamt := 0.0 ;
FOR i:= 0 to Anzahl_Werte_im_Array BY 1 DO
   Array_Gesamt := Array_Gesamt + Array_Element[i] ;
END_FOR ;
Array_Mittelwert := Array_Gesamt / INT_to_REAL(Anzahl_Werte_im_Array) ;
Zur Erläuterung :
Array_Gesamt und Array_Mittelwert ist ein REAL
Array_Element ist dein Array
Anzahl_Werte_im_Array ist ein INT und wird von dir beim Auffüllen des Array hochgezählt. Du musst dann hier nur beachten, dass du nicht über 60 kommst. Im Code (beim Befüllen) wäre das dann etwa so :
Code:
Anzahl_Werte_im_Array := Anzahl_Werte_im_Array +1 ;
if Anzahl_Werte_im_Array > 60 then Anzahl_Werte_im_Array := 60 ; END_IF ;
Gruß
Larry
 
Hallo Larry, Danke für die Hilfe. Ich habe wie gesagt noch nie etwas in SCL gemacht und benötige weitere Hilfe.Du siehst ja oben meine paar Zeilen in SCL und den DB dazu.
Ich habe im DB das Array erstellt und den Zähler. Im FC stehen mein Zeilen.
Kann ich jetzt deinen Code so ohne weiteres damit rein basteln?
D.h. das ich für Array_Gesamt und Array_Mittelwert erst noch mal eine REAL Variable in meinem DB anlegen muss. Ist das so richtig?

Bei den Programzeilen nicht wundern das da "Poti Istwert" steht. Der Potiwert kommt von einem Merkerdoppelwort als Realzahl.
Ich habe an die SPS ein Poti am anlogen Eingang angeschlossen um mir Eingangswerte zu simulieren, da ich die Waage im Moment nicht da habe. Funktioniert ganz gut um Werte zu simulieren.
 
Zuletzt bearbeitet:
Also erstmal würde ich dir hierfür ganz dringend einen FB empfehlen. Dieser Baustein hat den Vorteil, dass du alle benötigten Variablen direkt mit ihm "verheiraten" kannst. Du musst halt nur die Variablen, die du wieder benötigst im STAT-Bereich des Bausteins anlegen ...

Nachtrag:
Ich hatte mir deinen Code bisher gar nicht angesehen ... aber ja : du kannst meinen Code da im Prinzip einfach dazubasteln (nur halt die Variablennamen des Arrays anpassen) ...

Gruß
Larry
 
Zurück
Oben