map() Funktion - habe ich einen Denkfehler?

Hallo,

habe ich einen Denkfehler? Ich möchte z.B. 20 Messwerte auf 5 Werte mappen. Also 0-3 = 0, 4-7 = 1 usw.
Klar, ich könnte auch einfach Wert geteilt durch 5 rechnen, ich brauchs aber für ein anderes Projekt (das ist nur ein Test, weil es nicht funktioniert wie ich es mir dachte).
Hier ist der TestCode:

void setup(void) {
  Serial.begin(9600);
  Serial.println("Hallo zu MAP-Test");
}

void loop() {
  for (int i=0;i<20;i++) {
    int pos = map(i,0,19,0,4);
    Serial.print(i);
    Serial.print(": ");
    Serial.println(pos);    
  }

  while(true){
  }
}

Und das gibt der SerialMonitor aus:

Hallo zu MAP-Test
0: 0
1: 0
2: 0
3: 0
4: 0
5: 1
6: 1
7: 1
8: 1
9: 1
10: 2
11: 2
12: 2
13: 2
14: 2
15: 3
16: 3
17: 3
18: 3
19: 4

Kann mich bitte jemand aufklären?

Vielen Dank

Ich verstehe dein Problem nicht.

Was ist falsch an dem Ergebnis?
Was hattest zu erwartet?

vieleicht int pos = map(i,0,20,0,5);

Also 0-3 = 0, 4-7 = 1 usw.
Klar, ich könnte auch einfach Wert geteilt durch 5 rechnen

Nee, ist mir nicht klar. (Bei mir ist 4 / 5 = 0 und auch 3 / 5 = 0)

" 0-3 = 0, 4-7 = 1 usw. " interpretiere ich so, dass du am oberen Ende 16...19 => 4 erwartest. ( Also "geteilt durch 4" )

Uwe's Vorschlag sollte das gleiche sein wie map(i,0,16,0,4) .
Zumindest solange i im Bereich 0...19 bleibt.

Hallo,
ok, ich versuch es mal noch genauer. Erster Schreibfehler war: "den Wert durch 4 teilen", nicht durch 5. Ich will 5 neue Werte.

In der Referenz steht folgendes: map(value, fromLow, fromHigh, toLow, toHigh). Ich habe das so verstanden, ich gebe 10 Werte von 1 bis 10 rein, möchte gerne 5 neue Werte und dann entspricht:

1,2 = 1
3,4 = 2
5,6 = 3
7,8 = 4
9,10 = 5

Deswegen war meine Idee: map(i,1,10,1,5). Aber anscheinend wird hier irgendwas geteilt und nicht einfach nur neu zugeordnet.

map macht Division mit Ganzen Zahlen ( integer ). Der Rest wird abgeschnitten.
map(i,1,9,1,5) rechnet (i-1) * (5-1) / (9-1) + 1

For the mathematically inclined, here's the whole function

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

i map
1 1  (0*4/8 + 1) 
2 1  (1*4/8  +1)
3 2  (2*4/8  +1)
4 2  (3*4/8  +1)
...

Interessanter ist eher, was map ausserhalb des definierten Bereichs macht ( i <= 0 oder i >= 9 in deinem Beispiel):
Begrenzen oder Extrapolieren ?
Die Referenz schweigt sich dazu aus. Falls die Formel tatsächlich so implementiert ist, wird extrapoliert.

Die Formel ist so implementiert.
Wenn man z.B. den Wert von analogRead() auf den Bereich von 0 bis 255 ummappen möchte, nimmt man besser nicht map(wert,0,1023,0,255) sondern map(wert,0,1024,0,256)

Wenn man z.B. den Wert von analogRead() auf den Bereich von 0 bis 255 ummappen möchte, nimmt man besser nicht map(wert,0,1023,0,255) sondern map(wert,0,1024,0,256)

Als Beispiel für map richtig.

Unabhängig davon: Noch besser ist /4 oder >>2.

michael_x:

Wenn man z.B. den Wert von analogRead() auf den Bereich von 0 bis 255 ummappen möchte, nimmt man besser nicht map(wert,0,1023,0,255) sondern map(wert,0,1024,0,256)

Als Beispiel für map richtig.

Unabhängig davon: Noch besser ist /4 oder >>2.

XD Ich hätte für das Beispiel doch besser 99 statt 255 nehmen sollen.

Ich hätte für das Beispiel doch besser 99 statt 255 nehmen sollen.

Sehr guter Einwand:
man nimmt map (i, 0,1024, 0,100) um sicherzugehen, dass man nur max zweistellige Werte im Bereich 0 .. 99 kriegt.
Und damit die 99 einen genauso großen Bereich abdeckt wie die 98 oder alle anderen Werte.

Darauf kommt man nicht so leicht ohne deine Anregung.