map function issue ?

Hello everybody,

I have a strange issue with the map function.

I have a value from 4000 to 12000 and I need to map it to 1 to 8, so 4000 is 1 and 12000 is 8.

here is my code:

int result = map(value, 4000, 12000, 1, 8);

and here is the result:

value: 2803 result : 0
value: 2803 result : 0
value: 2803 result : 0
value: 2857 result : 0
value: 2857 result : 0
value: 2857 result : 0
value : 3296 result : 1
value : 3296 result : 1
value : 5084 result : 1
value : 5084 result : 1
value : 5357 result : 2
value : 6000 result : 2
value : 6122 result : 2
value : 6382 result : 3
value : 6382 result : 3
value : 7317 result : 3
value : 7142 result : 3
value : 7500 result : 4
value : 7500 result : 4
value : 8333 result : 4
value : 8333 result : 4
value : 8823 result : 5
value : 8571 result : 4
value : 8571 result : 4
value : 8823 result : 5
value : 8823 result : 5
value : 9677 result : 5
value : 9677 result : 5
value : 10000 result : 6
value : 9677 result : 5
value : 10344 result : 6
value : 10000 result : 6
value : 10000 result : 6
value : 10714 result : 6
value : 11111 result : 7
value : 11538 result : 7
value : 11111 result : 7
value : 12000 result : 8
value : 12000 result : 8
value : 12000 result : 8

As you can see the upper limit is good, when value reach 12000 it is map to 8.
But the lower limit is not good, value is map to 1 around 3200 instead of 4000.

Do you have any explain for this result ? Did I miss something ?

It's a consequence of how the map function is written using integer math. The easiest way to fix it would be to first test if the number is less than 4000 and if so use a 0 and if not then use the map function.

int input = someFunctionToGetTheInput;

int output;

if(input < 4000){
     output = 0;
}
else {
     output = map(value, 4000, 12000, 1, 8);
}

If the input value might go over 12000 and you want to contrain that to an 8 then you might want to do a similar test on that as well.

Thank you :slight_smile:

I was expected a reply like this and the two tests is my actual workaround, I'll let it like this.

There is also the constrain function.

Delta_G:
It's a consequence of how the map function is written using integer math.

Not really. It's a consequence of the OP stating that the input range would be 4000 to 12000, then testing it with a value of 2803. The results are entirely as expected, it's just a shame that a lot of the tutorials fail to mention that the result will not be constrained.

just some thought

Sometimes one must look through the map function

output = map(value, 4000, 12000, 1, 8);

is almost

output = value/1000 - 3;

Check for a FastMap Class - Class from map function - FastMap - Libraries - Arduino Forum

update: added code tags

Sometimes one must look through the map function

output = map(value, 4000, 12000, 1, 8);

is almost

output = value/1000 - 3;

If the upper limit is a smiley face...

Oops:)

Yes, the map fuction is not well described in the tutorial or on the arduino reference sheet.

But with constraint or some tests it works well :slight_smile:

M4vrick:
I have a strange issue with the map function.

I have a value from 4000 to 12000 and I need to map it to 1 to 8, so 4000 is 1 and 12000 is 8.

here is my code:

int result = map(value, 4000, 12000, 1, 8);

The 'map()' function is one of the worst functions in the Arduino core library.
Undocumented function.
Non-intuitive function.
Example programs show how to use this function the wrong way.

So nearly everybody seems to use the function the wrong way.

Correct would be:

  • Include the lower bound into the range
  • but DO NOT include the upper bound into the range

So the correct usage in your case (map 4000 to value 1, map 12000 to value 8 ) would be indeed:

   int result = map(value, 4000, 12001, 1, 9);

lower bounds (4000 and 1): included in range
upper bounds (12001 and 9): NOT included in intended mapping range by one

We know it's bad, thats why there was a whole discussion about improving it.

http://forum.arduino.cc/index.php?topic=49982.0#bot