Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 6 of 6

Thread: map() returns different values on arduino vs. teensy

  1. #1

    map() returns different values on arduino vs. teensy

    After spending a night trying to debug an issue I was having, I narrowed it down the map() on my Teensy returning an incorrect value.

    map(1,0, 1, 100, 0); // returns 51 on teensy, 0 on arduino.

    I'd expect this to return 0, but the function returns 51 on my Teensy 3.2, Teensy LC and Teensy 3.0. I tested it with an Arduino Uno and this command returns 0 as expected.

    Interestingly, the Teensy works correctly if I do some fudgery:

    (int)map((float)1,0,1,100,0); // returns 0.

    I am using arduino 1.8.13, teensyduino 1.53

  2. #2
    Senior Member
    Join Date
    Jul 2020
    Posts
    477
    The code in wiring.h is
    Code:
    long map(T _x, A _in_min, B _in_max, C _out_min, D _out_max, typename std::enable_if<std::is_integral<T>::value >::type* = 0)
    {
    	long x = _x, in_min = _in_min, in_max = _in_max, out_min = _out_min, out_max = _out_max;
    	// Arduino's traditional algorithm
    	//return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
    	// st42's suggestion: https://github.com/arduino/Arduino/issues/2466#issuecomment-69873889
    	// more conversation:
    	// https://forum.pjrc.com/threads/44503-map()-function-improvements
    	if ((in_max - in_min) > (out_max - out_min)) {
    		return (x - in_min) * (out_max - out_min+1) / (in_max - in_min+1) + out_min;
    	} else {
    		return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
    	}
    }
    and it looks like the test for expansion v. contraction is wrong and should be:

    Code:
    	if (abs(in_max - in_min) > abs(out_max - out_min)) {
    BTW the variable names are poorly chosen, as they are not maximum and minimums, but definitions
    of number ranges. This probably explains the error creeping in.

  3. #3
    Quote Originally Posted by MarkT View Post
    The code in wiring.h is
    Code:
    long map(T _x, A _in_min, B _in_max, C _out_min, D _out_max, typename std::enable_if<std::is_integral<T>::value >::type* = 0)
    {
    	long x = _x, in_min = _in_min, in_max = _in_max, out_min = _out_min, out_max = _out_max;
    	// Arduino's traditional algorithm
    	//return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
    	// st42's suggestion: https://github.com/arduino/Arduino/issues/2466#issuecomment-69873889
    	// more conversation:
    	// https://forum.pjrc.com/threads/44503-map()-function-improvements
    	if ((in_max - in_min) > (out_max - out_min)) {
    		return (x - in_min) * (out_max - out_min+1) / (in_max - in_min+1) + out_min;
    	} else {
    		return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
    	}
    }
    and it looks like the test for expansion v. contraction is wrong and should be:

    Code:
    	if (abs(in_max - in_min) > abs(out_max - out_min)) {
    BTW the variable names are poorly chosen, as they are not maximum and minimums, but definitions
    of number ranges. This probably explains the error creeping in.
    Hey Mark, thanks for replying.. I didn't know the code was different than the arduino map() on purpose and looking at the "more conversation" thread linked in the commented code, it looks like Paul is aware of this exact issue as of May 2020. It also seems like someone else posted the fudgery (float) correction. I will stick with that until this issue is corrected, and I appreciate knowing that others have had this same problem.

  4. #4
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    12,729
    See post #2 here for edit to map() code to fix out of bounds return for TD 1.54 going beta.

    That Beta thread not live yet ...

  5. #5
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,066
    After much fiddling, I came up with this.

    https://github.com/PaulStoffregen/co...12352c30d71744

    Hopefully it's better?

    Here's a little test program...

    Code:
    void setup() {
      while (!Serial) ;
      Serial.println("MAP Test");
      Serial.println("--------");
    
      Serial.println(map(0, 0, 127, 60, 30), DEC);  // 60 is correct
      Serial.println(map(127, 0, 127, 60, 30), DEC); // 30 is correct
    
      Serial.println(map(50, 1, 50, 50, 1), DEC); // 1 is correct
      Serial.println(map(50, 50, 1, 1, 50), DEC); // 1 is correct
    
      long in1=0, in2=20;
      long out1=0, out2=4;
      Serial.printf("Range %d - %d maps to %d - %d\n", in1, in2, out1, out2);
      for (int i=in1-10; i <= in2+10; i++) {
        Serial.printf("%3d    %6.2f  %3d  %3d     %6.2f  %3d  %3d\n", i,
          map((double)i, in1, in2, out1, out2),
          map(i, in1, in2, out1, out2),
          map(i, in2, in1, out2, out1),
          map((double)i, in1, in2, out2, out1),
          map(i, in1, in2, out2, out1),
          map(i, in2, in1, out1, out2)
          );
      }
    
      Serial.println();
      Serial.println("Range 0-5 maps to 0-1023");
      for (int i=-5; i <= 10; i++) {
        Serial.printf("%3d  %8.2f  %5d  %5d  %8.2f  %5d  %5d\n", i,
          map((double)i, 0, 5, 0, 1023),
          map(i, 0, 5, 0, 1023),
          map(i, 5, 0, 1023, 0),
          map((double)i, 0, 5, 1023, 0),
          map(i, 0, 5, 1023, 0),
          map(i, 5, 0, 0, 1023)
          );
      }
    }
    
    void loop() {
    }

  6. #6
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,066
    Teensyduino 1.54-beta1 has the new & improved map() which hopefully solves all these problems.

    https://forum.pjrc.com/threads/63997...no-1-54-Beta-1

    If anyone is still watching this thread and concerned about map(), please give the beta a try and let me know if you see any remaining issue?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •