Hey guys, novice programmer here. I need some help with this awful potentiometer program I have pieced together. I got some help earlier from the vex forums on some of the code, but now I need help on changing the input value. So I need to be able to go in reverse as well as go forward and obviously keep the arm steady. So far I can get it to change direction only one way though and stay put. Any help would be appreciated.
#include "Main.h"
void OperatorControl (unsigned long ulTime)
{
int error;
int btn;
int pot;
int btn2;
int input;
input = 1
while(1)
{
btn = GetJoystickDigital(1,6,2);
btn2=GetJoystickDigital(1,6,1);
pot=GetAnalogInput(1);
error = 0.5*(input-pot);
input = input * 300
if (btn == 1)
{
input = input + 1;
input = input ++;
}
else if (btn2 == 1)
{
input = input -1;
input = input --;
}
if (error > 127)
{
error = -100;
Wait (5);
}
else if (error < -127)
{
error = -100;
Wait (5);
}
Setmotor (2,error);
Setmotor(2,error*-1);
}
}
Looking through the code, I see a few things that should be corrected but nothing fundamentally broken.
Can you elaborate on what it isn’t doing that you need it to do?
Here are a few minor corrections to consider:
Setmotor (2,error);
Setmotor(2,error*-1);
These are both trying to set the same motor, but to opposite speeds. You should probably get rid of the first line, since the 2nd line runs last and will “win”. The problem here is there will be a brief time after line 1 has run that the motor might actually start to act on the wrong speed command until the 2nd line runs and fixes it.
Of course the motor and the mechanical system it is driving are so slow compared to this brief blip that you won’t actually see the motor try to move the wrong way, but it could possibly cause the motor to stutter a bit and/or increase power consumption and heating in the motor.
input = input +1;
input = input ++;
The 1st line increments input by 1 and is perfectly fine as-is.
The 2nd line does nothing and should probably be removed.
If you were watching the value of input as the 2nd line were executed, you would see it briefly pop up by 1, and then return to its original value. That is because of the way the “post-increment” operator works and the order of operations that C uses.
Lets walk through an example where input=5:
[LIST]
[LIST]
*]The “input ++” operation is evaluated first, and it has 2 effects:
*] [LIST]
*] *]1st, it replaces itself with the value of “input” (5 in this case)
*] *]2nd it increments the variable “input” to 6.
*] [/LIST]
*]At the end of this step, “input” is 6, but the expression has been simplified to “input=5”.
*]The assignment operation is evaluated next, and it sets “input” back to 5.
[/LIST]
[/LIST]
When you just want to increment a variable, you would write:
input++;
The assignment back to input is built-into the increment operator. It is a bit confusing at first since there isn’t obviously an assignment happening here, but this compactness is one of reason programmers love C.
Hey Dean thanks for the help! Sorry about the setmotor part I had that in the program but I couldn’t copy paste it for some reason so I had to copy it out with the keyboard. Thanks for the help with the increments as well I wasn’t sure how it worked. So I need to figure out how to change the input value so it can go in reverse and forward and stay in place if it is moved forward or reveresed. So for example I need it to stay when the 6u == 0 and when 6u == 1 then it needs to go forward / reverse, then stay. Same thing for 6d. So all it’s doing right now is moving forward when 6u is pushed in and moving forwards when 6d is pushed in. I need 6d to get it to move in reverse when pushed in. Thank you!
It looks to me like each pass through your while loop will multiply input by 300, which is almost certainly not what you want since that is the variable you are storing your setpoint in.
You probably want to get rid of that, and figure out some other way to accomplish whatever it was put there to do…
Well, it is certainly doing something - I suspect it is quickly pushing input’s value so large that error becomes large as a result. Which then hits your limiting logic where you clamp error to 100. It should definitely be removed.
#include "Main.h"
void OperatorControl (unsigned long ulTime) {
int error, btn, btn2, pot, input = 1;
while(1) {
btn = GetJoystickDigital(1,6,2);
btn2 = GetJoystickDigital(1,6,1);
pot = GetAnalogInput(1);
error = 0.5 * (input - pot);
// Why? This will quickly overflow
input *= 300;
// No idea what this does
if(btn)
++input;
else if(btn2)
--input;
// I'm guessing this is some kind of clamp method
// Notice that when error goes over 127 it is changed to -100, NOT 100
if(error > 127 || error < -127) {
error = -100;
Wait(5);
}
Setmotor(2, error);
Setmotor(2, -error);
}
}
Read the comments.
input = input++;
This line drove me crazy, I’m trying to figure out what would actually happen.
Technically speaking, if input was say 5, input++ should return 5 to input and then increment input to 6, however since this is being assigned to input, and I’m pretty sure that assignment happens last, input then gets reassigned to 5. Which is kind of really funny to me for some reason.
It’s like code that undoes itself.
So yeah, your clamp method is broken and the input * 300 line probably doesn’t do what you think.
Ok so I made the fixes you all suggested. I read the wiki and it made more sense so I tried to transfer it into just if syntax. I’m just confused because in your clamp function you add 127 at the end just curious as to what that does? I’m wondering if this code below serves the same function as the +127 on the end of your clamp function?
error + 127;
Also I think I originally put in this post-increment to keep changing the value but I guess it doesn’t do anything. I thought that the input + 1; would change the value so it would go in reverse or forwards.
input= input++;
Then here is the cleaner code. Thanks so much for your help guys!
#include "Main.h"
void OperatorControl (unsigned long ulTime)
{
int error;
int btn;
int pot;
int btn2;
int input;
input = 1
while(1)
{
btn = GetJoystickDigital(1,6,2);
btn2=GetJoystickDigital(1,6,1);
pot=GetAnalogInput(1);
error = 0.5*(input-pot);
if (btn == 1)
{
input = input + 1;
}
else if (btn2 == 1)
{
input = input -1;
}
if (error > 127)
{
error = 127;
Wait (5);
}
else if (error < -127)
{
error = -127;
Wait (5);
}
error + 127
Setmotor(2,error*-1);
}
}
I believe this is a holdover from older versions of EasyC where the motor speed range was 0…255 rather than -127…127. My guess is that the rest of the code used the more sane signed motor speed, and he used the clamp function to both provide a clamp AND to shift it into the unsigned speed range of 0…254
You have the right idea, but as I said above, the increment operator (++) modifies the variable you attach it to, so you don’t need the explicit assignment operator (=), and in this case the = actually undoes the ++. Any of the following will increment input by 1:
input = input + 1;
input += 1;
input++;
input = ++input; // Weird and unnecessary but works
Certainly!
One other thing to look at is limiting the range of values that “input” can have. As you’ve got it written, it should work. However if you hold down the U or D button long enough, the value of input will go beyond the range that GetAnalogInput() can return. Eventually it will get really large (negative or positive). The only way to recover from that is to hold down the opposite button for the same amount of time to get it back into the useful range.
You should consider adding some clamping logic to your button processing code like so:
if (btn == 1)
{
input = input + 1;
if (input>1023)
input=1023
}
else if (btn2 == 1)
{
input = input - 1;
if (input<0)
input=0
}
Hey guys it totally worked!!! Thanks so much guys!! I would’ve been dead in the water with out you guys, I had no help from anyone else in the school so you guys were a big help!!! Thanks so much.
Hey guys thanks so much for helping again! So I’ve got two problems. One is that our lift (which is connected to the potentiometer) is bouncing up and down sometimes, now i’m pretty sure that’s just because we’re using elastics but I could be wrong and I think it’s also because it keeps trying to change the value but the arm is moving to much. My second problem is that the motors arne’t complying at all after around 20-30 mins of use, it may be because the motors are heating up but i’m not sure.
The code you’ve written is a closed-loop control system. You’ve probably heard about PID loops? What you have is just the P part of a PID loop. The power you send to the motor is Proportional to the positioning error.
This works to get you near the target, but it is somewhat unstable particularly when a constant force is applied (like gravity) since the motor power will drop to zero as the error drops to zero. Gravity will tug the lift down, which increases the error and the motor comes back on. This pattern repeats causing the oscillations you are seeing (just a guess, but seems likely).
There have been a ton of articles written about PID loops and how to tune them to prevent this type of instability, so I won’t go into lots of details (search these forums and you’ll find quite a bit). But way oversimplifying it, you use the I part of PID to help correct for an “offset” such as the error introduced by gravity. And you use the D part of PID to help stabilize the loop so it doesn’t oscillate after it gets to the target position.
It does sound like they are overheating, which can be caused by control loop instability. Basically, the motors never get to cool off because they are driving the oscillations in the lift. This turns into heat and battery drain.