Go Back   VEX Forum > Community > Technical Discussion

Technical Discussion Open Technical Discussion of the VEX Robotics System.

Reply
 
Thread Tools
  #1  
Old 10-02-2011, 11:33 AM
jpearman's Avatar
jpearman jpearman is offline
Senior Member
VEX # 8888
 
Join Date: Apr 2011
Location: Los Angeles
Posts: 3,139
Images: 2
RobotC programming tips

We've had thread like this before, however, though I would start a new one for RobotC programmers to post their tips and tricks.

To start it off here are a couple that may not be known.

functions can have default values for their parameters, for example.

Code:
/ pointless demo code

void
forward( int speed = 100 )
{
    motor[ port2 ] = speed;   
}

task main()
{
    // Forward at default
    forward( );
   
    // Forward at speed 10
    forward( 10 );
   
    // Do nothing
    while( true ){
       wait10Msec(500);
    }
}
If the function "forward" is called with no parameters then the default of 100 is used.

If you have included your own library of functions, for example.

Code:
#include "motorLib.c"
you can suppress warnings about unused functions by including the line
Code:
#pragma systemFile            // eliminates warning for "unreferenced" functions
in the top of that file
Reply With Quote
  #2  
Old 10-02-2011, 12:19 PM
magicode's Avatar
magicode magicode is offline
Senior Member
VEX # 4542
 
Join Date: Sep 2010
Posts: 608
Images: 8
Re: RobotC programming tips

I guess I'll start off with something simple: ternary operators. Obviously this isn't specifically for ROBOTC, but many beginners don't know about it. I find it to be very useful in shortening code. A ternary operation will look something like this:
Code:
value = (boolean statement) ? (value if statement is true) : (value if statement is false);
So in a real world example:
Code:
motor[port2] = abs(vexRT[Ch2]) > 10 ? vexRT[Ch2] : 0;
In contrast to this, the if else statement would look like this:
Code:
if(abs(vexRT[Ch2]) > 10)){
  motor[port2] = vexRT[Ch2];
}else{
  motor[port2] = 0;
}
You can also nest ternary statements. For example, if you wanted to say: move the motor forward at the value of the joystick if it is positive and above the threshold value, but move the motor backward at 1/2 joystick value of it is negative and below the threshold value, then you can nest the ternary statements to make a if else if else statement.
Code:
motor[port2] = vexRT[Ch2] > 10 ? vexRT[Ch2] : vexRT[Ch2 < -10 ? (vexRT[Ch2] / 2) : 0;
__________________
It's not a bug, it's a feature.
Reply With Quote
  #3  
Old 10-02-2011, 05:26 PM
jpearman's Avatar
jpearman jpearman is offline
Senior Member
VEX # 8888
 
Join Date: Apr 2011
Location: Los Angeles
Posts: 3,139
Images: 2
Re: RobotC programming tips

It's possible to keep other files on the cortex, goto Robot->File Management menu. You can save a copy of the source code on the cortex using this dialog box.
Reply With Quote
  #4  
Old 10-02-2011, 06:08 PM
magicode's Avatar
magicode magicode is offline
Senior Member
VEX # 4542
 
Join Date: Sep 2010
Posts: 608
Images: 8
Re: RobotC programming tips

Structs are useful when doing more complex programming. For those who don't know what they are, structs are variables made of a collection of other variables. Again, this is not unique to ROBOTC, but still useful in general, and not as widely known to beginning programmers. I'll demonstrate with an example:
Code:
typedef struct{
  int maxPos;
  int minPos;
  int armSpeed;
  int prevSensorValues[10];
} robotArm;
This is an example of a struct. If you have multiple arms on your robot, you can have a struct to hold the properties of each one.

A struct is implemented, and its components are accessed like this:
Code:
robotArm leftArm;
leftArm.maxPos = 2000;
leftArm.minPos = 150;
leftArm.armSpeed = 100;
__________________
It's not a bug, it's a feature.
Reply With Quote
  #5  
Old 10-02-2011, 07:19 PM
Thorondor's Avatar
Thorondor Thorondor is offline
Senior Member
VEX # 3057
 
Join Date: Jul 2011
Location: New Jersey
Posts: 321
Re: RobotC programming tips

how do i import a library of functions? Cause that would be epic. Right now my program is cluttered with all the functions i have written, which i can share with you guys. It might not be written in the best way possible, but they are quite nifty. I don't have the actual code with me so i can't copy past but the one i like a lot is basically this:
Code:
void drivedistance(int distance)
{
  rotations = distance / "wheel circumference";
  rotations = rotations * "number of rotations of optical shaft for one rotation of wheel";
  while(SensorValue(shaft) < rotations)
{
  GO FORWARD
}
 stop
}
i think thats basically all it is. I have other versions for intaking and things like that but its pretty useful if you know the exact number of inches you want to move. This way ure not just changing arbitrary values of optical shaft encoder numbers.
__________________
Tenacious Tech 2011-2012 Programmer
Technology Division 3rd Seed (9-1-0) Technology Division Amaze Award Programming Skills World Finalists (28 points)
Reply With Quote
  #6  
Old 10-02-2011, 07:35 PM
jpearman's Avatar
jpearman jpearman is offline
Senior Member
VEX # 8888
 
Join Date: Apr 2011
Location: Los Angeles
Posts: 3,139
Images: 2
Re: RobotC programming tips

Quote:
Originally Posted by Thorondor View Post
how do i import a library of functions? Cause that would be epic. Right now my program is cluttered with all the functions i have written, which i can share with you guys. It might not be written in the best way possible, but they are quite nifty. I don't have the actual code with me so i can't copy past but the one i like a lot is basically this:
Not suite sure what you are asking, if you want to share code there is a wiki here http://www.vexforum.com/local_links.php?catid=26 you could upload a file for sharing.

If you are asking how to use a library with RobotC, well, RobotC doesn't really use libraries in the traditional sense but you can include another source file at the beginning of you code using the #include directive.

Code:
#include "myfile.c"
The directory for these files can be set in the preferences dialog.

Last edited by jpearman; 10-02-2011 at 09:17 PM. Reason: typo
Reply With Quote
  #7  
Old 10-03-2011, 06:41 AM
Jesse323Z's Avatar
Jesse323Z Jesse323Z is offline
Senior Member
VEX # 323Z
 
Join Date: Apr 2011
Location: Indianapolis, IN
Posts: 2,278
Images: 12
Send a message via Skype™ to Jesse323Z
Re: RobotC programming tips

Thanks guys!
__________________
Reply With Quote
  #8  
Old 10-03-2011, 10:31 AM
jpearman's Avatar
jpearman jpearman is offline
Senior Member
VEX # 8888
 
Join Date: Apr 2011
Location: Los Angeles
Posts: 3,139
Images: 2
Re: RobotC programming tips

Here's another tip demonstrating the use of the switch statement.

Let's say you have a motor that you want to drive forward if you press one button and backwards if you press a different button. If you press both or neither buttons the motor should be stopped. You could program this with cascaded if..then..else statements but another way is to combine the two buttons into one variable and use a switch statement. The "<<" is a shift left operator which is often used instead of multiply by 2. DriveLiftMotor would be a function to actually send values to the motor. Everything in capitals are constants defined elsewhere in the code.

Code:
    // LiftCtl will be 0, 1, 2 or 3 depending on which buttons are pressed
    LiftCtl = (vexRT[ LIFT_DN_BUTTON ] << 1) + vexRT[ LIFT_UP_BUTTON ];

    switch( LiftCtl )
        {
        case    1:  // first button pressed
            DriveLiftMotor( LIFT_UP_SPEED );
            break;
        case    2: // second button pressed
            DriveLiftMotor( LIFT_DN_SPEED );
            break;
        default:  // either neither or both buttons pressed
            DriveLiftMotor( 0 );
            break;
        }
Reply With Quote
  #9  
Old 10-05-2011, 10:05 AM
jpearman's Avatar
jpearman jpearman is offline
Senior Member
VEX # 8888
 
Join Date: Apr 2011
Location: Los Angeles
Posts: 3,139
Images: 2
Re: RobotC programming tips

There have been several questions recently about moving part of the robot until it has reached a certain position. I though I would post a RobotC example showing how to drive a motor forwards or backwards while monitoring an encoder. This same idea could be used for raising a lift or anything else where an encoder is used to monitor the rotation of a motor.

Anytime a loop is used waiting for a terminal condition to be found it's important to think about what will happen if something goes wrong. This code also shows how to use a timeout so that if an error occurs, the motor stalls for example, the test will stop after a period of time.

This code is a simple example and does not use multi tasking or the built in timer both of which could be used as part of this.

Code:
#pragma config(Sensor, dgtl1,  encoder, sensorQuadEncoder)
#pragma config(Motor,  port2,  MyMotor, tmotorNormal, openLoop)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

/*-----------------------------------------------------------------------------*/
/*                                                                             */
/* Drive motor until an encoder has counted for a number of counts             */
/* or a timeout period has passed.                                             */
/*                                                                             */
/* Assumes the encoder will count up when the motors are running forwards      */
/*                                                                             */
/*-----------------------------------------------------------------------------*/

#define TIMEOUT_CNT_PER_SEC    10
#define MOTOR_FWD_SPEED        64
#define MOTOR_REV_SPEED      (-64)
#define MOTOR_STOP_SPEED        0

int 
DriveByEncoder( int encoder_count, int timeout_in_seconds = 5 )
{
    int  timeout;
    
    // Drive motor until encoder has moved a number counts or
    // timeout_in_seconds seconds have passed

    // Zero the encoder
    SensorValue[ encoder ] = 0;
   
    // Run the motor forwards or backwards
    if( encoder_count > 0 )
        motor[ MyMotor ] = MOTOR_FWD_SPEED;
    else
        motor[ MyMotor ] = MOTOR_REV_SPEED;
        
    // run loop until encoder hits encoder_count counts or timeout reached
    
    for( timeout=(timeout_in_seconds*TIMEOUT_CNT_PER_SEC); timeout > 0; timeout-- )
        {
        // check encoder
        if( encoder_count > 0 )
            {
            // going forwards
            if( SensorValue[ encoder ] >= encoder_count )
                break;
            }
        else
            {
            // going backwards
            if( SensorValue[ encoder ] <= encoder_count )
                break;
            }
        
        // wait 1/10 second
        wait1Msec( 100 );
        }
        
    // Stop the motor
    motor[ MyMotor ] = MOTOR_STOP_SPEED;
    
    // See if we sucessfully found the right encoder value
    if( timeout <= 0 )
        {
        // there was an error - perhaps do something
        // return error
        return (-1);
        }
    else
        // return success
        return 0;
}

/*-----------------------------------------------------------------------------*/
/*                                                                             */
/*  Test the new function                                                      */
/*                                                                             */
/*-----------------------------------------------------------------------------*/

task main()
{
    // forwards until 200 counts
    DriveByEncoder( 200 );

    // short wait
    wait10Msec( 200 );
    
    // backwards for 3000 counts with a 10 second timeout
    DriveByEncoder( -3000, 10 );
    
    // demo done
    while(true)
        wait1Msec( 10 );
}
Reply With Quote
  #10  
Old 10-05-2011, 10:47 AM
magicode's Avatar
magicode magicode is offline
Senior Member
VEX # 4542
 
Join Date: Sep 2010
Posts: 608
Images: 8
Re: RobotC programming tips

Quote:
There have been several questions recently about moving part of the robot until it has reached a certain position. I though I would post a RobotC example showing how to drive a motor forwards or backwards while monitoring an encoder. This same idea could be used for raising a lift or anything else where an encoder is used to monitor the rotation of a motor.
This is a great topic to talk about, so I'm going to do a related post about keeping an arm at a certain position with a potentiometer. I want to demonstrate the use of "fuzzy logic". I will use a simple mathematical function to prevent jerkiness in movement while keeping the arm at a certain position. If you want to find out more information on fuzzy logic (and I hope you do), look at this website: http://www.societyofrobots.com/progr...zy_logic.shtml
Society of robots is a great site to visit for anything robotics related in general.
Anyway, here is an example:
Code:
const double ERR_MTRPWR_RATIO = .05;
const int MTR_THRESH = 20
const int MAX_ARM = 3000;
const int MIN_ARM = 500;

int armPosition = 0;
int motorPower = 0;

task keepArmInPosition(){
  while(true){
    motorPower = (armPosition - SensorValue[armPot]) * ERR_MTRPWR_RATIO;
    motor[arm] = abs(motorPower) > MTR_THRESH ? motorPower : 0;
    endTimeSlice();
  }
}

task main(){
  StartTask(keepArmInPosition);
  while(true){
    //code
    armPos = 300;
    endTimeSlice();
  }
}
This code keeps the motor power proportional to the error in the potentiometer value (the difference in the potentiometer value of where you want the arm to be, and where the arm is).

Here is a rundown of the constants:

ERR_MTRPWR_RATIO: How much the motor responds to one unit of error. How much the motor power will change for every potentiometer tick away from your expected arm position.

MTR_THRESH: Threshold below which the motor will not run. This is to prevent burned out motors and jerkiness. Since you will never exactly stay at the potentiometer value that you want (the ticks are very very small) this is to stop the motor from spasming when the error is very small.

MAX_ARM: The maximum potentiometr value that you want your arm to go to.

MIN_ARM: The minimum potentiometer value that you want your arm to go to.
__________________
It's not a bug, it's a feature.
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 2 (0 members and 2 guests)
 
Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump


All times are GMT -6. The time now is 06:19 PM.


VEX and VEX Robotics are trademarks or service marks of Innovation First International, Inc.
Copyright © 2002-2013. All Rights Reserved. VEX Robotics, Inc. is a subsidiary of Innovation First International, Inc.
All other product names/marks of others are the property of their respective owners.