630 likes | 646 Views
Learn about topics in robotics programming and electronics in the 2006 FIRST Robotics Competition. Discover diagnostic screens, infrared distance sensors, EEPROM writing, odometry, and more.
E N D
Topics in Robotics Programming and Electronics 2006 FIRST Robotics Competition Dan Katanski, Team 240 Steve Martin, Team 470
This PowerPoint Available • On web site or Chief Delphi • Look under White Papers • Team 240’s web site scnc.jefferson.k12.mi.us/jhs/web240 Look for Kick-off link on Monday
Dan Katanski • 5th season Coach FIRST LEGO League • 3rd season Software mentor FRC Team 240 • 3 years Lead Inspector Great Lakes Regional • 2 years Lead Inspector National Championship, Atlanta, Georgia • Authored White Papers: • “Interrupts for Dummies” • “Quadrature Encoders” • “Measuring distance with Analog Pots” • 14th year working on Thanksgiving Parade • Email addresses: • dan@provide.net or katanskid@dteenergy.com
Steve Martin • 3rd season Software mentor FRC Team 470 • Eclectic background in software & electronics • Hobbyist since Age 6, • Lab Tech – SAI International at Age 16, • Industrial Controls Design / Repair: • DAVCO Inc., • SOMOS gmbh, • K&S Industrial • On Board Computer system – AMICK A4 Solar Vehicle • Media Systems Engineer – EMU Communication/Theatre Arts • Email: smartin@emich.edu
Agenda • Diagnostic Screens • Thoughts for New Programmers • Infrared Distance Sensor • Using the EEPROM - Writing to Non-volatile Memory • Odometry & Controlled Movement • Tachometers • Quadrature Encoders • Analog Potentiometers • State Machines • Autonomous Strategies • I/O Expansion
Grand Challenge • Scientific American, January 2006, pg 63 • “Innovations from a Robot Rally”
Diagnostic Screens • Best thing for robot diagnostics and maintenance • Secret: • Clear Screen ANSI escape sequence printf ("\033[2J"); // ANSI escape sequence for CLEAR. • Home ANSI escape sequence printf ("\033[0;0H"); // ANSI escape sequence for HOME. • HyperTerminal Emulator Start -> Programs -> Accessories -> Communications -> HyperTerminal (Not the IFI Loader terminal emulator)
Diagnostic Screens • Multiple diagnostic screens: • Robot • Operator Interface • Configuration Panel • Select which screen with a jumper or switch on digital inputs • Not to be used in competition • printf commands and serial communications slow down the message loop
Diagnostic Screens • Looks at every sensor, switch, pot, etc… • Intelligently display information • Convert APUs to inches traveled • Display values in more easily understood ways that are more readily understood by the team • EEPROM Dump • What’s in your EEPROM? • How does your program sees what is in the EEPROM
Thoughts for New Programmers • English best programming language… • Everything else just implements English • If you can’t describe it in English then you can’t program it! • Documentation, documentation, documentation • Three rules of programming • Describe what your code is making the robot do and why • Only you really understand why at the time of writing • Document to teach your teammates about your code • Not documenting code is stealing knowledge from your team
Thoughts for New Programmers • No magic numbers • E.g., Distance = Power * 1.87456 • What is 1.87456? • Show formula, give units, derivation, why and when it is used • Use English • Use macros // Arm up rocker switch. #define OI_ARM_UP p4_sw_aux1 #define OI_ARM_UP_ON OFF #define OI_ARM_UP_OFF ON // Handle an Arm Up switch press… If (IO_ARM_UP == IO_ARM_UP_ON) { // Easier to read! // Digital ports, 0=ON, 1 = OFF.
Thoughts for New Programmers • Variable scoping #include <stdio.h> int state = 1; // Global - seen by entire program. void foo (void) { #include <stdio.h> static int state = 1; // Local only within this file. void foo (void) { #include <stdio.h> void foo (void) { int state = 1; // Local function while executing. // Equals 1 every time functions is called. #include <stdio.h> void foo (void) { static int state = 1; // Local function value preserved.
Thoughts for New Programmers • Restrict variable scope • Use property functions instead of global variables • D = GetDistanceTraveled ( );
Infrared Distance Sensor • Good for 4” to 40” • Cheap About $10 • Analog port input • Simple wiring • Digi Key Part # GP2Y0D21YK
Infrared Distance Sensor • #define DISTANCE_POINTS 32 • // Distance values from sensor. • rom unsigned int DistArray [DISTANCE_POINTS] = { • 58, 63, 71, 78, 80, 82, 87, 91, 92, 96, 102, 107, 110, 114, 122, • 128, 134, 142, 150, 161, 169, 183, 198, 214, 234, 259, 287, 327, 377, 449, • 550, 575}; • // Distances in inches. • rom unsigned int DistInches [DISTANCE_POINTS] = { • 44, 39, 35, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, • 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, • 4, 3};
// Function: GetDist // Find the closes distance in inches from the analog input value using a binary search. int GetDist (void) { long l; int low, high, mid, old_mid; // For binary search. unsigned int d; // Value from analog port. low = 0; // Set initial values for the binary search. high = DISTANCE_POINTS; // The actual number of points. mid = 0; old_mid = -1; // These must be different/ d = Get_Analog_Value (DISTANCE_SENSOR); // Get sensor value of 0 to 1023. while ((high != low) && (mid != old_mid)) { // Binary search until found. //printf for debugging here… old_mid = mid; mid = (high + low) / 2; // Find the middle record. if (d >= DistArray [mid]) // Set new mid point low = mid; else if (d < DistArray [mid]) high = mid; } // while return (DistInches [mid]); // Return value. } // GetDist
Debugging Binary Search printf("DistArray [mid]:%u mid: %d low %d high %d\n\r", DistArray [mid], mid, low, high); printf("Comparing d: %6d DistArray: %6d", d, DistArray [mid]); Put this code inside the while loop to watch the search as it is occurring.
Interpolation • For finer resolution than whole inches • Sensor values are not real continuous • i.e., values jump a lot • This is an estimate • Use on sophisticated tools • Not just for autonomous mode
Using the EEPROM • Electronically Erasable Programmable Read Only Memory • Why? • Not lost by controller resets, program downloads, or power losses • Save autonomous instructions / strategy • Save self-calibration data
Using the EEPROM • See Kevin Watson’s web site • www.kevin.org/frc • Find “frc_eeprom.zip” • Look in files • eeprom_readme.txt • eeprom.c • eeprom.h • user_routines.c
Using the EEPROM • 1024 (1K) Bytes available • You must create a way to instruct your software to write to the EEPROM… • This may be a completely separate program, or • Be part of the main code • Checksums or other error checking? • Example • If autonomous strategy configuration panel is present then read panel and write setting to the EEPROM
Special Considerations • EEPROM is SLOW! • 4ms/Byte to Write • Trying to write too many locations at a time can cause Red LED of Death. • ALL Interrupts must be disabled during a write operation! VERY risky in competition! • Limited Life • EEPROM can only reliably survive 100,000 write cycles (fine print in spec sheet)
Using the EEPROM • How much can you write to the EEPROM? • 1024 locations available • Recommendation is to not try to write more than 1 location per 27ms loop. DO NOT try to call the Write routine within user_routines_fast.c! • If using Kevin’s code, DO NOT submit more than 16 bytes at a time for writing.
Using the EEPROM • Call EEPROM_Read() to read one byte at the specific address unsigned char EEPROM_Read (unsigned int address) • Call EEPROM_Write to write one byte at the specific address writing about one byte per 26.2 ms message loop unsigned char EEPROM_Write (unsigned int address, unsigned char data) • Call EERPROM_Write_Handler writes one byte from the queue – call multiple times to write more than one byte/27ms loop. void EEPROM_Write_Handler(void) • Call EEPROM_Queue_Free_Space to determine if you can submit another value for writing. Check BEFORE calling EEPROM_Write. unsigned char EEPROM_Queue_Free_Space(void)
Simple EEPROM Dump • Required Variable Definitions: unsigned int address = 0; /* EEPROM Read Address */ unsigned char eeprom_data = 0; /* Data from Read */ unsigned char Column = 0; /* Column Position Counter */ unsigned char high_addr = 0; /* Upper limit of Dump */
Simple EEPROM Dump high_addr= 24; /* pointer to highest address of dump*/ address = 0; /* start dump from eeprom address 0 */ while (address < high_addr) /* begin loop to display dump */ { while (column < 6) /* display in groups of 6 locations */ { eeprom_data = EEPROM_Read(address); /* read data from eeprom */ address = address + 1; /* increment eeprom read address */ column = column + 1; /* increment column position counter */ if (address > high_addr) /* if we've reach the highest adress */ column = 6; /* end the row. */ printf("%3d,",(int)eeprom_data); /* print the data */ } printf ("\33\133\102\n"); /* cursor down - because palm telnet won't do line feed */ column = 0; /* we're starting another row, reset column position counter */ } }
Using the EEPROM • Read everything carefully! • Can cause controller to get the “Red-light-of-death” • May have to reload the operating system into the controller • Not supported by FIRST or IFI • Use at you own risk!!!
Odometry & Controlled Movement • Sensors: Tachometers (pulse Counting) Quadrature Encoders Analog Potentiometers (Pots)
Benefits: Can be implemented with limited resources - sensors included in last year’s kit Can Sense Speed and Distance Can use Kevin’s Encoder code w/modifications Drawbacks: Cannot sense Direction Use of Interrupts can be problematic. Mechanical Noise can be a problem Tachometers (pulse counting)
Benefits: Can be used to sense Speed, Distance, and Direction. Code is available from Kevin’s site Drawbacks: Can be expensive Can be cheaply built but at the expense of time! Uses more I/O Lines Use of Interrupts can be problematic Mechanical Noise Issues Quadrature Encoders
Tachometers and Encoders Tachometers are equivalent to a Quadrature Encoder without using the 2nd channel for direction.
Encoder Interrupt Handler void Left_Encoder_Int_Handler(void) { // The left encoder's phase-A signal (Digital I/O 1) just transitioned // from zero to one, causing this interrupt service // routine to be called, so now check the logical state of the // phase-B signal (Digital I/O 6) and increment or decrement // the Left_Encoder_Count variable. if (LEFT_ENCODER_PHASE_B_PIN == 0) { Left_Encoder_Count -= LEFT_ENCODER_TICK_DELTA; Left_Speed_Count -= LEFT_ENCODER_TICK_DELTA; } else { Left_Encoder_Count += LEFT_ENCODER_TICK_DELTA; Left_Speed_Count += LEFT_ENCODER_TICK_DELTA; } }
Modified for Tachometer void Left_Encoder_Int_Handler(void) { // The left encoder's phase-A signal just transitioned // from zero to one, causing this interrupt service // routine to be called, so increment the Left_Encoder_Count variable. Left_Encoder_Count += LEFT_ENCODER_TICK_DELTA; Left_Speed_Count += LEFT_ENCODER_TICK_DELTA; } Ignore digital I/O six – use it for something else. Encoder code now only gives positive counts and speed. Keep track of direction another way: Look at PWM value to Victor Use an accelerometer
Interrupt Code Response Interrupt code is Positive Edge triggered Count happens here:
Mechanical Jitter Issues Gear vibration, lose mechanical couplings can cause waveforms to look like this:
Dealing with Jitter • Filter removes multiple edges
Benefits: Relatively Inexpensive Can be used for Distance and Direction Low software overhead – Not dependent on interrupts Can Sense Speed and Distance Drawbacks: Sample Rate issues can limit max useable Speed Small “Dead” zone, though usually not a big problem Analog Potentiometers for Distance
Distance with Analog Potentiometers • Cheap and Easy • No Interrupts! • Accurate (0.3” on 2005 robot) • See White Paper on Chief Delphi Measuring Distance with Analog Potentiometers
Distance with Analog Potentiometers • Vishay Spectrol Potentiometer can be purchased from Allied Electronics catalog • Allied part number 970-0063 • Continuous 360 degree turning • Small dead band, 20 degrees • Very liner output, +/- 2% • Mechanical life, 10,000,000 cycles • Inexpensive, price about $13.00 each
Distance with Analog Potentiometers Connect with surgical tubing to reduce side loading on pot
Distance with Analog Potentiometers • The secret is in the software! • Sample the pot ever 26.2 ms • MUST sample before pot turns 180 degrees! • Can give direction and distance • Limits speed depending on design • Just count the number of times that the pot has passed zero • Speed is the distance traveled between samples divided by time
Distance with Analog Potentiometers • Pot revolution counting code every 26.2 ms #define REVERSE_DIRECTION 512L d = Get_Analog_Value (DRIVE_WHEEL_POT); // Get analog value ever 26.2 ms m = d - WheelPrevious; // Compute the difference in analog port values. m = (m >= 0) ? m : -m; // Take the absolute value. // Assumption movement is always less than REVERSE_DIRECTION, 512 if (d > WheelPrevious) { // Is the new value bigger, Yes. if (m > REVERSE_DIRECTION) // Is it so big that it looks like a direction reverse? --WheelCount; // Yes, passed "Go", so count a revolution. } else if (d < WheelPrevious) { // The new value is smaller. if (m > REVERSE_DIRECTION) // Is it so smaller it looks like a direction reverse? ++WheelCount; // Yes, passed "Go". } // Do nothing if the distance is the same. WheelLeftPrevious = d; // Save the last point for comparison.
Distance with Analog Potentiometers • Magic formula; d = (1024 - Initial) + ((WheelCount - 1) * 1024) + Current; // APUs traveled Distance = d * DISTANCE_PER_REVOLUTION // 1024 is the number of values returned by the 10-bit analog port; // values are from 0 to 1023 (Magic Number description)
State Machines • Programming technique • Divides program into steps or states • State driven or Event driven • Can be “reentrant” • Perform one state change per execution • Can “preserves state” • static int state; • Allows multiple tasks to be performed • State Diagrams or Directed Graphs • Type of storyboard to plan strategy
State Machines • Simple State Machine while (TRUE) { switch (state) { case 1: state = 2; break; case 2: state = 1; break; default: // This should never happen } // switch state } // while
In Autonomous Mode • Use State Machines in Autonomous Mode • Nested state machines – great technique • Three levels of sate machines used last year: • user_routines_fast selects which autonomous strategy to be performed • Autonomous_ScoreHanging moves the robot and arm to perform strategy • Move performs a robot move
Moving • Use state machine and functions • void Move_Start (long distance, unsigned char maxpower, unsigned long ramp) • int Move (void) • void Move_Stop (void) • Move has three states: • Ramp • Travel • Brake
Using Move // STEP 1: Move across the field into the opponents territory. case 1: // Drive 30 feet or 360 inches into the opponents area. Move_Start (3600, 60, 50); // (distance, maxpower, ramp); // (10ths-of-inches, power, 100ths-sec); next_state = 2; break; // Wait for the move to complete. case 2: if (Move () != COMPLETE) next_state = 2; // Move not finished. else next_state = 3; // Move is finished – On with the show... break;