Forum: Mikrocontroller und Digitale Elektronik Skalierung von Messwerten in C


von DirkF (Gast)


Lesenswert?

Hallo, ich erfasse diverse Größen (Temperatur,Kraft,Druck) mit einem 
10-Bit AD Wandler des PIC18.
Als Beispiel
0-1023 Digit = -50....+300 Grad Celsius.
0-1023 Digit = - 25... 100 BAR (4-20 mA Messung)

Gint es eine fertige Funktion in C, die aus dem Eingangs Integer einen 
skalierten Ausgangsinteger macht ? Ich kenn sowas von der Siemens S7.

int Skalieren ( int In-min, INT IN-max, INT Out-min, INT OUT-max)

Werte für die Temperaturmessung:

INT Skalieren (0,1023,-500,3000);  // 1 Nachkommastelle

Ergebnis sollte dann ebenfalls als INT mit 1 Nachkommastelle sein.

Danke für eure Hilfe im voraus !

von spess53 (Gast)


Lesenswert?

Hi

>Gint es eine fertige Funktion in C,

Weiß ich nicht. Aber in der Zeit, in der du hier auf Antwort wartest, 
hätte ich eine solche Funktion in  Pascal dreimal geschrieben. In 
Assembler wahrscheinlich auch.
Außerdem fehlt deiner Funktion irgendwie der umzurechnende Wert.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

1
                                                       out_max - out_min
2
 salierter_wert = out_min +  ( Messwert - in_min ) * ---------------------
3
                                                         in_max - in_min

wenn du noch 1 Kommastelle haben willst, musst du noch einen Faktor 10 
anbringen
1
                                  10 * ( Messwert - in_min )  * ( out_max - out_min )
2
 salierter_wert = 10 * out_min +  ----------------------------------------------------
3
                                                    in_max - in_min

Auf Datentypen und mögliche Überläufe achten!

von Bernd N (Gast)


Lesenswert?


von DirkF (Gast)


Lesenswert?

Hallo, danke für die Hinweise. Habe es hin bekommen:


//**********************scale**********************************

  int scale (int in_min, int in_max, int out_min, int out_max, int wert)
  {
  int abc;
  abc = ((float)wert / ( (float)in_max - (float)in_min))*((float)out_max 
- (float)out_min) + (float)out_min;
  return (abc);
  }


//******************************Main**************************


void main(void)
{

  int ergebnis;
           int wert=600;
  ergebnis = scale (0,1024,-500,2500,wert);

von Karl H. (kbuchegg)


Lesenswert?

DirkF schrieb:
> Hallo, danke für die Hinweise. Habe es hin bekommen:
>
>
> //**********************scale**********************************
>
>   int scale (int in_min, int in_max, int out_min, int out_max, int wert)
>   {
>   int abc;
>   abc = ((float)wert / ( (float)in_max - (float)in_min))*((float)out_max
> - (float)out_min) + (float)out_min;
>   return (abc);
>   }

Warum hab ich blos geahnt, dass du float nehmen wirst :-)

Es ist unnötig!

Und schieb die Division nach hinten! Du willst so spät wie möglich 
dividieren!

(Da ist noch ein Fehler, den ich zu verantworten habe. Vom Messwert muss 
noch in_min abgezogen werden. Bei dir fällt es nicht auf, weil dein 
in_min gleich 0 ist.

Sieh dir nochmal die Formel weiter oben an. Da hab ich das in_min 
eingebaut.
)

Und schmeiss die float raus. Es reicht wenn du alles in long rechnest.

von Tretet den Trog (Gast)


Lesenswert?

Soll Mami Haendchen halten beim Dreisatz ? Wo ist das Problem dabei ?

von Bernd N (Gast)


Lesenswert?

Und das Beispiel war extra in Fixed Point :-(

von Karl H. (kbuchegg)


Lesenswert?

Tretet den Trog schrieb:
> Soll Mami Haendchen halten beim Dreisatz ? Wo ist das Problem dabei ?

Eher lineare Gleichung.
Dreisatz ist der Spezialfall, wenn in_min und out_min gleich 0 sind.
Ist aber ähnlich trivial wie der Dreisatz.

von Falk B. (falk)


Lesenswert?


von DirkF (Gast)


Lesenswert?

Hallo, danke für den Hinweis mit dem Long. Der code ist jetzt wesentlich 
kleiner geworden !

//**********************scale**********************************

  int scale (int in_min, int in_max, int out_min, int out_max, int wert)
  {
  int abc;
  abc = ((long)out_max - (long)out_min)* (long)wert / ( (long)in_max - 
(long)in_min);
  abc = abc + out_min;

  return (abc);
  }

//******************************Main**************************

void main(void)
{
  int ergebnis;
  int wert = 600;  // vom AD Wandler 10 Bit
  ergebnis = scale (0,1024,-500,2500,600); // skalieren in 
-50,0...+250,0°C

von Karl H. (kbuchegg)


Lesenswert?

Den in_min Offset Fehler hast du immer noch.

Sagtest du nicht auch etwas von einer Skalierung, so dass im Endergebnis 
noch 1 'Nachkommastelle' auftaucht? (Kannst du natürlich auch über die 
out_min, out_max Werte erreichen, wenn du deren möglichen Zahlenbereich 
nicht ausnutzen wirst.

Und es reicht wenn du das Ergebnis von  ( max - min )   auf long 
castest. Die Subtraktion muss nicht long gemacht werden. Nicht bei 
deinen Zahlenwerten. Wenn du es allerdings ein wenig allgmeiner halten 
willst, dann lass es so wie es ist.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.