# WinCC 7 - Farbverlauf



## matthias2525 (22 Mai 2010)

Hallo,

ich möchte die Temperaturen eines Pufferspeicher Färbig Darstellen.

Ich habe 4 Teperaturwerte(von oben nach unten), nun möchte ich dass sich die farbe für jeden Wert je nach Temperatur ändert und in den anderen  Temperaturbereich Verläuft.


Wie kann ich das lösen??



mfg
Matthias


----------



## Thomas_v2.1 (22 Mai 2010)

Hallo,
willst du einen festen Farbumschlag bei bestimmten Werten, oder kontinuierliche Änderung?

Einen festen Farbumschlag bei bestimmten Werten macht man am einfachsten mit dem Dynamik-Dialog. Also wenn du z.B. bei einem Rechteck die Füllfarbe animieren willst, gibts du im Dynamik-Dialog deine Variable an von der die Animation abhängen soll, und dann die entsprechenden Wertebereiche mit der zugehörigen Farbe (z.B. 0-10 = grün, -70 = grau, 70-100 = rot).

Einen kontinuierlichen Farbverlauf kann man dann einfacher mit einem C-Skript machen. Also wenn du das Rechteck hast, erstellst du bei "Hintergrundfarbe" eine C-Aktion.
Die könnte dann folgendermaßen aussehen:

```
long _main(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName)
{
  // WINCC:TAGNAME_SECTION_START
  #define TAG1 "rTemperatur_unten"
  // WINCC:TAGNAME_SECTION_END

  float val;
  int b, r, g;

  // Variablenwert darf nur von 0-100 gehen
  val = GetTagFloat(TAG1 );
  g = 0; // Grünanteil
  r = (int) 255.0 * (val / 100.0); // Rotanteil
  b = (int) 255.0 - (255.0 * (val / 100.0)); // Blauanteil

  // Farbrückgabewert Hexadezimal: b, g, r => 0xbbggrr
  return (b << 16) | (g << 8) | r;
}
```

Ergebnis:
Bei einem Variablenwert von 0 erhältst du einen blauen Hintergrund, bei steigendem Wert bis 100 wird der Blauanteil reduziert und der Rotanteil erhöht.
Bei der Berechnung kann man noch optimieren, aber so sieht man besser wie die Farbwerte berechnet werden.

Den Code kopiert man sich dann einmal in eine Projektfunktion, damit dieser nur einmal im Projekt vorhanden ist.


----------



## matthias2525 (22 Mai 2010)

Super Danke funktioniert,

aber ich bekomme beim Speichern eíne Performance Warnug wegen zyklischem Tirigger, habe die Aktualisierungszeit auf 10s gestellt.

Schön währe es wenn ich mit den 4 Werten etwa so einen Verlauf bei dementsprechender Temperatur hinbekomme:

http://www.core-info.de/bilder/Farbverlauf.jpg

mfg


----------



## Thomas_v2.1 (22 Mai 2010)

matthias2525 schrieb:


> aber ich bekomme beim Speichern eíne Performance Warnug wegen zyklischem Tirigger, habe die Aktualisierungszeit auf 10s gestellt.



Du kannst als Triggerbedingung eine Änderung der Variable einstellen, dann bekommst du auch keine Performance Warnung.



matthias2525 schrieb:


> Schön währe es wenn ich mit den 4 Werten etwa so einen Verlauf bei dementsprechender Temperatur hinbekomme:
> 
> http://www.core-info.de/bilder/Farbverlauf.jpg



Wirklich so wie auf dem Bild? Denn so wie es aussieht ist das kein üblicher Farbverlauf eines Farbraumes wie RGB oder HSV, sondern das Spektrum des Lichts der Wellenlänge nach aufgezeichnet.
Das in RGB-Werte umzurechnen ist etwas aufwändiger, da sich die RGB-Werte nichtlinear zur Wellenlänge verhalten. Hier gibt es aber einen Beispielcode in Fortran:
http://www.physics.sfasu.edu/astro/color/spectra.html

Einfacher wäre es im HSV-Farbraum zu arbeiten, und dann beim Farbton (H) nur bis 300° zu gehen. Das dürfte deinem Farb-Verlauf annähernd entsprechen


----------



## Thomas_v2.1 (23 Mai 2010)

Thomas_v2.1 schrieb:


> Einfacher wäre es im HSV-Farbraum zu arbeiten, und dann beim Farbton (H) nur bis 300° zu gehen. Das dürfte deinem Farb-Verlauf annähernd entsprechen



Ich habe das mal nach dem Schema auf Wikipedia
http://de.wikipedia.org/w/index.php?title=Datei:HSV-RGB-comparison.svg&filetimestamp=20060830160028
umgesetzt.

Ergibt dann vereinfacht folgende Funktion:

```
// Einfache Umwandlung eines Farbwertes x (von 0..100) in RGB Farbwerte
void HtoRGB(double x, unsigned char *rr, unsigned char *gg, unsigned char *bb )
{
	double r, g, b;
	double d = 100.0/6.0;		
	int baseColor = floor(x / d);
	
	switch (baseColor) {
		case 0:
			r = 1.0;
			g = x / d;
			b = 0.0;
			break;
		case 1:
			r = -1.0 * (x - 2*d) / d;
			g = 1.0;
			b = 0.0;
			break;
		case 2:
			r = 0.0;
			g = 1.0;
			b = (x - 3*d) / d;
			break;
		case 3:
			r = 0.0;
			g = -1.0 * (x - 4*d) / d;
			b = 1.0;
			break;
		case 4:
			r = (x - 5*d) / d;
			g = 0.0;
			b = 1.0;
			break;
		case 5:
			r = 1.0;
			g = 0.0;
			b = -1.0 * (x - 6*d) / d;
			break;
	}
	*rr = (unsigned char) (r * 255.0);
	*gg = (unsigned char) (g * 255.0);
	*bb = (unsigned char) (b * 255.0);
}
```

Wenn ich dann den Magenta-Bereich aussparen will, muss ich beim Aufrufen der Funktion meinen Farbwert z.b. mit 0,8 multiplizieren:

```
HtoRGB(z * 0.8, &p.Red, &p.Green, &p.Blue);
```

Der mit der obigen Funktion erzeugte Farbverlauf mit 500 Pixel Breite sieht dann so aus:
Anhang anzeigen farbverlauf.bmp


----------



## RaffniX (1 November 2010)

Thomas_v2.1 schrieb:


> ```
> long _main(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName)
> ```



Hey,

genau diesen Code hab ich auch gesucht! :TOOL:
Aber was sollen die Eingabewerte der Funktion bringen?? Weil lpszPictureName, lpszObjectName und lpszPropertyName werden ja in der "Methode" eh nicht genutzt?? oder sehe ich das falsch?

Grüße


----------



## Thomas_v2.1 (1 November 2010)

RaffniX schrieb:


> genau diesen Code hab ich auch gesucht! :TOOL:
> Aber was sollen die Eingabewerte der Funktion bringen?? Weil lpszPictureName, lpszObjectName und lpszPropertyName werden ja in der "Methode" eh nicht genutzt?? oder sehe ich das falsch?


Was hast du denn daran gesucht? Der Funktionsname und die Parameter werden von WinCC automatisch in der Form angelegt wie sie für das zu dynamisierende Objekt notwendig sind. Der obige Funktionsaufruf war eben für die Hintergrundfarben-Animation eines Rechteckes.
Die Parameter PictureName, ObjectName und PropertyName kommen auch bei den meisten Funktionen mit, ob man sie nun braucht oder nicht. 
Im Aktions-Editor von WinCC kann man den Funktionsaufruf auch garnicht ändern.


----------



## RaffniX (1 November 2010)

Will nen Farbumschlag von blau nach rot realisieren... Also die Hintergrundfarbe von Rechtcken in Äbhängigkeit einer Prozessvariablen ändern!
Ich wusste nicht, dass die Parameter automatisch angelegt werden...
Aber so macht es einen Sinn


----------



## RaffniX (8 November 2010)

Thomas_v2.1 schrieb:


> Hallo,
> 
> 
> ```
> ...



Hey, also hab jetzt mit diesem code versucht nen Farbumschlag zu realisieren. Das funktioniert auch:TOOL:

Jetzt habe ich noch vor, diesen Code direkt in eine c-Aktion zu schreiben und hab das auch getan... Dann kriege ich den Fehler, dass ich in einer void Funktion nix ändern kann und kriege aber auch das void nicht weg. Gibt es da einen anderen Operator als return zur Übergabe des Farbwertes??

Mein Code sieht folgendermaßen aus:

```
#include "apdefap.h"
void OnPropertyChanged(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName,  long  value)
{
#define TAG1 "1HBB20CT001/MA"
#define TAG2 "1HBB20CT002/MA"
#define TAG3 "1HBB20CT0012/MA"

int b, r=255, g;

float tFeld;

float var1 = GetTagFloat(TAG1);
float var2 = GetTagFloat(TAG2);
float var3 = GetTagFloat(TAG3);

// Prüfen der Messstelle

if ( (var2/var3)< 0.77)
{
var2 = var3;
}


tFeld = (var1*2.8 + var2)/3.8;

// Wertanpassung

tFeld = (tFeld*20.0)/3.0;

b= (int) 255.0 - (255.0*(tFeld/100));

g=b;

return ( b<<16 | g<<8 | r);


}
```

Grüße


----------



## RaffniX (8 November 2010)

Hat sich erledigt, war in Ereignis und nicht Eigenschaft...


----------

