Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Unexpected values when using Arduino Leonardo #3

Closed
satoer opened this issue Oct 2, 2021 · 7 comments
Closed

Bug: Unexpected values when using Arduino Leonardo #3

satoer opened this issue Oct 2, 2021 · 7 comments
Assignees
Labels
question Further information is requested

Comments

@satoer
Copy link

satoer commented Oct 2, 2021

I don't get it. Used Multimap several times before with great success, but now with an Arduino Leonardo I get unexpected results.

I've made an example to the bear minimum:

#include "MultiMap.h"
int In[]   = { 0  ,   512};
int Out[]  = { 0  ,   255};

void setup() {
  Serial.begin(9600);
}

void loop() {
  for (int i = 0; i <= 512; i++) {
    int mapValue = multiMap<int>(i, In, Out, 2);
    Serial.println(String(i) + ": " + String (mapValue));
  }
  delay(10000);
}

And this is the result:

0: 0
1: 0
2: 0
3: 1
4: 1
5: 2
6: 2
7: 3
8: 3
9: 4
10: 4
11: 5
12: 5
13: 6
14: 6
15: 7
16: 7
17: 8
18: 8
19: 9
20: 9
21: 10
22: 10
23: 11
24: 11
25: 12
26: 12
27: 13
28: 13
29: 14
30: 14
31: 15
32: 15
33: 16
34: 16
35: 17
36: 17
37: 18
38: 18
39: 19
40: 19
41: 20
42: 20
43: 21
44: 21
45: 22
46: 22
47: 23
48: 23
49: 24
50: 24
51: 25
52: 25
53: 26
54: 26
55: 27
56: 27
57: 28
58: 28
59: 29
60: 29
61: 30
62: 30
63: 31
64: 31
65: 32
66: 32
67: 33
68: 33
69: 34
70: 34
71: 35
72: 35
73: 36
74: 36
75: 37
76: 37
77: 38
78: 38
79: 39
80: 39
81: 40
82: 40
83: 41
84: 41
85: 42
86: 42
87: 43
88: 43
89: 44
90: 44
91: 45
92: 45
93: 46
94: 46
95: 47
96: 47
97: 48
98: 48
99: 49
100: 49
101: 50
102: 50
103: 51
104: 51
105: 52
106: 52
107: 53
108: 53
109: 54
110: 54
111: 55
112: 55
113: 56
114: 56
115: 57
116: 57
117: 58
118: 58
119: 59
120: 59
121: 60
122: 60
123: 61
124: 61
125: 62
126: 62
127: 63
128: 63
129: -63
130: -63
131: -62
132: -62
133: -61
134: -61
135: -60
136: -60
137: -59
138: -59
139: -58
140: -58
141: -57
142: -57
143: -56
144: -56
145: -55
146: -55
147: -54
148: -54
149: -53
150: -53
151: -52
152: -52
153: -51
154: -51
155: -50
156: -50
157: -49
158: -49
159: -48
160: -48
161: -47
162: -47
163: -46
164: -46
165: -45
166: -45
167: -44
168: -44
169: -43
170: -43
171: -42
172: -42
173: -41
174: -41
175: -40
176: -40
177: -39
178: -39
179: -38
180: -38
181: -37
182: -37
183: -36
184: -36
185: -35
186: -35
187: -34
188: -34
189: -33
190: -33
191: -32
192: -32
193: -31
194: -31
195: -30
196: -30
197: -29
198: -29
199: -28
200: -28
201: -27
202: -27
203: -26
204: -26
205: -25
206: -25
207: -24
208: -24
209: -23
210: -23
211: -22
212: -22
213: -21
214: -21
215: -20
216: -20
217: -19
218: -19
219: -18
220: -18
221: -17
222: -17
223: -16
224: -16
225: -15
226: -15
227: -14
228: -14
229: -13
230: -13
231: -12
232: -12
233: -11
234: -11
235: -10
236: -10
237: -9
238: -9
239: -8
240: -8
241: -7
242: -7
243: -6
244: -6
245: -5
246: -5
247: -4
248: -4
249: -3
250: -3
251: -2
252: -2
253: -1
254: -1
255: 0
256: 0
257: 0
258: 0
259: 0
260: 1
261: 1
262: 2
263: 2
264: 3
265: 3
266: 4
267: 4
268: 5
269: 5
270: 6
271: 6
272: 7
273: 7
274: 8
275: 8
276: 9
277: 9
278: 10
279: 10
280: 11
281: 11
282: 12
283: 12
284: 13
285: 13
286: 14
287: 14
288: 15
289: 15
290: 16
291: 16
292: 17
293: 17
294: 18
295: 18
296: 19
297: 19
298: 20
299: 20
300: 21
301: 21
302: 22
303: 22
304: 23
305: 23
306: 24
307: 24
308: 25
309: 25
310: 26
311: 26
312: 27
313: 27
314: 28
315: 28
316: 29
317: 29
318: 30
319: 30
320: 31
321: 31
322: 32
323: 32
324: 33
325: 33
326: 34
327: 34
328: 35
329: 35
330: 36
331: 36
332: 37
333: 37
334: 38
335: 38
336: 39
337: 39
338: 40
339: 40
340: 41
341: 41
342: 42
343: 42
344: 43
345: 43
346: 44
347: 44
348: 45
349: 45
350: 46
351: 46
352: 47
353: 47
354: 48
355: 48
356: 49
357: 49
358: 50
359: 50
360: 51
361: 51
362: 52
363: 52
364: 53
365: 53
366: 54
367: 54
368: 55
369: 55
370: 56
371: 56
372: 57
373: 57
374: 58
375: 58
376: 59
377: 59
378: 60
379: 60
380: 61
381: 61
382: 62
383: 62
384: 63
385: 63
386: -63
387: -63
388: -62
389: -62
390: -61
391: -61
392: -60
393: -60
394: -59
395: -59
396: -58
397: -58
398: -57
399: -57
400: -56
401: -56
402: -55
403: -55
404: -54
405: -54
406: -53
407: -53
408: -52
409: -52
410: -51
411: -51
412: -50
413: -50
414: -49
415: -49
416: -48
417: -48
418: -47
419: -47
420: -46
421: -46
422: -45
423: -45
424: -44
425: -44
426: -43
427: -43
428: -42
429: -42
430: -41
431: -41
432: -40
433: -40
434: -39
435: -39
436: -38
437: -38
438: -37
439: -37
440: -36
441: -36
442: -35
443: -35
444: -34
445: -34
446: -33
447: -33
448: -32
449: -32
450: -31
451: -31
452: -30
453: -30
454: -29
455: -29
456: -28
457: -28
458: -27
459: -27
460: -26
461: -26
462: -25
463: -25
464: -24
465: -24
466: -23
467: -23
468: -22
469: -22
470: -21
471: -21
472: -20
473: -20
474: -19
475: -19
476: -18
477: -18
478: -17
479: -17
480: -16
481: -16
482: -15
483: -15
484: -14
485: -14
486: -13
487: -13
488: -12
489: -12
490: -11
491: -11
492: -10
493: -10
494: -9
495: -9
496: -8
497: -8
498: -7
499: -7
500: -6
501: -6
502: -5
503: -5
504: -4
505: -4
506: -3
507: -3
508: -2
509: -2
510: -1
511: -1
512: 255

Any idea why the output does not met the expectation?


added cpp in the code block markup for syntax highlighting

@satoer satoer changed the title Unexpected values Bug: Unexpected values when using Arduino Leonardo Oct 2, 2021
@satoer
Copy link
Author

satoer commented Oct 2, 2021

Just tried the same code on a ESP32. This resulted in the expected outcome:

0: 0
1: 0
2: 0
3: 1
4: 1
5: 2
6: 2
7: 3
8: 3
9: 4
10: 4

...

500: 249
501: 249
502: 250
503: 250
504: 251
505: 251
506: 252
507: 252
508: 253
509: 253
510: 254
511: 254
512: 255

truncated for readability

@RobTillaart
Copy link
Owner

Hi Satoer,

The explanation is probably quite simple, the size of an int is 16 bit on a Leonardo and 32 bit on an ESP32
What you see is that an intermediate result in the math became larger than 32767 and caused overflow and sign flipping.

you can verify my hypothesis with the sketch below.

void setup()
{
  Serial.begin(115200);
  Serial.println(sizeof(int));
}

void loop()
{}

Solution for your sketch

#include "MultiMap.h"
int32 In[]   = { 0  ,   512};
int32 Out[]  = { 0  ,   255};

void setup() {
  Serial.begin(9600);
}

void loop() {
  for (int i = 0; i <= 512; i++) {
    int mapValue = multiMap<int32>(i, In, Out, 2);  // <<<<<<<<<<< make it explicit 32 bits integers.
    Serial.println(String(i) + ": " + String (mapValue));
  }
  delay(10000);
}

@RobTillaart
Copy link
Owner

We can try to check the input value of 129 (which was the first to fail

int In[] = { 0 , 512};
int Out[] = { 0 , 255};

As there is only one segment, the output = outmin + (input * (outmax - outmin)) / (inmax - in min)

output = 0 + (129 * ( 255 - 0)) / (512- 0)
output = (129 * 255) / 512
output = 32895 / 512 <<<<< here it happens 32895 > 32767 so overflow.

32895 flips to - (65535 - 32685) = -32640

output = -32640 /512
output = - 63 exactly what you got.

So always check intermediate math results if unexpected values pop up (even when most look OK).

@RobTillaart RobTillaart self-assigned this Oct 2, 2021
@RobTillaart RobTillaart added the question Further information is requested label Oct 2, 2021
@satoer
Copy link
Author

satoer commented Oct 2, 2021

First code had output: 2

Second code received an error:
'int32' does not name a type

Changed every 'int32' to 'long' and it fixed the problem! The outcome is as suspected. Thank you, this was driving me crazy.

@RobTillaart
Copy link
Owner

should been int32_t my mistake

long is 32 bit on Leonardo and I expect too on ESP.

These 'intermediate overflows' happen sometimes when porting code or when mixing unsigned and signed math.
Typical solution is to make intermediate values "big" enough.
If that is not possible one needs to rewrite the algorithm so all (intermediate) variables stay within a defined range.

@RobTillaart
Copy link
Owner

Similar things can happen when e.g. a time variable overflows, most famous is millis() after some 49.7 days. or micros() after ~70 minutes. If you math is not prepared to handle the overflows correctly strange values may pop up.

Recently I read about a bug that occurred every ~25 days, which was almost in sync with the moon cycle so people were quite amazed. In the end it was a mix of millis() overflow combined with signed/unsigned math mixture.

@satoer
Copy link
Author

satoer commented Oct 2, 2021

Thanks Rob, You've been really helpful, and got my program working. Didn't suspected a overflow because the values are well below a 16 bit integer. I didn't took intermediate results in consideration though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants