Download A Ballistic Chronograph

Document related concepts

Coilgun wikipedia , lookup

Geophysical MASINT wikipedia , lookup

Immunity-aware programming wikipedia , lookup

Opto-isolator wikipedia , lookup

Liquid-crystal display wikipedia , lookup

Transcript
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