Increasing map() output resolution

I am using the map() function in my project to convert from an analogRead() value to a PWM value (0-255).

map(analogRead(a0), 0, 1023, 0, 255);

I found that this code did not provide full resolution of the PWM output. Output skipped by approximately 3 steps, minimum, such as: 255, 252, 250, 247, 244... This was surprising, because the "from" range is 4x as big as the "to" range, so surely there is enough precision there to achieve 1-step resolution on the output. So I changed the code to:

map(analogRead(a0), 0, 1023 * 2, 0, 255 * 2);

And it works perfectly! I get sub-1-PWM-step resolution on the output. So I thought I'd pass that along to anybody who needs to map between two ranges of disparate size and wants to increase the effective resolution of the mapping. The exact multiplier required will depend on the relative size of the ranges, I think. I kind of expected that r1 / r2 would end up being the necessary multiplier, but it wasn't. I guess you just have to inject enough resolution to clear up the rounding errors, and you're good.

I can’t reproduce that.

void setup ()
  {
  Serial.begin (115200);
  Serial.println ();
  int old = 0;
  for (int i = 0; i < 1024; i++)
    {
    int j = map(i, 0, 1023, 0, 255);
    Serial.print (i);
    Serial.print (" -> ");
    Serial.println (j);
    if (old != j && (old + 1) != j)
      Serial.println ("Skipped!");
    old = j;
    }  // end of for
  }  // end of setup

void loop () { }

Output:

0 -> 0
1 -> 0
2 -> 0
3 -> 0
4 -> 0
5 -> 1
6 -> 1
7 -> 1
8 -> 1
9 -> 2
10 -> 2
11 -> 2
12 -> 2
13 -> 3
14 -> 3
15 -> 3
16 -> 3
17 -> 4
18 -> 4
19 -> 4
20 -> 4
21 -> 5
22 -> 5
23 -> 5
24 -> 5
25 -> 6
26 -> 6
27 -> 6
28 -> 6
29 -> 7
30 -> 7
31 -> 7
32 -> 7
33 -> 8
34 -> 8
35 -> 8
36 -> 8
37 -> 9
38 -> 9
39 -> 9
40 -> 9
41 -> 10
42 -> 10
43 -> 10
44 -> 10
45 -> 11
46 -> 11
47 -> 11
48 -> 11
49 -> 12
50 -> 12
51 -> 12
52 -> 12
53 -> 13
54 -> 13
55 -> 13
56 -> 13
57 -> 14
58 -> 14
59 -> 14
60 -> 14
61 -> 15
62 -> 15
63 -> 15
64 -> 15
65 -> 16
66 -> 16
67 -> 16
68 -> 16
69 -> 17
70 -> 17
71 -> 17
72 -> 17
73 -> 18
74 -> 18
75 -> 18
76 -> 18
77 -> 19
78 -> 19
79 -> 19
80 -> 19
81 -> 20
82 -> 20
83 -> 20
84 -> 20
85 -> 21
86 -> 21
87 -> 21
88 -> 21
89 -> 22
90 -> 22
91 -> 22
92 -> 22
93 -> 23
94 -> 23
95 -> 23
96 -> 23
97 -> 24
98 -> 24
99 -> 24
100 -> 24
101 -> 25
102 -> 25
103 -> 25
104 -> 25
105 -> 26
106 -> 26
107 -> 26
108 -> 26
109 -> 27
110 -> 27
111 -> 27
112 -> 27
113 -> 28
114 -> 28
115 -> 28
116 -> 28
117 -> 29
118 -> 29
119 -> 29
120 -> 29
121 -> 30
122 -> 30
123 -> 30
124 -> 30
125 -> 31
126 -> 31
127 -> 31
128 -> 31
129 -> 32
130 -> 32
131 -> 32
132 -> 32
133 -> 33
134 -> 33
135 -> 33
136 -> 33
137 -> 34
138 -> 34
139 -> 34
140 -> 34
141 -> 35
142 -> 35
143 -> 35
144 -> 35
145 -> 36
146 -> 36
147 -> 36
148 -> 36
149 -> 37
150 -> 37
151 -> 37
152 -> 37
153 -> 38
154 -> 38
155 -> 38
156 -> 38
157 -> 39
158 -> 39
159 -> 39
160 -> 39
161 -> 40
162 -> 40
163 -> 40
164 -> 40
165 -> 41
166 -> 41
167 -> 41
168 -> 41
169 -> 42
170 -> 42
171 -> 42
172 -> 42
173 -> 43
174 -> 43
175 -> 43
176 -> 43
177 -> 44
178 -> 44
179 -> 44
180 -> 44
181 -> 45
182 -> 45
183 -> 45
184 -> 45
185 -> 46
186 -> 46
187 -> 46
188 -> 46
189 -> 47
190 -> 47
191 -> 47
192 -> 47
193 -> 48
194 -> 48
195 -> 48
196 -> 48
197 -> 49
198 -> 49
199 -> 49
200 -> 49
201 -> 50
202 -> 50
203 -> 50
204 -> 50
205 -> 51
206 -> 51
207 -> 51
208 -> 51
209 -> 52
210 -> 52
211 -> 52
212 -> 52
213 -> 53
214 -> 53
215 -> 53
216 -> 53
217 -> 54
218 -> 54
219 -> 54
220 -> 54
221 -> 55
222 -> 55
223 -> 55
224 -> 55
225 -> 56
226 -> 56
227 -> 56
228 -> 56
229 -> 57
230 -> 57
231 -> 57
232 -> 57
233 -> 58
234 -> 58
235 -> 58
236 -> 58
237 -> 59
238 -> 59
239 -> 59
240 -> 59
241 -> 60
242 -> 60
243 -> 60
244 -> 60
245 -> 61
246 -> 61
247 -> 61
248 -> 61
249 -> 62
250 -> 62
251 -> 62
252 -> 62
253 -> 63
254 -> 63
255 -> 63
256 -> 63
257 -> 64
258 -> 64
259 -> 64
260 -> 64
261 -> 65
262 -> 65
263 -> 65
264 -> 65
265 -> 66
266 -> 66
267 -> 66
268 -> 66
269 -> 67
270 -> 67
271 -> 67
272 -> 67
273 -> 68
274 -> 68
275 -> 68
276 -> 68
277 -> 69
278 -> 69
279 -> 69
280 -> 69
281 -> 70
282 -> 70
283 -> 70
284 -> 70
285 -> 71
286 -> 71
287 -> 71
288 -> 71
289 -> 72
290 -> 72
291 -> 72
292 -> 72
293 -> 73
294 -> 73
295 -> 73
296 -> 73
297 -> 74
298 -> 74
299 -> 74
300 -> 74
301 -> 75
302 -> 75
303 -> 75
304 -> 75
305 -> 76
306 -> 76
307 -> 76
308 -> 76
309 -> 77
310 -> 77
311 -> 77
312 -> 77
313 -> 78
314 -> 78
315 -> 78
316 -> 78
317 -> 79
318 -> 79
319 -> 79
320 -> 79
321 -> 80
322 -> 80
323 -> 80
324 -> 80
325 -> 81
326 -> 81
327 -> 81
328 -> 81
329 -> 82
330 -> 82
331 -> 82
332 -> 82
333 -> 83
334 -> 83
335 -> 83
336 -> 83
...
1000 -> 249
1001 -> 249
1002 -> 249
1003 -> 250
1004 -> 250
1005 -> 250
1006 -> 250
1007 -> 251
1008 -> 251
1009 -> 251
1010 -> 251
1011 -> 252
1012 -> 252
1013 -> 252
1014 -> 252
1015 -> 253
1016 -> 253
1017 -> 253
1018 -> 253
1019 -> 254
1020 -> 254
1021 -> 254
1022 -> 254
1023 -> 255

The word “skipped” does not appear, so it appears that no numbers are not mapped in sequence.

Some output omitted because of posting maximum length, but you can reproduce it yourself. Full output in attachment.

output.txt (11.5 KB)

I concur with Ninja Nick. With the original function arguments, the map function reduces to calculating (255*x)/1023 where x is the mapped value. Changing this to (510*x)/2046 should have no effect on the result.

Pete

How odd. Now I can't replicate it either.

NEVERMIND!

@joshua are you sure that analogRead() give you every number from 0 to 1023 ?

The good code by @Gammon use a for loop with every value from 0 to 1023

You post this code:

map(analogRead(a0), 0, 1023, 0, 255);

And I think you send results to Serial Monitor, but what values for analog? I think is a better test if

int val=analogRead(a0);
byte res=map(val, 0, 1023, 0, 255);

and print on Serial Monitor val and res.

nid69ita: @joshua are you sure that analogRead() give you every number from 0 to 1023 ?

I think this is a very likely explanation. I was carefully moving the pot as slow as I could to be sure to make a 1-step change in analogRead(), and the results I was getting from the map() seemed too consistent to be anything except programmatical in nature, but I bet I was just not moving the pot slow enough. The debug serial.print() I was using outputs the result of the map(), but not the result of the analogRead(), so that would be easy to miss.

For this particular mapping it is easier and faster and better to use

byte PWMvalue = analogRead(a0)/4;

it will behave better than map() which has "trouble" with the largest value and the lowest values. * only 1023 will map on 255 - see output NICK in reply #1 - * the lowest 5 values map on 0

I am using the map() function in my project to convert from an analogRead() value to a PWM value (0-255)

Why? What's wrong with division.

AWOL:

I am using the map() function in my project to convert from an analogRead() value to a PWM value (0-255)

What's wrong with division.

I'm not always converting to full-range, simply "pwm = analog / 4" won't work.

I'm not always converting to full-range, simply "pwm = analog / 4" won't work.

OK, in either case map(analogRead(a0), 0, 1024, 0, 256); gives more consistent results.

AWOL:

I'm not always converting to full-range, simply "pwm = analog / 4" won't work.

OK, in either case map(analogRead(a0), 0, 1024, 0, 256); gives more consistent results.

I see what you're getting at there.