Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
A Ballistic Chronograph Brandon Atkinson Steven Turner May 4, 2001 University of Maine ECE 403 Final Report Abstract The goal of the “Ballistic Chronograph” project was to create a device having the ability to measure the speed of a paintball (or any similarly shaped projectile) and display this information to a display for a human to read. The design approach consisted of research, including Internet browsing, reading and consultation with advisors. The first decision made in the design was selecting the proper microprocessor. This decision was based on the minimum number of clock cycles needed for the project’s accuracy specification, coupled with the need for a certain number of input and output pins, along with the desire for a relatively simple and inexpensive design. The second stage of design was brainstorming a measurement system. The problems in this stage were numerous. How do you detect the presence of a paintball without impeding its motion? What type of sensor will work most consistently without failure? These are just a few of the questions that were asked. The third stage of design involved choosing and assembling the display and physical prototype, followed by testing and verification. This stage went rather well, bringing only a couple of problems to light. The testing consisted of velocity measurement verification with an oscilloscope and real paintball projectiles. It is interesting to note that the accuracy of this project’s velocity readings is comparable to the accuracy of some commercial products, although the speeds paintballs travel at are considerably less than the speeds of bullets. 2 Table of Contents Abstract ............................................................................................... page 2 Table of Contents................................................................................ page 3 List of Figures ..................................................................................... page 4 Introduction......................................................................................... page 5 Breakdown .......................................................................................... page 7 Details ................................................................................................. page 8 Results and Conclusions ................................................................... page 20 Directions For Use ............................................................................ page 22 Appendix........................................................................................... page 23 3 List of Figures Schematics Schematic 1 – Infrared Emitter Schematic ....................................... page 24 Schematic 2 – Infrared Detector Schematic...................................... page 25 Schematic 3 – Power Supply Schematic........................................... page 26 Schematic 4 – Wired OR Schematic................................................. page 27 Schematic 5 – Full Circuit Schematic............................................... page 28 Flowcharts Flowchart 1 - Project Overview.......................................................... page 7 Flowchart 2 – Main Code ................................................................. page 29 Flowchart 3 – LCD_INIT Routine.................................................... page 30 Flowchart 4 – CALC_RES Routine.................................................. page 31 Flowchart 5 – RES_OUT Routine .................................................... page 32 Flowchart 6 – Sq_Res Routine ......................................................... page 33 Flowchart 7 – Acc Routine ............................................................... page 34 Flowchart 8 – ACC_OUT Routine ................................................... page 35 Flowchart 9 – Interrupt Service Routine........................................... page 36 Tables Table 1 – Approximate Current Total............................................... page 54 4 Introduction The ballistic chronograph measures and displays the velocity of a projectile passing through it. The device interprets triggers of the internal sensors caused by the passing projectile as time-stamped events. After all the sensors are triggered the processor does some math with the time-stamps and displays the velocity measurement. Chronographs are used to ‘calibrate’ firearms to a certain range of muzzle velocities (at least with paintball guns). Paintball is usually played with muzzle velocities in the high 100’s to low 200’s feet-per-second (fps). Paintball is played with people shooting plastic balls filled with paint at each other, so it is important that the weapons are shooting paintballs fast enough to break the paintballs, but slow enough that people playing don’t get hurt. Under normal circumstances, a chronograph used for paintball would be useful before any match was played. All guns that were to be used in a game would be tested, one by one. A set speed would be decided for the game, and each gun would be adjusted until the muzzle speed was the same as the target speed decided upon beforehand. In this type of application, portability is not a big concern, because the adjusting happens before a match, and can take place away from the game (usually played outdoors). Accuracy is a big concern, however. Most chronographs operate on ambient light and the ‘shadow’ of the projectile. This dependence on ambient conditions creates a source of error for measurements. The chronograph built for this project is not dependent on ambient light conditions, so measurements are more repeatable. There are several chronographs on the commercial market. Most of the chronographs for sale seem to be marketed as rifle calibrating devices, so the velocity range specifications are higher than for this project, but it is interesting to note some of them. 5 One chronograph, from Oehler Research, uses ambient light sensors (uses light from the sun or room to detect the projectile) that can be adjusted to different positions to attain better accuracy. The adjustment range is from one foot between sensors to four feet between sensors. The accuracy of this commercial grade chronograph at 1 ft. between sensors (the same spacing as this project’s sensors) is published as within 5 feet/second (fps) at 1000 fps. The accuracy recorded by this project is somewhere around 3 fps at 500 fps. So it seems that the chronograph built in this project is reasonably accurate. The specifications for this project are as follows: Operation range (actual velocity of projectile passing) ................ 100-500 fps Accuracy ..................................................................................... within 10 fps 6 Breakdown Most simply the ballistic chronograph consists of inputs, a processor, and a display (see Flowchart 1, below). The inputs are implemented with IR sensors detecting a passing projectile and connected to a PIC microprocessor. When the IR sensors are triggered, the PIC services an interrupt and determines which sensors have been triggered. The PIC uses a timing interrupt to determine the amount of time in between sensor trips. When all of the sensors have been triggered, the PIC has enough information (the time between sensors and the known distance between sensors) to determine the velocity of the projectile passing through the system. With the speed of the projectile determined, the PIC can now pass the velocity to an LCD display module so that it can be viewed. The sends the appropriate commands through one of its ports to the LCD module. The module captures these commands and displays the appropriate text on the LCD display. Projectile IR Sensors & Emitters PIC Microprocessor LCD Display Flowchart 1 – Project Overview 7 Speed of Projectile Details Hardware Sensors The sensor system consists of 3 sets of sensors. Each of the 3 sets of sensors consists of an emitter circuit and a receiver circuit. The Emitter The emitter circuit consists of two diodes and two biasing resistors, R1 and R2 (see Schematic 1, page 24). The diodes are infrared emitter diodes (Lite-on manufactured Digikey PN# 160-1031-ND), meaning that instead of lighting up the way a visible LED does under bias, the diodes emit infrared radiation at a certain frequency. There is a direct correlation between the bias current magnitude and the amount of radiation thrown from the emitters. For this project’s purposes, a strong IR beam is desired, therefore small 100-ohm resistors are used to maximize the current flow through the diodes. The schematic shows that there are two parallel diodes used in each emitter. One of the reasons for this is to maximize IR intensity as well. The other reason for having two parallel diodes in the emitters is to ensure direct alignment with the series phototransistors in the detector circuit. 8 The Detector The real work in designing the sensor system was in designing a reliable detector portion. Originally, the design consisted of one IR-phototransistor, and a single resistor (see Schematic 2, page 25). This circuit worked under test conditions in lab. When an object passed through the IR beam from the emitter, the voltage Vout dropped from its default state (near 5 volts) to its ‘triggered’ state (near zero volts). A square wave was then used to power the IR-LED to simulate repeated switching. This revealed that slewing occurs as the IR light is taken away from the base of the IR-phototransistor. This slewing was a major concern in the beginning stages of design. The delay in changing states that this slewing represents means there will be some finite speed the circuit is able to detect. From the experiment using the 5v square wave powering the emitter, the maximum slew rate was found to be 0.0617 V/microsecond. From this information it was possible to make an estimate as to what maximum speed could be detected. Assuming the paintball to be a 0.5 inch diameter sphere, approximating the emitter beam as a plane, and knowing the resolution of the microprocessor (1/1e6 seconds) we found that the minimum time needed to switch states was 81.04 microseconds, and the maximum detectible velocity measurement at this time is 514 fps (feet per second). It is evident that the maximum velocity the sensor is able to measure is very close to the top end specification of 500 fps set for the project. In reality, the maximum measured velocity is probably much more than 514 fps simply because the microprocessor is edge triggered, rather than level sensitive, so full voltage deflection is not necessary, and the slew measurement taken in lab includes the slew of the IR-LED switching as well. 9 Adding the Second IR-Phototransistor Since the single transistor sensor seemed to work, why would adding the second transistor be necessary? The reason for adding the second phototransistor is more of a physical one than electrical. The tube the paintball is shot through is a 2” diameter tube, and the paintball is about 0.5” in diameter. If the emitter and receiver are placed on the centerline of either side of the tube, there is a good chance that the IR beam will not be broken. Shifting the emitter and detector down, away from the center line of the tube, while adding another set of sensors above the center line of the tube near the first set increases the chance that the passing projectile will be detected. The two transistors are wired in series so that if one of the phototransistors turns off, the output will go to the ‘triggered’ state near 0 volts. 10 The Wired-OR While designing the sensor system, it was important that the outputs of the system were compatible with the PIC microprocessor we were using. Some potential designs included ideas using the interrupt-on-change feature of the pins on PORTB, and another used the RB0 pin on PORTB to trigger the interrupt, while the sensors were connected to pins on PORTB and their states were checked in the interrupt service routine. The first instinct could be to use the design that took up the least number of input pins. However, on the PIC16F84 microprocessor, the RB0/INT pin has a Schmitt Trigger input stage, giving us the ability to use positive feedback to speed up the transition between low and high states. The built-in Schmitt Trigger also has a small amount of hysteresis, meaning that there is no absolute switching threshold, rather there are different switching thresholds depending on whether the voltage is making a low-to-high or high-to-low transition. The appeal in having hysteresis on the external interrupt is the tendency to reject noise and prevent false edges from triggering the Interrupt Service Routine. The drawback of using RB0/INT pin is that there is only one, and there are 3 sensors that need to trigger interrupts. This is where the wired-OR circuit (see Schematic 3, page 26) comes in. The wired-OR consists of a pull-up resistor, and three PNP transistors. The Vout from each detector is wired into the base of a corresponding PNP transistor. With all of the sensors in the ‘un-triggered’ state, Vout_Sensor_1, Vout_Sensor_2, Vout_Sensor_3, will be close to 4.5v (small voltage drop due to base-collector diode in phototransistors). This means that each of the PNPs in the wired-OR will essentially be off. Due to a voltage below 5v on the bases of the transistors, there will be some current flow through the transistors. This is not important, as long as Vout_Wired_Or deflects over a considerable range with a distinct edge. In fact, having the wired-OR BJT’s biased at rest gives us a current gain, speeding up the transition from the rest state to triggered state. Once one of the sensors is triggered, the voltage at the output node of the wired-OR switches sharply to the triggered state near zero. This circuit, along with tying all of the outputs of the sensors to input pins of the PIC allows us to use a single external interrupt pin with three sensors. Resolving which pin triggered the interrupt is up to the interrupt service routine on the PIC. 11 Internal Power supply The power supply built for this project is pretty straight forward, so most of it is hardly worth mentioning. What is worth mentioning, however, is the thought process that had to be conformed to in choosing components for a power supply like this (see Schematic 4, page 27). Before the power supply was constructed, knowing the needs of the loading devices (everything other than power supply) in terms of current was necessary. The approach used in this project was to assume everything was ‘on’ and using it worst case (highest) values of current draw (see Table 1, page 54). As is evident from the table, the majority of the current drawn in the circuit is from the sensor circuits. Tallying up all the remaining currents, a final estimated current draw was found. In the analysis, some small currents were not counted (like the oscillator) and it was decided that the maximum current should be rounded up considerably due to the external power block. Although the estimated current draw of the circuit came to about one quarter of an Ampere, it was decided that the power supply would be designed to supply 1 Ampere or current. This left plenty of room for any devices that may be connected to the power block, small uncounted currents and/or any current fluctuations due to external temperatures. All components used in the supply were rated at greater than one Ampere, and a oneAmpere fuse was chosen. The fuse is included to prevent fire in the case of a short circuit. (Note: wire used in the construction of the power supply is heavy gage, to prevent an excessive amount of heat from being generated.) 12 PIC16F84 The PIC16F84 is a RISC (reduced instruction set computing) based microprocessor. It has 1k x 14 of program memory and 68 general-purpose registers (RAM). There are two ports, Port A which is 5-bits, and Port B which is 8-bits. For our project, we used RA2RA0 for LCD control, RB7-RB4 for LCD data, RB3-RB1 for sensor input, and RB0 for sensor interrupt. We also have the PIC clocked by a 4MHz oscillator in OSC1/CLKIN. Hantronix LCD Module The Hantronix LCD Module is an LCD driver & controller package with a 4x16 character dot matrix LCD screen. It can be interfaced with either 4-bit or 8-bit data; we used the 4-bit data option. 13 Hardware Design Summary There were a number of considerations made in the design of this project. Since the use of a chronograph in the game of ‘paintball’ would most likely happen long before play, portability was not a major concern. If portability were a major concern, battery operation would be necessary. This would most likely require redesigning the entire project for low power consumption, since diodes and ‘always on’ transistors are major sources of current drain and hence consume large quantities of power. The decision to make the unit non-portable allowed for a simpler design loosening the design constraints, while not sacrificing functionality. The sensor options were mainly between ambient light detecting sensors or an emitter/receiver pair. With the ambient light detecting sensors, the functioning of the chronograph depends on an adequate amount of light being available (bright conditions). Most commercial grade chronographs use ambient light sensors, as most chronographs are for use with ‘real’ guns that normally require outdoor use. While using this sensor arrangement allows for more room for error in firing (since there is no ‘beam’ to be broken), errors in measurement can occur if ambient light conditions are changing or just inadequate. Furthermore, since this project is designed for use with paintballs rather than bullets, there is no worry about hitting the chronograph with the projectile. The paintball will simply break, leaving the chronograph unharmed. For these reasons, we chose to use an IR emitter/receiver arrangement. This method of sensing uses an infrared emitter on one side of the firing path, and a receiver on the other side of the firing path. A passing paintball creates an infrared ‘shadow’ to trip the sensor. This arrangement is very insensitive to ambient light conditions since ambient light has relatively small IR component compared to the emitter intensity. This also allows for a more constant environment than would be possible depending on ambient conditions. 14 Software The software for the ballistic chronograph handles inputs from three IR sensors and outputs to a Hantronix 4X16 LCD display. The sensors are configured in a wired-or, so that when one of them is brought low, RB0/INT is brought low and interrupts on the falling edge. The status of Port B(RB3-RB1) is taken so that the sensor causing the interrupt can be determined. For the output to the LCD, the upper nibble of Port B(RB7RB4) is used for data, and Port A (RA2-RA0) is used for control lines. The software is interrupt driven with the only interrupts being the timer overflow, which is used for timing, and RB0/INT which is used for sensor inputs. Error checking is done within the ISR to account for bogus sensor inputs. Below is a description of the code used in the project: LCD_INIT Description: Initializes the LCD for 4-bit communication. (see Flowchart 3, page 30) Initializes the Hantronix 4X16 LCD as described in the manufacturer’s notes. SEND_CMD Description: Sends the command in register W to the LCD Uses code modified from Microchip Application Note AN587 to send a command split in upper and lower nibbles to the LCD. The wait delays are long enough so that the busy bit does not need to be checked. SEND_CHAR Description: Sends the character in register W to the LCD Uses code modified from Microchip Application Note AN587 to send a character split in upper and lower nibbles to the LCD. The wait delays are long enough so that the busy bit does not need to be checked. 15 INTRO_SCREEN Description: Sends an introduction screen to the LCD. Sends the text “Ballistic Chronograph Atkinson&&Turner (c)2000” to the LCD. Formats the text to approximately center each line. TOG_E Description: Toggles E line. Toggles the E line (the clock for the LCD) with a wait in between the up and down switches. WAIT_19 Description: Delays about 18.4ms. Uses an inner and outer loop to busy wait for about 18.4ms. This delay is more than long enough for the LCD functions. CALC_RES Description: Takes 3 byte number of cycles from XA, XB, and XC and returns 2 byte speed in ResA and ResB. (see Flowchart 4, page 31) The speed can be determined by dividing 1e6 (fosc/4) by the number of cycles. The division is handled by subtracting the number of cycles X from a count initialized to 1e6 until a negative result is yielded. The number of subtractions is the result. Since the arguments are 3 bytes each, the subtraction is handled in parts, high byte to low byte, borrowing from a higher byte if needed, and incrementing a counter after all 3 bytes are handled. If the result is negative, the function returns, and the result is given. 16 RES_OUT Description: Takes result in ResA and ResB and prints it on the LCD. (see Flowchart 5, page 32) This function divides by 100 to get the 100’s place, and subtracts the 100’s, divides by 10 to get the 10’s place, and subtracts the 10’s and is left with the 1’s place. The division is handled by counting the number of subtractions until a negative result is yielded. The subtractions take place in the ResB because 100 and 10 are 1 byte numbers. Sq_Res Description: Squares a number. (see Flowchart 6, page 33) A result from a velocity calculation is determined and stored with this routine. It calculates the square, by adding the velocity v to itself v times. Acc Description: Calculates the acceleration. (see Flowchart 7, page 34) This routine assumes that the two speeds are instantaneous velocities one foot apart. Using this assumption, the formula is a = (v12 – v22)/2. The Sq_Res routine is used to square the two velocities, then this routine subtracts them and uses bit rotation to divide by 2. The sign (positive or negative) of the acceleration is also returned in NEGACC. ACC_OUT Description: Outputs the acceleration. (see Flowchart 8, page 35) This routine continually subtracts 10 from the acceleration given by Acc. This allows the digits to be built up for the output display much like a car odometer. Once the digits are determined, they are converted to ASCII and output along with the proper sign from NEGACC. Interrupt Service Routine (ISR) Description: Interrupt service routine. (see Flowchart 9, page 36) 17 Handles the interrupts from the 3 sensors and from the timer overflow. Checks which interrupt occurred, then services it. Uses a flag, SENFLAG, to determine which sensors have been triggered in order to prevent invalid inputs. TIMER Checks to see if SENFLAG is set, if not, it drops out. Otherwise, it increments the counter. If the count is larger than a maximum count, it turns the timer interrupt off. This prevents bad inputs from either making the chip hang or giving bad outputs. SEN1 First sensor. Clears counters and sets S1 flag on SENFLAG. SEN2 Second sensor. Checks for the S1 flag on SENFLAG, if not set, it drops out. Otherwise, it clears SENFLAG, then sets the S2 flag on SENFLAG. It stores the counts for the sensor 1 to sensor 2, and clears the counters. SEN3 Third sensor. Checks for the S2 flag on SENFLAG, if not set, it drops out. Otherwise, it calculates and out puts the two speeds and the acceleration. Main code Description: The main routine for the program. (see Flowchart 2, page 29) Sets up data direction for Ports A and B (RA3-RA0 outputs, RB7-RB4 outputs, RB3RB0 inputs). Calls LCD_INIT to initialize LCD, and INTRO_SCREEN to print intro. The code is interrupt driven, so main enables the interrupts then drops into an infinite loop. 18 Software Design Summary Since the PIC is interrupt driven, the bulk of the ‘real’ work is done in the ISR. Proper design methods were used to make the code readable, editable, and possibly portable. Thus, as much of the code as is possible and prudent is done in subroutines to add abstraction to the main parts of the code. In fact, all of the code involving the LCD display could easily be transferred to another program and implemented with little effort. The code is commented thoroughly to allow future editing and readability. 19 Results and Conclusions Testing Methods Our testing method assumed that the sensor provide an accurate representation of the paintball passing through. By hooking the sensors up to an oscilloscope and setting it on the ‘Roll’ mode, we were able to capture the signals generated when the sensors were triggered. By dividing 1 foot (the distance between sensors) by the time we obtain this way, we were able to measure the actual speed of the projectile. Conveniently, the oscilloscope provides the frequency of the pulses, or 1 divided by the time. Because of this, we didn’t even need to take out a calculator to determine the time. This method works very well for firing a paintball. It is not practical to always test the chronograph by firing a paintball, and it is not possible to fire paintballs at the extremes or our specs with our paintball equipment. In order to solve this problem, we created a paintball simulator using another PIC chip. This simulator pulses the sensor inputs on the chronograph to simulate a paintball passing through the sensors. When using this, we disconnect the sensors and hook up the test PIC chip in their place. We then proceed with the above method. The software for the testing PIC chip is very simple. It consists of loops that busy wait in between pulses on the sensor input pins. The testing program is set up to test through range of the specs to show that the chronograph is working properly. 20 Results In our testing, we found that our chronograph can measure speeds beyond both extremes of our spec. Below our 100 fps spec, we were able to measure around 80 fps within 1 fps of accuracy. Above our 500 fps spec, we were able to measure around 600 fps within 3 fps of accuracy. This is clearly beyond or specifications for both range of 100 fps to 500 fps and for accuracy of +/- 10 fps. Conclusion & Future Improvements The ballistic chronograph proved to be an interesting and worthwhile project. We were able to learn much about IR sensors, the PIC microprocessor, and interfacing to LCD modules. We were happy to not only get our project working, but to also beat our specs and put in an attractive enclosure. There are some things we could improve upon, however. One thing we could try would be to do our project with a faster microprocessor to obtain better accuracy. Another interesting addition would be to measure two speeds and determine the deceleration. Finally, it would be interesting to determine the energy of the paintball coming out of the barrel. 21 Directions For Use Indoor Use For indoor use, screw end-stop in the threaded end of the chronograph. Make sure the end-stop is securely fastened. Place the chronograph on a fairly level, flat surface. Plug chronograph into 120VAC-60Hz outlet (U.S. Standard). When the start-up text finishes coming up on the display, fire your loaded paintball gun in the open end of the chronograph. When firing, take care to keep the gun level and away from the sides of the chronograph, paintballs may break on the sides of chronograph otherwise. Measurement will appear on display. Outdoor Use The end-stop is not absolutely necessary for outdoor use. If end-stop is not used, care should be taken so that exiting paintballs will not harm people or property. Cleaning the Chronograph Paintballs will sometimes break inside the chronograph. For clean-up, simply remove the end-stop, stuff paper towels or rags into non-threaded end of chronograph, and push rags/paper towels through chronograph with a short stick. Repeat until chronograph is sufficiently clean. 22 Appendix Schematics ....................................................................................... page 24 Flow Charts...................................................................................... page 29 Data Sheets ...................................................................................... page 37 Project Proposal .............................................................................. page 39 Source Code ..................................................................................... page 40 Parts List .......................................................................................... page 53 Tables............................................................................................... page 54 23 Schematics Schematic 1 – IR Emitter Circuit 24 Schematic 2 – IR Detector Circuit 25 Schematic 3 – Wired OR Schematic 26 Schematic 4 – Power Schematic 27 Schematic 5 – Entire Circuit Schematic 28 Flowcharts Main Code Initialize Ports Initialize LCD (LCD_INIT) Print Intro Screen (INTRO_SCREEN) Set up Interrupts Loop ∞ Flowchart 2 – Main Code 29 LCD_INIT Put LCD in Control Mode Send 0x30 3 Times Send 4 Bit Control Send Function Set Send Display Off Clear Display Entry Mode Send Cursor Return Flowchart 3 – LCD_INIT Routine 30 CALC_RES Set Up 1 Million Clear Result MilA-XA Yes Return Neg? No MilB-XB Yes Neg? Yes No No MilC-XC MilA-1 Yes Neg? No Return M ilA=0 ? Yes MilB==0? Yes MilA==0? No No MilB-1 MilA-1 Result+1 Flowchart 4 – CALC_RES Routine 31 Return RES_OUT Clear Digits ResB-100 Neg? No DigA+1 Yes ResA=0? No ResA-1 Yes ResB+100 ResB-10 Neg? No DigB+1 Yes ResB+10 DigC=ResB Add ASCII '0' to Digits Send Digits to LCD Return Flowchart 5 – RES_OUT Routine 32 Sq_Res Store RES in Counter Clear Sq_Res Sq_Res = Sq_Res + Res Decrement Counter Counter = 0? No Yes Return Flowchart 6 – Sq_Res Routine 33 Acc Clear NEGACC Flag Acc = V2 -V1 Acc < 0? No Yes NEGACC = 1 Acc = V1 -V2 Acc = Acc / 2 Return Flowchart 7 – Acc Routine 34 ACC_OUT Clear Digits Acc = Acc -10 Acc >= 0? No DigE = Acc +10 Yes DigD + 1 Yes NEGACC = 1? Print "-" No No DigD = 10? Convert Digits to ASCII Yes DigD = 0 Print Digits DigC + 1 Return No DigC = 10? Yes DigC = 0 DigB + 1 No DigB = 10? Yes DigB = 0 DigA + 1 Flowchart 8 – ACC_OUT Routine 35 ISR Get PortB Timer Overflow? Yes Clear Interrupt Flag Increment Counter Return No Counter Overflow? No Sensor 1? Yes Clear SENFLAG Clear Counters Clear Interrupt Flag No Sensor 2? No Sensor 3? Yes Is SENFLAG = S1? No Return Yes No Return Yes Set SENFLAG=S2 Is SENFLAG = S2? No Return Yes Clear SENFLAG Print V1 (RES_OUT) Get V2 Yes Return Clear SENFLAG Yes Store Temp Counters for V1 Count er = Max? No Clear Interrupt Flag Calculate Result (CALC_RES) of V2 Print V2 (RES_OUT) Square V2 (Sq_Res) Calculate Acceleration (Acc) Return Return Store V2 Calculate Result (CALC_RES) of V1 Print Acceleration (ACC_OUT) Clear Interrupt Flag Square V1 (Sq_Res) Return Flowchart 9 – Interrupt Service Routine 36 Data Sheets Data Sheet 1 – Character Module Initialization 37 Data Sheet 2 – Commands for Character Modules 38 Project Proposal Ballistic Chronograph Short Description The ballistic chronograph will measure and numerically display the speed of a projectile. In order to determine the speed, microprocessor will measure the time the projectile takes to travel between two fixed points. Inputs Outputs Specifications Projectile Two sensors Speed of projectile At least 3-digit display Measures speeds from 100-500 fps Will be accurate within 10 fps 39 Source Code ;************************************************************************** ;* Ballistic Chronograph Code ;* Steven Turner & Brandon Atkinson ;* 2000-2001 ;************************************************************************** ;************************************************************************** ;* CONSTANTS ;************************************************************************** W F EQU EQU 0 1 ; destination bits C Z EQU EQU 0 2 ; status bits TMR0 OPT PCL STATUS FSR PORTA TRISA PORTB TRISB INTCON EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU 0x01 TMR0 0x02 0x03 0x04 0x05 PORTA 0x06 PORTB 0x0B ; PIC built-in registers INTMSK EQU 0x90 ; mask for interrupts TOIF INTF RBIE TOIE EQU EQU EQU EQU 2 1 3 5 ; ; ; ; RP0 RP1 EQU EQU 5 6 ; bank selects S1 S2 S3 EQU EQU EQU 1 2 3 ; sensor flags TRISAMSK TRISBMSK EQU EQU 0x00 0x07 ; tristate port masks LCD_DATA LCD_DATA_TRIS LCD_CNTL E RW RS EQU EQU EQU EQU EQU EQU PORTB TRISB PORTA 0 1 2 ; LCD control DELOUT DELIN EQU EQU D'23' D'200' ; values for WAIT_19 XAMAX EQU 0x01 ; largest XA can get timer overflow interrupt flag RB0 interrupt flag RB0 interrupt enable timer interrupt enable ; LCD Enable control line ; LCD Read/Write control line ; LCD Register Select control line 40 ;**************************************************************************** ;* VARIABLES ;**************************************************************************** TEMP EQU 0x10 ; temp value CNTOUT CNTIN EQU EQU 0x11 0x12 ; count loops for WAIT_19 CHAR EQU 0x13 ; character for LCD routines MilA MilB MilC EQU EQU EQU 0x14 0x15 0x16 ; bytes for 1 million in CALC_RES XA XB XC EQU EQU EQU 0x17 0x18 0x19 ; ISR counters ResA ResB EQU EQU 0x1A 0x1B ; results for CALC_RES DigA DigB DigC DigD DigE EQU EQU EQU EQU EQU 0x1C 0x1D 0x1E 0x1F 0x20 ; digits for RES_OUT & ACC_OUT BIN EQU 0x21 ; Port B capture in ISR XA1 XB1 XC1 EQU EQU EQU 0x22 0x23 0x24 ; temp values for ISR counters Sq1 Sq2 Sq3 CountA CountB EQU EQU EQU EQU EQU 0x25 0x26 0x27 0x28 0x29 ; temp values for Sq_Res V1Sq1 V1Sq2 V1Sq3 V2Sq1 V2Sq2 V2Sq3 EQU EQU EQU EQU EQU EQU 0x2A 0x2B 0x2C 0x2D 0x2E 0x2F ; vars for v1 & v2 squared Acc1 Acc2 Acc3 EQU EQU EQU 0x30 0x31 0x32 ; output of acceleration from Acc ResTEMPA ResTEMPB EQU EQU 0x33 0x34 ; temp values for ISR NEGACC EQU 0x35 ; flag for negative acc values SENFLAG EQU 0x36 ; flag of sensor triggers for ISR ; ****** END EQUATES ************************************************************ 41 ; ****** PIC SETUP CODE ************************************************************* ORG GOTO ORG GOTO 0x000 START 0x004 ISR ; setup code for PIC ; ****** MAIN CODE ************************************************************** START LOOP ; POWER_ON Reset (in HW) ; Do initialization (Bank 0) CLRF CLRF CLRF CLRF STATUS INTCON PORTA PORTB BSF CLRF MOVLW MOVWF MOVLW MOVWF BCF STATUS, RP0 TRISA 0x0F TRISB 0x0F OPT STATUS, RP0 ; Select Bank 0 CALL LCD_INIT ; initialize LCD CALL INTRO_SCREEN ; print out intro screen CLRF MOVLW MOVWF BSF SENFLAG INTMSK INTCON INTCON, TOIE ; clear out sensor flag ; setup interrupt ; enable Timer GOTO LOOP ; loop forever ; ALL PORT output should output Low. ; Select Bank 1 ; RA3 - RA0 outputs ; RB7 - 4outputs, RB3 - 0 inputs ; strong pullups, falling edge RB0 ;************************************************************************************* ;* ISR ;************************************************************************************* ISR MOVF PORTB, W ; get portB MOVWF BIN BTFSC CALL INTCON, TOIF TIMER ; check timer overflow BTFSS CALL BIN, S1 SEN1 ; check S1 BTFSS CALL BIN, S2 SEN2 ; check s2 BTFSS CALL BIN, S3 SEN3 ; check s3 RETFIE TIMER BCF MOVF BTFSC RETURN INCF BTFSS RETURN INCF MOVLW SUBWF BTFSS RETURN CLRF ; timer overflow handling ; clear int flag ; if no sensors set, drop out INTCON, TOIF SENFLAG, F STATUS, Z XB, F STATUS, Z ; increment counter XA, F XAMAX XA, W STATUS, C ; check if too large SENFLAG ; if too big reset sensors 42 RETURN SEN1 CLRF BSF CLRF CLRF CLRF CLRF BCF RETURN SENFLAG SENFLAG, S1 TMR0 XA XB XC INTCON, INTF MOVF MOVWF TMR0, W XC1 ; grab time BTFSS RETURN CLRF BSF SENFLAG, S1 ; check for 1st sensor ; drop out if not set CLRF MOVF MOVWF MOVF MOVWF CLRF CLRF BCF RETURN TMR0 XA, W XA1 XB, W XB1 XA XB INTCON, INTF MOVF MOVWF TMR0, W XC ; grab time BTFSS RETURN CLRF SENFLAG, S2 ; check for 2nd sensor ; drop out if not set CALL CALL MOVF MOVWF MOVF MOVWF MOVF MOVWF MOVF MOVWF MOVF MOVWF MOVF MOVWF MOVF MOVWF MOVF MOVWF CALL CALL MOVF MOVWF MOVF MOVWF MOVF MOVWF MOVLW CALL MOVLW CALL MOVLW CALL CALC_RES Sq_Res Sq1, W V2Sq1 Sq2, W V2Sq2 Sq3, W V2Sq3 ResA, W ResTEMPA ResB, W ResTEMPB XA1, W XA XB1, W XB XC1, W XC CALC_RES Sq_Res Sq1, W V1Sq1 Sq2, W V1Sq2 Sq3, W V1Sq3 0x01 SEND_CMD 0x80 SEND_CMD 'v' SEND_CHAR ; mark 1st sensor ; clear counters ; clear int flag SEN2 SENFLAG SENFLAG, S2 ; set only S2 SEN3 SENFLAG ; calculate result ; square result ; store result ; store result ; move temps back ; put out 2nd speed ; square result ; store result ; clear LCD ; goto line 1 ; output result 1 43 MOVLW CALL MOVLW CALL MOVLW CALL CALL MOVF MOVWF MOVF MOVWF MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL CALL CALL MOVLW CALL CALL BCF '1' SEND_CHAR '=' SEND_CHAR ' ' SEND_CHAR RES_OUT ResTEMPA, W ResA ResTEMPB, W ResB 0xC0 SEND_CMD 'v' SEND_CHAR '2' SEND_CHAR '=' SEND_CHAR ' ' SEND_CHAR RES_OUT Acc 0xD0 SEND_CMD ACC_OUT INTCON, INTF ; output result 2 ; calculate acceleration ; clear int flag RETURN ;************************************************************************************ ;* SUBROUTINES ;************************************************************************************ ;************************************************************************************ ;* LCD_INIT Subroutine ;* ;* Initializes LCD for 4 bit communication ;* Initialize LCD by sending: ;* RS RW D7 D6 D5 D4 ;* 0 0 0 0 1 1 ;* wait > 4.5 ms ;* 0 0 0 0 1 1 ;* wait > 100us ;* 0 0 0 0 1 1 ;* 0 0 0 0 1 0 for 4 bit control ;* send command 001010xx (function set) (0x28) ;* send command 00001000 (display off) (0x08) ;* send command 00000101 (display clear) (0x01) ;* send command 00000110 (entry mode) (0x06) ;************************************************************************************ LCD_INIT CALL WAIT_19 CALL WAIT_19 CALL WAIT_19 BCF LCD_CNTL, RS ; put in control mode BCF LCD_CNTL, RW MOVLW MOVWF CALL CALL CALL CALL CALL CALL 0x30 LCD_DATA TOG_E WAIT_19 TOG_E WAIT_19 TOG_E WAIT_19 ; send 0011 3 times MOVLW MOVWF CALL CALL 0x20 LCD_DATA TOG_E WAIT_19 ; send 0010 for ; 4 bit control 44 MOVLW CALL 0x28 SEND_CMD ; send funtion set MOVLW CALL 0x08 SEND_CMD ; send display off MOVLW CALL 0x01 SEND_CMD ; clear display MOVLW CALL 0x06 SEND_CMD ; entry mode MOVLW CALL 0x0E SEND_CMD ; send cursor CALL CALL WAIT_19 WAIT_19 RETURN ;************************************************************************************ ;* TOG_E Subroutine ;* ;* Toggles E line ;************************************************************************************ TOG_E BSF CALL BCF RETURN LCD_CNTL, E WAIT_19 LCD_CNTL, E ; toggle E for LCD ;************************************************************************************ ;* WAIT_19 Subroutine ;* ;* Uses a double loop to eat up CPU time and give >18.4ms delay ;* DELOUT=23, DELIN=200, gives about 18.4ms of delay ;************************************************************************************ WAIT_19 BKOUT BKIN MOVLW MOVWF MOVLW MOVWF NOP DECFSZ GOTO DECFSZ GOTO RETURN DELOUT CNTOUT DELIN CNTIN ; get outer level count ; get inner delay CNTIN, F BKIN CNTOUT, F BKOUT ; dec, skip next if 0 ; dec outer count, skip next if 0 ;************************************************************************************ ;* SEND_CMD Subroutine ;* ;* Modified from Microchip code ;* Sends the command to the LCD in upper and lower nibbles ;************************************************************************************ SEND_CMD MOVWF MOVF ANDLW MOVWF CALL SWAPF ANDLW MOVWF CALL CALL RETURN CHAR CHAR, W 0xF0 LCD_DATA TOG_E CHAR, W 0xF0 LCD_DATA TOG_E WAIT_19 ; Character to be sent is in W ; Get upper nibble ; Send data to LCD ; Get lower nibble ; Send data to LCD 45 ;************************************************************************************ ;* SEND_CHAR Subroutine ;* ;* Modified from Microchip code ;* Sends a character to the LCD in upper and lower nibbles ;************************************************************************************ SEND_CHAR MOVWF MOVF ANDLW MOVWF BSF CALL SWAPF ANDLW MOVWF CALL BCF RETURN CHAR CHAR, W 0xF0 LCD_DATA LCD_CNTL, RS TOG_E CHAR, W 0xF0 LCD_DATA TOG_E LCD_CNTL, RS ; Character to be sent is in W ; Get upper nibble ; Send data to LCD ; Set LCD to data mode ; Get lower nibble ; Send data to LCD ;************************************************************************************ ;* CALC_RES Subroutine ;* ;* Determines the speed, given the number of cycles taken. ;* Speed = 1e6/X where X is the number of cycles. ;* Result is stored as ResA*FF+ResB ;********************************************************************************** CALC_RES LOOP_RES OPC CHKA FINISH MOVLW MOVWF MOVLW MOVWF MOVLW MOVWF CLRF CLRF 0x0F MilA 0x42 MilB 0x40 MilC ResA ResB ; set up 1M MOVF SUBWF BTFSS RETURN XA, W MilA, F STATUS, C ; MilA-XA MOVF SUBWF BTFSC GOTO MOVF BTFSC RETURN DECF XB, W MilB, F STATUS, C OPC MilA, F STATUS, Z ; MilB-XB MOVF SUBWF BTFSC GOTO MOVF BTFSC GOTO DECF GOTO MOVF BTFSC RETURN DECF DECF XC, W MilC, F STATUS, C FINISH MilB, F STATUS, Z CHKA MilB, F FINISH MilA, F STATUS, Z INCF BTFSC INCF ResB, F STATUS, Z ResA, F ; clear out result ; if neg, then done ; A= neg (done) ; if not neg, go to next op ; check if A is zero ; A=0, B=neg (done) ; subtract 1 from A MilA, F ; MilC-XC ; if not neg, next part ; check if B is zero ; if B is zero goto next ; B is not zero ; if A=0 then done ; A=0 B=0 C=neg (done) MilA, F MilB, F ; MilB=FF ; increment result ; add carry if needed 46 GOTO LOOP_RES ; next iteration ;********************************************************************************** ;* RES_OUT Subroutine ;* ;* Takes result given by CALC_RES & outputs to LCD ;********************************************************************************** RES_OUT DIG_100 INC100 DIG_10A DIG_10 DIG_1A DIG_1 CLRF CLRF CLRF DigA DigB DigC ; clear out counters MOVLW SUBWF BTFSC GOTO MOVF BTFSC GOTO DECF INCF GOTO 0x64 ResB, F STATUS, C INC100 ResA, F STATUS, Z DIG_10A ResA, F DigA, F DIG_100 ; 100's MOVLW ADDWF MOVLW SUBWF BTFSS GOTO INCF GOTO 0x64 ResB,F 0x0A ResB, F STATUS, C DIG_1A DigB, F DIG_10 MOVLW ADDWF MOVF MOVWF 0x0a ResB, F ResB, W DigC ; put 10 back on negative # MOVLW ADDWF ADDWF ADDWF '0' DigA, F DigB, F DigC, F ; covert digits to ASCII MOVF CALL MOVF CALL MOVF CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL RETURN DigA, W SEND_CHAR DigB, W SEND_CHAR DigC, W SEND_CHAR ' ' SEND_CHAR 'f' SEND_CHAR 't' SEND_CHAR '/' SEND_CHAR 's' SEND_CHAR ; output result ; if neg ; done 100's ; take 1 from ResA ; put 100 back on negative # ; 10's ; if neg ; print “ ft/s” 47 ;********************************************************************************** ;* INTRO_SCREEN ;* ;* Prints out the introduction screen for the project ;* More readable and about the same amount of code as using a table ;********************************************************************************** INTRO_SCREEN MOVLW CALL CALL CALL 0x02 SEND_CMD WAIT_19 WAIT_19 ; home MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL ' ' SEND_CHAR ' ' SEND_CHAR ' ' SEND_CHAR 'B' SEND_CHAR 'a' SEND_CHAR 'l' SEND_CHAR 'l' SEND_CHAR 'i' SEND_CHAR 's' SEND_CHAR 't' SEND_CHAR 'i' SEND_CHAR 'c' SEND_CHAR ; print "Ballistic" MOVLW CALL 0xC2 SEND_CMD ; line 2, col 2 MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL 'C' SEND_CHAR 'h' SEND_CHAR 'r' SEND_CHAR 'o' SEND_CHAR 'n' SEND_CHAR 'o' SEND_CHAR 'g' SEND_CHAR 'r' SEND_CHAR 'a' SEND_CHAR 'p' SEND_CHAR 'h' SEND_CHAR ; print "Chrongraph" MOVLW CALL 0x90 SEND_CMD ; line 3 MOVLW CALL MOVLW 'A' SEND_CHAR 't' ; print "Atkinson&&Turner" 48 CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL SEND_CHAR 'k' SEND_CHAR 'i' SEND_CHAR 'n' SEND_CHAR 's' SEND_CHAR 'o' SEND_CHAR 'n' SEND_CHAR '&' SEND_CHAR '&' SEND_CHAR 'T' SEND_CHAR 'u' SEND_CHAR 'r' SEND_CHAR 'n' SEND_CHAR 'e' SEND_CHAR 'r' SEND_CHAR MOVLW CALL 0xD4 SEND_CMD ; line 4, col 4 MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL '(' SEND_CHAR 'c' SEND_CHAR ')' SEND_CHAR ' ' SEND_CHAR '2' SEND_CHAR '0' SEND_CHAR '0' SEND_CHAR '0' SEND_CHAR ; print "(c) 2000" RETURN ;****************************************************************************** ;* Sq_Res Subroutine ;* ;* Squares result (ResA|ResB), returns ;* to Sq1|Sq2|Sq3 ;****************************************************************************** Sq_Res CLRF Sq1 ; clear out result CLRF Sq2 CLRF Sq3 Sq_Res1 MOVF MOVWF INCF MOVF MOVWF ResA, W CountA CountA, F ResB, W CountB MOVF ADDWF ResB, W Sq3, F ; copy counters 49 Sq_Res2 BTFSC INCFSZ GOTO INCF STATUS, C Sq2, F Sq_Res2 Sq1, F MOVF ADDWF BTFSS INCF ResA, W Sq2, F STATUS, C Sq1, F DECFSZ GOTO DECFSZ GOTO RETURN CountB, F Sq_Res1 CountA, F Sq_Res1 ; if carry inc next ; if carry, inc next ;******************************************************************************* ;* Acc subroutine ;* ;* Calculates the acceleration given two squared ;* speeds V1Sq1|V1Sq2|V1Sq3, V2Sq1|V2Sq2|V2Sq3 ;* Stored to Acc1|Acc2|Acc3 ;******************************************************************************* Acc Acc_1 CLRF MOVF MOVWF MOVF MOVWF MOVF MOVWF NEGACC V2Sq1, W Acc1 V2Sq2, W Acc2 V2Sq3, W Acc3 MOVF SUBWF V1Sq1, W Acc1, F ; sub high byte MOVF SUBWF BTFSS DECF V1Sq2, W Acc2, F STATUS, C Acc1, F ; sub mid byte MOVF SUBWF BTFSC GOTO MOVLW SUBWF BTFSS DECF V1Sq3, W Acc3, F STATUS, C Acc_1 0x01 Acc2, F STATUS, C Acc1, F ; sub low byte BTFSS GOTO Acc1, 7 Acc_2 ; if negative do opposite INCF MOVF MOVWF MOVF MOVWF MOVF MOVWF NEGACC, F V1Sq1, W Acc1 V1Sq2, W Acc2 V1Sq3, W Acc3 MOVF SUBWF V2Sq1, W Acc1, F ; sub high byte MOVF SUBWF BTFSS DECF V2Sq2, W Acc2, F STATUS, C Acc1, F ; sub mid byte MOVF SUBWF V2Sq3, W Acc3, F ; sub low byte ; put V2 in result ; put V2 in result 50 Acc_2 BTFSC GOTO MOVLW SUBWF BTFSS DECF STATUS, C Acc_1 0x01 Acc2, F STATUS, C Acc1, F BCF RLF RRF RRF RRF Acc3, Acc1, Acc1, Acc2, Acc3, 0 W F F F ; clear out odds ; get high bit in C RETURN ;********************************************************************************* ;* ACC_OUT Subroutine ;* ;* Takes result given by Acc & outputs to LCD ;********************************************************************************* ACC_OUT ACCO_10 ACCO_10A ACCO_CARRY CLRF CLRF CLRF CLRF CLRF DigA DigB DigC DigD DigE ; clear out counters MOVLW CALL MOVLW CALL MOVLW CALL 'a' SEND_CHAR '=' SEND_CHAR ' ' SEND_CHAR ; output “a= “ MOVF BTFSC GOTO MOVLW CALL NEGACC, F STATUS, Z ACCO_10 '-' SEND_CHAR ; check for negative MOVLW SUBWF BTFSS GOTO INCF MOVLW SUBWF BTFSS GOTO CLRF INCF MOVLW SUBWF BTFSS GOTO CLRF INCF MOVLW SUBWF BTFSS GOTO CLRF INCF GOTO 0x0A Acc3, F STATUS, C ACCO_CARRY DigD, F 0x0A DigD, W STATUS, Z ACCO_10 DigD DigC, F 0x0A DigC, W STATUS, Z ACCO_10 DigC DigB, F 0x0A DigB, W STATUS, Z ACCO_10 DigB DigA, F ACCO_10 MOVF BTFSC GOTO DECF GOTO Acc2, F STATUS, Z ACCO_1 Acc2, F ACCO_10A ; output negative sign ; if negative ; carry from Acc2 51 ACCO_1 MOVLW ADDWF MOVWF 0x0A Acc3, W DigE MOVLW ADDWF ADDWF ADDWF ADDWF ADDWF '0' DigA, DigB, DigC, DigD, DigE, MOVF CALL MOVF CALL MOVF CALL MOVF CALL MOVF CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL MOVLW CALL RETURN DigA, W SEND_CHAR DigB, W SEND_CHAR DigC, W SEND_CHAR DigD, W SEND_CHAR DigE, W SEND_CHAR ' ' SEND_CHAR 'f' SEND_CHAR 't' SEND_CHAR '/' SEND_CHAR 's' SEND_CHAR '^' SEND_CHAR '2' SEND_CHAR ; put the remainder in 1's place ; covert digits to ASCII F F F F F ; print digits ; print “ ft/s^2” end 52 Parts List Quantity 6 Part Description IR Phototransistor 6 IR Photodiode 13 2 3 Many 1 1 2 16 pin chip carrier Perf. Board Sheets Wire wrap wire spools Various Resistors 470uF Electrolytic Cap. 0.1uF Ceramic Cap Archer ‘Copper Clad’ board LM7805 Voltage Reg. 1 Ampere Fuse 1 1 1 120v-14.4v transformer (1.2 Ampere) 1 1 1 1 Power LED with resistor Hantronix LCD Module RadioShack Project Box RadioShack QR Power B. 1 RadioShack Isolation Block PNP Transistors (2N3906) PIC16F84 TTL Crystal Clock Oscillator 3 1 1 Comment Digikey Part # 160-1062-ND Digikey Part # 160-1031-ND 53 (Speaker-like power terms) (Wired-OR) 10MHz rated 4MHz Jameco Part # 27967 Tables Circuit Component Current Draw 3 ‘ON’ Detectors Max Current from 3 ‘ON’ Wired OR transistors Maximum Current from PIC Maximum Current from Display LM7805 max current 0.234 A 0.0034 A TOTAL 250.2 mA 4.5 mA 0.3 mA 8.0 mA Table 1 – Approximate Current Total 54