' Rocket Altimeter Project (RAP) ' by Anish C. Trivedi and Sean H. Breheny ' Last Modified January 12, 2001 ' Code for the BSII to make an acceleration ' datalogger for model rockets. ' Please see associated schematic,text explanation, ' photos, and movies at http://www.rocket-roar.com ' NOTE: a few lines of code seem to be unnecessary, but since they were present when ' I tested the system, I just commented them as such but did not remove them. ' Set pin directions, all output except for ' PIN7 (DRDY) and PIN10 (data in) DIRS=%1111101101111111 ' Variables in RAM sample var word ' Temp var for each sample numsamples var word ' Used to count samples in multiple instances indicator var byte ' Indicates if data has already been recorded palminput var byte ' Take input from serial port avg var word(3) ' Temp variables for storing samples to be averaged ioptr var word ' Current location being written/read in circ. buffer launchptr var word ' Location where launch was detected in circ. buffer islaunch var bit ' Indicates if launch has been detected standv var word ' To load standard (1 g, at rest) acceleration from EEPROM lavg var word ' Not used (should have been deleted) ' Constants lf con 10 ' Value of a line feed romstart con 5 ' Location of beginning of circ. buffer in EEPROM size con 721 ' Size of circ. buffer in words (720 words + one extra) startmargin con 60 ' Amount of samples (words) of pre-launch data to keep lthresh con 2000 ' Launch detection threshold ' Data in EEPROM flag data @0,0 ' Buffer empty/full flag standard data @1,0,0 ' Standard (1 g, at rest) acceleration reading lptr data @3,0,0 ' Place to store launch pointer (launchptr) value dbuffer data @romstart,0(2*size) ' Actual data buffer ' Reset point startpoint: out12=0 ' LED off islaunch=0 ' Launch has NOT been detected yet read flag,indicator ' Determine whether buffer contains data if indicator = 0 then writedata ' If not, await launch ' if there is data, go to command mode ' Command Mode out12 = 1 ' LED on (indicates data present) ' Menu selectmode: debug ">>" ' Give ">>" prompt over serial port serin 16,84,[palminput] ' Accept input from INxx at 9600,N,8,1 ' with built-in level converter if palminput = "r" then readdata ' If "r", spit the buffer out over serial link if palminput = "c" then cleardata ' If "c", clear the data flag if palminput = "l" then calibrate ' If "l", go to calibrate standard goto selectmode ' If none, issue another prompt ' Section to record data writedata: debug "WL",lf ' For debugging purposes, send "WL" (Wait Launch) over the serial link read standard,standv.highbyte ' Read in the standard (stored big endian) read standard+1,standv.lowbyte gosub initadc ' Set up the AD7706 launchptr=0 ' Clear launchptr ioptr=0 ' Set ioptr to beginning of buffer numsamples=0 ' No samples yet lavg=0 ' Not used (should have been deleted) ' Loop to read samples from the ADC and write to EEPROM readsample: gosub getsample ' Read from the ADC write (romstart+(2*ioptr)),sample.highbyte ' Store sample (big endian) write ((romstart+(2*ioptr))+1),sample.lowbyte ' Stored at location pointed to ' by ioptr (in 16-bit words) ioptr = ioptr + 1 ' Increment pointer ' Check to see if ioptr hits end of circular buffer, if so ' wrap around to zero if ioptr < size then skip1 ioptr = 0 skip1: if not islaunch=1 then checklaunch ' If we haven't already detected launch, check for it ' If you get here, launch has already been detected gosub howmany ' Determine how many samples we have ' If we have not yet filled the buffer (without overwriting the pre-launch margin), then ' continue reading from ADC and writing to EEPROM if numsamples < (size - startmargin - 1) then readsample ' Otherwise, we are done grabbing samples, write the launchptr to EEPROM write lptr,launchptr.highbyte ' (big endian) write lptr+1,launchptr.lowbyte debug "LF",lf ' Send "LF" (Launch sequence Finish) to serial port for debugging end ' Enter low-power mode ' Check for a launch condition (high acceleration) checklaunch: ' If the difference between the current sample and the rest acceleration level ' is less than the launch detection threshold, then just continue sampling if abs((sample-standv)) < lthresh then readsample ' If it IS greater than or equal, then launch has occurred out12=1 ' Turn on LED islaunch=1 ' Set launch flag launchptr=ioptr ' Set launchptr to current buffer location write flag,1 ' Write flag into EEPROM to say that buffer contains data debug "LD",lf ' Send "LD" (Launch Detect) to serial port for debug purposes goto readsample ' Continue sampling ' Subroutine to read out data to the serial port readdata: ' Read standard from EEPROM read standard,standv.highbyte read standard+1,standv.lowbyte ' Send it over serial port debug "Std=",dec standv,lf debug "Start D",lf ' Indicate start of data ' Read launchptr so we know where to start reading data read lptr,launchptr.highbyte read lptr+1,launchptr.lowbyte ioptr = launchptr ' Set IO pointer to launch point ' Loop to read data ' NOTE: First sample to come out is the one right after launch detect. Samples then come out ' sequentially, except for the last 60, which are from before launch, so the data ' comes out like this (680 samples starting at launch)(60 samples from before launch) ' You need to cut and paste the data to get a vector which is fully sequential in time readrom: ' Read a sample read (romstart+(2*ioptr)),sample.highbyte read ((romstart+(2*ioptr))+1),sample.lowbyte ioptr = ioptr+1 ' Increment pointer ' If pointer has reached the top of circular buffer, wrap around to 0 if ioptr < size then skip4 ioptr = 0 skip4: debug dec sample,lf ' Send the sample over the serial port as a human-readable decimal number gosub howmany ' Find out how many samples sent so far ' If we have not yet read all 720 samples, keep on going if numsamples < (size-1) then readrom ' If finished, indicate it by sending "End D" over serial port debug "End D",lf ' Go back to menu goto selectmode ' Subroutine to clear data flag ' This sets up the unit so that it will be ' waiting to detect launch after next reset cleardata: write flag,0 ' Clear the flag debug "Data neut",lf ' Indicate it over the serial port out12=0 ' Turn off LED end ' Go into low power mode ' Subroutine to determine 1 g, rest acceleration calibrate: debug "Cal",lf ' Indicate over serial port that system is in calibration mode pause 60000 ' Wait one full minute to allow user to place rocket on launch ' pad (for most accurate reading) gosub initadc ' Set up the AD7706 avg = 0 ' Clear avg (line not really needed) ' Take 3 samples, at one second intervals, and store in avg(0),avg(1),avg(2) for numsamples = 0 to 2 gosub getsample pause 1000 avg(numsamples) = sample next ' Calculate approximate average (in such a way as to prevent overflow) avg(0)=((avg(0)/3)+(avg(1)/3)+(avg(2)/3)) ' Write standard (average of 3 samples) into EEPROM write standard,avg.highbyte(0) write standard+1,avg.lowbyte(0) debug "Avg=",dec avg(0),lf ' Display the average value by sending over serial port out12=0 ' Blink LED for 1 sec to indicate measurement is complete pause 1000 out12=1 goto selectmode ' Back to menu ' Subroutine to set up AD7706 ADC initadc: ' Reset ADC out11 = 0 pause 100 out11 = 1 pause 100 shiftout 9,8,1,[%00100000] ' Configure a write to CLOCK register shiftout 9,8,1,[%00001101] ' Master clock ENABLE, 4.9152 MHz config, 60 Samp/sec shiftout 9,8,1,[%00010000] ' Configure a write to the SETUP register shiftout 9,8,1,[%01010010] ' Self calibration, gain=4, bipolar buffered input return ' Subroutine to get a sample from ADC getsample: ' If sample not yet ready, keep looping if in7 = 1 then getsample shiftout 9,8,1,[%00111000] ' Configure read from DATA register, 1st channel selected shiftin 10,8,0, [sample\16] ' Read in 16 bits, store in sample return ' Subroutine to compute how many samples are in circular buffer howmany: ' If launchptr > ioptr, the answer is just ioptr-launchptr ' Otherwise, it is size+ioptr-launchptr numsamples=ioptr-launchptr if ioptr >= launchptr then op1 numsamples=numsamples+size op1: return