Error when passing elapsedMillis to map function

Status
Not open for further replies.

b3nton

New member
Error when passing elapsedMillis to map function [SOLVED]

I am developing a closed loop controller to run a test sequence for product validation. In order to produce a time dependent ramped input signal for the controller, I am mapping elapsed time to signal magnitude (using elapsedMillis). Originally, I developed the code on a Mega 2560 board, and the code uploads and runs fine, with the mapped time output controlling the intensity of the LED on pin 13.

I then tried to upload the code to my new Teensy 3.5 (needed for higher speed optical encoder reads). Now, at compile, I receive an error on my map function. Specifically:

"no matching function for call to 'map(elapsedMillis&, int, int, int, int&)'"

Here is my code:
Code:
#include <elapsedMillis.h>

elapsedMillis delTime;

int mState = 1;
int cnt = 0;
int val = 0;
int dither = 255;
int rap45 = 255;
int rap90 = 255;
int ramp = 255;

void setup()
{
  pinMode(13, OUTPUT);
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect
  }
}

void loop()
{
  if (mState ==1) {        // State 1: 30x 5 deg dither cycles
    if (delTime <= 250) {
      if (delTime <= 125) {   // ramp up if <125ms, ramp down if >125ms
        val = map(delTime,0,125,0,dither);
      }
      else {
        val = map(delTime,125,250,dither,0);
      }
      analogWrite(13, val);
      Serial.println(val);
    }
    else {
      cnt++;
      delTime = 0;
      if (cnt >= 30) {   // handle dither cycle count
        cnt = 0;
        mState = 2;
        delTime = 0;
      }
    }
  }
  else if (mState == 2) {   // State 2: 45 deg Rapids (2x)
    if (delTime <= 500) {
      if (delTime <= 250) {   // ramp up if <250ms, ramp down if >250ms
        val = map(delTime,0,250,0,rap45);
      }
      else {
        val = map(delTime,250,500,rap45,0);
      }
      analogWrite(13, val);
      Serial.println(val);
    }
    else {
      cnt++;
      delTime = 0;
      if (cnt >= 2) {   // handle rapids cycle count
        cnt = 0;
        mState = 3;
        delTime = 0;
      }
    }
  }
  else if (mState == 3) {   // State 3: 90 deg fast rapids (1x)
    if (delTime <= 500) {
      if (delTime <= 250) {   // ramp up if <250ms, ramp down if >250ms
        val = map(delTime,0,250,0,rap90);
      }
      else {
        val = map(delTime,250,500,rap90,0);
      }
      analogWrite(13, val);
      Serial.println(val);
    }
    else {
      cnt++;
      delTime = 0;
      if (cnt >= 1) {   // handle rapids cycle count
        cnt = 0;
        mState = 4;
        delTime = 0;
      }
    }
  }
  else if (mState == 4) {   // State 4: 90 deg fast ramp (1x)
    if (delTime <= 5000) {
      if (delTime <= 2500) {   // ramp up if <2500ms, ramp down if >2500ms
        val = map(delTime,0,2500,0,ramp);
      }
      else {
        val = map(delTime,2500,5000,ramp,0);
      }
      analogWrite(13, val);
      Serial.println(val);
    }
    else {
      cnt++;
      delTime = 0;
      if (cnt >= 1) {   // handle rapids cycle count
        cnt = 0;
        mState = 5;
        delTime = 0;
      }
    }
  }
  else if (mState == 5) {   // State 5: 90 deg slow rapids (2x)
    if (delTime <= 1000) {
      if (delTime <= 500) {   // ramp up if <500ms, ramp down if >500ms
        val = map(delTime,0,500,0,rap90);
      }
      else {
        val = map(delTime,500,1000,rap90,0);
      }
      analogWrite(13, val);
      Serial.println(val);
    }
    else {
      cnt++;
      delTime = 0;
      if (cnt >= 2) {   // handle rapids cycle count
        cnt = 0;
        mState = 6;
        delTime = 0;
      }
    }
  }
  else if (mState == 6) {   // State 6: 90 deg slow ramp (1x)
        if (delTime <= 10000) {
      if (delTime <= 5000) {   // ramp up if <125ms, ramp down if >125ms
        val = map(delTime,0,5000,0,ramp);
      }
      else {
        val = map(delTime,5000,10000,ramp,0);
      }
      analogWrite(13, val);
      Serial.println(val);
    }
    else {
      cnt++;
      delTime = 0;
      if (cnt >= 1) {   // handle rapids cycle count
        cnt = 0;
        mState = 7;
        delTime = 0;
      }
    }
  }
  else if (mState == 7) {   // State7: 90 deg slow rapids (2x)
    if (delTime <= 1000) {
      if (delTime <= 500) {   // ramp up if <500ms, ramp down if >500ms
        val = map(delTime,0,500,0,rap90);
      }
      else {
        val = map(delTime,500,1000,rap90,0);
      }
      analogWrite(13, val);
      Serial.println(val);
    }
    else {
      cnt++;
      delTime = 0;
      if (cnt >= 1) {   // handle rapids cycle count
        cnt = 0;
        mState = 8;
        delTime = 0;
      }
    }
  }
}

Is there some fundamental difference in the way that the Teensy handles the map function (vs the Mega 2560) such that it rejects my elapsedMillis variable? If so, is there a way around this? Any help is greatly appreciated!
 
Last edited:
Seems sane at a glance between OP code and MAP. What happens if you do this upfront and then use the new delTimeNow in the compares and map()?

Code:
void loop()
{
[B][U]long delTimeNow = delTime;[/U][/B]
  if (mState ==1) {        // State 1: 30x 5 deg dither cycles
    if (delTimeNow <= 250) {
 
Is there some fundamental difference in the way that the Teensy handles the map function

Yes, there is indeed quite a difference. Teensy's map() function does much more than Arduino's, where the math is always done as long integers.

On Teensy, the type of your data is automatically detected. If you use integer types, the math is done as long int, the same as Arduino. But if you use floats, the math is done as 32 bit floats (taking advantage of the fast hardware FPU on Teensy 3.5 & 3.6), and if you use 64 bit double, the math is done at the higher 64 bit precision. Teensy's map() returns different data types depending on which input type you used, so you actually get the full floating point resolution as output, if you gave it floating point input.

Teensy's map function also has an improvement to more uniformly map the upper end of the range than Arduino's when rounding to the nearest integers, so you'll get slightly different (and generally better) results than Arduino's map(), even if not use the floating point option.

The downside is the compiler needs to know which type of math you want. All you need to do in this case is cast the data to int. Like this:

Code:
        val = map((int)delTime,0,500,0,rap90);

Edit: or Defragster's approach also solves the problem. Putting the data into a variable also gives the compiler the info about which data type you are using.
 
Cool - my solution was in the right direction, I didn't have time to look at the Teensy code - just popped up the indicated map() link. According to Paul's note - the delTimeNow for consistency could be defined as 'int'.

The other benefit of the intermediate variable is freezing the time on entry - it could possibly tick over during testing and then the MAX value for map() might tick over the tested limits.
 
EDIT: not sure where my previous message went, perhaps I erroneously deleted it. In any event, thank you all again, and I was able to add the "solved" tag to my title.
 
Status
Not open for further replies.
Back
Top