440 likes | 832 Views
WORKSHOP: PROGRAMMING ENVIRONMENT Steve Waldo Programming Mentor, Team 1816 s-waldo@comcast.net Anna W. Team 1816 programming sub-team lead Workshop What you’ll need, and what you’ll need to know, to begin programming your FRC robot ! This presentation adapted from:
E N D
WORKSHOP:PROGRAMMING ENVIRONMENT Steve Waldo Programming Mentor, Team 1816s-waldo@comcast.net Anna W. Team 1816 programming sub-team lead
Workshop What you’ll need, andwhat you’ll need to know,to begin programming your FRC robot !
This presentation adapted from: "Introduction to C Programming for FIRST " PowerPoint presentations by David Maxwell Available for download at: http://www.usfirst.org/community/frc under the tabs Team Resources > Programming
You need 5 things: • MPLAB software • IDE (Integrated Development Environment) [EDITOR] • C18 (C program compiler) [Translates your program into machine instructions] • http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002 • FRC default C source code (FIRSTRobotics Competition) • IFI Loader (Innovation First, Inc.) • You can download 2. default code and 3. IFI_Loader from http://www.ifirobotics.com/rc.shtml (scroll to bottom) • A PC running Windows • A serial cable from a serial or USB port on your PC to the programming port on the Robot Controller (RC).
Also: WPILib Simplified Robot Controller Programming available at this web site: http://users.wpi.edu/~bamiller/WPILib/
Overview of Programming Process Just once: • Obtain and read instructions from IFI • Obtain default code, and IFI Loader e.g. from IFI website http://www.ifirobotics.com/rc.shtml • Obtain MPLAB IDE and C18 e.g. fromwww.microchip.com • Install MPLAB, and IFI_Loader on your PC Henceforth: • Write and compile your code: Run MPLAB, edit (a copy of) code, and compile the code – this creates a .hex file • Download your code to your Robot Contoller: Run IFI Loader to transfer the .hex file to your RC
1. To write and compile your code • Start MPLAB IDE • File -> Open Workspace… • Select the .mcw file from the Default Code you downloaded. • Double-click user_routines.c in project window. • Scroll down and edit Default_Routine(). • Menu: Project -> Make (or button) • Verify you get a “BUILD SUCCEEDED” message
An example code change: pwm01 = p1_y; pwm02 = p2_y; pwm03 = p3_y; pwm04 = p4_y; pwm05 = p1_x; pwm06 = p2_x; pwm07 = p3_x; pwm08 = p4_x; original pwm01 = p1_y; pwm02 = p1_x; pwm03 = p3_y; pwm04 = p4_y; pwm05 = p1_x; pwm06 = p2_x; pwm07 = p3_x; pwm08 = p4_x; I could change to:
2. To download code to your Robot Controller • Power up the Robot Controller (RC) • Connect serial cable from PC to PROGRAM port. • Start IFI_Loader on your PC. • Select appropriate COM port (for your serial cable). • “Browse” to find the .hex file you just compiled. • Click DOWNLOAD – after the download is complete, the program will automatically begin to execute on the RC if you are linked to an operator interface. • For SAFETY: have robot’s wheels in air the first time!
C Concepts The very basics…
One project, many files… • .c -Source Files • .h -Header Files • .lib -Library Files • .lkr -Linker Scripts • Edit the .c and .h files • Compile • Link FrcCode.hex
Variables unsigned char wheel_count; /* range: 0 to 255 */ char wheel_count; /* range: -128 to 127 */ unsigned int wheel_count; /* range: 0 to 65535 */ int wheel_count; /* range: -32768 to 32767 */ Tip: choose variable names others on your team will easily understand Tip: put lots of explanatory comments into your source files /* This is a comment. It is ignored by the compiler. It ends here. */
C is case-sensitive unsigned char wheel_count; (is not the same as) unsigned char Wheel_count;
Functions (also known as subroutines) three_doubled = Double_Number(3); Tip: use functions (subroutines) wherever you can … so if you need to make a change, you only have to make the change in one place…
Example Function LOCAL NAME FOR INPUT VARIABLE TYPE OF ANSWER RETURNED TYPE OF INPUT GIVEN FUNCTION NAME unsigned int Doubled_Number (unsigned int num2double) { unsigned int result; result = 2 * num2double; return result; }
LOCAL VARIABLES RETURN VALUE Example Function • unsigned int Doubled_Number (unsigned int num2double) • { • unsigned int result; • result = 2 * num2double; • return result; • } INSTRUCTIONS TO EXECUTE
Simplest Function • void Do_Nothing(void) • { • return; • }
Function Prototypes(go into a header [ .h ] file) unsigned int Double_Number (unsigned int num2double); void Do_Nothing (void);
MUST be in left-most column! Pre-Processor Note The # symbol denotes a pre-processor statement that is evaluated before the compiler takes over. #include “ifi_aliases.h”
Macros as aliases(easier names for more complex expressions) #define p4_sw_aux2 rxdata.oi_swB_byte.bitselect.bit7 /* Auxiliary input*/
Macros (as constants) #define FIELD_WIDTH 125 #define FIELD_LENGTH 300 #define FIELD_PERIMETER (FIELD_WIDTH*2 + FIELD_LENGTH*2) Use provided constants found in: ifi_aliases.h Put yours in: user_routines.h Tip: use constants wherever you can instead of “raw numbers” … so if you need to make a change, you only have to make the change in one place…and so you remember what the number is for. Tip: make constants’ names ALL CAPS so they are easily recognized by others as constants wherever seen in your program
Assignment statements relay3_fwd = p3_sw_trig; Note that instructions in the C programming language end with a semicolon
Comparison and Logical Operators + - * / add subtract multiply divide && || & | and or bit-wise and bit-wise or > >= < <= greater greater less than less thanthan or equal to or equal to == != equal not equal Tip: Don’t use = (assignment) when you mean == (test of equality)
if ( LOGICAL CONDITION 1 ) { DO THIS } else if ( LOGICAL CONDITION 2 ) { DO THIS } else { DO THIS BY DEFAULT } Conditionals (decision-making)
Looping: while while(condition is TRUE) { execute these instructions } The while loop repeats a statement until the test at the top proves false. count = 0; while(count < 7) { count = count + 1;} Example:
Looping: while • This is an infinite loop. while(1) { /* do this forever */ }
Debugging : the print function printf pwm01 = 125 + 2; printf(“PWM01 = %d\n”,(int)pwm01); If you have the serial cable connected from your robot controller to your PC, and then you can see this output in the Terminal Window in IFI_Loader: PWM01 = 127 Tip: Use printf statements liberally when writing and testing any new part of your program.
Default Code Explained C by example…
You only need to edit the three files that start with “user_”. Which files do you care about? • To follow the flowchart we’ll be looking inside: • main.c • user_routines.c • user_routines_fast.c
Step-by-Step Walkthrough void main (void) { IFI_Initialization (); /* DO NOT CHANGE! */ User_Initialization(); /* You edit this in user_routines.c */ while (1) /* This loop will repeat indefinitely. */ { if (statusflag.NEW_SPI_DATA) /* 26.2ms loop area */ { Process_Data_From_Master_uP(); /* You edit this in user_routines.c */ if (autonomous_mode) /* DO NOT CHANGE! */ { User_Autonomous_Code(); /* You edit this in user_routines_fast.c */ } } Process_Data_From_Local_IO(); /* You edit this in user_routines_fast.c */ /* I'm fast! I execute during every loop.*/ } /* while (1) */ } /* END of Main */ main.c
void User_Initialization (void) { rom const char *strptr = "IFI User Processor Initialized ..."; Set_Number_of_Analog_Channels(SIXTEEN_ANALOG); /* DO NOT CHANGE! */ /* FIRST: Set up the I/O pins you want to use as digital INPUTS. */ digital_io_01 = digital_io_02 = digital_io_03 = digital_io_04 = INPUT; digital_io_05 = digital_io_06 = digital_io_07 = digital_io_08 = INPUT; digital_io_09 = digital_io_10 = digital_io_11 = digital_io_12 = INPUT; digital_io_13 = digital_io_14 = digital_io_15 = digital_io_16 = INPUT; digital_io_18 = INPUT; /* Used for pneumatic pressure switch. */ /* SECOND: Set up the I/O pins you want to use as digital OUTPUTS. */ digital_io_17 = OUTPUT; /* Example - Not used in Default Code. */ /* THIRD: Initialize the values on the digital outputs. */ rc_dig_out17 = 0; /* FOURTH: Set your initial PWM values. Neutral is 127. */ pwm01 = pwm02 = pwm03 = pwm04 = pwm05 = pwm06 = pwm07 = pwm08 = 127; pwm09 = pwm10 = pwm11 = pwm12 = pwm13 = pwm14 = pwm15 = pwm16 = 127; /* FIFTH: Set your PWM output types for PWM OUTPUTS 13-16. */ Setup_PWM_Output_Type(IFI_PWM,IFI_PWM,IFI_PWM,IFI_PWM); /* Add any other initialization code here. */ Initialize_Serial_Comms(); Putdata(&txdata); /* DO NOT CHANGE! */ printf("%s\n", strptr); User_Proc_Is_Ready(); /* DO NOT CHANGE! - last line of User_Initialization */ } User_Initialization();in user_routines.c
Step-by-Step Walkthrough void main (void) { IFI_Initialization (); /* DO NOT CHANGE! */ User_Initialization(); /* You edit this in user_routines.c */ while (1) /* This loop will repeat indefinitely. */ { if (statusflag.NEW_SPI_DATA) /* 26.2ms loop area */ { Process_Data_From_Master_uP(); /* You edit this in user_routines.c */ if (autonomous_mode) /* DO NOT CHANGE! */ { User_Autonomous_Code(); /* You edit this in user_routines_fast.c */ } } Process_Data_From_Local_IO(); /* You edit this in user_routines_fast.c */ /* I'm fast! I execute during every loop.*/ } /* while (1) */ } /* END of Main */ main.c
Process_Data_From_Master_uP();in user_routines.c /****************************************************************** * FUNCTION NAME: Process_Data_From_Master_uP * PURPOSE: Executes every 26.2ms when it gets new data from the master * microprocessor. * CALLED FROM: main.c * ARGUMENTS: none * RETURNS: void *******************************************************************/ void Process_Data_From_Master_uP(void) { Getdata(&rxdata); /* Get fresh data from the master microprocessor. */ Default_Routine(); /* Optional. See below. */ /* Add your own code here. */ printf("PWM1 %3d, PWM2 %3d\n",(int)pwm01,(int)pwm02); /* printf EXAMPLE */ Generate_Pwms(pwm13,pwm14,pwm15,pwm16); Putdata(&txdata); /* DO NOT CHANGE! */ }
Step-by-Step Walkthrough void main (void) { IFI_Initialization (); /* DO NOT CHANGE! */ User_Initialization(); /* You edit this in user_routines.c */ while (1) /* This loop will repeat indefinitely. */ { if (statusflag.NEW_SPI_DATA) /* 26.2ms loop area */ { Process_Data_From_Master_uP(); /* You edit this in user_routines.c */ if (autonomous_mode) /* DO NOT CHANGE! */ { User_Autonomous_Code(); /* You edit this in user_routines_fast.c */ } } Process_Data_From_Local_IO(); /* You edit this in user_routines_fast.c */ /* I'm fast! I execute during every loop.*/ } /* while (1) */ } /* END of Main */ main.c
INPUTS OUTPUTS Default_Routine();- PWM Mapping /******************************************************************** * FUNCTION NAME: Default_Routine * PURPOSE: Performs the default mappings of inputs to outputs. * CALLED FROM: this file, Process_Data_From_Master_uP routine * ARGUMENTS: none * RETURNS: void ------------------------------------------------------------------------------*/ void Default_Routine(void) { /*---------- Analog Inputs (Joysticks) to PWM Outputs----------------------- *-------------------------------------------------------------------------- * This maps the joystick axes to specific PWM outputs. */ pwm01 = p1_y; pwm02 = p2_y; pwm03 = p3_y; pwm04 = p4_y; pwm05 = p1_x; pwm06 = p2_x; pwm07 = p3_x; pwm08 = p4_x; pwm09 = p1_wheel; pwm10 = p2_wheel; pwm11 = p3_wheel; pwm12 = p4_wheel; ifi_aliases.hcontains all of these macro definitions and more… unsigned char Range: 0 to 255
Default_Routine();- 1 Joystick Drive /*---------- 1 Joystick Drive ---------------------------------------------- *-------------------------------------------------------------------------- * This code mixes the Y and X axes on Port 1 to allow one joystick drive. * Joystick forward = Robot forward * Joystick backward = Robot backward * Joystick right = Robot rotates right * Joystick left = Robot rotates left * Connect the right drive motors to PWM13 and/or PWM14 on the RC. * Connect the left drive motors to PWM15 and/or PWM16 on the RC. */ pwm13 = pwm14 = Limit_Mix(2000 + p1_y + p1_x - 127); pwm15 = pwm16 = Limit_Mix(2000 + p1_y - p1_x + 127);
Default_Routine();- Buttons to Relays /*---------- Buttons to Relays---------------------------------------------- *-------------------------------------------------------------------------- * This default code maps the joystick buttons to specific relay outputs. * Relays 1 and 2 use limit switches to stop the movement in one direction. * The & used below is the C symbol for AND */ relay1_fwd = p1_sw_trig & rc_dig_in01; /* FWD only if switch1 is not closed. */ relay1_rev = p1_sw_top & rc_dig_in02; /* REV only if switch2 is not closed. */ relay2_fwd = p2_sw_trig & rc_dig_in03; /* FWD only if switch3 is not closed. */ relay2_rev = p2_sw_top & rc_dig_in04; /* REV only if switch4 is not closed. */ relay3_fwd = p3_sw_trig; relay3_rev = p3_sw_top; relay4_fwd = p4_sw_trig; relay4_rev = p4_sw_top; relay5_fwd = p1_sw_aux1; relay5_rev = p1_sw_aux2; relay6_fwd = p3_sw_aux1; relay6_rev = p3_sw_aux2; relay7_fwd = p4_sw_aux1; relay7_rev = p4_sw_aux2; relay8_fwd = !rc_dig_in18; /* Power pump only if pressure switch is off. */ relay8_rev = 0; ifi_aliases.hlists these aliases
Default_Routine();- Limit Switches /*---------- PWM outputs Limited by Limit Switches ---------*/ Limit_Switch_Max(!rc_dig_in05, &pwm03); Limit_Switch_Min(!rc_dig_in06, &pwm03); Limit_Switch_Max(!rc_dig_in07, &pwm04); Limit_Switch_Min(!rc_dig_in08, &pwm04); Limit_Switch_Max(!rc_dig_in09, &pwm09); Limit_Switch_Min(!rc_dig_in10, &pwm09); Limit_Switch_Max(!rc_dig_in11, &pwm10); Limit_Switch_Min(!rc_dig_in12, &pwm10); Limit_Switch_Max(!rc_dig_in13, &pwm11); Limit_Switch_Min(!rc_dig_in14, &pwm11); Limit_Switch_Max(!rc_dig_in15, &pwm12); Limit_Switch_Min(!rc_dig_in16, &pwm12); void Limit_Switch_Max(unsigned char switch_state, unsigned char *input_value) { if (switch_state == CLOSED) { if(*input_value > 127) *input_value = 127; } }
Default_Routine();- Feedback LEDs I /*---------- ROBOT FEEDBACK LEDs------------------------------------------------ *------------------------------------------------------------------------------ * This section drives the "ROBOT FEEDBACK" lights on the Operator Interface. * The lights are green for joystick forward and red for joystick reverse. * These may be changed for any use that the user desires. */ if (user_display_mode == 0)/* User Mode is Off */ {/* Check position of Port 1 Joystick */ if (p1_y >= 0 && p1_y <= 56) {/* Joystick is in full reverse position */ Pwm1_green = 0;/* Turn PWM1 green LED - OFF */ Pwm1_red = 1;/* Turn PWM1 red LED - ON */ } else if (p1_y >=125 && p1_y <= 129) {/* Joystick is in neutral position */ Pwm1_green = 1;/* Turn PWM1 green LED - ON */ Pwm1_red = 1;/* Turn PWM1 red LED - ON */ } else if (p1_y >= 216 && p1_y <= 255) {/* Joystick is in full forward position*/ Pwm1_green = 1;/* Turn PWM1 green LED - ON */ Pwm1_red = 0;/* Turn PWM1 red LED - OFF */ } else {/* In either forward or reverse position */ Pwm1_green = 0;/* Turn PWM1 green LED - OFF */ Pwm1_red = 0;/* Turn PWM1 red LED - OFF */ }/*END Check position of Port 1 Joystick
Default_Routine();- Feedback LEDs II /* This drives the Relay 1 and Relay 2 "Robot Feedback" lights on the OI. */ Relay1_green = relay1_fwd; /* LED is ON when Relay 1 is FWD */ Relay1_red = relay1_rev; /* LED is ON when Relay 1 is REV */ Relay2_green = relay2_fwd; /* LED is ON when Relay 2 is FWD */ Relay2_red = relay2_rev; /* LED is ON when Relay 2 is REV */ Switch1_LED = !(int)rc_dig_in01; Switch2_LED = !(int)rc_dig_in02; Switch3_LED = !(int)rc_dig_in03; }/* (user_display_mode = 0) (User Mode is Off) */ else/* User Mode is On - displays data in OI 4-digit display*/ { User_Mode_byte = backup_voltage*10;/* so that decimal doesn't get truncated. */ } } /* END Default_Routine(); */
Places to modify: in:user_routines.c • Add variables • Initialization • Modify Default_Routine() • Add to slow loop • Add to fast loop • Add to Autonomous code in:user_routines_fast.c
Key Documents to Read! • From Innovation First website: • 2004 Full-Size Control System Quick Start Guide for the OI and Full-Size RC [6 pages] • 2004 Programming Reference Guide 4/12/2004 [29 pages] • www.innovationfirst.com/firstrobotics/documentation • From www.cs.cmu.edu/~camcam • CMUcam2 manual
Resources • http://innovationfirst.com/FIRSTRobotics • http://www.microchip.com • Kernighan, Brian W. and Ritchie, Dennis. The C Programming Language (2nd Edition) [about $33 to $41 at Amazon.com]