The Map Function

The map function takes a long integer value, x, in the range in_min through in_max and maps it into the range out_min through out_max. It is very convenient for scaling measurements and the function is defined:

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;
}

It is important to realize some limitations of this function.

  • In most applications in_min and out_min will be zero. However since these are passed as variables, the subtractions and additions of zero will be performed, wasting cpu cycles.
  • It performs integer arithmetic and not floating point arithmetic. This is generally good as there is no floating point hardware support in most Arduino boards and floating point should be avoided. However this can result in unexpected results. x*out_max might result in an overflow and the division will truncate the quotient rather than round to nearest.

Some Arduino models define a function mapResolution that does power-of-two scaling:

static inline uint32_t mapResolution(uint32_t value, uint32_t from, 
                                     uint32_t to) {
	if (from == to)
		return value;
	if (from > to)
		return value >> (from-to);
	else
		return value << (to-from);
}

While this code will be replicated whenever the function is called, the compiler’s optimization step will always reduce to just a shifting operation if from and two are constants or no code at all if from=to. You might want to consider writing your own map function as an inline function:

static inline long myMap(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;
}

If written as a macro, then it will work for any scalar data type (float, long, even char):

#define map(_x, _in_min, _in_max, _out_min, _out_max) \
  (_x - _in_min)*(_out_max - _out_min)/(_in_max - _in_min) + _out_min;