Using the pow() function??

s Hi there!

I am trying to use the pow() function to create an exponential map. I have looked in various places online and have been able to locate very little info on the function and even less on using it for exponential mapping. Any suggestions and/or links that might be able to help me achieve my goal would be greatly appreciated!

Thanks!!

Walter

create an exponential map

Do you mean draw a graph of an exponential function? If so, what sort of display are you going to use?

Pete

is multimap() - http://arduino.cc/playground/Main/MultiMap - a solution for your problem?

Thanks for all the replys guys!

Riva:
http://arduino.cc/en/Reference/Pow

I’ve been through that webpage quite a few times but never could pull much from it.

el_supremo:

create an exponential map

Do you mean draw a graph of an exponential function? If so, what sort of display are you going to use?

Pete

By map I just mean take input say 0-255 and scale it to say 0-2000. However, I would like to do it exponentially.

robtillaart:
is multimap() - http://arduino.cc/playground/Main/MultiMap - a solution for your problem?

Possibly? I am not very familiar with using multimap(). What I am trying to do is take the input from a ps2 controller analog stick (0-255 and scale it exponentially to 0-2000. I am using the the ps2 controller to control a differential drive robot, but currently just pushing the stick forward a tiny bit sends the not shooting across the room. This is why I need to create the exponential map(or similar) : to make the controls less sensitive.

Thanks!!

Walter

How about posting your code?

How to use this forum

I don’t think you need an exponential mapping function. A simple quadratic might work well. The function y = 3xx/100 will map the input range of 0-255 to an output range of 0-1950 (close enough to 2000?). The multiplies are done using long integers to avoid overflow problems. This code tests the function:

uint16_t my_map(uint16_t pot_value)
{
  return(3L*pot_value*pot_value/100L);
}

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

  Serial.println(my_map(0));
  Serial.println(my_map(1));
  Serial.println(my_map(10));
  Serial.println(my_map(100));
  Serial.println(my_map(200));
  Serial.println(my_map(255));
}

void loop(void)
{
}

and prints:

0
0
3
300
1200
1950

Pete

+1 for pete

doing it integer is way faster, reverse engineering gives an almost exact solution

y = x * x * a / b;

x* x = 0 .. 65025 which should map to 0 .. 2000
==> a/b == 2000/65025 == 80 / 2601

y = 80L * x * x /2601L

if you want to add rounding to the formula

y = (1300L + 80L * x * x) /2601L;

as the square can be calculated in 16 bit, it can be optimized a few clock cycles :wink:
y = (1300L + 80L * (x * x)) /2601L;

I was going to go with y=x^2/32.5 for simplicity

It meets the linear version at the ends, and in the middle where the linear one would give 1000, it gives 500 (ie 2000/4). Gets steep after that.

if you want to do it exponentially, you might have to use floats

y = ax y = 0…2000 x = 0…255

because zero is difficult for exponential functions we use

y = ax-1 y = 1…2001 x = 0…255 !! a0 == 1 ==> -1

a = xthroot(2001) = 20011/255 = 1.03025817

so the formula becomes

y = pow(1.03025817, x) -1;

... but currently just pushing the stick forward a tiny bit sends the not shooting across the room.

Doesn't the OP want a logarithm and not an exponent?

Walter103:
s Hi there!

I am trying to use the pow() function to create an exponential map...

Walter

...

"pushing the stick forward a tiny bit sends the not shooting across the room" is X.

The exponential map is Y.

Thanks for all the suggestions! using a quadratic equation would certainly be worth a try. I’ll work through all the suggestions and see what works best. However, It will probably take me a while as I’m currently swamped with school work.

For all who are interested, here is the code as it stands without any modifications:

#include <SoftPWM.h>
#include <SoftPWM_timer.h>
#include <Servo.h>
#include <PS2X_lib.h>  //for v1.6

PS2X ps2x; // create PS2 Controller Class

int error = 0; 
byte type = 0;
byte vibrate = 0;

Servo Signal1; //creates servo object
Servo Signal2; 

int Input1 = 1500;
int Input2 = 1500;

int Speed1 = 1500;
int Speed2 = 1500;

int setMotorSensitivity()
{
 float gamma = 1.5;
for (x=0; x<256; x++)
{
   float normx = x / 255.0;
   float normy = pow (normx, gamma);
   int y = (int) (0.5 + normy * 255);

   serial.print("x: ");
   serial.print(x, DEC);
   serial.print("   y: ");
   serial.println(y, DEC);
}
  
}
 
  
void setup()
{
  Serial.begin(57600);

  Speed1.attach(4);  //the pin for the servo control 
  Speed2.attach(5);

  error = ps2x.config_gamepad(13,11,10,12, true, true);   //setup pins and settings:  GamePad(clock, command, attention, data, Pressures?, Rumble?) check for error

  if(error == 0)
    Serial.println("Controller found! You may now send commands");

  else if(error == 1)
    Serial.println("No controller found, check wiring, see readme.txt to enable debug. visit www.billporter.info for troubleshooting tips");

  else if(error == 2)
    Serial.println("Controller found but not accepting commands. see readme.txt to enable debug. Visit www.billporter.info for troubleshooting tips");

  else if(error == 3)
    Serial.println("Controller refusing to enter Pressures mode, may not support it. ");

  type = ps2x.readType(); 
  switch(type) 
  {
  case 0:
    Serial.println("Unknown Controller type");
    break;
  case 1:
    Serial.println("DualShock Controller Found");
    break;
  }
}
//My sabortooth motordriver can use the two signals 1000us-2000us to control the two motors
void loop()
{
  if(error == 1)
  {
    return;
  }
  else
  {
    
    
    ps2x.read_gamepad(false, 0);
    

    Input1 = map(ps2x.Analog(PSS_LY), 0, 255, 2000, 1000);
    Speed1 = setMotorSensitivity(Input1);
    Signal1.writeMicroseconds(Speed1);
    //Serial.print ("Input1: ");
    //  Serial.println (Input1);


    Input2 = map(ps2x.Analog(PSS_LX), 0, 255, 2000, 1000);
    Speed2 = setMotorSensitivity(Input2);
    Signal2.writeMicroseconds(Speed2);
    //Serial.print ("Input2: ");
    // Serial.println (Input2);
    delay(8);
  }
}

Thanks!

Walter

Your code doesn't even compile.

Pete

el_supremo:
Your code doesn't even compile.

But have you got the libraries, el_s?

Doesn’t matter. Errors in this function are independent of the libraries.

int setMotorSensitivity()
{
 float gamma = 1.5;
for (x=0; x<256; x++)
{
   float normx = x / 255.0;
   float normy = pow (normx, gamma);
   int y = (int) (0.5 + normy * 255);

   serial.print("x: ");
   serial.print(x, DEC);
   serial.print("   y: ");
   serial.println(y, DEC);
}
  
}

Pete

I believe I may have uploaded the wrong version of my code. I will check it when I get back home today

Sorry guys,

Walter