Potentiometer Autonomous selector

Reposted from the Official Vex Answers forum section:

A potentiometer gets plugged into an Analog input on your microcontroller. It will return a value from 0 - 1023 which correlates to the angle at which the potentiometer is set. You could have your program set to have a different autonomous routine for each of the 1024 different values, like this:

AutoSelector = GetAnalogInput ( 1 );

    if ( AutoSelector == 1 )
    {
    
    AutonomousOne();

    }

    else if ( AutoSelector == 2 )
    {
    
    AutonomousTwo();

    }

    else if ( AutoSelector == 3 )
    {
    
    AutonomousThree();

    }

//etc....

But then even a slight wiggle of your potentiometer would select a different autonomous routine. A better idea would be to divide up your potentiometer readings up into zones or ranges. You could select what autonomous code you wanted to run by turning it to within or before the first third of it’s total range, within the second third, or to within or beyond the last third. You could even put label stickers on your potentiometer or robot to tell which section does which autonomous! Then you might have code that looks like this:

AutoSelector = GetAnalogInput ( 1 );

    if ( AutoSelector <= 400 )
    {
    
    AutonomousOne();

    }

    else if ( AutoSelector > 400 && AutoSelector <= 800 )
    {
    
    AutonomousTwo();

    }

    else if ( AutoSelector > 800 )
    {
    
    AutonomousThree();

    }

//etc....

AutonomousOne();, AutonomousTwo();, and AutonomousThree(); are function calls to functions you could make. You could also just as easily put your autonomous code there instead of those statements, but I would recommend splitting your different autonomous routines into different functions for the sake of readability and clean code.

If you download Team 1103’s code from last year, they (well Josh) used this method, look in the UserSettings() function. He uses two pots but the principle is the same.

Yes but Josh divides the variable by a number in order to get 0,1,2 or 3. Since the range is from 1-1024 if you divide the variable by 256 you will only get four different numbers.

     AutoSelector = GetAnalogInput ( 1 );

     AutoSelector = AutoSelector / 256;

    if ( AutoSelector == 0 )
    {
    
    AutonomousOne();

    }

    else if ( AutoSelector == 1 )
    {
    
    AutonomousTwo();

    }

    else if ( AutoSelector == 2 )
    {
    
    AutonomousThree();

    }

    else if ( AutoSelector == 3 )
    {
    
    AutonomousFour();

    }

The position of the potentiometer could be anywhere from 1-255 and then the variable we be returned as 0 and if it were 256-511 it would read 1 and so forth. The variable cannot return to decimals. This is the way I do it and I believe this is also the way josh (1103) did it.

You can do this ^^^ for however many autonomous runs you want. You just need to divide 1024 by how many auto runs you have and you get the number you divide the variable by.

You guys are right, that is a much easier way of doing things. It makes adding additional autonomous sections much simpler.

Josh also used an LCD screen to display which Autonomous he was selecting, instead of using a bent axle or something similar to point a certain way. Using an LCD screen is something to consider doing as well. :slight_smile:

Yes my team puts a small square bar through the potentiometer and at the end of that we put a collar with a standoff coupler on it and on that coupler a .5in standoff. It works quite nicely as a knob.

And we also use the LCD Screen to display the autonomous selected on the first line and what is going on in the auto on the second line. It also lets us know when we need to match load objects. :smiley:

Since we’re talking about auto selectoin potentiometers, I think I’ll jump in.

to start, I use RobotC, which feeds sensor values as their true size (12 bits) instead of scaling them to match the PIC (10 bits) like easyC does, so robotC analog sensor values are between 0 and 4095.

I have two potentiometers, “Mode” and “Code”. Mode has 6 positions, Code has 4.

To get the value of the Code pot, I read it then shift it 10 positions lower (to get a number between 0 and 3). On embedded platforms, it’s much faster to do a bit shift than divide if you would be dividing by a power of two (although, honestly, it dosen’t matter on the Cortex).

I then store that value into an enumerated type (enums can be manipulated as ints), so I end up with an enum of code1,code2,code3,code4.

The complete line of code to do all of this (assuming the enum is already defined) would be something like:
auto_code_t code = (SensorValue[ANA_CODE] >> 10);

To get the value of Mode pot, I read it and divide by 760, to get values between 0 and 5. I then send it to an enum (which can be manipulated as an int) of red_iso,red_int,blue_iso,blue_int,psc,rsc.

I then have 5 LED’s which indicate my selections. I take the first bit as Position (Isolation or Interaction), and the second as Color (Red or Blue). The highest bit I use (third bit) will only be set if the second bit is not set (since we only have 6 choices), so when that bit (which I call “Match Mode”) is set, red is selected but ignored. I use Match Mode + Isolation to get PSC, and Match Mode + Interaction to get RSC (the only selection which never results in an autonomous mode, for when all else fails).

To get CD1 and CD2 LED’s, I just mask the lowest two bits and send it to the LED’s (so led1 = code & 0x01; led2 = code & 0x02;), and robotC dosen’t seem to care if I set a Dig to 2.

I eventually mask out various bits and do switches. I pull out the Color into its own enum (which corresponds to + and - 1 for red and blue respectively), and mask it out. I switch based on 8 states (iso/int and the 4 codes) and call 8 functions, and feed the color as an input (all turns can multiply the angle by the color directly, as blue = -1 and red = 1). If we are in PSC, we have more functions for those routines. If we are in RSC, we do nothing (this selection is also used if we don’t want any autonomous at all).

I wrote yet more functions to handle autonomous navigation, but that is beyond the scope of this post.

As for the mechanical interface, BJC decided to take the shaft collars that have lost their set screws (of which we have many) and replace them with #8 bolts of ~1/2" length, to make nice knobs. We don’t have any sort of mechanical indication, since we have the LED’s. If I had a LCD display, I would definitely choose it over the bank of LED’s (especially since I’m down to only one spare digital and one spare analog port).

You can also take a look at a small white paper I uploaded a while back on the topic of multi-autonomous programming. https://vexforum.com/local_links.php?action=jump&catid=26&id=175

The code included within the ZIP file was written in EasyC2 for the PIC controller. There is also an attached PDF file with photos describing the use of multiple limit switches or a single potentiometer to select the autonomous routine you want to run.

I haven’t taken the time to submit an update with code written in EasyC4 yet. That maybe something that I will undertaken over the holiday break and update the code I posted.

I definately like the options of using the LCD to select which routine you want run. At the time I put together the code post using EasyC2 (2009-2010 season), the LEDs and LCDs were not available. Now that I have an LCD display I will definately incorporate that as one of the options for selecting an auton routine as well as update the code for EasyC4.

Which brings us back to wishing we had non-volatile memory so we could select the autonomous code using the LCD buttons and store it as a default somewhere in the cortex, Oh well. The LCD is great, it’s a bit of a luxury at $58 (with the required cable) but once you have one and start using it, it’s hard to give it up.