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

asked Mar 26, 2023 at 20:28
1
  • 1
    What about just saying float meterPosition = voltage * 64.0 ; ? 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.

answered Mar 27, 2023 at 10:02
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.

answered Mar 26, 2023 at 20:34

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.