0

I have a function that takes as parameter some doubles and does a subtraction operation on it. However I'm getting a result of 0 when one of the parameter is 0 for some reason.

int calcPID(double current, double desired, double k){
  double diff;
  diff = desired - current;
  Serial.print("desired = ");
  Serial.print(desired);
  Serial.print(", current = ");
  Serial.print(current);
  Serial.print(", diff = ");
  Serial.println(diff);
  int r = (int)diff;
  return r;
}

Output

desired = 250.00, current = 1.69, diff = 248.31
desired = 250.00, current = 0.00, diff = 0.00

When the current is 0.00 the result (diff) is also 0.00, when it should be 250. Can someone tell me what's going on?

dda
  • 1,588
  • 1
  • 12
  • 17
Lightsout
  • 177
  • 4
  • 13

3 Answers3

1

You are not providing the input values in the correct type:

calcPID(0.00, 250, 0.0);

will return 0, while

calcPID(0.00, 250.0, 0.0);

will return 250

UPDATE

Here you can get a working test case: it's running on a different processor, so don't expect to behave exactly as the 8bit MCU at Arduino's core.

Roberto Lo Giacco
  • 1,281
  • 9
  • 19
  • 1
    Is this based on a test, or a source-code reading, or what? What's the name of the library .cpp and .h files you looked at? How do you account for implicit type conversion not occurring? – James Waldby - jwpat7 Jan 26 '17 at 02:46
  • @jwpat7 I didn't look at any library, I just looked at the above code and the only viable option I was able to find is if the OP is expecting type conversion to occur in C as if it was Java. When I posted my answer there was only the calcPID function reported, but now, looking at the updated example I'm more convinced about my answer, so much I updated it with a test. – Roberto Lo Giacco Jan 26 '17 at 16:57
1

I can't reproduce that.

int calcPID(double current, double desired, double k) {
  double diff;
  diff = desired - current;
  Serial.print("desired = ");
  Serial.print(desired);
  Serial.print(", current = ");
  Serial.print(current);
  Serial.print(", diff = ");
  Serial.println(diff);
  int r = (int)diff;
  return r;
}

void setup ()
{
  Serial.begin (115200);
  Serial.println ();
  calcPID (1.69, 250, 42);
  calcPID (0, 250, 42);
}  // end of setup

void loop ()
{
}  // end of loop

That gives expected output of:

desired = 250.00, current = 1.69, diff = 248.31
desired = 250.00, current = 0.00, diff = 250.00

I strongly suspect you are passing NaN (not a number) or Inf (infinity) instead of zero. If you add another test line like this:

 calcPID (1.0 / 0, 250, 42);

Then you get the result:

desired = 250.00, current = inf, diff = inf

Now I know you reported getting zero, but earlier versions of the IDE printed 0 for NaN or Inf. I suggested a change to the way the libraries handle that which has been implemented in more recent versions.

Here, for example.


If this doesn't answer your question, please post a Minimal, Complete, and Verifiable example - like I did above.

Nick Gammon
  • 38,184
  • 13
  • 65
  • 124
1

@Roberto Lo Giacco The difference is, that on Arduino (IDE) are headers for *.ino done before standard C++ compilation

#include <stdio.h> // on *.ino it is done in IDE hidden way
int calcPID(double current, double desired, double k) ; // forward definition, for *.ino it is done in Arduino IDE hidden way
int main()
{
    calcPID (1.69, 250, 42);
    calcPID (0, 250, 42);
    calcPID (0.0, 250.0, 42);
    return 0;
}

int calcPID(double current, double desired, double k) {
  double diff;
  diff = desired - current;
  printf("desired = %5.2f, current = %5.2f, diff = %5.2f, true = %i\n", desired, current, diff, diff > 0);
  int r = (int)diff;
  printf("desired = %5.2f, current = %5.2f, diff = %i, true = %i\n", desired, current, r, r > 0);
  return r;
}

This compiles and executes on your machine well a gives correct result same as @Nick Gammon have.

Without the definition int calcPID(double current, double desired, double k) ; standard C assumes definition with ints and makes different conversions, which leads to your "incorrect" result. So the result depends on forward definition, which Arduino does behind scene. But for *.cpp and *.h it may be different, so it would be interesting, how bakalolo organized his code.

gilhad
  • 1,420
  • 2
  • 11
  • 18