0

I am experimenting using the map() method in an ArduinoIDE sketch in an attempt to obtain a pixel position for a horizontal meter in the range 0-320 from an input value in the range 0-5. However, when I do this I see in the method that the input must be 'long' type. Here's my example code:

  float voltage = 2.5;
  float meterPosition = map(voltage, 0, 5, 0, 320);
  tft.fillRect(0, 0, meterPosition, 10, TFT_GREEN);
  tft.setCursor(10, 70);
  tft.setTextSize(3);
  tft.println(voltage);
  tft.println(meterPosition);

But when I run this, despite the input value being 50% of the input range, I expected the meterPosition value to be 160, but it is 128, due I think because the values for this method must be of type 'long' and so the 'float' value is rounded and becomes a 'long' type (I think that's what is happening!!).

I am confused as to the function of the map() method if you are unable to map any range to any other range without using decimals as the input. I am obviously missing something here, so what do I need to change in my map() method code for it to work in my example please, if I am unable to use floats?

Thanks. John

1
  • 1
    What about just saying float meterPosition = voltage * 64.0 ; ?
    – 6v6gt
    Commented Mar 27, 2023 at 13:33

2 Answers 2

1

As you already noticed, the map() function is meant to work with the long data type. Here is its implementation:

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

If you want to use floats, you could write a version of this function that works with floats. Note, however, that since you are using zeros for both in_min and out_min, the expression simplifies itself to the point of becoming trivial:

float meterPosition = voltage * 320 / 5.0;

I would suggest two small changes to this expression though:

  • add parentheses around (320 / 5.0): this ratio will then be evaluated at compile-time and you will save an expensive run-time floating-point division

  • round to the nearest integer in order to minimize the error: your pixel position will have to be an integer anyway.

With these suggestions, we have:

int meterPosition = round(voltage * (320 / 5.0));

Do not forget the .0 in 5.0, otherwise you would get an integer division.

Note that using map() with ranges scaled by a factor 100 is not a terribly good idea: you will waste quite a lot of CPU cycles doing useless computations, and the result will be polluted by two rounding errors instead of one.

0

Apologies for my stupidity folks! I think I have realised how to do this, it is simply a matter of scaling the input values and input range by 100.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.