Go Down

Topic: Issue using abs() (Read 1 time) previous topic - next topic

DryRun

Jul 14, 2019, 06:06 pm Last Edit: Jul 14, 2019, 06:07 pm by DryRun
Hi,

I want to replace this function and use abs() to find the absolute value.

Code: [Select]
if (speed < 0)                             
      speed = -speed;

with
Code: [Select]
speed = abs(speed);

But it's not equivalent for some reason?? Am i using abs() correctly?

UKHeliBob

How is speed declared ?
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Delta_G

But it's not equivalent for some reason??
What result do you get?  That should be perfectly fine.  The only caveat with abs is to remember that it is a macro and not a function so watch out if you have to write an expression in there twice.  But in the trivial example you show in your post it should be the same.  

Post a complete test code and output that demonstrates your issue.  
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

DryRun

How is speed declared ?
Code: [Select]
float speed;

From the example given on: https://www.arduino.cc/reference/en/language/functions/math/abs/
I'm wondering if the correct use of abs() should just be:
Code: [Select]
abs(speed);
instead of
Code: [Select]
speed = abs(speed);
?

jremington

#4
Jul 14, 2019, 06:15 pm Last Edit: Jul 14, 2019, 06:15 pm by jremington
fabs() for floats/doubles

Delta_G

fabs() for floats/doubles
And that's why it is important to post a complete piece of code and not just the one dumb line you can't tell anything is wrong from. 
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

oqibidipo

fabs() for floats/doubles
And to make things more confusing, Arduino.h defines abs() as
Code: [Select]
#define abs(x) ((x)>0?(x):-(x))

DryRun

#7
Jul 14, 2019, 09:37 pm Last Edit: Jul 14, 2019, 10:30 pm by DryRun
But there is no mention of fabs() in the Arduino reference docs.
https://www.arduino.cc/reference/en/language/functions/math/fabs/ gives an error. Maybe this should be added. Unless it's not officially supported?

And that's why it is important to post a complete piece of code and not just the one dumb line you can't tell anything is wrong from. 
My apologies... but i had only started writing the function at that time. I am trying to calculate the speed of rotation of my robot using the encoders on both wheels. I am sending the commands via serial monitor to turn the robot right or left. Here is what i have so far:

Code: [Select]

int left, right, turnout = 0;   //global variables

//the turn function. It uses the encoder pulse values from both DC motors to calculate current
//speed of rotation and then based on the user command, turns left or right, and outputs the
//appropriate PWM value to send to each motor.
void turn()     
{
   
  float turnspeed = 0;
  float rotationratio = 0;
  int turnmin = -5, turnmax = 5;

 
  if (left == 1 || right == 1)
  {
                               
    turnspeed = (pulseright + pulseleft);  //current turn speed; variables of type int; pulseright and pulseleft have polarities.
   
    turnspeed = abs(turnspeed);     //should return absolute float value of turn speed
   
    rotationratio = 5 / turnspeed;          //set the speed of rotation
   
    if (rotationratio <= 5)
    {
      rotationratio = 0.5;
    }
     
    if (rotationratio > 5)  //this implies that turnspeed < 1
    {
      rotationratio = 5;
    }
  }

  if (left ==1)
  {
    turnout += rotationratio;
  }
  else if (right == 1 )
  {
    turnout -= rotationratio;
  }
  else turnout = 0;
 
  if (turnout > turnmax)   
    turnout = turnmax;     //the max value setting of amplitude
  if (turnout < turnmin)   
    turnout = turnmin;      //the min value setting of amplitude
 
  Turn_pwm = turnout;    //PWM value sent to both motors to initiate the rotation of the robot
}


When i tried
Code: [Select]
turnspeed = fabs(turnspeed); it doesn't work, for some reason.

septillion

fabs() and abs() don't alter the variable, so you must assign it to something which can be the same variable again if you only want to store an absolute version. So
Code: [Select]
var = abs(var);
//or
absf(var);


And yeah, some functions that come from standard C libraries are not explicitly documented on Arduino. In this case because (although I hate the implementation), abs() should work just fine.
Use fricking code tags!!!!
I want x => I would like x, I need help => I would like help, Need fast => Go and pay someone to do the job...

NEW Library to make fading leds a piece of cake
https://github.com/septillion-git/FadeLed

DryRun

#9
Jul 14, 2019, 09:57 pm Last Edit: Jul 14, 2019, 10:09 pm by DryRun
So, this is the code that i had previously in the function  for absolute value of speed and it worked:
Code: [Select]
if (turnspeed < 0)     //absolute value of current speed
   {
     turnspeed = -turnspeed;

But after i replaced it with the following, it's not working anymore, as there is no PWM output to the motors.
Code: [Select]
turnspeed = abs(turnspeed);

UKHeliBob

What do you see if you print turnspeed ?
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

DryRun

#11
Jul 14, 2019, 10:28 pm Last Edit: Jul 14, 2019, 10:29 pm by DryRun
What do you see if you print turnspeed ?
Output from Serial Monitor:
Code: [Select]
29.00
13.00
0.00
24.00
10.00
34.00
18.00
5.00
29.00
14.00
0.00
24.00
10.00
34.00
20.00
6.00
29.00
14.00
0.00
24.00
10.00
33.00
18.00
4.00
28.00
14.00
0.00
24.00
9.00
33.00
19.00
4.00
28.00
14.00
0.00
24.00
10.00
34.00
20.00
5.00
29.00
15.00
0.00
24.00
10.00
33.00
19.00
5.00
29.00
14.00
0.00
24.00
9.00
32.00
19.00
4.00
28.00
14.00
0.00
24.00
10.00
34.00


So, it's working as expected to output only positive values of the encoder rotation speed. But for some reason, there is no PWM output, meaning that the variable 'turnout' is zero. :smiley-confuse:

Delta_G

#12
Jul 14, 2019, 10:28 pm Last Edit: Jul 14, 2019, 10:32 pm by Delta_G
Code: [Select]
turnspeed = (pulseright + pulseleft);

What are pulseright and pulseleft?

Please, can we have a complete example that we can compile and test that exhibits the problem instead of snippets? 

https://snippets-r-us.com/
https://stackoverflow.com/help/minimal-reproducible-example

where do left and right get values?
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

Delta_G

Code: [Select]
fabs(turnspeed);     //should return absolute float value of turn speed

It does return the absolute value, but this line is as useless as writing:

Code: [Select]


27.5;




It doesn't store the value anywhere.  It doesn't alter the value of turnspeed. 

You need:

Code: [Select]
turnspeed = fabs(turnspeed);
|| | ||| | || | ||  ~Woodstock

Please do not PM with technical questions or comments.  Keep Arduino stuff out on the boards where it belongs.

pert

But there is no mention of fabs() in the Arduino reference docs.
https://www.arduino.cc/reference/en/language/functions/math/fabs/ gives an error. Maybe this should be added.
We do have adding documentation for this and the many other undocumented math functions on the "to-do" list:
https://github.com/arduino/reference-en/issues/522
and some related discussion here:
https://github.com/arduino/reference-en/issues/362

There is a weird situation because some cores use the Arduino macro implementation of abs(), which works with any type, while other cores (including Arduino megaAVR Boards, ESP8266, and ESP32) use the standard implementation of abs(), which does not work with float. So it's pretty much a huge mess and the incomplete documentation doesn't help matters.

Unless it's not officially supported?
I don't really know what "officially supported" means.

Go Up