Hello-- So our team has just figured out how to program the potentiometer to display the voltage on the front panel. Our next goal is to be able to convert the voltage into angle. Does anybody know of an equation where you can convert the voltage into an angle? Thanks!
The voltage that the potentiometer will put out is relative to whatever angle it is set at. The way you go about reading the potentiometer’s output as an angle is to set it at the desired angle manually, read the potentiometer and save that voltage. To get the robot to set itself to that angle, you just recall the voltage that you measured earlier.
I know that this is super simplified, but its basically what you do, no fancy math involved
Assuming a linear potentiomenter and straightforward mechanical motion, the formula is just the equation for a line:
y = mx + b
Read the voltage as x.
Multiply it by a scaling constant m.
Add an offset constant b.
The corresponding angle is y.
To determine the constants, read the voltage at two known angles. Put the voltage and angle in for x and y. Now you have two equations with two unknowns, and you can solve for m and b.
Or you can do what Garrett suggests and not worry about angles at all. Just use voltage in your programming. You don’t need to say “put the angle at 30 degrees”. You can say “move until the voltage is 1.36” instead.
We are looking at doing something like the illustration attached. The fixed resistor is there for the zero resistance case of the pot. Points 1 and 2 are the analog inputs, with 1 being the difference from the high side of the pot to the wiper and 2 being the full drop of the pot. Using these two measurements, you can divide 1 by 2 to get a percentage (assuming a linear pot). If you know the full available angle of the pot, multiply the full angle by the percentage and (voila!) you have your angle from zero.
Of course, if there’s an offset, you need to add that to get angle versus gravity or robot direction or whatever…
If you were using a simple variable resistor, that diagram might be appropriate. But a properly-wired potentiometer always puts the maximum resistance across the power input, and the wiper provides a voltage proportional to its travel from one end to the other.
Just wire one end of the pot to +5, the other end to 0, and the wiper to the analog signal input. All three of those are conveniently provided on the analog input pins.
So you have a potentiometer that goes from 0 to 5 volts, right? In your code, it will read back to you that voltage, right?
A potentiometer is nothing else but a voltage divider when setup the way you do. You turn it all the way in one direction, and it shows 0V, and you start turning it the other direction and it will (hopefully) linearly go to 5V. That is, if you have a linear potentiometer.
There are to basic kinds, linear and logarithmic. Logarithmic potentiometers are usually used for audio applications since hearing is exponential in the way it is perceived.
Therefore, if you have a linear pot, it should increase linearly (in a straight line) from 0 to 5 volts.
If you’re using LabVIEW, the value is returned to you as a voltage. In C++ or Java, I’m not sure… I’ve never used those for the new FIRST system. I’m pretty sure it’s returned back as a floating point voltage from 0 to 5 volts though.
Therefore, for a 170˚ rotation potentiometer, all you need to do is figure out your scaling factor (or slope). There should be no offset (y-intercept) unless you need it.
So… at 5V, say it’s at 170˚. At 0V, say it’s at 0˚. Or…
(x, y): (0, 0), (5, 170)
Hopefully you know how to find slope… if not:
m = (y2 - y1) / (x2 - x1), or (170 - 0) / (5 - 0)
Simplified, it’s 170 / 5, or even simpler, 34.
So finally, to get an angle, simply multiply your voltage by 34.
angle = voltage * 34
0˚ = 0V * 34
170˚ = 5V * 34
Beware of cheap potentiometers. They have a lot of dead-band near either end. For a 170˚ pot, only expect about 150˚ of it to be useful. The extremes will just stick at 0 and 5V.
Also, consider yourself lucky that the WPI lib does all the math to get you a clean voltage from 0 to 5 volts. Real world use of voltage is a lot harder to use properly.
This is true and absolutely correct. However, we’ve had people make mistakes like that before and it’s just easier to put in a preventative item like that than have the team swear off pots for another four years …
It is not that hard to get the wiring done right. It would be sad if a team really stopped using a common type of sensor because they did not follow some simple instructions and blamed the sensor. Many pieces of industrial electronics products use exactly the same set up to control some function. I have never seen a second resisitor added as a “preventative measure” because it is just not necessary as Alan has stated. Ohm’s Law applied correctly to this situation will prove this point.
I would hope that you are doing a thorough check of EACH AND EVERY wire, individually, for ALL of your circuits before turning on the power. Preferably, a second person should also check your work after you have satisfied yourself that you have found and fixed all your errors. An incorrectly wired pot will not damage the CRio but it is quite likely that an incorrectly wired motor controller can become damaged.
Here is the equation we used last year:
positionDeg = (analogPot->GetAverageVoltage() - INHERENT_ZERO) * VOLTAGE_TO_DEGREES;
where INHERENT_ZERO was a value we measured and defined within our code for the position we chose to view as zero degrees;
and VOLTAGE_TO_DEGREES was a value calculated ahead of time to convert the voltage over a 90 deg travel into degrees. (This is simple to do because it is just a linear conversion. Take the difference of the pot voltage at 0 and at 90 and then divide by 90 to get this value.)
Hope that helps.
Let:
y = positionDeg
m = VOLTAGE_TO_DEGREES
x = analogPot->GetAverageVoltage()
b = -VOLTAGE_TO_DEGREES*INHERENT_ZERO
then:
y = mx + b
EXACTLY!
While calculating a very simple linear equation is all nice and good, I prefer to use an interpolation curve with 2 points.
Basically, you cal two pairs of numbers (an analog value and corresponding engineering unit value for each pair) and calculate M and B dynamically. I find it’s easier to calibrate.
the code can then does the following (for the 2-point curve):
dx = max_ana - min_ana;
dy = max_eng - min_eng;
m = dx / dy;ana_raw = get_analog_value();
ana_offset = ana_raw - min_ana;
eng_offset = ana_offset * m;
eng = eng_offset + min_eng;
eng is the result.
Under the same basic logic, you can develop blocks to linearly interpolate a 1d input and 1d output table to generate a piecewise function which is calibrated like a pair of tables (input and output), or two 1d input tables and a 2d output table to end up with a 3d surface whichis calibrated with two axis breakpoints and the values for each cell.
Such interpolation curves and tables seem to be a staple of embedded control algorithms, since they are very easy to implement and calibrate (relative to fully modeling the system), and get ‘close enough’. FRC software is usually in the ‘close enough’ realm anyway, so they are perfect.