4080A Programming help.

For those of you who were watching the San Antonio competition you may have noticed that we ended up dead in the water at some point almost every match :mad: Our robot performed flawlessly on the practice field and our autonomous and programming skills programs were spot on when we tested them with a competition switch but did not seem to cooperate with the field controllers. We were told multiple times that it was our program, and someone commented that we may be getting caught in a loop. We are going to re-load the master firmware, but with a major competition coming up next Saturday we are worried that the problem may be in the code we wrote, and we cannot see where we may have gone wrong.

We have posted our short program below :smiley: for review in the case that someone may see our problem. keep in mind we are not programmers, and neither is our mentor so this is our best effort and really pushing the limits of our programming knowledge. Our programming skills will do 50-52 with a field switch, but goes haywire and has not done more than 40 when hooked to the field electronics.

Thanks in advance for any insight!

We have to just attach the RobotC file since pasting the code exceeds the post size limit at 54,000 characters…
SanAntonio.c (52.5 KB)

Did you lose control during autonomous, driver control or both? (sounds like both from what you explained).

What was on the LCD when you lost control?

The only place I see where you will get stuck (with just a quick look at the code) is in the pre_auton funcion, you wait for a center button push and have no timeout or check for competition mode etc. If the robot were to do a full reset (loss of VEXnet perhaps) and the whole program run again, then you will get stuck here, I would be surprised if that happened multiple times in a competition.

Otherwise, I don’t think it’s your code. If it runs on a competition switch, it should run on field control.

Which version of ROBOTC are you using? There are still some small problems with V4.06 and IMEs.

I should add that when field control is plugged in after the robot is powered on, everything will do a full reset as the VEXnet channel is changed. Best case is to plug in field control and then turn everything on.

Thank you, we are using 3.62 but are considering upgrading to 4.XX since we got a VEX IQ to do some outreach with. How can we do a timeout to keep from having to push the middle button in the event of a reset? We copied and pasted the LCD code out of the sample program and then just changed it to suite our needs as best as we could. The LCD remained on when we had the failures.

While this is not the most eloquent coding we are proud to have passed 50 points without repositioning.

Most of the time code would not cause a disconnection because the code is running on the user processor and the connection is done on the master processor. A field competition forces the controller to use wifi channel 1 (that is why you notice it reset when you plug into the field with the robot on.)
There may be interference on channel 1 which would cause the disconnections

I also noticed that you have an unmatched } in your user control as well as brackets where you do not need. These extra brackets would not be harmful but are unnecessary.

In you autonomous code I see that you call all motors in every move

motor[frontLeft] = 127;
motor[frontRight] = 127;
motor[backLeft] = 127;
motor[backRight]	= 127;

to make you code easier to read and debug you can make helper functions such as drive and turn and then call those in your program.

the drive function would look like


void drive(byte speed)
{
motor[frontLeft] = speed;
motor[frontRight] = speed;
motor[backLeft] = speed;
motor[backRight]	= speed;
}

and would be called as


drive(127);

this is how we do our programs and saves many lines. It also allows motors to be added or subtracted from assemblies (making 6 motor drive) by adding 2 lines to the drive function.)

Also we were unable to see what was on the LCD when the failures occurred.

With our previous robot we had similar issues at the Austin competition but not at Lake Highlands, and we did nothing to the code in between. This current robot has 100% brand new parts. We may ditch the IME’s and squeeze a set of quad encoders in somewhere.

You can make the while loop in the pre autonomous be


while(nLCDButtons != centerButton && bIfiRobotDisabled)

so it only loops if the robot is disabled (before the match starts) and the center button is not pressed

If you’re interested, you can grab an ethernet cable, strip it, locate pins 1 and 6, strip them, just twist them all together in one bundle and put it together with electrical tape. Use this with a competition switch and it will now behave exactly like the field control switch so you can test things. The only differences are:

  1. It switches the wifi channel to a different one.
  2. It resets the cortex if plugged in once connected. In other words, it’s like turning the cortex off and on once you plug the cable in. This does not happen if you plug the cable in and then turn on the controller.

To find the pin #s, first take a look at the wires through the connector plug (which is typically clear) and match it up to the correct diagram here.

Wait, how does this work? When you plug it into your controller, does it start the autonomous or what, or does it only disable it. I don’t have a competition switch so I’d love to see how to enable and disable autonomous without one.

Oh sorry I assumed you had one. The cable does nothing on its own, it needs the competition switch to do that.

You could make your own if you want.

EDIT: This is at your own risk!! If you fry your joystick, welp, sorry. That being said, this isn’t too difficult and if you follow the instructions and double check your work, you should be fine.

If you want to make your own:

  • Cut off one end of a cable
  • Tie pins 1,4, and 7 together (and 6 if you want to simulate the real competition control). This is our ground.
  • When pin 2 is connected to ground, it is auton. When it is disconnected, it is driver. So you can wire pin 2 and ground to some kind of cheap switch for switching those
  • Same story with Pin 3 except connected is disabled, disconnected is enabled.

In a real competition the sequence of events is:

  • Disabled
  • Auton
  • Disabled
  • Driver
  • Disabled

Make sure you test it like that.

I’m guessing the problem is probably just an issue with a loose VexNET key, and so you lost connection, the robot reset, and got stuck in initialization. Try using some electrical tape to hold the key in the cortex and joystick better, that helped us with some of our connection issues. You also may want to try a different set of keys and see if that helps.

It looks fine to me, there are more braces than needed, but they are matched.

That’s not going to do it alone, the waitForPress function is where the code blocks.

That’s a shame, what about the joystick or cortex leds?

Again, exactly when did you lost control? Did you ever get control back ?

Every year we have questions about “robots not working” with the field control system. Every year wonderful and esoteric theories are put forward by forum members (and every year I hear of event staff blaming user code). Most of the time these are all wrong and the solutions are simple, things like bad batteries and over heated motors.

Think about what was different during the matches as compared to practice. Try and explain to us the procedure you have for turning the robot on and connecting the field control cable. We need a bit more information. I will fix up the lcd code for you later and post it.

video of one of your said matchs?

I am on a chromebook right now so there is not much I can do as far as video editing or a screenshot (I am new to the chromebook) I will get some more information to go on in a day or so to see if we can get to the bottom of this.

Thanks!

We may have to try that, we were considering buying one of these

I mean, if you have the money, have fun. I’d just rather spend that kind of money on parts and spend an hour and only ~15$ to make my own competition switch.

Looks like there was a price reduction on the field control system, it used to be $199. At $150 I may have to get myself one, wish it was $99 and excluded the CAT5 cables.

Didn’t get around to posting this yesterday, ROBOTC crashed on me and I lost the changes. Anyway, here is a modified version of the LCD user interface that will quit if the robot becomes enabled. If there is no competition switch connected then this won’t run at all, then again, you have no way to enter autonomous without the switch so it doesn’t really matter.

//Declare count variable to keep track of our choice
int count = 0;

//Wait for Press--------------------------------------------------
void waitForPress()
{
    while( (nLCDButtons == 0) && bIfiRobotDisabled )
        wait1Msec(5);
}
//----------------------------------------------------------------

//Wait for Release------------------------------------------------
void waitForRelease()
{
    while( (nLCDButtons != 0) && bIfiRobotDisabled )
        wait1Msec(5);
}


void pre_auton()
{
    bStopTasksBetweenModes = true;

    //Completely clear out any previous sensor readings by setting the port to "sensorNone"
    SensorType[in2] = sensorNone;
    wait1Msec(1000);
    //Reconfigure Analog Port 2 as a Gyro sensor and allow time for ROBOTC to calibrate it
    SensorType[in2] = sensorGyro;
    wait1Msec(2000);

    // Turn on LCD Backlight
    bLCDBacklight = true;

    //------------- Beginning of User Interface Code ---------------

    //Clear LCD
    clearLCDLine(0);
    clearLCDLine(1);
    //Loop while center button is not pressed
    while( (nLCDButtons != kButtonCenter)  && bIfiRobotDisabled )
        {
        //Switch case that allows the user to choose from 4 different options
        switch(count)
            {
            case 0:
                //Display first choice
                displayLCDCenteredString(0, "Right Middle");
                displayLCDCenteredString(1, "<     Enter    >");
                break;
            case 1:
                //Display second choice
                displayLCDCenteredString(0, "Left Middle");
                displayLCDCenteredString(1, "<     Enter    >");
                break;
            case 2:
                //Display third choice
                displayLCDCenteredString(0, "No Autonomous");
                displayLCDCenteredString(1, "<     Enter    >");
                break;
            case 3:
                //Display fourth choice
                displayLCDCenteredString(0, "Prog. Skills");
                displayLCDCenteredString(1, "<     Enter    >");
                break;
            case 4:
                //Display fifth choice
                displayLCDCenteredString(0, "Right Hang");
                displayLCDCenteredString(1, "<     Enter    >");
                break;
            case 5:
                //Display sixth choice
                displayLCDCenteredString(0, "Left Hang");
                displayLCDCenteredString(1, "<     Enter    >");
                break;
            default:
                count = 0;
                break;
            }
        
        // wait for a button press    
        waitForPress();
        //Increment or decrement "count" based on button press
        if(nLCDButtons == kButtonLeft)
            {
            waitForRelease();
            if(--count < 0)
                count = 5;
            }
        else
        if(nLCDButtons == kButtonRight)
            {
            waitForRelease();
            if(++count > 5)
                count = 0;
            }
        }
}

I made several changes.

  1. You don’t need to define the buttons (const short leftButton = 1; etc.) as ROBOTC has these pre-defined for you.

  2. I added a test for the robot being enabled in waitForPress, waitForRelease and the while loop in the pre_auton code, this will cause these functions to quit if the robot is enabled.

  3. The wait1Msec(5); in waitForPress and waitForRelease was outside the braces and therefore meaningless, I revised that code so the cpu gets some time.

  4. The check for the left and right buttons in every branch of the switch statement was sort of redundant so I simplified that.

  5. The “displayLCDCenteredString(1, “< Enter >”);” statements were not really working as they were longer than the 16 characters the LCD can display, I reduced to 16 chars and removed the tabs which caused the weird display (unless did you want that ? )

  6. I made the left and right buttons wrap around the selection at both ends. If you add more choices then you will need to revise the code that wraps from choice 5 to 0.

I also simplified (but did not change) your driver control code, too many nested while loops.

task usercontrol()
{
    string mainBattery, backupBattery;
    
    // User control code here, inside the loop
    while (true)
        {
        //Remote Control Commands
        motor[frontLeft] = vexRT[Ch2] - vexRT[Ch1];
        motor[backLeft] =  vexRT[Ch2] + vexRT[Ch1];
        motor[frontRight] = vexRT[Ch3] + vexRT[Ch4];
        motor[backRight] =  vexRT[Ch3] - vexRT[Ch4];

        //Lift
        if(vexRT[Btn5U] == 1)
            {
            motor[liftHighLeft]  = 127;
            motor[liftHighRight] = 127;
            motor[liftLowLeft]   = 127;
            motor[liftLowRight]  = 127;
            }
        else
        if(vexRT[Btn5D] == 1)
            {
            motor[liftHighLeft]  = -127;
            motor[liftHighRight] = -127;
            motor[liftLowLeft]   = -127;
            motor[liftLowRight]  = -127;
            }
        else
            {
            motor[liftHighLeft]  = 10;
            motor[liftHighRight] = 10;
            motor[liftLowLeft]   = 10;
            motor[liftLowRight]  = 10;
            }

        //Intake Control
        if(vexRT[Btn6U] == 1)
            {
            motor[intakeRight] = 127;
            motor[intakeLeft]  = 127;
            }
        else
        if(vexRT[Btn6D] == 1)
            {
            motor[intakeRight] = -127;
            motor[intakeLeft]  = -127;
            }
        else
            {
            motor[intakeLeft]  = 0;
            motor[intakeRight] = 0;
            }


        clearLCDLine(0); // Clear line 1 (0) of the LCD
        clearLCDLine(1); // Clear line 2 (1) of the LCD

        //Display the Primary Robot battery voltage
        displayLCDString(0, 0, "Primary: ");
        sprintf(mainBattery, "%1.2f%c", nImmediateBatteryLevel/1000.0,'V'); //Build the value to be displayed
        displayNextLCDString(mainBattery);

        //Display the Backup battery voltage
        displayLCDString(1, 0, "Backup: ");
        sprintf(backupBattery, "%1.2f%c", BackupBatteryLevel/1000.0, 'V');  //Build the value to be displayed
        displayNextLCDString(backupBattery);

        //Short delay for the LCD refresh rate
        wait1Msec(25);
        }
}

Also, reduced the loop delay, 100mS was a bit long.

The way I prevent the robot from dying if I DC during a match is by making a task for my LCD program chooser, so when the robot disconnects and reboots, rather than getting locked up in a while loop in the pre-auton, it just starts a task that does nothing and enables driver control.

Thank you!!! Check your email :slight_smile:

Absolutely, and for an example, see one of the demo programs in this thread.

ROBOTC LCD autonomous selection