Map() function strange operation. Undesired results.

Hi Everyone,

Before I continue I will say that everything worked just fine before I started altering the code to eliminate a harmless but annoying bug (unrelated to map).

I reverted my troubleshooting steps (or at least this is what I believe) but the map() doesn't re-map the value properly anymore.

Reference:
https://www.arduino.cc/en/Reference/Map

As soon as the re-mapped value exceeds the number 2386, it continues with -2385, -2384,...,0, 1, 2, ....2385, 2386, -2385, etc. in circles.

HW: Arduino Pro Micro (detected as Leonardo) + Load Cell + HX711 amp.

Update: below is the most recent troubleshooting. I simplified the code as much as possible and getting same weird results. Looks like map() function is able to return 4772 values only.

Code:

#include <Q2HX711.h>

Q2HX711 Hx711(SDA, SCL);

void setup()
{
  Serial.begin(115200);
}
void loop()
{
  Serial.println(Hx711.read());
  Serial.println(map(Hx711.read(), 8600000, 9500000, 0, 10000));
}

Results:

8597487
-12
8600161
19
8603438
59
8607447
105
8611786
156
8616300
208
8621365
266
8626653
323
8631604
379
8636677
434
8641470
486
8645838
530
8649340
567
8652780
604
8656285
647
8660201
690
8664058
733
8667916
776
8671879
820
8675731
862
8679833
908
8683606
953
8687992
1000
8692128
1047
8696468
1098
8701438
1156
8706614
1213
8712163
1280
8718241
1347
8724581
1418
8730529
1483
8736536
1552
8742663
1620
8749236
1691
8755464
1762
8761248
1819
8766278
1879
8772005
1945
8778390
2020
8785212
2093
8791770
2173
8799594
2261
8807431
2344
8814687
-2350
8821316
-2277
8828018
-2196
8835920
-2111
8842728
-2027
8851797
-1921
8862240
-1795
8873832
-1659
8886938
-1510
8900811
-1327
8920028
-1104
8940268
-878
8959536
-675
8978334
-459
8998162
-242
9016838
-42
9035107
175
9056067
419
9077996
656
9099435
894
9120410
1131
9142581
1386
9166747
1669
9193197
1981
9223377
2325
9254417
-2099
9284553
-1787
9311148
-1507
9335308
-1239
9359710
-957
9387460
-624
9418346
-280
9449624
76
9482481
454
9516518
806
9545852
1111
9572156
1405
9598541
1687
9622721
1936
9642398
2155
9665010
-2340
9691638
-2026
9720947
-1703
9749484
-1375
9781357
-999
9816123
-602
9852884
-187
9889719
209
9925222
589
9956322
935
9993050
1391
10032229

I'd be printing three values, not one.

Print the reading from the Hx711 instance. It may not be what you think it is.

Print the constrained() value. It may not be what you think it is.

Forgot to mention:

If I read raw value before the map() like so:

loadCellValue = constrain(Hx711.read(), loadCellMin, loadCellMax);
Serial.println(loadCellValue);

//remappedValue = map(loadCellValue, loadCellMin, loadCellMax, -1000, 3095);
//Serial.println(remappedValue);

everything is sequential throughout the whole 8600000 - 9500000 range:

8600000
8618829
8653422
8696927
8750884
8818942
8985702
9282556
9490334
9500000

PaulS:
I'd be printing three values, not one.

Print the reading from the Hx711 instance. It may not be what you think it is.

Print the constrained() value. It may not be what you think it is.

Just updated above. Forgot to mention it in OP.

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

That's what map looks like. Run a few of your numbers through on paper and see if any of the intermediate results overflow a long.

Delta_G:

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




That's what map looks like. Run a few of your numbers through on paper and see if any of the intermediate results overflow a long.

Yes, I did that multiple times. Also it worked before. Unless I changed something that I can't see. But even if it was a wrong data type somewhere, still returning only 4772 values regardless of the new range... I don't get it...

I made the code as simple as possible. Same problem, same weird 4772 value range:

#include <Q2HX711.h>

Q2HX711 Hx711(SDA, SCL);

int16_t remappedValue;

void setup()
{
  Serial.begin(115200);
}
void loop()
{
  remappedValue = map(Hx711.read(), 8600000, 9500000, 0, 10000);

  Serial.println(remappedValue);
}

maxturcan:
Yes, I did that multiple times. Also it worked before. Unless I changed something that I can't see. But even if it was a wrong data type somewhere, still returning only 4772 values regardless of the new range... I don't get it...

What is the value of loadCellValue when it wraps around. Run it once and print both the constrained value and the mapped value at the same time so we can see how they relate.

Simplest code and 2 prints one after another:

#include <Q2HX711.h>
Q2HX711 Hx711(SDA, SCL);
void setup()
{
  Serial.begin(115200);
}
void loop()
{
  Serial.println(Hx711.read());
  Serial.println(map(Hx711.read(), 8600000, 9500000, 0, 10000));
}

Results:

8597487
-12
8600161
19
8603438
59
8607447
105
8611786
156
8616300
208
8621365
266
8626653
323
8631604
379
8636677
434
8641470
486
8645838
530
8649340
567
8652780
604
8656285
647
8660201
690
8664058
733
8667916
776
8671879
820
8675731
862
8679833
908
8683606
953
8687992
1000
8692128
1047
8696468
1098
8701438
1156
8706614
1213
8712163
1280
8718241
1347
8724581
1418
8730529
1483
8736536
1552
8742663
1620
8749236
1691
8755464
1762
8761248
1819
8766278
1879
8772005
1945
8778390
2020
8785212
2093
8791770
2173
8799594
2261
8807431
2344
8814687
-2350
8821316
-2277
8828018
-2196
8835920
-2111
8842728
-2027
8851797
-1921
8862240
-1795
8873832
-1659
8886938
-1510
8900811
-1327
8920028
-1104
8940268
-878
8959536
-675
8978334
-459
8998162
-242
9016838
-42
9035107
175
9056067
419
9077996
656
9099435
894
9120410
1131
9142581
1386
9166747
1669
9193197
1981
9223377
2325
9254417
-2099
9284553
-1787
9311148
-1507
9335308
-1239
9359710
-957
9387460
-624
9418346
-280
9449624
76
9482481
454
9516518
806
9545852
1111
9572156
1405
9598541
1687
9622721
1936
9642398
2155
9665010
-2340
9691638
-2026
9720947
-1703
9749484
-1375
9781357
-999
9816123
-602
9852884
-187
9889719
209
9925222
589
9956322
935
9993050
1391
10032229

maxturcan:
Yes, I did that multiple times. Also it worked before. Unless I changed something that I can't see. But even if it was a wrong data type somewhere, still returning only 4772 values regardless of the new range... I don't get it...

OK, I can do math. Let's see.

Let's let loadCellValue be 9200000.

Now map looks like:

(9200000 - 8600000) * 4095 / (9500000 - 8600000)

(600000) * 4095 / 900000

2457000000 / 900000

And right there it is. 2457000000 overflows a long. That's going to end up as a negative number. And when you finish the math with that negative number, you get the negative result.

You're not up against some data type with 4772 values. You're doing more math there, so you're reducing that range.

You're going to have to rewrite your own version of map that can deal with this.

Delta_G:
OK, I can do math. Let's see.

Let's let loadCellValue be 9200000.

Now map looks like:

(9200000 - 8600000) * 4095 / (9500000 - 8600000)

(600000) * 4095 / 900000

2457000000 / 900000

And right there it is. 2457000000 overflows a long. That's going to end up as a negative number. And when you finish the math with that negative number, you get the negative result.

You're not up against some data type with 4772 values. You're doing more math there, so you're reducing that range.

You're going to have to rewrite your own version of map that can deal with this.

Hmm.... I did that a few times but I was looking at the results only, not possible overflows at each calculation step...

Thank you sir for pointing me to the right direction!

Since you map to [-1000..3095], you couldSerial.println(map(Hx711.read()/100, 86000, 95000, -1000, 3095));instead ofSerial.println(map(Hx711.read(), 8600000, 9500000, -1000, 3095));
Jacques

jbellavance:
(Hx711.read()/100

Yes! Thank you! I used /1000.

FWIW I noticed that using constrain() after the map() increases the serial output speed by 2x. I don't know if Windows is getting the readings 2x faster, but still, moved the constrain AFTER map().

Thanks everyone for your help!

maxturcan:
Yes! Thank you! I used /1000.

Don't. You'll lose accuracy that way.

From 8600 to 9500 you have 901 possible values.
From -1000 to 3095 you have 4096 possible values.
That means that you are throwing away most of the possibilities for output values, and for no good reason.

You don't need map(), just common sense and arithmetic.

From 8600000 to 9500000 you have a spread of 900000.
From -1000 to 3095 you have a spread of 4095.
So you want to multiply by the fraction 4095/900000. In lowest terms, this fraction equals 91/20000.
So, just subtract 8600000, then multiply by 91, then divide by 20000, and finally subtract 1000.
Note that, in the range you seem to care about, the multiplication will not overflow a long.

long inputValue = Hx711.read();
int outputValue = (((inputValue - 8600000L) * 91L) / 20000) - 1000;
Serial.println(outputValue);