0

Arduino has a map() function that scales an integer value from one range to another. For example, you can take input from an 8-bit ADC sensor that ranges from 0–1024, and proportionally scale it to the range 0-100.

How would I do this in Python?

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • 1
    Do you mean doing a wraparound (101 would go back to 0, -10 would go to 90), or clamping (101 would go to 100, -10 would go to 0)? – Ayush Garg Jan 09 '22 at 17:07
  • 1
    My assumption would be scaling, which would be division (i.e. `math.floor(x / 10.24)` to scale `x` from the 0-1024 range to a roughly proportionate int in the 0-100 range). In any case, yeah, "range" isn't a useful verb in this context and this question needs some clarification. – Samwise Jan 09 '22 at 17:09
  • 2
    Providing a link to documentation of the C `range()` function you mention would probably also be helpful. I can't seem to Google up anything like what you describe, but I know very little about C. If you [edit your question](https://stackoverflow.com/posts/70643627/edit) to sufficiently clarify it, it can be reopened. – CrazyChucky Jan 09 '22 at 17:12
  • 1
    I'm sorry I meant map() not range. Similar to this https://www.best-microcontroller-projects.com/arduino-map.html#Arduino_Map – Justin Anderson Jan 09 '22 at 17:19
  • 4
    Do mean [this map](https://www.arduino.cc/reference/en/language/functions/math/map/)? Because there is clear math explanation of the implementation that can be used almost verbatim to implement your own function in python. – buran Jan 09 '22 at 17:23
  • Yes, sorry. I 3dited my original question to clarify that. I was looking at the range function in python and mixed them up. – Justin Anderson Jan 09 '22 at 17:25
  • Sound's like normalizing (re-scaling) between [a, b] for me despite the discretizing of signal values in ADC as @buran mentioned in map() function. – Mario Jan 10 '22 at 22:39

2 Answers2

4

Like buran mentioned in the comments, the Arduino reference page for map() shows the full implementation, which can be copied almost verbatim into Python.

Here's the Arduino C++ code:

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

And here's what it would look like in Python. The only real gotcha is that / in Python returns a float even when both operands are integers; // is specifically integer division.

def map_range(x, in_min, in_max, out_min, out_max):
  return (x - in_min) * (out_max - out_min) // (in_max - in_min) + out_min

(I've also renamed it so it doesn't shadow Python's own map, which is something different entirely.)

CrazyChucky
  • 3,263
  • 4
  • 11
  • 25
-2

Why don't you just divide by the original range max value and multiply by new range max-value?

new_value = (int) (my_value/max_value)*new_range_max

EDIT: if the original value is binary you can convert it to decimal by doing:

int(b, 2)  # Convert a binary string to a decimal int.

Reference: https://stackoverflow.com/a/13656358/11381650

pedro_bb7
  • 1,601
  • 3
  • 12
  • 28