Potentiometer Programming in RobotC

#1

This is rookie team 2822. We have a flywheel bot with turntable arms. The turntable arms allow us to adjust the angle of the shot. Currently, we have two joystick controls that activate the turntable arms to go up and down. The turntables use a worm and wheel drive for adequate torque. We connected a potentiometer to the wheel of the drive. Can anyone help us with the RobotC programming? We would like joystick controls to activate the worm and wheel to stop at certain potentiometer reading.

Here the pseudocode:

while joystick button is pressed // activate worm motor for the high shot angle
{
if sensorvalue (potentiometer) between 0 and 1000 // turntable arm moves up
motor = 127
if sensorvalue (potentiometer) between 1002 and 4095 // turntable arm moves down
motor = -127
if sensorvalue (potentometer) is 1001 // turntable arm reaches desired potentiometer reading
motor = 0
}

Not sure if the pseudocode makes any sense. Basically, we need motor to go forward or go in reverse to reach a certain potentiometer reading. Then, the motor would stop at the correct reading. Eventually, we would have code that adjust the turntable arm at the low post, mid-field and far shot.

Any help with the RobotC code is welcomed!!!

0 Likes

#2

You will not get great accuracy with going to full 127 and -127. What will happen is it will oscillate as you only stop when the pot reads exactly 1001.

What will work better for you is a more advanced control loop. You can start with a proportional loop. It will slow down as you get closer. Once you master this youc an do other types.

See this thread:
https://vexforum.com/t/simple-p-controller-for-arm-position/23699/1

0 Likes

#3

Thank you Team80_Giraffes for the link to the thread. The potentiometer in our turntable arm is connected to the shaft of the wheel not the worm. Of course, the wheel turns really slow with great torque to lift the flywheel shooter. Just to clarify on the link that you gave me…

pidRequestedValue would be the reading of the potentiometer…correct?

“if( vexRT Btn8U ] == 1 )
pidRequestedValue = 1800;
else
if( vexRT Btn8D ] == 1 )
pidRequestedValue = 800;”

Can’t wait to find out if it works! Any recommendations from the forum are welcome!!

0 Likes

#4

Yes, you switch your buttons to the potentiometer setting you want the arm to move to. And magic ensues.

The background task of the “arm manager” is constantly trying to get your arm/turntable to the selected value. Your button chooses a new target. The next time in the loop, a new error value is found, and then a new motor value to minimize that error is set. It then loops around next time and sees how far away it is from the target and decides on a new motor value. It slows down the motor as you get closer.

Just don’t have any other code trying to write to that motor or it will fight each other.

Once you find the shortcomings of this, we can get you on to PID which shortens the time to get to the selected value and can hold it a bit tighter. But one step at a time. PID requires a lot of tuning and observations about overshoot and dampening. Let’s get the P controller working and you will probably be happy with the results for this year.

0 Likes

#5

So, a P controller is actually quite simple once you get the hang of it. Here’s some sample code:


float target, //the potentiometer value you want
error, //the difference between target and current
proportionalCoefficient, //what you multiply error by to get motor power
proportional, //P term, what you set motors to
motorPower; //what you set the motors to

target = 2498;
error = target - SensorValue[potentiometer];
proportional = error * proportionalCoefficient;
motorPower = proportional;
motor[arm] = motorPower;
wait1Msec(20);

I separated the proportional and motorPower variables, even though they always carry the same value by the end, because if you decide to add I and D terms, it makes your life easier, and it (somewhat) shows that a P controller is a simplified, incomplete algorithm.
If you find that the arm stays consistently under the readings you want, that is what the Integral term is for. The Derivative term is there to reduce the oscillation caused by the integral. You might not find this since you are using a worm gear, which cannot be back driven if used properly (I don’t know how good the Vex ones are at that), so don’t worry about the ID part yet. We will get to that later if necessary.

0 Likes

#6

Thanks Ipieroni for the help. Would I add the “sample code” for each target within the button assignment? What is the main difference between your response and Team80_Giraffes?

See this thread:
https://vexforum.com/t/simple-p-controller-for-arm-position/23699/1

Thank you in advance for your help!

0 Likes

#7

There really is not much of a difference, I just like adding in my own examples when I can. It also helps to reduce the number of pages you have open (I do a lot of posting from iPads and iPhones while I’m not at home), and I can easily switch between the post I’m writing and any other code that’s in a thread. I don’t have anything against linking to other threads, and jpearman always does a really great job explaining code, it’s just my preference.
As for the sample code, you would include that in your main task, then use a button assignment to change the target value. It would look something like this:


#define arm port2 //I don't really feel like opening RobotC just for a #pragma, and I think this technically works

#define armPot in1 //Potentiometer

task main() {
  float target,
    error,
    prop, //proportional
    kP, //This is the same as proportionalCoefficient, I just wanted to shorten the name
    motorPower;
  while(true) {
    if(vexRT[Btn5U]) //When you only want one line of code inside an if statement, you don't need these { }
      target = 2498;
    else if(vexRT[Btn5D])
      target = 1249;
    else if(vexRT[Btn6U])
      target = 3747;

    error = target - SensorValue[armPot];

    prop = error * kP;

    motorPower = prop;

    //This clamps the motor power to the useable bounds. This is not necessary, as the Cortex firmware does it automatically, but it is nice to have.
    if(motorPower > 127)
      motorPower = 127;
    else if(motorPower < -127)
      motorPower = -127;

    motor[arm] = motorPower;
  }
}

The error and proportional calculations in a P controller can be combined into just a proportional calculation, but this way makes adding more terms later easier.

0 Likes

#8

Can someone let us know what the value of the proportionalCoefficient is usually is ? or should be ?

Thanks.

0 Likes

#9

I always start with 0.5 and then mess with that value till I get something that works well. You will have to experiment with the number to get what woks for your bot.

0 Likes