map() function

I have been researching the map function and its issues with truncating integers and found this code

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

void loop()
{
 long y;

 Serial.println("TEST 0 =============================");

 y = map(10,0,1023,0,0);    
 Serial.println(y);
 y = NewMap(10,0,1023,0,0);  
 Serial.println(y);

 Serial.println();

 y = map(10,0,0,0,0);        
 Serial.println(y);
 y = NewMap(10,0,0,0,0);    
 Serial.println(y);

 Serial.println();

 y = map(0,0,0,0,0);        
 Serial.println(y);
 y = NewMap(0,0,0,0,0);      
 Serial.println(y);

 Serial.println();

 y = map(-1,10,0,0,10);      
 Serial.println(y);
 y = NewMap(-1,10,0,0,10);  
 Serial.println(y);

 Serial.println();

 // BUG should return 5  
 y = map(1,-2147483647L,2147483647L,0,10);      
 Serial.println(y);
 y = NewMap(1,-2147483647L,2147483647L,0,10);  
 Serial.println(y);


 Serial.println();
 Serial.println("TEST 1 =============================");
 Serial.println("y = map(i, 0, 1023, -123456789, 123456789);");
 Serial.println();

 for (int i=0; i<= 1024; i+=103)
 {
   y = map(i, 0, 1023, -123456789, 123456789);
   Serial.print(i);
   Serial.print(" old => ");
   Serial.print(y);
   y = NewMap(i, 0, 1023, -123456789, 123456789);
   Serial.print("\t new => ");
   Serial.println(y);
 }

 Serial.println();
 Serial.println("TEST 2 =============================");
 Serial.println("y = map(i, 0, 1000000000, -100, 100);");
 Serial.println();

 for (long i=0; i<=1000000000; i+=100000000)
 {
   y = map(i, 0, 1000000000, -100, 100);
   Serial.print(i);
   Serial.print(" old => ");
   Serial.print(y);
   y = NewMap(i, 0, 1000000000, -100, 100);
   Serial.print("\t new => ");
   Serial.println(y);
 }

 Serial.println();
 Serial.println("TEST 3 =============================");
 Serial.println("y = map(i, 0, 1000000, -1000000, 1000000);");
 Serial.println();

 for (long i=0; i<= 1000000; i+=100000)
 {
   y = map(i, 0, 1000000, -1000000, 1000000);
   Serial.print(i);
   Serial.print(" old => ");
   Serial.print(y);
   y = NewMap(i, 0, 1000000, -1000000, 1000000);
   Serial.print("\t new => ");
   Serial.println(y);
 }

 Serial.println();
 Serial.println("TEST 4 =============================");
 Serial.println("y = map(i, 0, 1000000, 1000000, -1000000);");
 Serial.println();

 for (long i=0; i<= 1000000; i+=100000)
 {
   y = map(i, 0, 1000000, 1000000, -1000000);
   Serial.print(i);
   Serial.print(" old => ");
   Serial.print(y);
   y = NewMap(i, 0, 1000000, 1000000, -1000000);
   Serial.print("\t new => ");
   Serial.println(y);
 }

 Serial.println();
 Serial.println("TEST 5 =============================");
 Serial.println("y = map(i, 0, 10, 0, 1);");
 Serial.println();
 for (int i=0; i <= 10; i++)
 {
   y = map(i, 0, 10, 0, 1);
   Serial.print(i);
   Serial.print(" old => ");
   Serial.print(y);
   y = NewMap(i, 0, 10, 0, 1);
   Serial.print("\t new => ");
   Serial.print(y);
   y = BalancedMap(i, 0, 10, 0, 1);
   Serial.print("\t B => ");
   Serial.println(y);
 }
 
 Serial.println();
 Serial.println("y = map(i, 0, 10, 0, 1);");
 Serial.println();
 
 for (int i=0; i <= 10; i++)

I was just wondering if this was the best solution around or has anybody got a better solution?

Please explain the problem. It is not self evident. Why is it a problem in your particular case? Do you have code that it is breaking?

There's a float version of the map function in LC_baseTools you could try. (see the library manager)

-jim lee

Yeah, or you can scale and/or translate using plain old math. That's all that map() uses internally.

This is the section of the code which seems to be busting. The problem seems to be at the half way points of both the fade up and fade down. If the fpwm is 4096 and we are in fade down situation it will reach about half way then shoot up to strange numbers 6000! Have no idea where the number originates from and after lot of debugging think its the map function. I am using an adafruit 16channel pwm driver.

void SetLed(int fpin,                  //Pin number
            unsigned long ftime,       //Current time in millis
            unsigned long fstart,      //Start time of LED channel in millis
            unsigned long ffadeup,     //Fadeup period in millis
            unsigned long fperiod,     //Total photo period in millis
            unsigned long ffadedown,   //Fadedown period in millis
            unsigned long fstop,       //Stop time of LED channel in millis
            int fpwm,                  //Max value of brightness 0-4096
            int fVpin,                 //ProgressBar Blynk widget
            int fVpin2)                //Brightness bytes Blynk widget                             
{
  //ON PERIOD//
  if (ftime > fstart + ffadeup && ftime <= fstart + fperiod - ffadedown)
  {
    pwm.setPin(fpin, fpwm, false);           //set pin to max pwm set
    progress = round(fpwm*100/4096);  //turn the pwm into %
    Blynk.virtualWrite (fVpin, progress);  // write the % to Blynk 
    Blynk.virtualWrite (fVpin2, fpwm);     // write pwm bytes to Blynk
    Serial.println("ON");
  }
  //FADEUP PERIOD//
  else if (ftime > fstart && ftime <= fstart + ffadeup)
  {
    brightness = map(ftime - fstart, 0, ffadeup, 0, fpwm);  //map pwm to time
    pwm.setPin(fpin, brightness, false);  //set pin to mapped pwm
    progress = round(brightness*100/4096);  //convert mapped pwm to %
    Blynk.virtualWrite (fVpin, progress);  //write % to Blink
    Blynk.virtualWrite (fVpin2, brightness);  //write mapped pwm bytes to Blynk
    Serial.println("FADEUP");
  }
  //FADEDOWN PERIOD//
  else if (ftime > fstart + fperiod - ffadedown && ftime <= fstart + fperiod)
  {
    brightness = map(ftime - fstart - fperiod + ffadedown, 0, ffadedown, fpwm, 0);
    pwm.setPin(fpin, brightness, false);
    progress = round(brightness*100/4096);
    Blynk.virtualWrite (fVpin, progress);
    Blynk.virtualWrite (fVpin2, brightness);
    Serial.println("FADEDOWN");
   }
  //OFF PERIOD//
  else if (ftime > fstop || ftime < fstart)
  {
    pwm.setPin(fpin, 0, false);
    Blynk.virtualWrite(fVpin, 0);
    Blynk.virtualWrite (fVpin2, 0);
    Serial.println("OFF");
  }
}

@aarg I would be very interested in learning your way just using maths could you give an example please

Wait.. are you fading an RGB LED from color to color over time?

-jim lee

Proietti:
@aarg I would be very interested in learning your way just using maths could you give an example please

It helps to look at the source:

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

Suppose you call this very common case:

PWMout = map(ADCin, 0, 256, 0, 1024);

internally this looks like

return (x - 0) * (256 - 0) / (1024 - 0) + 0;

which reduces to

return x * 256 / 1024;

further reduces to

return x / 4;

thus we could have just said

PWMout = ADCin / 4;

@jimlee no not rgb but high power leds for my aquarium. The pwm pins of the adafruit driver connect to meanwell drivers

@aarg that math looks very interesting. I will try to work on that tomorrow. Thanks

Can you explain, in human, what your trying to do?

-jim lee

aarg:
PWMout = map(ADCin, 0, 256, 0, 1024);

thus we could have just said

PWMout = ADCin / 4;

I think you got one of them backwards.
map(ADCin, 0, 256, 0, 1024) is ADCin * 4
map(ADCin, 0, 1024, 0, 256) is ADCin / 4

Converting 10-bit to 8-bit is easier done this way
PWMout = ADCin >> 2;

Leo..

Wawa:
I think you got one of them backwards.
map(ADCin, 0, 256, 0, 1024) is ADCin * 4
map(ADCin, 0, 1024, 0, 256) is ADCin / 4

Converting 10-bit to 8-bit is easier done this way
PWMout = ADCin >> 2;

Leo…

Better to write it it the more natural way with a division, rather than a shift, and let the compiler do the legwork.

Ok I have tried the mathematical way and the fadeup works perfectly. The fadedown does not. When the fade down is triggered the 4096 byte(which is the 100% value of the fpwm) jumps to some 8000 number. I suspect it has something to do with the fact that 0-fpwm within the formula gives a negative number. Any ideas on how to resolve this?

FADEUP CODE (works correctly)

    //brightness = map(ftime - fstart, 0, ffadeup, 0, fpwm); //Original map function

    long x = ftime - fstart;
    brightness = x * fpwm / ffadeup;
    pwm.setPin(fpin, brightness, false);

FADEDOWN CODE (works incorrectly)

    //brightness = map(ftime - fstart - fperiod + ffadedown, 0, ffadedown, fpwm, 0); //Original map function
    long y = ftime - fstart - fperiod + ffadedown;
    brightness = y * (0-fpwm) / ffadedown + fpwm;
    pwm.setPin(fpin, brightness, false);