Forum: Mikrocontroller und Digitale Elektronik map() Befehl in avr-gcc


von Herman Uh. (Gast)


Lesenswert?

1
long map(long x, long in_min, long in_max, long out_min, long out_max)
2
{
3
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
4
}

Komme leider noch nicht so zurecht mit der Mathematik bei µC.
Würde gerne die ganze Funktion auf uint8_t umbauen.

1
uint8_t map(uint8_t x, uint8_t in_min, uint8_t in_max, uint8_t out_min, uint8_t out_max)
2
{
3
  return (uint16_t)(x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
4
}

Reicht das so?
Die uint8_t Parameter können 0 - 255 darstellen. Möchte die Formel 
möglichst mit wenigen größeren Variablen rechnen.

von Irgendwer (Gast)


Lesenswert?

Und für was soll das "(uint16_t)(x - in_min)" gut sein?

Deine Bedingung "uint8_t Parameter können 0 - 255 darstellen" musst du 
aber noch mindestens um Folgendes ergänzen wenn das passen könnte:
x >= in_min
out_max >= out_min
in_max > in_min

PS: was ist eine "map" Befehl?

von M. K. (sylaina)


Lesenswert?

Irgendwer schrieb:
> PS: was ist eine "map" Befehl?

Die Funktion steht doch oben, was daran verstehst du denn nicht?

Irgendwer schrieb:
> Und für was soll das "(uint16_t)(x - in_min)" gut sein?

Lass mal überlegen: Vielleicht ein Type Cast damit mit 16 Bit an der 
Stelle gerechnet wird?

Irgendwer schrieb:
> Deine Bedingung "uint8_t Parameter können 0 - 255 darstellen" musst du
> aber noch mindestens um Folgendes ergänzen wenn das passen könnte:
> x >= in_min
> out_max >= out_min
> in_max > in_min

Ich wage hier einen Spruch ins Blaue und sage mal, dass alleine die 
Namensgebung das schon so vorhersagt. In der Funktion wird es nur nicht 
geprüft, könnte man vielleicht noch implementieren aber im µC hat man ja 
immer wenig Platz…

von PittyJ (Gast)


Lesenswert?

Ein paar Anmwerkungen:

Naja, in C gibt es keine Befehle, sondern nur Funktionen.

In C++ gib es auch eine map. Die macht aber komplett etwas anderes. Man 
sollte so eine Namensgleichheit vermeiden. Lieber einen Funktionsnamen 
benutzen, der genau sagt, was darin gemacht wird. Der Name kann auch 
mehr als 3 Buchstaben haben.

Wird mit uint8_t gerechnet, kommt man schnell an Überläufe bei 
Subtraktion und Multiplikation. Da der TE nichts zum Wertebereich 
genannt hat, ist das alles nur Spekulation.

Und wenn diese Funktion seht oft aufgerufen wird, könnte man evtl auch 
(in_max - in_min)
vorher berechnen lassen. Manchmal bleibt der Wertebereich ja gleich. 
Damit hätte man gleich 2 Berechnungen eleminiert.

von Klaus W. (mfgkw)


Lesenswert?

PittyJ schrieb:
> Und wenn diese Funktion seht oft aufgerufen wird, könnte man evtl auch
> (in_max - in_min)
> vorher berechnen lassen. Manchmal bleibt der Wertebereich ja gleich.
> Damit hätte man gleich 2 Berechnungen eleminiert.

Das kann man auch erreichen, wenn man die Funktion inline deklariert. 
Den Rest macht dann der Optimierer beim Übersetzen.
So bleibt der Quelltext schöner lesbar.

von Wolfgang (Gast)


Lesenswert?

Irgendwer schrieb:
> PS: was ist eine "map" Befehl?

Wie der Name schon suggeriert, bildet der Befehl einen Wert aus dem 
einen Wertebereiche (linear) auf den anderen ab. Dreisatz mit 
Verschiebung könnte man das wohl auch nennen.
Die Frunktion wird die in der Arduino Umgebung zur Verfügung gestellt.
http://arduino.cc/en/reference/map

von Klaus W. (mfgkw)


Lesenswert?

Herman Uh. schrieb:
> Komme leider noch nicht so zurecht mit der Mathematik bei µC.
> Würde gerne die ganze Funktion auf uint8_t umbauen.

Dann mach das doch!

Im ersten Schritt ersetzt du einfach alle long durch uint8_t (und gibst 
der Funktion einen aussagekräftigeren Namen).

Im zweiten Schritt lohnt es sich zu überlegen, was dann alles nicht mehr 
funktioniert.
Das können alle Zwischen- und Endergebnisse sein, abhängig davon ob mit 
welchen Wertebreichen du wirklich arbeitest.
Dementsprechend muß man dann für die Zwischen- und das Endergebnis 
großzügigere Datentypen vorsehen.

Gute Gelegenheit, etwas C zu lernen...

Nimmt man bei Arduino nicht ohnehin C++?
Dann könnte man auch gleuich aus der Funktion ein Funktionstemplate 
machen, das je nach Typ der Aufrufparameter eine angepasste Funktion 
nimmt.

Gute Gelegenheit, etwas C++ zu lernen...

von Karl H. (kbuchegg)


Lesenswert?

Michael Köhler schrieb:

> Irgendwer schrieb:
>> Und für was soll das "(uint16_t)(x - in_min)" gut sein?
>
> Lass mal überlegen: Vielleicht ein Type Cast damit mit 16 Bit an der
> Stelle gerechnet wird?

Das würde es so und so.

Regel in C:
Gerechnet wird im größten in einer Operation vorkommenden Datentyp, 
jedoch nicht kleiner als int.

D.h.: wenn das alles uint8_t sind, dann wird sowieso erst mal alles in 
int gerechnet.
Erst wenn der Compiler beweisen kann, dass es keinen Unterschied macht, 
kann er die int-Rechnerei auf uint8_t runterbrechen. Allerdings dürfte 
er da bei den Multiplikationen so seine Schwierigkeiten haben.

Im übrigen frage ich mich, warum der TO nicht hergeht und mal einen Test 
seiner Änderungen fährt? Kommen die richtigen Ergebnisse raus? Tun sie 
das auch bei den Grenzwerten, wenn die Zahlen an die Limits kommen?
Sorry, aber das ist nun wirklich etwas, was man als angehender 
Programmierer lernen muss: man ist erst mal selbst für seinen Code 
verantwortlich und hat sicherzustellen, dass er funktioniert. Dazu 
gehört auch, dass man den Code testest und sich überlegt wie man durch 
testen möglichst viele Fehler ausschliessen kann. Wie soll denn das in 
Zukunft weitergehen? Fragst du wegen jedem Pfurz in einem Forum nach? 
Ein bisschen mehr Mut zur Eigenverantwortung und zu den eigenen 
Fähigkeiten!

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.