Skip to content

Embedded Systems

How the Arduino map() function works

map(value, fromLow, fromHigh, toLow, toHigh) rescales a number from one range to another. A reading 25% of the way up the first range comes out 25% of the way up the second. The classic use turns analogRead's 0 to 1023 into analogWrite's 0 to 255: map(512, 0, 1023, 0, 255) gives 127.

The formula

map() draws a straight line through two points and reads off the answer:

out = (x − fromLow) × (toHigh − toLow) over fromHigh − fromLow + toLow

For 512 into 0 to 255: 512 × 255 ÷ 1023 = 127.6. map() works in whole numbers (long), so it drops the fraction and returns 127.

Follow the light

A light sensor on A0 reads high in daylight and low in the dark. Mapped onto an LED, the LED's brightness follows the room:

void loop() {
  int reading = analogRead(A0);
  analogWrite(9, map(reading, 0, 1023, 0, 255));
}

Swap the output ends and the line runs backwards: map(reading, 0, 1023, 255, 0) makes a dark room bright and a bright room dark, a path light. A reading of 256 now gives about 192.

Live experiment

Switch, follow, or follow backwards

Slide the light on the sensor from night to day. The switch is fully on below 512 and off above it; the follower writes map(reading, 0, 1023, 0, 255) and glows with the room; written backwards, 255 to 0, it glows brightest in the dark.

Try it yourself: free lesson

“Auto-brightness” is lesson 6 of 6 in Signal Shore, Embedded Systems World 3. Free with an account. Lessons unlock in order, so you’ll do the 19 before it first.

Three traps

It rounds down. Whole-number maths throws away the fraction every time, so small output ranges come out lumpy. map(5, 0, 10, 0, 1) is 0, not 0.5. For decimals, write the formula yourself with floats.

It's only a straight line. map() is perfect for a knob, which is linear. A sensor whose response curves, like a thermistor, is only right near the two points you choose. Calibrate with two known readings, map(reading, 396, 620, 15, 35) for 15 °C and 35 °C, and it's spot on between them but drifts outside: a reading of 713 says 43 °C when it's really 45.

Where you'll use it

Knob to motor speed, light level to brightness, raw count to degrees or percent: whenever one number needs to become another with the same proportions, map() is one line. Just check the input really stays in range, and that a straight line really fits.

Free lesson

Now build it yourself

Each lesson comes in three short parts: see the idea, try it on a live board, then build it yourself, with quick checks as you go.

Try it yourself: free lesson

“Auto-brightness” is lesson 6 of 6 in Signal Shore, Embedded Systems World 3. Free with an account. Lessons unlock in order, so you’ll do the 19 before it first.

Or start from the very first lesson, no account needed

Practice questions

Three quick questions from the lessons. Pick an answer to check it.

  1. Question 1 of 3map(reading, 0, 1023, 255, 0) with a reading of 1023 gives…
    Show the answer

    Answer: 0. The output range runs backwards, 255 down to 0, so the top of the input range lands on 0. Full daylight means an LED that's off; full dark means 255.

    • Why not “127”? 127 is the middle of the output range, which a reading halfway up, about 512, would give.
    • Why not “255”? 255 is where the output range starts, so it's what the bottom of the input range, 0, maps to.
    • Why not “1023”? 1023 is the input. map() hands back a number in the output range, 255 down to 0.
  2. Question 2 of 3map(512, 0, 1023, 0, 100) gives about…
    Show the answer

    Answer: 50. Halfway in, halfway out.

    • Why not “5”? 5 would be about a twentieth of the way up. 512 is about halfway up 0 to 1023, so the answer is about 50.
    • Why not “100”? 100 is the top of the output range, what a reading of 1023 would give.
    • Why not “512”? 512 is the input. map() keeps its fraction of the way up, half, and applies it to 0 to 100.
  3. Question 3 of 3Brightness that follows the light, instead of switching on and off, needs…
    Show the answer

    Answer: analogWrite with a value from map(). analogWrite sets any brightness from 0 to 255, and map() turns the light reading into one.

    • Why not “Two thresholds”? Two thresholds make a switch with hysteresis: on or off, never anything in between.
    • Why not “delay()”? delay() just waits; it doesn't set a brightness at all.
    • Why not “digitalWrite”? digitalWrite only gives fully on or fully off, so it can't follow the light smoothly.
Keep practising: free lesson

“Auto-brightness” is lesson 6 of 6 in Signal Shore, Embedded Systems World 3. Free with an account. Lessons unlock in order, so you’ll do the 19 before it first.

Questions people ask

What does map() do in Arduino?

It rescales a number from one range to another, keeping its place along the range. map(value, 0, 1023, 0, 255) turns a reading halfway up 0 to 1023 into a value halfway up 0 to 255, about 127.

Does map() constrain the result to the output range?

No. A value outside the input range maps to a value outside the output range. If that can happen, wrap the result in constrain(), like constrain(map(x, 0, 1023, 0, 255), 0, 255).

Can map() work with decimals?

No. map() works in whole numbers and drops the fraction, so map(5, 0, 10, 0, 1) gives 0, not 0.5. For decimals, write the same formula yourself with float variables.

Should I use map() or divide by 4 to go from 0–1023 to 0–255?

Either works. Dividing by 4 gives each output value exactly four readings. map(x, 0, 1023, 0, 255) reaches 255 only at a reading of exactly 1023, so the top value is rare, but the difference is invisible on an LED.

Every topic