-1

Why does this print output -3? xpos can be any value.

void loop() {
xPos = analogRead(xPin);
yPos = analogRead(yPin);
pwm = xPos*(255/1023);
Serial.println(pwm);

}
  • What types are your variables declared as? (int, float, etc) – Peter Bloomfield Jul 1 '15 at 10:23
  • xPos and yPos are ints and pwm is currently float i tried int aswell, and its outputting 0 not -3 sorry, (xPos*255)/1023 outputs -3. – glen cashen Jul 1 '15 at 10:32
  • @user10936 Could you edit your question to include the setup() loop and the declarations of xPos, yPos, and pwm. There could be something there that you're overlooking. – CharlieHanson Jul 1 '15 at 12:35
  • Just swap the priority of the operations. So use pwm = xPos*255/1023; instead. – Gerben Jul 1 '15 at 12:41
1

The problem is that (255/1023) is being treated as an integer calculation, meaning the result gets truncated to 0. You can make the compiler promote it to a floating-point calculation by explicitly making at least one of the values floating-point. For example:

pwm = xPos*(255.0f/1023.0f);
  • Is the f designator necessary? Without it does the compiler treat the calculation as doubles and then re-cast it to float or something? Also, is it not sufficient to add the decimal point to just the numerator or denominator? I know it works in 'regular C++ on a computer', but in an embedded environment would it bloat the program memory? – CharlieHanson Jul 1 '15 at 12:40
  • 2
    @chaaarlie2 Without the f designator, a C++ compiler would treat it as double during the calculation, which normally requires slightly more resources. Most Arduinos treat float and double the same though so it wouldn't necessarily make a practical difference. It's not usually a good idea to rely on platform quirks like that though. – Peter Bloomfield Jul 1 '15 at 13:45
  • @chaaarlie2 I would always put the f designator on both values, simply for consistency. The chances are that the compiler would be smart enough to convert the integer to floating-point at compile-time (rather than run-time), so it probably doesn't matter from a technical point-of-view. – Peter Bloomfield Jul 1 '15 at 13:46
  • I prefer the format pwm = xPos * val1 / (float) val2; which works equally for hardcoded values, constants and variables. – Igor Stoppa Jul 1 '15 at 14:25
1

The previous answer correctly suggested writing

pwm = xPos*(255.0f/1023.0f);

in place of the original form pwm = xPos*(255/1023);. But because 255/1023 - 1/4 = -1/1364 which is fairly small (ie it differs by 1 part in 1364), just saying

pwm = xPos/4;

will usually give the correct result or nearly so.

Note, the following python program shows that this result is exact 514 times as xPos ranges from 0 to 1023, and is one too large 510 times, which for many processes being controlled by PWM signals is close enough.

#!/usr/bin/env python
c = [0]*8
for i in range(1024):
    vf = int(i*255.0/1023.0)
    vi = i/4
    d = vi-vf
    c[d+3] += 1
    #print '{:5} {:5} {:5} {:5}'.format(i, d, vi, vf)
print c

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.