# Minimalwertauswahl bei Codesys



## Don_Travolta (25 Februar 2010)

Hallo zusammen,

bin gerade beim programmieren auf folgendes Problem gestossen:
Ich habe zwölf Analogwerte. Ich will aus den zwölf Analogwerten den werte auswählen der am niedrigsten ist und diese information binär weiterverarbeiten.
Soll heisen:
Wert 1=> "3"
Wert 2=> "4"
Wert 3=> "5"
....
Wert 12 => "2" soll binär angezeigt werden das der Wert von 12 der niedrigste ist.
Das Programm müsste also 12 Analoge Eingänge haben und 12 binäre Ausgänge. Eventuell noch einen analogen Ausgang der zeigt welcher wert bei den Eingängen der niedrigste ist.
Wichtig ist das wenn mehrer Eingänge den gleichen niedrigsten Wert haben immer der erste in der Reihenfolge signalisiert wird. Soll heisen Ausgangsseitig soll immer nur ein binärer Ausgang anstehen.

Vielleicht hat da einer eine Idee.
Eventuell in ST oder CFC.
Danke!
lg
Stefan


----------



## Controllfreak (25 Februar 2010)

Such mal nach Bubble Sort


----------



## SPSstudent (25 Februar 2010)

Sollte eigentlich funktionieren (habs nicht getestet):


```
VAR_IN
  Wert1,Wert2,Wert3,... : INT;
END_VAR
VAR_OUT
  bWert1istMin,bWert2istMin,bWert3istMin, ... : BOOL;
END_VAR
VAR
  minWert : INT;
END_VAR
-----------

minWert := MIN(Wert1,Wert2,Wert3,...);

IF minWert = Wert1 THEN
  bWert1istMin := TRUE;
ELSIF minWert = Wert2 THEN
  bWert2istMin := TRUE;
ELSIF minWert = Wert3 THEN
  bWert3istMin := TRUE;
ELSIF ...
END_IF
```

Edit: Die Min-Funktion hat wohl doch nur 2 Parameter.
Könnte man umgehen mit MIN(MIN(MIN(Wert1,Wert2),Wert3),Wert4), ... *hust*

Edit2:
Oder statt verschachteltem Aufruf:
minWert := MIN(Wert1,Wert2);
minwert := MIN(minWert,Wert3);
minWert := MIN(minWert,Wert4);
...

Ein Sortieralgorithmus wie von Controllfreak vorgeschlagen würde auch gehen, aber du brauchst die Zahlen ja vermutlich nicht sortiert und dann kann man sich das sparen.


----------



## Controllfreak (25 Februar 2010)

SPS Student hat die bessere Lösung.
Bubble Sort wäre dann besser wenn die Werte in eine an/absteigende Reihenfolge sortiert werden müssten


----------



## Larry Laffer (25 Februar 2010)

... wenn die Werte allerdings in einem ARRAY vorliegen (oder vorliegend gemacht werden können), dann liesse sich das mittels einer Schleife wesentlich eleganter (und auch mit weniger Code machen). Vielleicht etwa so :
	
	



```
Suchwert := Liste[1] ;
 
for i := 1 to 12 by 1 do
   if Liste[i] < Suchwert then
      Suchwert := Liste[i] ;
   end_if ;
end_for ;
```
Gruß
LL


----------



## Don_Travolta (28 Februar 2010)

*Macht a bisserle Probleme*

Hy,
habe mich für die Lösung von SPSstudent entschieden.

Habe den FB in ST geschrieben und getest. Folgende Fehler sind mir aufgefallen:
Ich habe 12 Eingänge in Real definiert und 12 Ausgänge in BOOL und zusätzlich einen REAL-Ausgang und mir anzuzeigen wie groß der MINwert ist.
Wenn ich für die Eingänge 1-12 die Werte 1-12 vorgebe dann wird der Binäreausgang 01 als TRUE siginalisert. Was auch richtig ist da WERT_01 mit "1" der niedrigste Werte ist.
Wenn ich aber für 1 einen höheren Wert vorgebe sollte jetzt der WERT_02 der niedrigste sein und nur mehr der Ausgang 02 mit TRUE signalisiert werden. Es beleibt aber der Ausgang 01 weiter mit TRUE anstehen. Gleiches passiert wenn ich jetzt den Eingang 02 erhöhe. 
Wo liegt da das Problem? Vielleicht kann mir wer helfen.

Danke!


----------



## Lupo (28 Februar 2010)

Don_Travolta schrieb:


> habe mich für die Lösung von SPSstudent entschieden.



So wie ich das sehe hast du das nicht getan - die genannte Lösung würde aus meiner Sicht nämlich funktionieren.


----------



## chrigu (28 Februar 2010)

so wie du es gelöst hast, setzt du einmal den niedrigsten Wert. 
bWert1istMin
ändert sich aber nun der niedrigste Wert bleibt dieses Bit immer noch gesetzt plus das neue niedrigste kommt dazu. 
Das heisst du musst z.B. zuerst alle Bits auf FALSE setzten und dann die Zuweisung machen


----------



## Larry Laffer (28 Februar 2010)

... ich sehe das so wie Chrigu.
Das könntest du aber zum Beispiel so ähnlich umgehen :
	
	



```
binWert_01 ;= (minWert = Wert_01) ;
binWert_02 ;= (minWert = Wert_02) ;
usw.
```
Gruß
LL


----------



## Don_Travolta (28 Februar 2010)

Also ich habe das Programm von SPSstudent 1:1 abgeschrieben.
ICh habe leider keine Erfahrung in ST. Programmiere sonst immer in CFC/Logicad und da gibts für das ein Modul.
In Codesys muß ich leider selbe etwas schnitzen.

Hier mal mein Programmcode:
_MINWERT := MIN(WERT_01,WERT_02);
MINWERT := MIN(MINWERT,WERT_03);
MINWERT := MIN(MINWERT,WERT_04);
MINWERT := MIN(MINWERT,WERT_05);
MINWERT := MIN(MINWERT,WERT_06);
MINWERT := MIN(MINWERT,WERT_07);
MINWERT := MIN(MINWERT,WERT_08);
MINWERT := MIN(MINWERT,WERT_09);
MINWERT := MIN(MINWERT,WERT_10);
MINWERT := MIN(MINWERT,WERT_11);
MINWERT := MIN(MINWERT,WERT_12);_

_IF MINWERT = WERT_01 THEN
  BIN_WERT_01 := TRUE;
ELSIF MINWERT = WERT_02 THEN
  BIN_WERT_02 := TRUE;
ELSIF MINWERT = WERT_03 THEN
  BIN_WERT_03 := TRUE;
ELSIF MINWERT = WERT_04 THEN
  BIN_WERT_04 := TRUE;
ELSIF MINWERT = WERT_05 THEN
  BIN_WERT_05 := TRUE;
ELSIF MINWERT = WERT_06 THEN
  BIN_WERT_06 := TRUE;
ELSIF MINWERT = WERT_07 THEN
  BIN_WERT_07 := TRUE;
ELSIF MINWERT = WERT_08 THEN
  BIN_WERT_08 := TRUE;
ELSIF MINWERT = WERT_09 THEN
  BIN_WERT_09 := TRUE;
ELSIF MINWERT = WERT_10 THEN
  BIN_WERT_10 := TRUE;
ELSIF MINWERT = WERT_11 THEN
  BIN_WERT_11 := TRUE;
ELSIF MINWERT = WERT_12 THEN
  BIN_WERT_12 := TRUE;
END_IF;_

so wie ich das verstehe fehlt mir da also noch was.
lg


----------



## Larry Laffer (28 Februar 2010)

hast du den Beitrag von Chrigu gelesen ?
Wenn ja, dann würde das in der Konsequenz heißen, dass du irgendwo stehen haben mütest (und zwar vor dem IF-Block) :
	
	



```
BinWert_01 := false ;
BinWert_02 := false ;
usw.
```
... oder du ermittels den Binwert so, wie ich es dir gepostet habe ...   (Beitrag #9) 

Gruß
LL


----------



## Don_Travolta (28 Februar 2010)

Code schaut jetzt folgendermaßen aus:
MINWERT := MIN(WERT_01,WERT_02);
MINWERT := MIN(MINWERT,WERT_03);
MINWERT := MIN(MINWERT,WERT_04);
MINWERT := MIN(MINWERT,WERT_05);
MINWERT := MIN(MINWERT,WERT_06);
MINWERT := MIN(MINWERT,WERT_07);
MINWERT := MIN(MINWERT,WERT_08);
MINWERT := MIN(MINWERT,WERT_09);
MINWERT := MIN(MINWERT,WERT_10);
MINWERT := MIN(MINWERT,WERT_11);
MINWERT := MIN(MINWERT,WERT_12);
BIN_WERT_01 := FALSE;
BIN_WERT_02 := FALSE;
BIN_WERT_03 := FALSE;
BIN_WERT_04 := FALSE;
BIN_WERT_05 := FALSE;
BIN_WERT_06 := FALSE;
BIN_WERT_07 := FALSE;
BIN_WERT_08 := FALSE;
BIN_WERT_09 := FALSE;
BIN_WERT_10 := FALSE;
BIN_WERT_11 := FALSE;
BIN_WERT_12 := FALSE;

IF MINWERT = WERT_01 THEN
   BIN_WERT_01 := TRUE;
ELSIF MINWERT = WERT_02 THEN
 BIN_WERT_02 := TRUE;
ELSIF MINWERT = WERT_03 THEN
 BIN_WERT_03 := TRUE;
ELSIF MINWERT = WERT_04 THEN
 BIN_WERT_04 := TRUE;
ELSIF MINWERT = WERT_05 THEN
 BIN_WERT_05 := TRUE;
ELSIF MINWERT = WERT_06 THEN
 BIN_WERT_06 := TRUE;
ELSIF MINWERT = WERT_07 THEN
 BIN_WERT_07 := TRUE;
ELSIF MINWERT = WERT_08 THEN
 BIN_WERT_08 := TRUE;
ELSIF MINWERT = WERT_09 THEN
 BIN_WERT_09 := TRUE;
ELSIF MINWERT = WERT_10 THEN
 BIN_WERT_10 := TRUE;
ELSIF MINWERT = WERT_11 THEN
 BIN_WERT_11 := TRUE;
ELSIF MINWERT = WERT_12 THEN
 BIN_WERT_12 := TRUE;
END_IF;

Habe es mal Offline simuliert, dürfte funktionieren.

Ich habe zwischenzeitlich mal probiert:

.....
ELSIF MINWERT = WERT_12 THEN
 BIN_WERT_12 := TRUE;
*ELSE*
*BIN_WERT_01 := FALSE;*
*....*
*BIN_WERT_12 := FALSE;*

*END_IF;*

Das hat aber nichts gebracht, war das gleich Ergebniss wie am Anfang, verstehe aber nicht wieso. Arbeitet er das ELSE erst aber wenn keine der IF´s True ergibt?

@Larry Lafter (gutes Spiel)

Wo hätte ich diesen Ausdruck einbauen müssen:
binWert_01 ;= (minWert = Wert_01) ;
binWert_02 ;= (minWert = Wert_02) ;

@ Lupo
Es hat eh funktioniert aber wenn Du mein Eröffnungspost genau gelesen hättest, wäre Dir aufgefallen das ich immer nur einen anstehenden binären Ausgang brauche.

@all danke nochmals




lg


----------



## Larry Laffer (28 Februar 2010)

statt dem :


Don_Travolta schrieb:


> Code schaut jetzt folgendermaßen aus:
> BIN_WERT_01 := FALSE;
> BIN_WERT_02 := FALSE;
> BIN_WERT_03 := FALSE;
> ...


... könntest du das von mir genannte schreiben :
	
	



```
BinWert_01 := (Wert_01 = minWert) ;
BinWert_02 := (Wert_02 = minWert) ;
BinWert_03 := (Wert_03 = minWert) ;
BinWert_04 := (Wert_04 = minWert) ;
BinWert_05 := (Wert_05 = minWert) ;
BinWert_06 := (Wert_06 = minWert) ;
BinWert_07 := (Wert_07 = minWert) ;
BinWert_08 := (Wert_08 = minWert) ;
BinWert_09 := (Wert_09 = minWert) ;
BinWert_10 := (Wert_10 = minWert) ;
```
... jetzt gechecked ...?


----------



## Larry Laffer (28 Februar 2010)

Nachtrag :
das mit dem ELSE würde auch funktionieren, wenn du es richtig machst - es muß sich auf das richtige IF beziehen ...


----------



## Don_Travolta (28 Februar 2010)

BinWert_01 := (Wert_01 = minWert) ;
BinWert_02 := (Wert_02 = minWert) ;
BinWert_03 := (Wert_03 = minWert) ;
BinWert_04 := (Wert_04 = minWert) ;
BinWert_05 := (Wert_05 = minWert) ;
BinWert_06 := (Wert_06 = minWert) ;
BinWert_07 := (Wert_07 = minWert) ;
BinWert_08 := (Wert_08 = minWert) ;
BinWert_09 := (Wert_09 = minWert) ;
BinWert_10 := (Wert_10 = minWert) ;

Hätte ich gleich nach der bestimmung des Minwerte einbauen können und hätte ich mir dann die IF Then geschichte erspart?

Bin leider ein absoluter Newbie was ST programmierung betrifft. Entschuldigt die dummen Fragen.

Wenn ich es mit ELSE gelöste hätte wäre es so richtig gewesen:

IF MINWERT = WERT_01 THEN
BIN_WERT_01 := TRUE;
ELSE
BIN_WERT_01 := FALSE;
END_IF;

IF MINWERT = WERT_02 THEN
BIN_WERT_02 := TRUE;
ELSE
BIN_WERT_02 := FALSE;
END_IF;

etc.

oder hätte ich da auch mit ELSIF arbeiten können?

lg


----------



## Larry Laffer (28 Februar 2010)

> Hätte ich gleich nach der bestimmung des Minwerte einbauen können und hätte ich mir dann die IF Then geschichte erspart?


... ja ...



> Wenn ich es mit ELSE gelöste hätte wäre es so richtig gewesen:
> 
> IF MINWERT = WERT_01 THEN
> BIN_WERT_01 := TRUE;
> ...


... ja ...



> oder hätte ich da auch mit ELSIF arbeiten können?


... das wäre m.E. in dem nZusammenhang so nicht sinnvoll geworden / gewesen ...

Gruß
LL


----------



## PN/DP (28 Februar 2010)

*nur 1 Ausgang True*



Larry Laffer schrieb:


> ```
> BinWert_01 := (Wert_01 = minWert) ;
> BinWert_02 := (Wert_02 = minWert) ;
> BinWert_03 := (Wert_03 = minWert) ;
> ...


Ist zwar schön kurz, erfüllt aber leider nicht die Aufgabenstellung aus dem EP:


Don_Travolta schrieb:


> Wichtig ist das wenn mehrer Eingänge den gleichen niedrigsten Wert haben immer der erste in der Reihenfolge signalisiert wird. Soll heisen Ausgangsseitig soll immer nur ein binärer Ausgang anstehen.


Die längere IF...ELSEIF-Kette von Don_Travolta in #12 funktioniert dagegen richtig.

Gruß
Harald


----------



## zotos (28 Februar 2010)

PN/DP schrieb:


> Ist zwar schön kurz, erfüllt aber leider nicht die Aufgabenstellung aus dem EP:
> 
> Die längere IF...ELSEIF-Kette von Don_Travolta in #12 funktioniert dagegen richtig.
> 
> ...



Ich glaube Du hast die Lösung von Larry nur nicht verstanden. Sie liefert ein auch nur Bool Signale als ergebnis und das entspricht doch der Aufgabenstellung.

z.B. die Variable BinWert_01 ist vom typ Bool und kann TRUE oder FALSE sein und sie ist TRUE wenn der Wert_01 eben der Minwert ist.


----------



## PN/DP (28 Februar 2010)

*nur genau 1 Ausgang True*

Hallo zotos,

wenn Wert_01 = Wert_02 = minWert, dann werden BinWert_01 und BinWert_02 beide True.
Es sollte aber nur genau 1 Ausgang True werden. (siehe den von mir Rot markierten Text im Zitat des EP in #17)

Gruß
Harald


----------



## zotos (28 Februar 2010)

PN/DP schrieb:


> Es sollte aber nur genau 1 Ausgang True werden.


Ich war zu voreilig Du hast recht.


----------



## Larry Laffer (1 März 2010)

@PN/DP:
Stimmt - ich hatte das Ganze tatsächlich nur unter dem Aspekt eines einfacheren Codes gesehen ... 

Gruß
LL


----------



## Thomas_v2.1 (1 März 2010)

Wenn die ganzen Ein- und Ausgangsparameter in einer Reihe liegen, kann man auch gut mit Pointerarithmetik arbeiten und erspart sich so die dämliche Tipperei:

```
FUNCTION_BLOCK FB_MIN
	VAR_INPUT
	WERT1, WERT2, WERT3, WERT4, WERT5, WERT6 : REAL;
END_VAR
VAR_OUTPUT
	BIN_WERT1, BIN_WERT2, BIN_WERT3, BIN_WERT4, BIN_WERT5, BIN_WERT6 : BOOL;
	minVal : REAL;
END_VAR
VAR
	i : INT;
	ptrMin, ptrAct : POINTER TO REAL;
	ptrOutMin, ptrOutAct : POINTER TO BOOL;
END_VAR

VAR CONSTANT
	ANZAHL : INT := 6;
END_VAR

(*****************************************)
ptrMin     := ADR(WERT1);
ptrAct     := ptrMin;
ptrOutMin  := ADR(BIN_WERT1);
ptrOutAct  := ptrOutMin;
ptrOutMin^ := TRUE;

FOR i := 2 TO ANZAHL DO
	ptrAct    := ptrAct    + SIZEOF(ptrAct^);
	ptrOutAct := ptrOutAct + SIZEOF(ptrOutAct^);
	IF ptrAct^ < ptrMin^ THEN
		ptrMin     := ptrAct;
		ptrOutMin^ := FALSE;
		ptrOutMin  := ptrOutAct;
		ptrOutMin^ := TRUE;
	ELSE
		ptrOutAct^ := FALSE;
	END_IF
END_FOR
minVal := ptrMin^ ; (* Min-Wert ausgeben *)
```


----------

