| @@ -0,0 +1,129 @@ | ||
| //Make sure this file only gets #included once | ||
| #ifndef __ROBOT_H__ | ||
| #define __ROBOT_H__ | ||
| //Prevent any unnecessary warnings | ||
| #pragma systemFile | ||
| //Define all constants | ||
| #include "constants.h" | ||
|
|
||
| /////////////////////////////////////////////////////////////////////////////// | ||
| //MARK: - Enumerations | ||
| /////////////////////////////////////////////////////////////////////////////// | ||
|
|
||
| //Enumeration to define easy motor speeds | ||
| typedef enum _MHMotorPower{ | ||
| //To stop is to not move. Duh. | ||
| MHMotorPowerStop = 0, | ||
| //If you wanna stall the motors, it's safe to put it at a power of 30, but that's about the lowest it's safe to go | ||
| MHMotorPowerStall = 30, | ||
| //31 is about the minimum power you can assign to a motor before it begins to twitch | ||
| MHMotorPowerMin = 31, | ||
| //While a true half is 63.5, we're defining integer constants here, so we'll give it the high end | ||
| MHMotorPowerHalf = 64, | ||
| //For some reason, the maximum possible power for a VEX motor is 127. Don't ask me why. | ||
| MHMotorPowerMax = 127 | ||
| }MHMotorPower; | ||
| //Enumeration to define robot drive sides | ||
| typedef enum _MHDriveSide{ | ||
| //The left side of the drive, when the robot is facing away from you | ||
| MHDriveSideLeft, | ||
| //The right drive side, when the robot is facing away from you | ||
| MHDriveSideRight | ||
| }MHDriveSide; | ||
|
|
||
| /////////////////////////////////////////////////////////////////////////////// | ||
| //MARK: - Drive Functions | ||
| /////////////////////////////////////////////////////////////////////////////// | ||
|
|
||
| /* The simplest of drive functions | ||
| int left: Integer to represent how fast you want the left side of the drive to go | ||
| int right: Integer to represent how fast you want the right side of the drive to go | ||
| This function does not return anything | ||
| Called like: drive(42, 42); */ | ||
| void drive(int left, int right); | ||
| /* Change the speed of only one side of the drive | ||
| MHDriveSide side: Constant to represent which side of the drive you want to change speed | ||
| int power: Integer to represent the power you want the side of the drive to move | ||
| This function does not return anything | ||
| Called like: driveSideWithPower(MHDriveSideLeft, 42); */ | ||
| void driveSideWithPower(MHDriveSide side, int power); | ||
| /* Brings the robot to a full stop | ||
| This function takes no parameters | ||
| This function does not return anything | ||
| Called like: stop(); */ | ||
| void stop(); | ||
| /* Stops the motors on only one side of the drive | ||
| MHDriveSide side: Constant to represent which side of the drive you want to stop | ||
| This function does not return anything | ||
| Called like: stopDriveSide(MHDriveSideLeft); */ | ||
| void stopDriveSide(MHDriveSide side); | ||
|
|
||
| /////////////////////////////////////////////////////////////////////////////// | ||
| //MARK: - Ball Launching Functions | ||
| /////////////////////////////////////////////////////////////////////////////// | ||
|
|
||
| /* Runs the motors to accept ammunition into the launching chamber | ||
| This function takes no parameters | ||
| This function does not return anything | ||
| Called like: intake(); */ | ||
| void intake(); | ||
| /* Stops the intake motors to prevent any more ammunition from coming into the launch chamber | ||
| This function takes no parameters | ||
| This function does not return anything | ||
| Called like: holdIntake(); */ | ||
| void holdIntake(); | ||
| /* Runs the motors to launch any ammunition in the launching chambers | ||
| This function takes no parameters | ||
| This function does not return anything | ||
| Called like: launch(); */ | ||
|
|
||
| void launch(); | ||
| /* Stops the launch motors, to prevent any ammunition from being fired from the launch chamber | ||
| This function takes no parameters | ||
| This function does not return anything | ||
| Called like: holdLaunch(); */ | ||
| void holdLaunch(); | ||
| /* Runs all motors in the cannon assembly to immediately launch any ammunition that comes in the intake | ||
| This function takes no parameters | ||
| This function does not return anything | ||
| Called like: fire(); */ | ||
| void fire(); | ||
| /* Stops all motors in the cannon assembly, to prevent anything from entering or leaving the launch chamber | ||
| This function takes no parameters | ||
| This function does not return anything | ||
| Called like: holdFire(); */ | ||
| void holdFire(); | ||
|
|
||
| //Actually implement the functions declared above | ||
| #include "robot.c" | ||
| #endif |
| @@ -0,0 +1,12 @@ | ||
| Cherry Hill East Robotics - F Team | ||
| ===== | ||
|
|
||
| This repository contains all the code that powers the robot of the Cherry Hill East Robotics's F Team | ||
|
|
||
| ##License | ||
|
|
||
| You can read all about what you're allowed to and not do in the [LICENSE](https://github.com/EastRobotics/FTeam/blob/master/LICENSE) file. We use the Mozilla Public License, Version 2.0, if you're familiar with it | ||
|
|
||
| ##Usage | ||
|
|
||
| If you're another Robotics team competing in a VEX competition, you're free to use this code, either in its entirety or any part of it, as long as you make your code open source, and credit us where the credit is due. Same goes for everyone else, but I haven't heard of these things being built for anything else. Just compile `main.c`, and make sure that all of its `#include`s are where they're supposed to be |
| @@ -0,0 +1,183 @@ | ||
| ///////////////////////////////////////////////////////////////////////////////////////// | ||
| //**Reset encoders**/ | ||
| ///////////////////////////////////////////////////////////////////////////////////////// | ||
| void resetEncoders(){ //Clears drive encoders | ||
| nMotorEncoder[leftDriveMiddle] = 0; | ||
| nMotorEncoder[rightDriveMiddle] = 0; | ||
| } | ||
| ///////////////////////////////////////////////////////////////////////////////////////// | ||
| //**Basic**/ | ||
| // | ||
| //Caveman-simple driving with nothing | ||
| ///////////////////////////////////////////////////////////////////////////////////////// | ||
| void basicDrive(int leftPower, int rightPower){ | ||
| motor[leftDriveFront]=motor[leftDriveMiddle]=motor[leftDriveBack] = leftPower; | ||
| motor[rightDriveFront] = motor[rightDriveMiddle] = motor[rightDriveBack] = rightPower; | ||
| } | ||
| ///////////////////////////////////////////////////////////////////////////////////////// | ||
| //**Drive**/ | ||
| // | ||
| //Simple driving with straighening but no stopping limit | ||
| ///////////////////////////////////////////////////////////////////////////////////////// | ||
| void drive(int power){ | ||
|
|
||
| if(power != 0) //Adds ability to use to use function to stop drive | ||
| { | ||
| basicDrive(power, power); | ||
| //Compares left and right encoder values to straighten robot | ||
| if(nMotorEncoder[leftDriveMiddle] == nMotorEncoder[rightDriveMiddle]) | ||
| { | ||
| basicDrive(power, power); | ||
| } | ||
| else if(nMotorEncoder[leftDriveMiddle] < nMotorEncoder[rightDriveMiddle]) | ||
| { | ||
| basicDrive(power, power-40); | ||
| } | ||
| else | ||
| { | ||
| basicDrive(power-40,power); | ||
| } | ||
|
|
||
| } | ||
| else //Stops drive if power is zero | ||
| { | ||
| basicDrive(0,0); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| ///////////////////////////////////////////////////////////////////////////////////////// | ||
| //**Encoder-based Drive**/ | ||
| // | ||
| //Info: | ||
| // • + or - power determines front or back | ||
| // • encoder count must be positive | ||
| // • drive power of 80 is very reliable | ||
| ///////////////////////////////////////////////////////////////////////////////////////// | ||
| void encoderDrive(int power, int encoderCount){ | ||
|
|
||
| while(abs(nMotorEncoder[leftDriveMiddle]) < encoderCount){ | ||
| basicDrive(power, power); //Drive robot at power | ||
| } | ||
| drive(0); //Turn off after it has reached destination | ||
| } | ||
|
|
||
| ///////////////////////////////////////////////////////////////////////////////////////// | ||
| //**Encoder-based Drive w/ Lift**/ | ||
| // | ||
| //Info: | ||
| // • + or - power determines front or back | ||
| // • + or - position determines lift up or down | ||
| // • encoder count must be positive | ||
| ///////////////////////////////////////////////////////////////////////////////////////// | ||
| void encoderDriveWithLift(int power, int encoderCount, int position){ | ||
|
|
||
| while(abs(nMotorEncoder[leftDriveMiddle]) < encoderCount && abs(nMotorEncoder[rightDriveMiddle]) < encoderCount - 300){ | ||
| drive(power); //Drive robot at power | ||
|
|
||
| if(nMotorEncoder[leftDriveMiddle] >= encoderCount) | ||
| motor[leftDriveFront]=motor[leftDriveMiddle] = motor[leftDriveBack] = 0; | ||
|
|
||
| if(nMotorEncoder[rightDriveMiddle] >= encoderCount) | ||
| motor[rightDriveFront] = motor[rightDriveMiddle] = motor[rightDriveBack] = 0; | ||
| } | ||
|
|
||
| //Slow down near destination | ||
| while(abs(nMotorEncoder[leftDriveMiddle]) < encoderCount && abs(nMotorEncoder[rightDriveMiddle]) < encoderCount){ | ||
| drive(power); //Drive robot at power | ||
|
|
||
| if(nMotorEncoder[leftDriveMiddle] >= encoderCount) | ||
| motor[leftDriveFront]=motor[leftDriveMiddle] = motor[leftDriveBack] = 0; | ||
|
|
||
| if(nMotorEncoder[rightDriveMiddle] >= encoderCount) | ||
| motor[rightDriveFront] = motor[rightDriveMiddle] = motor[rightDriveBack] = 0; | ||
| } | ||
| drive(0); //Turn off after it has reached destination | ||
| } | ||
|
|
||
| ///////////////////////////////////////////////////////////////////////////////////////// | ||
| //**Spin**/ | ||
| // | ||
| //Spin robot using encoders | ||
| //positive degrees10 = clockwise | ||
| ///////////////////////////////////////////////////////////////////////////////////////// | ||
| void spin(int power, int encoderCount){ | ||
| //Clockwise with positive power | ||
| if(power > 0){ | ||
| while(abs(nMotorEncoder[leftDriveMiddle]) < encoderCount){ | ||
| basicDrive(power, -power); | ||
| } | ||
| } | ||
| else{ | ||
| while(abs(nMotorEncoder[leftDriveMiddle]) < encoderCount){ | ||
| basicDrive(power, -power); | ||
| } | ||
| } | ||
| drive(0); | ||
| } | ||
|
|
||
| ///////////////////////////////////////////////////////////////////////////////////////// | ||
| //**Hook turn**/ | ||
| // | ||
| //Spin robot using encoders | ||
| //positive degrees10 = clockwise | ||
| ///////////////////////////////////////////////////////////////////////////////////////// | ||
| void hookSpin(int power, int encoderCount){ | ||
| //Clockwise with positive power | ||
| if(power > 0){ | ||
| while(abs(nMotorEncoder[leftDriveMiddle]) < encoderCount){ | ||
| basicDrive(power, -25); | ||
| } | ||
| } | ||
| else{ | ||
| while(abs(nMotorEncoder[leftDriveMiddle]) < encoderCount){ | ||
| basicDrive(25, -power); | ||
| } | ||
| } | ||
| drive(0); | ||
| } | ||
|
|
||
| ///////////////////////////////////////////////////////////////////////////////////////// | ||
| //**Lift the lift up**/ | ||
| // Encodercount sign does not matter. sign of power determines | ||
| ///////////////////////////////////////////////////////////////////////////////////////// | ||
| void liftLift(int encoderCount) | ||
| { | ||
| //int encoderAverage = (abs(nMotorEncoder[leftLiftBottom]) + abs(nMotorEncoder[rightLiftBottom]))/2; | ||
| while(true) { | ||
| if(abs(nMotorEncoder[rightLiftBottom]) < encoderCount) { | ||
| motor[leftLiftBottom] = motor[leftLiftTop] = motor[rightLiftBottom] = motor[rightLiftTop] = 127; | ||
| } else { | ||
| motor[leftLiftBottom] = motor[leftLiftTop] = motor[rightLiftBottom] = motor[rightLiftTop] = 0; | ||
| return; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| ///////////////////////////////////////////////////////////////////////////////////////// | ||
| //**Lower the lift down**/ | ||
| ///////////////////////////////////////////////////////////////////////////////////////// | ||
| void lowerLift(int encoderCount) | ||
| { | ||
| //int encoderAverage = (abs(nMotorEncoder[leftLiftBottom]) + abs(nMotorEncoder[rightLiftBottom]))/2; | ||
| while(true) { | ||
| if(abs(nMotorEncoder[rightLiftBottom]) > encoderCount) { | ||
| motor[leftLiftBottom] = motor[leftLiftTop] = motor[rightLiftBottom] = motor[rightLiftTop] = -127; | ||
| } else { | ||
| motor[leftLiftBottom] = motor[leftLiftTop] = motor[rightLiftBottom] = motor[rightLiftTop] = 0; | ||
| return; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void timeLift(int power, int time) | ||
| { | ||
| } | ||
|
|
||
| ///////////////////////////////////////////////////////////////////////////////////////// | ||
| //**Time-based intake** | ||
| // | ||
| //Spins intake for designated time | ||
| ///////////////////////////////////////////////////////////////////////////////////////// | ||
| void intake(int power, int time){ | ||
| } |
| @@ -0,0 +1,3 @@ | ||
| void autonomous() { | ||
|
|
||
| } |
| @@ -0,0 +1,9 @@ | ||
| /* | ||
| This file is the function library, the functions are basically | ||
| short cuts to control parts of the robot | ||
| */ | ||
| //nmotorencoder | ||
|
|
||
| void lift(int power){ //this function works the same way, using the input power to control the lift | ||
| motor[ltLift] = motor[lmLift] = motor[llLift] = motor[rtLift] = motor[rmLift] = motor[rlLift] = power; | ||
| } |
| @@ -0,0 +1,165 @@ | ||
| typedef enum { | ||
| FieldZoneUnknown = 0x0, | ||
| FieldZoneHanging = 0x1, | ||
| FieldZoneMiddle = 0x2, | ||
| FieldZoneAny = FieldZoneHanging | FieldZoneMiddle | ||
| } FieldZone; | ||
|
|
||
| typedef enum { | ||
| FieldColorUnknown = 0x0, | ||
| FieldColorRed = 0x1, | ||
| FieldColorBlue = 0x2, | ||
| FieldColorAny = FieldColorRed | FieldColorBlue | ||
| } FieldColor; | ||
|
|
||
| static bool doneSelection = false; | ||
| static FieldZone selectedFieldZone = -1; | ||
| static FieldColor selectedFieldColor = -1; | ||
|
|
||
| struct AutonomousRoutine { | ||
| AutonomousRoutine *prev; | ||
| AutonomousRoutine *next; | ||
| FieldZone zone; | ||
| FieldColor color; | ||
| char *name; | ||
| int tag; | ||
| } AutonomousRoutine; | ||
|
|
||
| static AutonomousRoutine routines[20]; | ||
| static int slot = 0; | ||
|
|
||
| static AutonomousRoutine *first = NULL; | ||
| static AutonomousRoutine *selected = NULL; | ||
|
|
||
| void AddAutonomousRoutine(FieldZone zone, FieldColor color, char *name, int tag) { | ||
| routines[slot].prev = NULL; | ||
| routines[slot].next = NULL; | ||
| routines[slot].zone = zone; | ||
| routines[slot].color = color; | ||
| routines[slot].name = name; | ||
| routines[slot].tag = tag; | ||
|
|
||
| if (first == NULL) { | ||
| first = &routines[slot]; | ||
| } else { | ||
| AutonomousRoutine *prev = first; | ||
| while (prev->next) | ||
| prev = prev->next; | ||
| routines[slot].prev = prev; | ||
| prev->next = &routines[slot]; | ||
| } | ||
|
|
||
| slot++; | ||
| } | ||
|
|
||
| TControllerButtons waitForButtons(TControllerButtons allowed) { | ||
| TControllerButtons previous = 0; | ||
| TControllerButtons selected = 0; | ||
| while (selected == 0) { | ||
| if ((allowed & kButtonLeft) != 0 && (previous & kButtonLeft) == kButtonLeft && (nLCDButtons & kButtonLeft) == 0) { | ||
| selected = kButtonLeft; | ||
| } else if ((allowed & kButtonCenter) != 0 && (previous & kButtonCenter) == kButtonCenter && (nLCDButtons & kButtonCenter) == 0) { | ||
| selected = kButtonCenter; | ||
| } else if ((allowed & kButtonRight) != 0 && (previous & kButtonRight) == kButtonRight && (nLCDButtons & kButtonRight) == 0) { | ||
| selected = kButtonRight; | ||
| } | ||
|
|
||
| previous = nLCDButtons; | ||
| wait1Msec(20); | ||
| } | ||
| return selected; | ||
| } | ||
|
|
||
| task selection() { | ||
| doneSelection = false; | ||
|
|
||
| displayLCDCenteredString(0, "Select Zone"); | ||
| displayLCDString(1, 0, "Hanging"); | ||
| displayLCDString(1, 10, "Middle"); | ||
| switch (waitForButtons(kButtonLeft | kButtonRight)) { | ||
| case kButtonLeft: | ||
| selectedFieldZone = FieldZoneHanging; | ||
| break; | ||
| case kButtonRight: | ||
| selectedFieldZone = FieldZoneMiddle; | ||
| break; | ||
| } | ||
| clearLCDLine(0); | ||
| clearLCDLine(1); | ||
|
|
||
| displayLCDCenteredString(0, "Select Color"); | ||
| displayLCDString(1, 0, "Red"); | ||
| displayLCDString(1, 12, "Blue"); | ||
| switch (waitForButtons(kButtonLeft | kButtonRight)) { | ||
| case kButtonLeft: | ||
| selectedFieldColor = FieldColorRed; | ||
| break; | ||
| case kButtonRight: | ||
| selectedFieldColor = FieldColorBlue; | ||
| break; | ||
| } | ||
| clearLCDLine(0); | ||
| clearLCDLine(1); | ||
|
|
||
| AutonomousRoutine *routine = first; | ||
| while (routine) { | ||
| if ((routine->zone & selectedFieldZone) == 0 || (routine->color & selectedFieldColor) == 0) { | ||
| if (routine->prev) | ||
| routine->prev->next = routine->next; | ||
| if (routine->next) | ||
| routine->next->prev = routine->prev; | ||
| } | ||
| routine = routine->next; | ||
| } | ||
|
|
||
| displayLCDCenteredString(0, "Select Routine"); | ||
| AutonomousRoutine *current = first; | ||
| while (selected == NULL) { | ||
| displayLCDCenteredString(1, current->name); | ||
| displayLCDString(1, 0, (current != NULL && current->prev != NULL) ? "<-" : " "); | ||
| displayLCDString(1, 14, (current != NULL && current->next != NULL) ? "->" : " "); | ||
| switch (waitForButtons(kButtonLeft | kButtonCenter | kButtonRight)) { | ||
| case kButtonLeft: | ||
| if (current != NULL && current->prev != NULL) | ||
| current = current->prev; | ||
| break; | ||
| case kButtonRight: | ||
| if (current != NULL && current->next != NULL) | ||
| current = current->next; | ||
| break; | ||
| case kButtonCenter: | ||
| if (current) | ||
| selected = current; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| doneSelection = true; | ||
| } | ||
|
|
||
| void SelectAutonomousRoutine() { | ||
| if (!bIfiRobotDisabled) return; | ||
|
|
||
| bLCDBacklight = true; | ||
| startTask(selection); | ||
|
|
||
| while (!doneSelection) { | ||
| if (!bIfiRobotDisabled) doneSelection = true; | ||
| wait1Msec(25); | ||
| } | ||
|
|
||
| stopTask(selection); | ||
| bLCDBacklight = false; | ||
| } | ||
|
|
||
| FieldZone SelectedFieldZone() { | ||
| return selectedFieldZone; | ||
| } | ||
|
|
||
| FieldColor SelectedFieldColor() { | ||
| return selectedFieldColor; | ||
| } | ||
|
|
||
| AutonomousRoutine * SelectedAutonomousRoutine() { | ||
| return selected; | ||
| } |
| @@ -0,0 +1,155 @@ | ||
| typedef enum { | ||
| FieldZoneUnknown = 0x0, | ||
| FieldZoneSkyRise = 0x1, | ||
| FieldZoneNot = 0x2, | ||
| FieldZoneAny = FieldZoneSkyRise | FieldZoneNot | ||
| }FieldZone; | ||
| typedef enum { | ||
| FieldColorUnknown = 0x0, | ||
| FieldColorRed = 0x1, | ||
| FieldColorBlue = 0x2, | ||
| FieldColorAny = FieldColorRed | FieldColorBlue | ||
| }FieldColor; | ||
| static bool doneSelection = false; | ||
| static FieldZone selectedFieldZone = -1; | ||
| static FieldColor selectedFieldColor = -1; | ||
| struct AutonomousRoutine { | ||
| AutonomousRoutine *prev; | ||
| AutonomousRoutine *next; | ||
| int zone; | ||
| int color; | ||
| char *name; | ||
| int tag; | ||
| }AutonomousRoutine; | ||
| static AutonomousRoutine routines[20]; | ||
| static int slot = 0; | ||
| static AutonomousRoutine *first = NULL; | ||
| static AutonomousRoutine *selected = NULL; | ||
| void AddAutonomousRoutine(FieldZone zone, FieldColor color, char *name, int tag) { | ||
| routines[slot].prev = NULL; | ||
| routines[slot].next = NULL; | ||
| routines[slot].zone = zone; | ||
| routines[slot].color = color; | ||
| routines[slot].name = name; | ||
| routines[slot].tag = tag; | ||
| if (first == NULL){ | ||
| first = &routines[slot]; | ||
| } | ||
| else{ | ||
| AutonomousRoutine *prev = first; | ||
| while(prev->next){ | ||
| prev = prev->next; | ||
| } | ||
| routines[slot].prev = prev; | ||
| prev->next = &routines[slot]; | ||
| } | ||
| slot++; | ||
| } | ||
| TControllerButtons waitForButtons(TControllerButtons allowed) { | ||
| TControllerButtons previous = 0; | ||
| TControllerButtons selected = 0; | ||
| while(selected == 0){ | ||
| if((allowed & kButtonLeft) != 0 && (previous & kButtonLeft) == kButtonLeft && (nLCDButtons & kButtonLeft) == 0){ | ||
| selected = kButtonLeft; | ||
| } | ||
| else if((allowed & kButtonCenter) != 0 && (previous & kButtonCenter) == kButtonCenter && (nLCDButtons & kButtonCenter) == 0){ | ||
| selected = kButtonCenter; | ||
| } | ||
| else if ((allowed & kButtonRight) != 0 && (previous & kButtonRight) == kButtonRight && (nLCDButtons & kButtonRight) == 0){ | ||
| selected = kButtonRight; | ||
| } | ||
| previous = nLCDButtons; | ||
| wait1Msec(20); | ||
| } | ||
| return selected; | ||
| } | ||
| task selection() { | ||
| doneSelection = false; | ||
| displayLCDCenteredString(0, "Select Zone"); | ||
| displayLCDString(1, 0, "SkyRise"); | ||
| displayLCDString(1, 10, "not"); | ||
| switch(waitForButtons(kButtonLeft | kButtonRight)){ | ||
| case kButtonLeft: | ||
| selectedFieldZone = FieldZoneSkyRise; | ||
| break; | ||
| case kButtonRight: | ||
| selectedFieldZone = FieldZoneNot; | ||
| break; | ||
| } | ||
| clearLCDLine(0); | ||
| clearLCDLine(1); | ||
| displayLCDCenteredString(0, "Select Color"); | ||
| displayLCDString(1, 0, "Red"); | ||
| displayLCDString(1, 12, "Blue"); | ||
| switch (waitForButtons(kButtonLeft | kButtonRight)) { | ||
| case kButtonLeft: | ||
| selectedFieldColor = FieldColorRed; | ||
| break; | ||
| case kButtonRight: | ||
| selectedFieldColor = FieldColorBlue; | ||
| break; | ||
| } | ||
| clearLCDLine(0); | ||
| clearLCDLine(1); | ||
| AutonomousRoutine *routine = first; | ||
| while(routine){ | ||
| if((routine->zone & selectedFieldZone) == 0 || (routine->color & selectedFieldColor) == 0){ | ||
| if(routine->prev){ | ||
| routine->prev->next = routine->next; | ||
| } | ||
| if(routine->next){ | ||
| routine->next->prev = routine->prev; | ||
| } | ||
| } | ||
| routine = routine->next; | ||
| } | ||
| displayLCDCenteredString(0, "Select Routine"); | ||
| AutonomousRoutine *current = first; | ||
| while(selected == NULL){ | ||
| displayLCDCenteredString(1, current->name); | ||
| displayLCDString(1, 0, (current != NULL && current->prev != NULL) ? "<-" : " "); | ||
| displayLCDString(1, 14, (current != NULL && current->next != NULL) ? "->" : " "); | ||
| switch(waitForButtons(kButtonLeft | kButtonCenter | kButtonRight)){ | ||
| case kButtonLeft: | ||
| if(current != NULL && current->prev != NULL){ | ||
| current = current->prev; | ||
| } | ||
| break; | ||
| case kButtonRight: | ||
| if(current != NULL && current->next != NULL){ | ||
| current = current->next; | ||
| } | ||
| break; | ||
| case kButtonCenter: | ||
| if(current){ | ||
| selected = current; | ||
| } | ||
| break; | ||
| } | ||
| } | ||
| doneSelection = true; | ||
| } | ||
| void SelectAutonomousRoutine() { | ||
| if(!bIfiRobotDisabled){ | ||
| return; | ||
| } | ||
| bLCDBacklight = true; | ||
| StartTask(selection); | ||
| while(!doneSelection){ | ||
| if(!bIfiRobotDisabled){ | ||
| doneSelection = true; | ||
| } | ||
| wait1Msec(25); | ||
| } | ||
| StopTask(selection); | ||
| bLCDBacklight = false; | ||
| } | ||
| FieldZone SelectedFieldZone(){ | ||
| return selectedFieldZone; | ||
| } | ||
| FieldColor SelectedFieldColor(){ | ||
| return selectedFieldColor; | ||
| } | ||
| AutonomousRoutine * SelectedAutonomousRoutine(){ | ||
| return selected; | ||
| } |
| @@ -0,0 +1,58 @@ | ||
| #pragma systemFile | ||
| #define VOLTAGE_THRESHOLD 1250 | ||
| void displayLCDVoltageString(int line); | ||
| void displayVoltage(int line, int position, int millivolts, bool leftAligned); | ||
| void LCDVoltageString(string *text, int batteryLevel); | ||
| void LCDVoltageLine(string *line); | ||
| void displayLCDVoltageString(int line){ | ||
| bLCDBacklight = false; | ||
| clearLCDLine(line); | ||
| int otherBatteryLevel = (float)SensorValue[otherBattery] * 1000 / 280; | ||
| displayVoltage(line, 0, nImmediateBatteryLevel, true); | ||
| displayVoltage(line, 11, otherBatteryLevel, false); | ||
| } | ||
| void displayVoltage(int line, int position, int millivolts, bool leftAligned){ | ||
| displayLCDPos(line, position); | ||
| if(millivolts <= VOLTAGE_THRESHOLD){ | ||
| displayNextLCDString(leftAligned ? "None " : " None"); | ||
| return; | ||
| } | ||
| float volts = ((float)millivolts / 1000); | ||
| string displayString; | ||
| sprintf(displayString, "%1.2f", volts); | ||
| displayNextLCDString(displayString); | ||
| displayNextLCDChar('V'); | ||
| } | ||
| void LCDVoltageString(string *text, int batteryLevel){ | ||
| if(batteryLevel <= VOLTAGE_THRESHOLD){ | ||
| *text = "None"; | ||
| return; | ||
| } | ||
| float volts = ((float)batteryLevel / 1000); | ||
| sprintf(*text, "1.2%fV", volts); | ||
| return; | ||
| } | ||
| void LCDVoltageLine(string *line){ | ||
| string primary; | ||
| string other; | ||
| LCDVoltageString(&primary, nImmediateBatteryLevel); | ||
| LCDVoltageString(&other, SensorValue[otherBattery]); | ||
| int length = strlen(primary) + strlen(other); | ||
| switch(length){ | ||
| case 10: | ||
| //Strings in ROBOTC must be added one at a time, because ROBOTC is stupid | ||
| *line = primary + " "; | ||
| *line += other; | ||
| return; | ||
| case 9: | ||
| *line = primary + " "; | ||
| *line += other; | ||
| return; | ||
| case 8: | ||
| *line = primary + " "; | ||
| *line += other; | ||
| return; | ||
| default: | ||
| *line = " Battery Error "; | ||
| } | ||
| } |
| @@ -0,0 +1,102 @@ | ||
| #pragma systemFile | ||
| #ifndef enums | ||
| #define enums | ||
| #endif | ||
| //List of common motor powers for easy referencing | ||
| static const int MHLiftMaxHeight = 904; | ||
| typedef enum _MHMotorPower{ | ||
| MHMotorPowerStop = 0, | ||
| //If you wanna stall the motors, it's safe to put it at a power of 30, but that's about the lowest it's safe to go | ||
| MHMotorPowerStall = 30, | ||
| //31 is about the minimum power you can assign to a motor before it begins to twitch | ||
| MHMotorPowerMin = 31, | ||
| //While a true half is 63.5, we're defining integer constants here, so we'll give it the high end | ||
| MHMotorPowerHalf = 64, | ||
| //For some reason, the maximum possible power for a VEX motor is 127. Don't ask me why. | ||
| MHMotorPowerMax = 127 | ||
| }MHMotorPower; | ||
| //The team color that the robot is on in a particualr match. Chosen in the pre_auton function | ||
| typedef enum _MHTeamColor{ | ||
| MHTeamColorNone, | ||
| MHTeamColorAny, | ||
| MHTeamColorRed, | ||
| MHTeamColorBlue | ||
| }MHTeamColor; | ||
| //All the possible point values that the robot can score during the autonomous task. Chosen in the pre_auton function | ||
| typedef enum _MHTeamColor{ | ||
| MHAutonStyleOnePoint = 1, | ||
| MHAutonStyleCubeAuton = 3, | ||
| MHAutonStyleSkyriseAuton = 12, | ||
| MHAutonStyleSkills = 30, | ||
| //MHAutonValueNone is bridged toll-free to MHTeamColorNone, since they're the same thing | ||
| MHAutonStyleNoAuton = MHTeamColorNone | ||
| }MHAutonStyle; | ||
| //typedef to frequently used amounts of time | ||
| typedef enum _MHTime{ | ||
| MHTimeOneMillisecond = 1, | ||
| MHTimeTenthSecond = 100, | ||
| MHTimeQuarterSecond = 250, | ||
| MHTimeHalfSecond = 500, | ||
| MHTimeOneSecond = 1000 | ||
| }MHTime; | ||
| //Constant to define the power threshold where the motors will begin to twitch | ||
| static const int MHMotorTwitchThreshold = 30; | ||
| //Defines the side of the robot that something should take place on | ||
| typedef enum _MHRobotSide{ | ||
| MHRobotSideRight = 0, | ||
| MHRobotSideLeft = 1, | ||
| MHRobotSideFront = 2, | ||
| MHRobotSideBack = 3, | ||
| }MHRobotSide; | ||
| typedef enum _MHLiftDirection{ | ||
| MHLiftDirectionUp = -1, | ||
| MHLiftDirectionDown = 1, | ||
| //MHLiftDirectionStop is bridged toll-free to MHMotorPowerStop, because they're the same thing | ||
| MHLiftDirectionStop = MHMotorPowerStop | ||
| }MHLiftDirection; | ||
| typedef enum _MHPneumaticPosition{ | ||
| //Handily, normal C does not have a boolean type. In that language, 0 is false and anything else is true. Since ROBOTC is derived from C, the same logic can be used here | ||
| MHPneumaticPositionClosed = 1, | ||
| MHPneumaticPositionOpen = 0 | ||
| }MHPneumaticPosition; | ||
| typedef enum _MHSkyrise{ | ||
| //These all are raw approximate postentiometer values, for use in the liftToPosition function of autonomous.h | ||
| MHSkyriseOneSkyrise = 900, | ||
|
|
||
| //TODO: Update to potentiometer values | ||
|
|
||
| MHSkyriseTwoSkyrises = 800, | ||
| MHSkyriseThreeSkyrises = 1700, | ||
| MHSkyriseFourSkyrises = 2200, | ||
| MHSkyriseFiveSkyrises = 3100, | ||
| MHSkyriseLiftInaccuracy = 400 | ||
| }MHSkyrise; | ||
| //In a couple places, it's useful to have all of the above in an array, so they can be referenced by index, and not raw value | ||
| static const MHSkyrise skyrises[5] = {MHSkyriseOneSkyrise, MHSkyriseTwoSkyrises, MHSkyriseThreeSkyrises, MHSkyriseFourSkyrises, MHSkyriseFiveSkyrises}; | ||
| //Constants to designate which direction the robot should rotate | ||
| typedef enum _MHRotationDirection{ | ||
| MHRotationDirectionClockwise = 1, | ||
| MHRotationDirectionCounterClockwise = -1, | ||
| MHRotationDirectionNoRotation = 0 | ||
| }MHRotationDirection; | ||
| //Constants to define different signifcant points in the lift in potentiometer values | ||
| typedef enum _MHLiftPosition{ | ||
| MHLiftPositionCurrentPosition = (-1), | ||
| MHLiftPositionTop = 0, | ||
| MHLiftPositionMiddlePost = 770, | ||
| MHLiftPositionLowPost = 1070, | ||
| MHLiftPositionOneCube = 1270, | ||
| MHLiftPositionBottom = 1570 | ||
| }MHLiftPosition; | ||
| //Constants to define positions for the turning gyroscope | ||
| typedef enum _MHRotationDistance{ | ||
| MHRotationDistanceNone = 0, | ||
| MHRotationDistanceTenthDegree = 1, | ||
| MHRotationDistanceOneDegree = 10, | ||
| MHRotationDistanceTenDegrees = 100, | ||
| MHRotationDistanceOneRadian = 573, | ||
| MHRotationDistanceHundredDegrees = 1000, | ||
| MHRotationDistanceQuarterRotation = 900, | ||
| MHRotationDistanceHalfRotation = 1800, | ||
| MHRotationDistanceFullTurn = 3600 | ||
| }MHRotationDistance; |
| @@ -0,0 +1,296 @@ | ||
| #pragma systemFile | ||
| //ROBOTC Default Values: string = "", numbers = 536885932 | ||
| #ifndef VOLTAGE_THRESHOLD | ||
| #include "battery.h" | ||
| #endif | ||
| #ifndef LCD | ||
| #define LCD | ||
| #endif | ||
| //Different default screen types, used by the displayScreen function in lcd.h to display a preconfigured screen | ||
| typedef enum _MHLCDScreenStyle{ | ||
| MHLCDScreenStyleColorSelection = 1, | ||
| MHLCDScreenStylePointSelection = 2, | ||
| MHLCDScreenStyleVoltage = 3, | ||
| MHLCDScreenStyleOff = 0, | ||
| MHLCDScreenStyleCustom = 4 | ||
| }MHLCDScreenStyle; | ||
| //Map of the possible LCD button combinations to make them easy to reference | ||
| typedef enum _MHLCDButton{ | ||
| MHLCDButtonLeft = 1, | ||
| MHLCDButtonCenter = 2, | ||
| MHLCDButtonRight = 4, | ||
| MHLCDButtonLeftCenter = 3, | ||
| MHLCDButtonLeftRight = 5, | ||
| MHLCDButtonCenterRight = 6, | ||
| MHLCDButtonAll = 7, | ||
| MHLCDButtonNone = 0 | ||
| }MHLCDButton; | ||
| //Constant to denote a string to be centered to the LCD width in the centerString function | ||
| static const int MHStringPaddingLCDCenter = 0; | ||
| //At the time of this writing (December 3, 2014), the standard VEX LCD width is 16 charachters. This is a constant to make that more obvious. If that ever changes, this constant will have to, too | ||
| static const int MHLCDScreenWidth = 16; | ||
| typedef struct MHLCDScreen{ | ||
| MHLCDScreenStyle style; | ||
| MHLCDScreenStyle lastScreenStyle; | ||
| MHLCDScreenStyle nextScreenStyle; | ||
| string header; | ||
| string footer; | ||
| string topLine; | ||
| string leftOption; | ||
| string middleOption; | ||
| string rightOption; | ||
| string bottomLine; | ||
| bool backlight; | ||
| }MHLCDScreen; | ||
| MHLCDScreen lastScreen; | ||
| MHLCDScreen nextScreen; | ||
| MHLCDScreen liveScreen; | ||
| //This sets up a screen based off of a default. It will operate on a custom screen, if a pointer to one is passed, but it defaults to nextScreen, if there is none passed. | ||
| void screenForScreenStyle(MHLCDScreenStyle style, MHLCDScreen *screen); | ||
| //This makes the passed screen go live on the VEX LCD. If both a header and a topLine is set, then the header will display. Same for the footer - bottomLine relationship | ||
| void displayScreen(MHLCDScreen screen); | ||
| //Displays a screen basec on a specified screen style | ||
| void displayScreenStyle(MHLCDScreenStyle style); | ||
| //If it has a configuration, this makes the screen stored in nextScreen go live on the VEX LCD | ||
| void displayNextScreen(); | ||
| //If it has a configuration, this makes the screen stroed in lastScreen go live on the VEX LCD | ||
| void displayLastScreen(); | ||
| //This edits a string that is passed so that it will be centered within a given space. If no area is given, it will be centered to the VEX LCD | ||
| //void centerString(string *original, int area); | ||
| //Prepares a MHLCDScreen for display by the displayScreen function | ||
| void prepareScreen(MHLCDScreen *screen); | ||
| //Clears the LCD screen when necessary | ||
| void clearLCD(); | ||
| //Prints a string to the first line of the LCD, and the second line, if a string for that line is specified | ||
| void print(const string lineOne, const string lineTwo); | ||
| //Checks to see if the buttons pressed are different from the ones passed in | ||
| bool otherButtonsPressed(MHLCDButton button); | ||
| //Halts program execution until a button is pressed on the VEX LCD, then waits an extra tenth of a second | ||
| void waitForPress(); | ||
| //Halts program execution until all buttons on the VEX LCD are released | ||
| void waitForRelease(); | ||
| //Displays a screen for 5 seconds, then switches back to the previous | ||
| void flashScreen(MHLCDScreen screen); | ||
| //Displays a screen style for 5 seconds, then switches back to the previous | ||
| void flashScreenStyle(MHLCDScreenStyle screenStyle); | ||
| //Waits for a specified amount of time (in seconds) while counting down the time on the LCD | ||
| void countDownForTime(MHTime time); | ||
| /* | ||
| void centerString(string *original, int area){ | ||
| string text = (string)*original; | ||
| if(area == MHStringPaddingLCDCenter){ | ||
| area = MHLCDScreenWidth; | ||
| } | ||
| int space = area - strlen(text); | ||
| string whitespace = ""; | ||
| for(int i = 0; i < floor(space / 2); i++){ | ||
| whitespace += " "; | ||
| } | ||
| if(space % 2 == 0){ | ||
| sprintf(*original, "%s%s%s", whitespace, text, whitespace); | ||
| } | ||
| else{ | ||
| sprintf(*original, "%s%s%s", whitespace, text, whitespace); | ||
| } | ||
| } | ||
| */ | ||
| void screenForScreenStyle(MHLCDScreenStyle style, MHLCDScreen *screen){ | ||
| if(!*screen){ | ||
| *screen = nextScreen; | ||
| } | ||
| screen->style = style; | ||
| string header; | ||
| string footer; | ||
| switch(style){ | ||
| case MHLCDScreenStyleColorSelection: | ||
| screen->style = MHLCDScreenStyleColorSelection; | ||
| screen->lastScreenStyle = MHLCDScreenStylePointSelection; | ||
| screen->nextScreenStyle = MHLCDScreenStyleVoltage; | ||
| screen->backlight = true; | ||
| screen->header = "2616F"; | ||
| screen->topLine = header; | ||
| screen->rightOption = "Blue"; | ||
| screen->middleOption = ""; | ||
| screen->leftOption = "Red"; | ||
| screen->footer = "Red Blue"; | ||
| screen->footer = screen->bottomLine; | ||
| break; | ||
| case MHLCDScreenStylePointSelection: | ||
| screen->style = MHLCDScreenStylePointSelection; | ||
| screen->lastScreenStyle = MHLCDScreenStyleVoltage; | ||
| screen->nextScreenStyle = MHLCDScreenStyleColorSelection; | ||
| screen->backlight = true; | ||
| screen->header = "2616F"; | ||
| screen->topLine = header; | ||
| screen->leftOption = "Cube"; | ||
| screen->middleOption = "Skill"; | ||
| screen->rightOption = "Skyrs"; | ||
| screen->bottomLine = "Cube Skill Skyrs"; | ||
| screen->footer = screen->bottomLine; | ||
| break; | ||
| case MHLCDScreenStyleVoltage: | ||
| screen->style = MHLCDScreenStyleVoltage; | ||
| screen->lastScreenStyle = MHLCDScreenStyleOff; | ||
| screen->nextScreenStyle = MHLCDScreenStylePointSelection; | ||
| screen->backlight = false; | ||
| screen->header = "2616F"; | ||
| screen->topLine = header; | ||
| LCDVoltageLine(&footer); | ||
| screen->footer = footer; | ||
| screen->bottomLine = footer; | ||
| break; | ||
| case MHLCDScreenStyleOff: | ||
| screen->style = MHLCDScreenStyleOff; | ||
| screen->nextScreenStyle = MHLCDScreenStyleOff; | ||
| screen->lastScreenStyle = MHLCDScreenStyleOff; | ||
| screen->backlight = false; | ||
| screen->header = ""; | ||
| screen->topLine = ""; | ||
| screen->footer = ""; | ||
| screen->bottomLine = ""; | ||
| break; | ||
| case MHLCDScreenStyleCustom: | ||
| screen->style = MHLCDScreenStyleCustom; | ||
| screen->nextScreenStyle = MHLCDScreenStyleCustom; | ||
| screen->lastScreenStyle = MHLCDScreenStyleCustom; | ||
| screen->backlight = true; | ||
| screen->header = "2616F"; | ||
| screen->topLine = ""; | ||
| screen->footer = ""; | ||
| screen->bottomLine = ""; | ||
| default: | ||
| screen->style = MHLCDScreenStyleCustom; | ||
| screen->nextScreenStyle = MHLCDScreenStyleCustom; | ||
| screen->lastScreenStyle = MHLCDScreenStyleCustom; | ||
| screen->backlight = true; | ||
| screen->header = "2616F"; | ||
| screen->topLine = ""; | ||
| screen->footer = ""; | ||
| screen->bottomLine = ""; | ||
| break; | ||
| } | ||
| return; | ||
| } | ||
| void displayScreen(MHLCDScreen screen){ | ||
| prepareScreen(&screen); | ||
| clearLCD(); | ||
| lastScreen = liveScreen; | ||
| bLCDBacklight = screen.backlight; | ||
| displayLCDCenteredString(0, screen.topLine); | ||
| if(screen.style == MHLCDScreenStyleVoltage){ | ||
| displayLCDVoltageString(1); | ||
| } | ||
| else{ | ||
| displayLCDCenteredString(1, screen.bottomLine); | ||
| } | ||
| liveScreen = screen; | ||
| screenForScreenStyle(screen.nextScreenStyle, &nextScreen); | ||
| } | ||
| void clearLCD(){ | ||
| clearLCDLine(0); | ||
| clearLCDLine(1); | ||
| } | ||
| void displayNextScreen(){ | ||
| if(liveScreen.nextScreenStyle){ | ||
| displayScreenStyle(liveScreen.nextScreenStyle); | ||
| } | ||
| else if(nextScreen){ | ||
| displayScreen(nextScreen); | ||
| } | ||
| } | ||
| void displayLastScreen(){ | ||
| if(lastScreen){ | ||
| displayScreen(lastScreen); | ||
| } | ||
| } | ||
| void prepareScreen(MHLCDScreen *screen){ | ||
| //These are all checking if the value is null, and assigning one, if it is. The probelm is that it might just be a null pointer. Pray that doesn't happen | ||
| if(screen->backlight == NULL){ | ||
| screen->backlight = false; | ||
| } | ||
| if(screen->nextScreenStyle != MHLCDScreenStyleColorSelection || screen->nextScreenStyle != MHLCDScreenStylePointSelection || screen->nextScreenStyle != MHLCDScreenStyleVoltage || screen->nextScreenStyle != MHLCDScreenStyleOff){ | ||
| screen->nextScreenStyle = MHLCDScreenStyleCustom; | ||
| } | ||
| if(screen->lastScreenStyle != MHLCDScreenStyleColorSelection || screen->lastScreenStyle != MHLCDScreenStylePointSelection || screen->lastScreenStyle != MHLCDScreenStyleVoltage || screen->lastScreenStyle != MHLCDScreenStyleOff){ | ||
| screen->lastScreenStyle = MHLCDScreenStyleCustom; | ||
| } | ||
| if(screen->style != MHLCDScreenStyleColorSelection || screen->style != MHLCDScreenStylePointSelection || screen->style != MHLCDScreenStyleVoltage || screen->style != MHLCDScreenStyleOff){ | ||
| screen->style = MHLCDScreenStyleCustom; | ||
| } | ||
| if(screen->header != ""){ | ||
| screen->topLine = screen->header; | ||
| } | ||
| //if(screen->footer != ""){ | ||
| // screen->bottomLine = screen->footer; | ||
| //} | ||
| //if(screen->rightOption != "" || screen->middleOption != "" || screen->leftOption != ""){ | ||
| // if(strlen(screen->rightOption) + strlen(screen->middleOption) + strlen(screen->leftOption) <= 16){ | ||
| // int space = MHLCDScreenWidth - strlen(screen->rightOption) + strlen(screen->leftOption); | ||
| // //centerString(screen->middleOption, space); | ||
| // sprintf(screen->bottomLine, "%s%s%s", screen->leftOption, screen->middleOption, screen->rightOption); | ||
| // } | ||
| // else{ | ||
| // screen->bottomLine = "Too many chars"; | ||
| // } | ||
| //} | ||
| } | ||
| void print(const string lineOne, const string lineTwo){ | ||
| clearLCDLine(0); | ||
| displayLCDPos(0, 0); | ||
| displayNextLCDString(lineOne); | ||
| if(lineTwo != ""){ | ||
| clearLCDLine(1); | ||
| displayLCDPos(1, 0); | ||
| displayNextLCDString(lineTwo); | ||
| } | ||
| } | ||
| bool otherButtonsPressed(MHLCDButton button){ | ||
| if(nLCDButtons == button){ | ||
| return false; | ||
| } | ||
| else{ | ||
| return true; | ||
| } | ||
| } | ||
| void waitForPress(){ | ||
| while(nLCDButtons == MHLCDButtonNone){/*We just have to wait a while*/} | ||
| waitForRelease(); | ||
| } | ||
| void waitForRelease(){ | ||
| while(nLCDButtons != MHLCDButtonNone){/*We just have to wait a while*/} | ||
| } | ||
| void waitForPressOfButton(MHLCDButton button){ | ||
| while(nLCDButtons != button){/*We just have to wait a while*/} | ||
| waitForRelease(); | ||
| } | ||
| void flashScreen(MHLCDScreen screen){ | ||
| displayScreen(screen); | ||
| wait1Msec(5000); | ||
| displayLastScreen(); | ||
| } | ||
| void flashScreenStyle(MHLCDScreenStyle screenStyle){ | ||
| MHLCDScreen newScreen; | ||
| screenForScreenStyle(screenStyle, &newScreen); | ||
| flashScreen(newScreen); | ||
| } | ||
| void displayScreenStyle(MHLCDScreenStyle style){ | ||
| MHLCDScreen screen; | ||
| screenForScreenStyle(style, &screen); | ||
| displayScreen(screen); | ||
| if(style == MHLCDScreenStyleVoltage){ | ||
| bLCDBacklight = false; | ||
| displayLCDVoltageString(1); | ||
| } | ||
| } | ||
| void countDownForTime(MHTime time){ | ||
| bool startState = bLCDBacklight; | ||
| bLCDBacklight = true; | ||
| for(int i = (int)(time/MHTimeOneSecond); i > 0; i++){ | ||
| string number; | ||
| sprintf(number, "%d", i); | ||
| displayLCDCenteredString(1, number); | ||
| wait1Msec(MHTimeOneSecond); | ||
| } | ||
| bLCDBacklight = startState; | ||
| } |
| @@ -0,0 +1,169 @@ | ||
| #pragma config(I2C_Usage, I2C1, i2cSensors) | ||
| #pragma config(Sensor, in1, otherBattery, sensorAnalog) | ||
| #pragma config(Sensor, in2, turningGyro, sensorGyro) | ||
| #pragma config(Sensor, in6, autonPotentiometer, sensorPotentiometer) | ||
| #pragma config(Sensor, in7, lLiftPotentiometer, sensorPotentiometer) | ||
| #pragma config(Sensor, in8, rLiftPotentiometer, sensorPotentiometer) | ||
| #pragma config(Sensor, dgtl1, cubeIntake, sensorDigitalOut) | ||
| #pragma config(Sensor, dgtl2, skyriseClaw, sensorDigitalOut) | ||
| #pragma config(Sensor, I2C_1, , sensorQuadEncoderOnI2CPort, , AutoAssign) | ||
| #pragma config(Sensor, I2C_2, , sensorQuadEncoderOnI2CPort, , AutoAssign) | ||
| #pragma config(Motor, port1, rbLift, tmotorVex393_HBridge, openLoop, reversed) | ||
| #pragma config(Motor, port2, lfDrive, tmotorVex393_MC29, openLoop) | ||
| #pragma config(Motor, port3, lbDrive, tmotorVex393_MC29, openLoop, encoderPort, None) | ||
| #pragma config(Motor, port4, ltLift, tmotorVex393_MC29, openLoop) | ||
| #pragma config(Motor, port5, lmLift, tmotorVex393_MC29, openLoop, encoderPort, I2C_2) | ||
| #pragma config(Motor, port6, lbLift, tmotorVex393_MC29, openLoop) | ||
| #pragma config(Motor, port7, rtLift, tmotorVex393_MC29, openLoop, reversed) | ||
| #pragma config(Motor, port8, rmLift, tmotorVex393_MC29, openLoop, reversed, encoderPort, I2C_1) | ||
| #pragma config(Motor, port9, rDrive, tmotorVex393_MC29, openLoop, reversed) | ||
| //*!!Code automatically generated by 'ROBOTC' configuration wizard !!*// | ||
|
|
||
| #pragma platform(VEX) | ||
| //Competition Control and Duration Settings | ||
| #pragma competitionControl(Competition) | ||
| #pragma autonomousDuration(15) | ||
| #pragma userControlDuration(105) | ||
| #include "Vex_Competition_Includes.h" | ||
| #include "enumerations.h" | ||
| #include "autonomous.h" | ||
| #ifndef LCD | ||
| //This file depends on lcd.h, but some other #includes might, too | ||
| #include "lcd.h" | ||
| #endif | ||
| MHAutonStyle roundAuton = MHAutonStyleNoAuton; | ||
| void pre_auton(){ | ||
| //displayScreenStyle(MHLCDScreenStyleVoltage); | ||
| //waitForPressOfButton(MHLCDButtonCenter); | ||
| ////Set up the style selection screen | ||
| //bLCDBacklight = true; | ||
| //displayLCDCenteredString(1, "Cube 1 Skyrise"); | ||
| //while(true){ | ||
| // if(nLCDButtons == MHLCDButtonLeft){ | ||
| // //Cube auton chosen | ||
| waitForRelease(); | ||
| roundAuton = MHAutonStyleCubeAuton; | ||
| //break; | ||
| // } | ||
| // else if(nLCDButtons == MHLCDButtonCenter){ | ||
| // //Time for programminng skills | ||
| // waitForRelease(); | ||
| //initAutonomousWithTeamColor(MHTeamColorRed); | ||
| //roundAuton = MHAutonStyleOnePoint; | ||
| //displayScreenStyle(MHLCDScreenStyleVoltage); | ||
| // break; | ||
| // } | ||
| // else if(nLCDButtons == MHLCDButtonRight){ | ||
| // //Skyrise auton chosen | ||
| // waitForRelease(); | ||
| // roundAuton = MHAutonStyleSkyriseAuton; | ||
| // break; | ||
| // } | ||
| //} | ||
| ////If it's not the one point, we continue | ||
| //if(roundAuton != MHAutonStyleOnePoint && roundAuton != MHAutonStyleCubeAuton){ | ||
| // displayLCDCenteredString(1, "Red Blue"); | ||
| // while(true){ | ||
| // if(nLCDButtons == MHLCDButtonLeft){ | ||
| // //We're on the red side | ||
| // waitForRelease(); | ||
| // initAutonomousWithTeamColor(MHTeamColorRed); | ||
| // break; | ||
| // } | ||
| // else if(nLCDButtons == MHLCDButtonRight){ | ||
| // //We're on the blue side | ||
| // waitForRelease(); | ||
| // initAutonomousWithTeamColor(MHTeamColorBlue); | ||
| // break; | ||
| // } | ||
| // } | ||
| //} | ||
| ////If it's the cube auton, we need to know which color we are | ||
| //if(roundAuton == MHAutonStyleCubeAuton){ | ||
| // displayLCDCenteredString(1, "Red Blue"); | ||
| // while(true){ | ||
| // if(nLCDButtons == MHLCDButtonRight){ | ||
| // waitForRelease(); | ||
| // initAutonomousWithTeamColor(MHTeamColorBlue); | ||
| // break; | ||
| // } | ||
| // else if(nLCDButtons == MHLCDButtonLeft){ | ||
| waitForRelease(); | ||
| initAutonomousWithTeamColor(MHTeamColorRed); | ||
| //break; | ||
| // } | ||
| // } | ||
| //} | ||
| ////Reconfigure the gyroscope | ||
| //displayLCDCenteredString(0, "Configuring Gyro"); | ||
| //displayLCDCenteredString(1, "Keep Robot Still"); | ||
| //SensorType[turningGyro] = sensorNone; | ||
| //wait1Msec(MHTimeOneSecond); | ||
| //SensorType[turningGyro] = sensorGyro; | ||
| //wait1Msec(MHTimeOneSecond * 2); | ||
| } | ||
| task autonomous(){ | ||
| displayScreenStyle(MHLCDScreenStyleVoltage); | ||
| bLCDBacklight = false; | ||
| float startBattery = nImmediateBatteryLevel; | ||
| float startOther = SensorValue[otherBattery]; | ||
| //Auton running here | ||
| runAutonomousStyleForTeamColor(roundColor, roundAuton); | ||
| if(startBattery != nImmediateBatteryLevel || startOther != SensorValue[otherBattery]){ | ||
| displayLCDVoltageString(1); | ||
| } | ||
| } | ||
| task usercontrol(){ | ||
| //Drive control | ||
| displayScreenStyle(MHLCDScreenStyleVoltage); | ||
| bLCDBacklight = false; | ||
| float startBattery = nImmediateBatteryLevel; | ||
| float startOther = SensorValue[otherBattery]; | ||
| //int frontDirection = 1; | ||
| while(true){ | ||
| if(startBattery != nImmediateBatteryLevel || startOther != SensorValue[otherBattery]){ | ||
| displayLCDVoltageString(1); | ||
| startBattery = nImmediateBatteryLevel; | ||
| startOther = SensorValue[otherBattery]; | ||
| } | ||
| string top; | ||
| sprintf(top, "%d", SensorValue[rLiftPotentiometer]); | ||
| displayLCDCenteredString(0, top); | ||
| if(abs(vexRT[Ch2]) <= 30){ | ||
| stopDriveSide(MHRobotSideRight); | ||
| } | ||
| else{ | ||
| motor[rDrive] = vexRT[Ch2] /* frontDirection*/; | ||
| } | ||
| if(abs(vexRT[Ch3]) <= 30){ | ||
| stopDriveSide(MHRobotSideLeft); | ||
| } | ||
| else{ | ||
| motor[lfDrive] = motor[lbDrive] = vexRT[Ch3] /* frontDirection*/; | ||
| } | ||
| //Lift control | ||
| if(vexRT[Btn6U]){ | ||
| lift(MHMotorPowerMax, MHLiftDirectionUp); | ||
| } | ||
| else if(vexRT[Btn6D]){ | ||
| lift(MHMotorPowerMax, MHLiftDirectionDown); | ||
| } | ||
| //If neither button is pressed, the lift must be stopped, or it will keep going | ||
| else{ | ||
| lift(MHMotorPowerStop, MHLiftDirectionStop); | ||
| } | ||
| //Skyrise Intake | ||
| if(vexRT[Btn8D]){ | ||
| SensorValue[skyriseClaw] = MHPneumaticPositionOpen; | ||
| } | ||
| else if(vexRT[Btn8R]){ | ||
| SensorValue[skyriseClaw] = MHPneumaticPositionClosed; | ||
| } | ||
| else if(vexRT[Btn7D]){ | ||
| SensorValue[cubeIntake] = MHPneumaticPositionOpen; | ||
| } | ||
| else if(vexRT[Btn7R]){ | ||
| SensorValue[cubeIntake] = MHPneumaticPositionClosed; | ||
| } | ||
| } | ||
| } |
| @@ -0,0 +1,326 @@ | ||
| //Includes | ||
| #include "enumerations.h" | ||
| #include "autonomous.h" | ||
| #include "lcd.h" | ||
| //Global Variables | ||
| MHAutonMode selection = MHAutonModeNoneSelected; | ||
| MHTeamColor color = MHTeamColorNone; | ||
| //LCD Selection | ||
| void pre_auton(){ | ||
| string current = "main"; | ||
| screenForScreenStyle(MHLCDScreenStyleMain, &liveScreen); | ||
| displayScreen(liveScreen); | ||
| //Everything needs to be stuffed in a loop, just to allow graceful back functionality without causing a stackoverflow | ||
| while(selection == MHAutonModeNoneSelected){ | ||
| //I'm not sure if the break and continue procs will apply to a nested switch statement, so until I find out, I'm using ifs | ||
| if(current == "main"){ | ||
| waitForPress(); | ||
| if(nLCDButtons == MHLCDButtonLeft){ | ||
| //Display the Point Selection screen, keep track of the color (red), restart the loop | ||
| waitForRelease(); | ||
| color = MHTeamColorRed; | ||
| screenForScreenStyle(MHLCDScreenStylePointSelection, &nextScreen); | ||
| displayNextScreen(); | ||
| current = "point"; | ||
| continue; | ||
| } | ||
| else if(nLCDButtons == MHLCDButtonCenter){ | ||
| //End the loop, specify no auton, go to voltage screen | ||
| waitForRelease(); | ||
| color = MHTeamColorAny; | ||
| selection = MHAutonModeNoAuton; | ||
| screenForScreenStyle(MHLCDScreenStyleVoltage, &nextScreen); | ||
| displayNextScreen(); | ||
| current = "volt"; | ||
| break; | ||
| } | ||
| else if(nLCDButtons == MHLCDButtonRight){ | ||
| //Display the Point Selection screen, keep track of the color (blue), restart the loop | ||
| waitForRelease(); | ||
| color = MHTeamColorBlue; | ||
| screenForScreenStyle(MHLCDScreenStylePointSelection, &nextScreen); | ||
| displayNextScreen(); | ||
| current = "point"; | ||
| continue; | ||
| } | ||
| /*else if(nLCDButtons == MHLCDButtonAll){ | ||
| //Display the voltage screen for 5 seconds, reinstate the main screen, restart the loop | ||
| waitForRelease(); | ||
| flashScreenStyle(MHLCDScreenStyleVoltage); | ||
| continue; | ||
| }*/ | ||
| else{ | ||
| waitForRelease(); | ||
| print("Invalid", "selection"); | ||
| wait1Msec(MHTimeOneSecond * 2); | ||
| displayScreen(liveScreen); | ||
| } | ||
| } | ||
| else if(current == "point"){ | ||
| waitForPress(); | ||
| if(nLCDButtons == MHLCDButtonLeft){ | ||
| //Set the proper 3 point auton, display voltage screen, end the loop | ||
| waitForRelease(); | ||
| if(color == MHTeamColorBlue){ | ||
| selection = MHAutonModeBlue3; | ||
| screenForScreenStyle(MHLCDScreenStyleVoltage, &nextScreen); | ||
| displayNextScreen(); | ||
| current = "volt"; | ||
| break; | ||
| } | ||
| else if(color == MHTeamColorRed){ | ||
| selection = MHAutonModeRed3; | ||
| screenForScreenStyle(MHLCDScreenStyleVoltage, &nextScreen); | ||
| displayNextScreen(); | ||
| current = "volt"; | ||
| break; | ||
| } | ||
| } | ||
| else if(nLCDButtons == MHLCDButtonCenter){ | ||
| //Clear the team color selection, go back to the main screen, restart the loop | ||
| waitForRelease(); | ||
| color = MHTeamColorNone; | ||
| displayLastScreen(); | ||
| current = "main"; | ||
| continue; | ||
| } | ||
| else if(nLCDButtons == MHLCDButtonRight){ | ||
| //Set the proper 5 point auton, display the voltage screen, end the loop | ||
| waitForRelease(); | ||
| if(color == MHTeamColorBlue){ | ||
| selection = MHAutonModeBlue5; | ||
| screenForScreenStyle(MHLCDScreenStyleVoltage, &nextScreen); | ||
| displayNextScreen(); | ||
| current = "volt"; | ||
| break; | ||
| } | ||
| else if(color == MHTeamColorRed){ | ||
| selection = MHAutonModeRed5; | ||
| screenForScreenStyle(MHLCDScreenStyleVoltage, &nextScreen); | ||
| displayNextScreen(); | ||
| current = "volt"; | ||
| } | ||
| } | ||
| /*else if(nLCDButtons == MHLCDButtonAll){ | ||
| //Display the voltage screen for 5 seconds, reinstate the Point Selection screen, restart the loop | ||
| waitForRelease(); | ||
| flashScreenStyle(MHLCDScreenStyleVoltage); | ||
| continue; | ||
| }*/ | ||
| else{ | ||
| waitForRelease(); | ||
| print("Invalid", "Point"); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| //Autonomous | ||
|
|
||
| task autonomous(){ | ||
| displayScreenStyle(MHLCDScreenStyleVoltage); | ||
| switch(selection){ | ||
| case MHAutonModeNoAuton: | ||
| //Since there's no autonomous, we can wait for the usercontrol; | ||
| return; | ||
| case MHAutonModeRed3: | ||
| //Here's the tried and true red 3 pointer | ||
| SensorValue[blockPneumatics] = false; | ||
| lift(-127); | ||
| wait1Msec(2500); | ||
| lift(0); | ||
| basicDrive(0, 127); | ||
| wait1Msec(850); | ||
| stopDrive(); | ||
| SensorValue[blockPneumatics] = true; | ||
| lift(-127); | ||
| wait1Msec(500); | ||
| lift(0); | ||
| basicDrive(-70, -70); | ||
| wait1Msec(1000); | ||
| stopDrive(); | ||
| //Auton over | ||
| return; | ||
| case MHAutonModeBlue3: | ||
| //Here's the battle-tested blue 3 pointer | ||
| SensorValue[blockPneumatics] = false; | ||
| lift(-127); | ||
| wait1Msec(2500); | ||
| lift(0); | ||
| basicDrive(127, 0); | ||
| wait1Msec(850); | ||
| stopDrive(); | ||
| SensorValue[blockPneumatics] = true; | ||
| lift(-127); | ||
| wait1Msec(500); | ||
| lift(0); | ||
| basicDrive(-70, -70); | ||
| wait1Msec(1000); | ||
| stopDrive(); | ||
| //Auton over | ||
| return; | ||
| case MHAutonModeBlue5: | ||
| //The 5 point blue auton | ||
| print("Blue 5 Point", "In Development"); | ||
| SensorValue[blockPneumatics] = false; | ||
| lift(-127); | ||
| wait1Msec(MHTimeHalfSecond); | ||
| basicDrive(MHMotorPowerMax, MHMotorPowerMax); | ||
| wait1Msec(MHTimeOneSecond); | ||
| stopDrive(); | ||
| lift(MHMotorPowerStop); | ||
| wait1Msec(MHTimeOneMillisecond * 5); | ||
| lift(MHMotorPowerMax); | ||
| wait1Msec(MHTimeOneSecond + MHTimeTenthSecond * 1.5); | ||
| lift(MHMotorPowerStop); | ||
| wait1Msec(MHTimeOneMillisecond * 5); | ||
| lift(-127); | ||
| wait1Msec(MHTimeOneSecond * 5 + MHTimeHalfSecond); | ||
| lift(MHMotorPowerStop); | ||
| basicDrive(MHMotorPowerHalf, MHMotorPowerHalf); | ||
| wait1Msec(MHTimeHalfSecond); | ||
| stopDrive(); | ||
| wait1Msec(MHTimeOneMillisecond * 5); | ||
| basicDrive(-MHMotorPowerHalf, MHMotorPowerHalf); | ||
| wait1Msec(MHTimeOneSecond - MHTimeTenthSecond); | ||
| stopDrive(); | ||
| wait1Msec(MHTimeOneMillisecond * 5); | ||
| basicDrive(MHMotorPowerMax, MHMotorPowerMax); | ||
| wait1Msec(MHTimeTenthSecond * 3); | ||
| stopDrive(); | ||
| lift(MHMotorPowerMax); | ||
| wait1Msec(MHTimeQuarterSecond); | ||
| lift(MHMotorPowerStop); | ||
| wait1Msec(MHTimeOneSecond); | ||
| SensorValue[blockPneumatics] = true; | ||
| wait1Msec(MHTimeHalfSecond); | ||
| lift(-MHMotorPowerMax); | ||
| wait1Msec(MHTimeQuarterSecond); | ||
| lift(MHMotorPowerStop); | ||
| basicDrive(-MHMotorPowerMax, -MHMotorPowerMax); | ||
| lift(MHMotorPowerMax); | ||
| wait1Msec(MHTimeHalfSecond); | ||
| stopDrive(); | ||
| SensorValue[blockPneumatics] = false; | ||
| wait1Msec(MHTimeOneSecond * 3.5); | ||
| lift(MHMotorPowerStop); | ||
| //Auton over | ||
| return; | ||
| case MHAutonModeRed5: | ||
| //The 5 point red auton | ||
| print("Red 5 Point", "In Development"); | ||
| SensorValue[blockPneumatics] = false; | ||
| lift(-127); | ||
| wait1Msec(MHTimeHalfSecond); | ||
| basicDrive(MHMotorPowerMax, MHMotorPowerMax); | ||
| wait1Msec(MHTimeOneSecond); | ||
| stopDrive(); | ||
| lift(MHMotorPowerStop); | ||
| wait1Msec(MHTimeOneMillisecond * 5); | ||
| lift(MHMotorPowerMax); | ||
| wait1Msec(MHTimeOneSecond + MHTimeTenthSecond * 1.5); | ||
| lift(MHMotorPowerStop); | ||
| wait1Msec(MHTimeOneMillisecond * 5); | ||
| lift(-127); | ||
| wait1Msec(MHTimeOneSecond * 5 + MHTimeHalfSecond); | ||
| lift(MHMotorPowerStop); | ||
| basicDrive(MHMotorPowerHalf, MHMotorPowerHalf); | ||
| wait1Msec(MHTimeHalfSecond); | ||
| stopDrive(); | ||
| wait1Msec(MHTimeOneMillisecond * 5); | ||
| basicDrive(MHMotorPowerHalf, -MHMotorPowerHalf); | ||
| wait1Msec(MHTimeOneSecond - MHTimeTenthSecond); | ||
| stopDrive(); | ||
| wait1Msec(MHTimeOneMillisecond * 5); | ||
| basicDrive(MHMotorPowerMax, MHMotorPowerMax); | ||
| wait1Msec(MHTimeTenthSecond * 3); | ||
| stopDrive(); | ||
| lift(MHMotorPowerMax); | ||
| wait1Msec(MHTimeQuarterSecond); | ||
| lift(MHMotorPowerStop); | ||
| wait1Msec(MHTimeOneSecond); | ||
| SensorValue[blockPneumatics] = true; | ||
| wait1Msec(MHTimeHalfSecond); | ||
| lift(-MHMotorPowerMax); | ||
| wait1Msec(MHTimeQuarterSecond); | ||
| lift(MHMotorPowerStop); | ||
| basicDrive(-MHMotorPowerMax, -MHMotorPowerMax); | ||
| lift(MHMotorPowerMax); | ||
| wait1Msec(MHTimeHalfSecond); | ||
| stopDrive(); | ||
| SensorValue[blockPneumatics] = false; | ||
| wait1Msec(MHTimeOneSecond * 3.5); | ||
| lift(MHMotorPowerStop); | ||
| //Auton over | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| //User Control | ||
|
|
||
| task usercontrol(){ | ||
| // User control code here, inside the loop | ||
| if(liveScreen.style != MHLCDScreenStyleVoltage){ | ||
| displayScreenStyle(MHLCDScreenStyleVoltage); | ||
| } | ||
| int origBattery = nImmediateBatteryLevel; | ||
| int origBackBattery = SensorValue[otherBattery]; | ||
| bool leftDriveShouldStop; | ||
| bool rightDriveShouldStop; | ||
| while(true){ | ||
| if(nImmediateBatteryLevel != origBattery || SensorValue[otherBattery] != origBackBattery){ | ||
| //displayLCDVoltageString(1); | ||
| } | ||
| //Bogdan Drive | ||
| if(abs(vexRT[Ch3]) <= 30){ | ||
| leftDriveShouldStop = true; | ||
| } | ||
| else{ | ||
| leftDriveShouldStop = false; | ||
| } | ||
| if(abs(vexRT[Ch2]) <= 30){ | ||
| rightDriveShouldStop = true; | ||
| } | ||
| else{ | ||
| rightDriveShouldStop = false; | ||
| } | ||
| if(leftDriveShouldStop){ | ||
| motor[lfDrive] = motor[lbDrive] = 0; | ||
| } | ||
| else{ | ||
| motor[lfDrive] = motor[lbDrive] = vexRT[Ch3]; | ||
| } | ||
| if(rightDriveShouldStop){ | ||
| motor[rfDrive] = motor[rbDrive] = 0; | ||
| } | ||
| else{ | ||
| motor[rfDrive] = motor[rbDrive] = vexRT[Ch2]; | ||
| } | ||
| //Lift | ||
| if(vexRT[Btn6D]){//using the lift function, this says run at full speed when 6U is pressed | ||
| lift(127); | ||
| } | ||
| else if (vexRT[Btn6U]){//Reverse direction | ||
| lift(-127); | ||
| } | ||
| else{//If neither button is pressed it won't move, it must be set to zero or it'll keep going after being pressed | ||
| lift(0); | ||
| } | ||
| //Pneumatics | ||
| if(vexRT[Btn5U]){ | ||
| SensorValue[blockPneumatics] = true; | ||
| } | ||
| if(vexRT[Btn5D]){ | ||
| SensorValue[blockPneumatics] = false; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| //Miscellaneous Functions | ||
|
|
||
| void lift(int power){ | ||
| motor[lfLift] = motor[lbLift] = motor[rfLift] = motor[rbLift] = power; | ||
| } | ||
| void stopDrive(){ | ||
| motor[rfDrive] = motor[rmDrive] = motor[rbDrive] = motor[lfDrive] = motor[lmDrive] = motor[lbDrive] = MHMotorPowerStop; | ||
| } |
| @@ -0,0 +1,54 @@ | ||
|
|
||
| void stash() | ||
| { | ||
|
|
||
| rollers (127,700); | ||
| wait1Msec(1000); | ||
|
|
||
| SensorValue[rDrive]=0; | ||
| SensorValue[lDrive]=0; | ||
|
|
||
| //liftTime(127,2000); | ||
|
|
||
| liftDown(1000,127); //lift | ||
| lift(30); | ||
|
|
||
| bar(1); //fling | ||
|
|
||
| driving(700,127,127); //1st ball | ||
| rollers(-127,700); | ||
| wait1Msec(500); | ||
| driving(750,-127,-127); | ||
|
|
||
| wait1Msec(2000); | ||
|
|
||
| driving(600,127,127); | ||
| bar(0); //pull in | ||
| driving(300,127,127); | ||
| driving(900,-127,-127); | ||
|
|
||
| liftDown(-127,0); | ||
|
|
||
| wait1Msec(2000); | ||
|
|
||
| driving(700,127,127); | ||
| driving(700,-127,-127); | ||
|
|
||
| wait1Msec(8000); | ||
| /* | ||
| drivingRolling(200,127,127,127); | ||
| driving(300,127,127); | ||
| lifting(127,48); | ||
| driving(100,127,127); | ||
| rollers(127,1000); | ||
| driving(600,-127,-127); | ||
| wait1Msec(1500); | ||
| */ | ||
|
|
||
|
|
||
| } |
| @@ -0,0 +1,58 @@ | ||
| <!DOCTYPE html> | ||
| <html lang="en_US"> | ||
| <head> | ||
| <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/> | ||
| <meta charset="utf-8"/> | ||
| <title translate="no">Frightening Lightning</title> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1"/> | ||
| <meta name="description" content="The centerpiece of the Cherry Hill High School East Robotics Team, 2616F "Frightening Lightning" is an award-winning VEX team based in Cherry Hill, NJ"/> | ||
| <meta name="author" content="Michael Hulet"/> | ||
| <meta name="application-name" content="2616F"/> | ||
| <link rel="author" href="mailto:bestraysfan@me.com"/> | ||
| <!--The next line will specify the default stylesheet of your site--> | ||
| <meta http-equiv="default-style" content="global stylesheet"/> | ||
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/3.0.3/normalize.css" type="text/css"/> | ||
| <!--The next line links to your stylesheet. Be sure to change the href to the location of your CSS file--> | ||
| <link rel="stylesheet" href="css/style.css" type="text/css" title="global stylesheet"/> | ||
| <!--This links to a favicon (the little image in the address bar) of the page. Be sure to change the href the the location of your favicon on your server, or remove the line and this comment altogether--> | ||
| <link rel="icon" href="img/favicon.ico" type="image/x-icon" sizes=""/> | ||
| <!--This is an example of a prefetch. These will be silently cached by the browser, in case the user visits them next. You may want to add multiple tags of this, or remove the line and this comment altogether, but don't forget to change the href to what's next (or whatever you want cached)--> | ||
| <link rel="prefetch" href="nextPage.html"/>> | ||
| <!--This style tag corresponds with the meta name="viewport" tag near the top, but because Internet Explorer is both retarded and relatively widely used (*cries*), you need to include this in your CSS. This also includes some common CSS for prettifying navigation on webpages. You really should copy and paste this at the top of your linked CSS file, then remove the tag and this comment, but I'm including it here so I don't have to make a whole other file, and it's in here, just in case.--> | ||
| <style> | ||
| @-ms-viewport{ | ||
| width: device-width; | ||
| } | ||
| #navigation{ | ||
| list-style: none; | ||
| } | ||
| #navigation li{ | ||
| display: inline; | ||
| } | ||
| </style> | ||
| <!--The following line is to include jQuery. If you're developing locally, be sure to add https: before the //--> | ||
| <script src="//code.jquery.com/jquery-1.11.0.min.js"></script> | ||
| <!--Be sure to change the src of the next line to the location of any JavaScript you might have. If you have none, it's safe to remove the next line, and jQuery above this one--> | ||
| <script src="js/script.js"></script> | ||
| </head> | ||
| <body> | ||
| <header> | ||
| <!--Personally, I usually include my navigation in the header of the page, but you can move it wherever you want, but it should keep this structure--> | ||
| <nav> | ||
| <!--I id'd this navigation, just to be clear, but you can change that to whatever you want, or remove it entirely, though that is not recommended, for CSS purposes--> | ||
| <ul id="navigation"> | ||
| <li></li> | ||
| <li></li> | ||
| <li></li> | ||
| </ul> | ||
| </nav> | ||
| </header> | ||
| <!--I id'd this content to make it clear that it's supposed to be the general wrapper that includes everything that's not in the header or the footer (the content of the page), but you can change it to whatever you want, or remove it entirely--> | ||
| <section id="content"> | ||
| <div id="wrapper"> | ||
| </div> | ||
| </section> | ||
| <footer> | ||
| </footer> | ||
| </body> | ||
| </html> |