Yes, I know I skipped September, it is still in the works but having digital camera issues. I can't seem to get good closeups. Yet. I will.
This issue is all about finding the distance from one point to another. Several methods are discussed:
I've had the joy of working on a really interesting project with a real 3D CAD expert. Mostly I helped with some math and spewed out ideas, but the simplicity and the results are astounding. The project is a laser 3D scanner built for much less than any commercial unit.
The basic idea is probably best shown by these pictures from http://www.cyberg8t.com/pendragn/actlite.htm (which is no longer, but has been cached)
- | = |
And then the position of the laser line is used to calculate the depth of the object.
Because the Laser and Motor have to be timed and driven together both use the parallel port data lines. Only 3 of the 8 data lines are needed:
Also the software interface for the parallel port is easy to use with Jan Axelsons Inpout32.dll (available at www.lvr.com).
Routines are:
Laser True Wait 0.3 ezVidCap1.SaveDIB ("c:\temp\laserOn.bmp") Picture2.Picture = LoadPicture("c:\temp\laserOn.bmp") Laser False Wait 0.3 ezVidCap1.SaveDIB ("c:\temp\laserOff.bmp") Picture1.Picture = LoadPicture("c:\temp\laserOff.bmp") Step_Clock |
This routine relies on the ezvidCap component from Ray Mercer
http://www.martin2k.co.uk/vb6/tips/x4.php
And a little easy port IO code:
Private Sub Step_Clock() Out Val("&H" + "0378"), 1: Wait 0.1 Out Val("&H" + "0378"), 0: Wait 0.1 End Sub Private Sub Laser(switch As Boolean) If switch = False Then Out Val("&H" + "0378"), 0 If switch = True Then Out Val("&H" + "0378"), 8 End Sub
' Set the pixel color values. For Y = 0 To Picture1.ScaleHeight - 1 For X = 0 To Picture1.ScaleWidth - 1 With pixels(X, Y) .rgbRed = Abs(CInt(.rgbRed) - pixels2(X, Y).rgbRed) .rgbGreen = Abs(CInt(.rgbGreen) - pixels2(X, Y).rgbGreen) .rgbBlue = Abs(CInt(.rgbBlue) - pixels2(X, Y).rgbBlue) If (.rgbRed > filter) And (.rgbGreen > filter) And (.rgbBlue > filter) Then .rgbRed = 0 .rgbGreen = 0 .rgbBlue = 0 Else .rgbRed = 255 .rgbGreen = 255 .rgbBlue = 255 End If End With Next X Next Y |
This routine is adapted from the book Visual Basic(r) Graphics Programming: Hands-On Applications and Advanced Color Development, 2nd Edition by Rod Stephens for image processing and edge detection.
Angle = (Frame / LastFrame) * Pi * 2 For PicY = 0 To Picture5.ScaleHeight - 1 Z = PicY For PicX = 0 To Picture5.ScaleWidth - 1 R = (Picture5.ScaleWidth / 2) - PicX R = R / 0.5 With pixels(PicX, PicY) RetR = .rgbRed If RetR = 0 Then X = R * Cos(Angle) Y = R * Sin(Angle) Print #1, X; ","; Y; ","; Z End If End With Next PicX Next PicY |
And the result is a "point cloud" that describes your subject. Additional software will be added to process the points into lines or faces, smooth and reduce the complexity of the image.
Now, this process can, and has to some degree, been done with a microcontroller. Here are the potential problems and how they are avoided:
This simple sonar ranging device eliminates a lot of the usual discrete components by executing complex functions in the software of the microcontroller. Several times per second, the it generates a few cycles (about 8) of a 40 kHz square wave on an output that directly drives the transmitter element. It then begins counting "ticks" (fast program loops) which will accumulate until it either detects a response from the 567 tone decoder or a maximum period has expired. Immediately following the 40 kHz burst, the output of the 567 chip is ignored for a short time. This is because the 567 will detect the burst, and the transmitter element will continue to ring or resonate for a short time. The 567 tone decoder chip is a phase locked loop designed to detect when the input frequency is within a certain pass-band. The passband or detection range is determined by the values of the discrete components connected to it. This makes it very easy to use. The 567 has been around for many years, it's cheap, and very useful. Ultrasonic sound waves emitted from the transmitter element travel through the air, hit an object and bounce back to the unit where the receiver element detects them. The output of the receiver is amplified and sent into the 567 chip. The 567 chip drives its output low when it detects the reflected 40 kHz signal. It will react to all reflections so it may produce more than one output pulse, but this version of the code will only register the first one. Several readings per second are averaged and a value proportional to the detected distance is sent out via a serial line. The pictures show this connected to a serial LCD. Be aware that the value is for demonstration purposes only and not been scaled to any actual units of length like feet or centimeters. You would have to add your own code or lookup table to display specific units of measure.
The program is designed to run in different modes. The dip-switches are used to select the mode of operation, such as "normal pulse o/p", "continuous tone o/p" with is used for tuning the 567 for best detection, "binary serial o/p", "ascii serial o/p", etc.
The processor has a "serin" pin which can be used as a control input from another processor. Through this pin, it could receive instructions but this block of code is unfinished and should be tailored to your application. If selected, nothing will happen, however, it would be a simple matter to add code that would allow the input to act as a "logic enable" or to accept various serial commands. Alternatively, the serin pin could be programmed as some sort of o/p.
The "serout" pin is used to output the range test results. In ascii o/p mode, the results are sent with the LCD-Backpack's value for the "I" instruction (#254) value first that instructs a backpack-LCD or serial-LCD to enter "instruction mode". The next byte sent is the address of line2 (#192) which sets the cursor of the LCD to the start of line 2. Then three ascii digits are sent, MSD first, center digit, LSD last. If the result is a BCD number less than 3 digits, spaces are sent to clear those digits from the display. In binary o/p mode, the straight binary test result is sent.
The transmitter is a 40kHz transducer from Digikey, part# P9895-ND.
The receiver is a 40kHz transducer from Digikey, part# P9890-ND.
The PCB design uses several surface mount components. It saves a lot of hole drilling and lead bending and clipping. Also, assemblies end up smaller, better looking and easier to modify or service. Soldering surface mount (especially the larger variants) is ease
;Filename: SONAR1.SRC ;Created: MAY.4.97 ;Last Modified: MAY.4.97 ;Language: PARALLAX assembler ;PCBname: SONAR1.JOB ;Schematic: SONAR1.SCH ;Processor: PIC16C71 ;Written By: William J. Boucher ; ;DESCRIPTION: ; ;This program is designed to run the mini robot sonar1 module as a ;rangefinder sensor. It generates a 40kHz pulse, the measures the time ;until an echo is detected. The dip-switches are used to select different ;modes of operate, such as "normal pulse o/p", "continuous tone o/p" ;for tuning purposes, "binary serial o/p", "ascii serial o/p", etc. ;This sensor is intended for use in miniature robot applications. ;The transmitter is a 40kHz transducer from Digikey, part# P9895-ND. ;The receiver is a 40kHz transducer from Digikey, part# P9890-ND. ;The processor has a "serin" pin which can be used as a control input from ;another processor. Through this pin, it could receive instructions. ;Also, the serin pin could be programmed as some sort of o/p. ;The "serout" pin is used to output the range test results. ;In ascii o/p mode, the results are sent with the "I" (254) value first ;which instructs a Stamp-based LCD to enter "instruction mode". ;The next byte sent is the address of line2 "192" which sets the cursor ;of the LCD to the start of line 2. Then three ascii digits are sent, ;MSD first, center digit, LSD last. If the result is a BCD number less ;than 3 digits, spaces are sent to clear those digits from the display. ;In binary o/p mode, the straight binary test result is sent. ;The serial data is programmed to have a bit width of 0.104ms (9600baud). ;The data words are sent with: ;- a single high start bit ;- inverted data, LSB first ;- a single low stop bit. ; ;TASKLIST 1/ Initialize registers & variable names & inputs/outputs. ; 2/ Read dipswitches to determine mode. ; 3/ Enter mode. ; 4/ Calculate/update variables as required. ; 5/ Send 8 bit result data in format selected. ; 6/ Repeat at step 2. ; ;---------------------------------------------------------------------------- DEVICE PIC16C71,HS_OSC,WDT_OFF,PWRT_ON,PROTECT_OFF ID 'SOR1' ;FIRST 2 & LAST 2 CHARS OF FILENAME ;---------------------------------------------------------------------------- ;EQUATES: ; LINE1 = 128 ;LCD LINE1 START ADDRESS LINE2 = 192 ;LCD LINE2 START ADDRESS I = 254 ;LCD INSTRUCTION COMMAND CLRLCD = 1 ;LCD CLEAR INSTRUCTION XMIT1 = 5.2 ;PIN 1 OF TRANSMITTER XMIT2 = 5.3 ;PIN 2 OF TRANSMITTER SERIN = 6.0 ;SERIAL INPUT PIN SEROUT = 6.1 ;SERIAL O/P PIN DETECT = 6.2 ;INPUT FROM OUTPUT OF LM567 TONE DETECTOR DIPSW1 = 6.4 ;DIP SWITCH 1 DIPSW2 = 6.5 ;DIP SWITCH 2 DIPSW3 = 6.6 ;DIP SWITCH 3 DIPSW4 = 6.7 ;DIP SWITCH 4 TIMER = 1 ;TMR0 ON BOARD TIMER TIMERVAL40K = 228 ;VALUE CONTROLS LOOP FREQ TO 40kHz ;226=38.5kHz ;224=35.2kHz ;31=5.45kHz TIMERFLAG = 11.2 ;TIMER0 OVERFLOW FLAG XMITA = 00000100B XMITB = 00001000B XMITLOW = 0 XMITENABLE = 11110011B XMITDISABLE = 11111111B ;---------------------------------------------------------------------------- ;VARIABLE STORAGE ORG 0CH ;SET TO START OF GENERAL PURPOSE RAM DELAYCOUNTER1 DS 1 DELAYCOUNTER2 DS 1 DELAYCOUNTER3 DS 1 SERINDATA DS 1 SEROUTDATA DS 1 BIN DS 1 R1 DS 1 R2 DS 1 COUNTER1 DS 1 COUNTER2 DS 1 BITCOUNTER DS 1 TEMP DS 1 TABLEENTRY DS 1 TABLEVALUE DS 1 RANGERESULT DS 1 RANGEAVERAGE DS 1 RANGEDATAH DS 1 RANGEDATAL DS 1 RESULTCOUNTER DS 1 STATS DS 1 ;---------------------------------------------------------------------------- ORG 0 ;INITIALIZE VARIABLES INITIALIZE CLR 8 ;TURN OFF A2D CONVERTER & SET CLKRATE ;& SET TO CHANNEL 0 <3:0> SETB RP0 ;SET RP0 TO UPPER REGISTER BANK MOV 1,#00000000B ;SET OPTION REG. RB-PULL-UPS ON ; & TIMER PRESCALER TO 1:2 ; & ASSIGN PRESCALER TO TIMER MOV 8,#3 ;SET PORT1 INPUTS AS DIGITAL ;MOV RA,#XMITDISABLE ;SET PORT RA DATA DIRECTIONS MOV RA,#XMITENABLE ;SET PORT RA DATA DIRECTIONS MOV RB,#11110101B ;SET PORT RB DATA DIRECTIONS CLRB RP0 ;SET RP0 TO LOWER REGISTER BANK CLRB SEROUT CLR STATS MOV RESULTCOUNTER,#8 ;---------------------------------------------------------------------------- MAINLOOP MOV TEMP,RB NOT TEMP SWAP TEMP AND TEMP,#00001111B MOV W,TEMP JMP PC+W JMP MODE0 JMP MODE1 JMP MODE2 JMP MODE3 JMP MODE4 JMP MODE5 JMP MODE6 JMP MODE7 JMP MODE8 JMP MODE9 JMP MODE10 JMP MODE11 JMP MODE12 JMP MODE13 JMP MODE14 ;---------------------------------------------------------------------------- ;MODE15: MODE15 JMP MAINLOOP ;---------------------------------------------------------------------------- ;MODE14: MODE14 JMP MAINLOOP ;---------------------------------------------------------------------------- ;MODE13: MODE13 JMP MAINLOOP ;---------------------------------------------------------------------------- ;MODE12: MODE12 JMP MAINLOOP ;---------------------------------------------------------------------------- ;MODE11: MODE11 JMP MAINLOOP ;---------------------------------------------------------------------------- ;MODE10: MODE10 JMP MAINLOOP ;---------------------------------------------------------------------------- ;MODE9: MODE9 JMP MAINLOOP ;---------------------------------------------------------------------------- ;MODE8: MODE8 JMP MAINLOOP ;---------------------------------------------------------------------------- ;MODE7: MODE7 JMP MAINLOOP ;---------------------------------------------------------------------------- ;MODE6:USE SERIN COMMANDS TO CONTROL MODULE MODE6 CALL RECEIVE CJE SERINDATA,#'1',MODE6A JMP MAINLOOP MODE6A CALL RANGETEST MOV SEROUTDATA,RANGERESULT CALL TRANSMIT JMP MAINLOOP ;---------------------------------------------------------------------------- ;MODE5:SERIN IS LOGIC ENABLE FOR MODE4 MODE5 JB SERIN,MODE4 JMP MAINLOOP ;---------------------------------------------------------------------------- ;MODE4:GENERATE CONTIUOUS 40kHz TRANSMISSION FOR CALIBRATION PURPOSES MODE4 ;CALL XMITON ;ENABLE TRANSMITTER DRIVER PINS JNB TIMERFLAG,$ ;WAIT HERE TIL TIMER RUNS OUT ;TIMERVALUE SET TO GIVE 40kHz ;NOP ;FREQUENCY FINE TUNE MOV TIMER,#TIMERVAL40K ;LOAD TIMER0 CLRB TIMERFLAG ;CLEAR TIMER0 OVERFLOW FLAG JB XMIT1,MODE4A ;TEST PRESENT O/P STATE NOP MOV RA,#XMITA ;FLIP O/P STATE JMP MAINLOOP MODE4A MOV RA,#XMITB ;FLIP O/P STATE JMP MAINLOOP ;---------------------------------------------------------------------------- ;MODE3:SERIN IS LOGIC ENABLE FOR MODE1 MODE3 JB SERIN,MODE1 JMP MAINLOOP ;---------------------------------------------------------------------------- ;MODE2:SERIN IS LOGIC ENABLE FOR MODE0 MODE2 JB SERIN,MODE0 JMP MAINLOOP ;---------------------------------------------------------------------------- ;MODE1:CONTINUOUS RANGING - SENDS DATA IN BINARY VIA SEROUT AT 9600 BAUD MODE1 CALL RANGETEST MOV SEROUTDATA,RANGERESULT CALL TRANSMIT JMP MAINLOOP ;---------------------------------------------------------------------------- ;MODE0:CONTINUOUS RANGING - SENDS DATA TO STAMP-LCD VIA SEROUT AT 9600 BAUD MODE0 JB STATS.0,MODE0RUN SETB STATS.0 ;INDICATE LCD INTIALIZED CALL POWERUPDELAY ;WAIT FOR LCD TO INITIALIZE MOV SEROUTDATA,#I ;LOAD "INSTRUCTION" VALUE CALL TRANSMIT MOV SEROUTDATA,#CLRLCD CALL TRANSMIT CALL DELAY5MS ;WRITE TITLE ON LCD LINE1 MOV SEROUTDATA,#I ;LOAD "INSTRUCTION" VALUE CALL TRANSMIT ;SEND VALUE TO LCD MOV SEROUTDATA,#LINE1 ;LOAD ADDRESS FOR CURSUR CALL TRANSMIT ;SEND VALUE TO LCD MOV COUNTER2,#10 ;LOAD NUMBER OF TABLE ENTRIES TO READ MOV TABLEENTRY,#10 ;LOAD TABLE ADDRESS TO READ CALL MODE0A ;PRINT LINE ON DISPLAY ;WRITE TITLE ON LCD LINE2 MOV SEROUTDATA,#I ;LOAD "INSTRUCTION" VALUE CALL TRANSMIT ;SEND VALUE TO LCD MOV SEROUTDATA,#LINE2 ;LOAD ADDRESS FOR CURSUR CALL TRANSMIT ;SEND VALUE TO LCD MOV COUNTER2,#10 ;LOAD NUMBER OF TABLE ENTRIES TO READ MOV TABLEENTRY,#20 ;LOAD TABLE ADDRESS TO READ CALL MODE0A ;PRINT LINE ON DISPLAY JMP MODE0RUN MODE0A CALL READTABLE ;GET TABLE VALUE MOV SEROUTDATA,TABLEVALUE ;LOAD VALUE TO SEND CALL TRANSMIT ;SEND VALUE TO LCD INC TABLEENTRY DJNZ COUNTER2,MODE0A RET MODE0RUN CALL RANGETEST ;RUN DISTANCE MEASUREMENT TEST CALL RANGEAVER MOV BIN,RANGEAVERAGE ;LOAD RANGE TEST RESULT TO CONVERT CALL BIN2BCD ;CONVERT BINARY RESULT TO BCD MOV SEROUTDATA,#I ;LOAD "INSTRUCTION" VALUE CALL TRANSMIT ;SEND VALUE TO LCD MOV SEROUTDATA,#LINE2+7 ;LOAD ADDRESS FOR CURSUR CALL TRANSMIT ;SEND VALUE TO LCD MOV TABLEENTRY,R1 ;LOAD 1'st (MSD) DIGIT TO SEND AND TABLEENTRY,#00001111B CALL READTABLE ;CONVERT NUMBER TO ASCII MOV SEROUTDATA,TABLEVALUE CALL TRANSMIT ;SEND VALUE TO LCD MOV TABLEENTRY,R2 ;LOAD 2'nd DIGIT TO SEND SWAP TABLEENTRY AND TABLEENTRY,#00001111B CALL READTABLE MOV SEROUTDATA,TABLEVALUE CALL TRANSMIT ;SEND VALUE TO LCD MOV TABLEENTRY,R2 ;LOAD 3'rd (LSD) TO SEND AND TABLEENTRY,#00001111B CALL READTABLE MOV SEROUTDATA,TABLEVALUE CALL TRANSMIT ;SEND VALUE TO LCD JMP MAINLOOP ;---------------------------------------------------------------------------- ;TRANSMIT: SENDS AN 8-BIT BYTE SERIALLY OUT THROUGH THE SEROUT PIN TRANSMIT ;CLC ;CLEAR CARRY STARTBIT SETB SEROUT ;BEGIN THE START BIT CALL BITDELAY ;DELAY PRODUCES BIT WIDTH FOR 9600 BAUD SENDDATA MOV BITCOUNTER,#8 ;INITIALIZE THE SERIAL DATA BIT COUNTER READDATA RR SEROUTDATA ;READ STATE OF BIT AND SEND INVERTED JC SENDA0 ;IF DATA BIT=1, SEND A 0 SENDA1 SETB SEROUT ;SEND A 1 JMP WAITABIT ;GO TO WAITABIT SENDA0 CLRB SEROUT ;SEND A 0 WAITABIT CALL BITDELAY ; DJNZ BITCOUNTER,READDATA ;WERE ALL BITS SENT YET? STOPBIT CLRB SEROUT ;CLEAR SEROUT TO BEGIN STOP BIT CALL BITDELAY ; ;CLRB SEROUT ;END STOP BIT ;RET ;---------------------------------------------------------------------------- ;WORD DELAY; 20 X 1 BIT = 2.083ms @ 20MHz WORDDELAY MOV DELAYCOUNTER2,#14 WDA MOV DELAYCOUNTER1,#255 DJNZ DELAYCOUNTER1,$ DJNZ DELAYCOUNTER2,WDA RET ;---------------------------------------------------------------------------- ;DELAY5MS: 5ms DELAY, USED AFTER SOME LCD INSTRUCTIONS DELAY5MS MOV DELAYCOUNTER2,#33 D5MSA MOV DELAYCOUNTER1,#255 DJNZ DELAYCOUNTER1,$ DJNZ DELAYCOUNTER2,D5MSA RET ;---------------------------------------------------------------------------- ;DELAY100MS: 100ms DELAY, USED AFTER SOME LCD INSTRUCTIONS DELAY100MS MOV DELAYCOUNTER3,#3 D100MSA MOV DELAYCOUNTER2,#217 D100MSB MOV DELAYCOUNTER1,#255 DJNZ DELAYCOUNTER1,$ DJNZ DELAYCOUNTER2,D100MSB DJNZ DELAYCOUNTER3,D100MSA RET ;---------------------------------------------------------------------------- ;RECEIVE:GETS A BYTE FROM SERIN AT 9600 BAUD - NOT DONE YET RECEIVE CLR SERINDATA RET ;---------------------------------------------------------------------------- ;NOTE: BIT DELAYS FOLLOWING PRODUCE 9600 BAUD RATE w/20MHz XTAL ;;--------------------------------------------------------------------------- ;TIME DELAY; 1 BIT = 104.166us @ 20MHz BITDELAY MOV DELAYCOUNTER1,#172 DJNZ DELAYCOUNTER1,$ RET ;---------------------------------------------------------------------------- ;;TIME DELAY; 1 BIT = 0.104ms @ 20MHz ;HALFBITDELAY MOV DELAYCOUNTER1,#86 ; DJNZ DELAYCOUNTER1,$ ; DJNZ DELAYCOUNTER1,HBDELAYA ; RET ;---------------------------------------------------------------------------- ;POWERUPDELAY; 1s @ 20MHz POWERUPDELAY MOV DELAYCOUNTER3,#250 PUDA MOV DELAYCOUNTER2,#255 PUDB MOV DELAYCOUNTER1,#26 DJNZ DELAYCOUNTER1,$ DJNZ DELAYCOUNTER2,PUDB DJNZ DELAYCOUNTER3,PUDA RET ;---------------------------------------------------------------------------- ;Binary number to be converted starts out stored like this: ; ; binary low byte ; BIN ; ######## ; ;BCD result ends up stored like this: ; ;R0 = digit5 (MSD) in lower nibble:digit4 ; R1 : R2 LSD ; dig3 : dig2 dig1 ; 0000 #### : #### #### BIN2BCD CLC ; clear the carry bit MOV COUNTER1,#8 CLR R1 CLR R2 LOOP8 RL BIN RL R2 RL R1 DJNZ COUNTER1,ADJDEC RET ADJDEC MOV FSR,#R2 CALL ADJBCD MOV FSR,#R1 CALL ADJBCD JMP LOOP8 ADJBCD MOV W,#3 ADD W,INDIRECT MOV TEMP,W SNB TEMP.3 ; test if result > 7 MOV INDIRECT,W MOV W,#48 ;OR #30H ADD W,INDIRECT MOV TEMP,W SNB TEMP.7 ; test if result > 7 MOV INDIRECT,W ; save as MSD RET ;---------------------------------------------------------------------------- RANGETEST MOV TIMER,#TIMERVAL40K ;LOAD TIMER0 CLRB TIMERFLAG ;CLEAR TIMER0 OVERFLOW FLAG MOV COUNTER1,#10 ;NUMBER OF HALFCYCLES TO XMIT ;CALL XMITON ;ENABLE TRANSMITTER DRIVER PINS RTA JNB TIMERFLAG,$ ;WAIT HERE TIL TIMER RUNS OUT ;TIMERVALUE SET TO GIVE 40kHz MOV TIMER,#TIMERVAL40K ;LOAD TIMER0 CLRB TIMERFLAG ;CLEAR TIMER0 OVERFLOW FLAG JB XMIT1,RTB ;TEST PRESENT O/P STATE NOP MOV RA,#XMITA ;FLIP O/P STATE JMP RTC RTB MOV RA,#XMITB ;FLIP O/P STATE RTC DJNZ COUNTER1,RTA ;CYCLE AGAIN? MOV RA,#XMITLOW ;PULL DOWN BOTH SIDES OF TRANSMITTER ;CALL MINRETURN ;RUN SHORT DELAY ;CALL XMITOFF ;DISABLE TRANSMITTER DRIVER PINS ;CALL MINRETURN ;RUN SHORT DELAY CALL WORDDELAY ;MAYBE REMOVE THIS LATER ; CLR TEMP ;RTG JB DETECT,RTF ;TEST FOR START OF VALID RANGE ; CALL RANGETICK ; DJNZ TEMP,RTG RTF CLR TEMP ;CLEAR RANGING ACCUMULATOR RTD JNB DETECT,SEERETURN;SEE A RETURN YET? CALL RANGETICK ;RUN SHORT DELAY BETWEEN RANGE INCREMENTS ADD TEMP,#1 JNZ RTD ;CHECK FOR OVER-RANGE JNC SEERETURN ;CHECK FOR MAX-RANGE DEC TEMP ;SET TO MAX RANGE SEERETURN MOV RANGERESULT,TEMP;SAVE TEST RESULT MOV COUNTER1,TEMP ;RUN A DELAY WHICH FILLS IN THE REST NOT COUNTER1 ; OF THE TIME A MAX RANGE HIT TAKES. JZ RTDONE RTE CALL RANGETICK DJNZ COUNTER1,RTE RTDONE RET ;---------------------------------------------------------------------------- ;RANGEAVER:AVERAGES RESULTS OF 8 TESTS BEFORE UPDATING RANGEAVER VALUE RANGEAVER ADD RANGEDATAL,RANGERESULT SNC INC RANGEDATAH DJNZ RESULTCOUNTER,RANGEAVEREND RR RANGEDATAH RR RANGEDATAL RR RANGEDATAH RR RANGEDATAL RR RANGEDATAH RR RANGEDATAL RR RANGEDATAH RR RANGEDATAL MOV RANGEAVERAGE,RANGEDATAL CLR RANGEDATAL CLR RANGEDATAH MOV RESULTCOUNTER,#8 RANGEAVEREND RET ;---------------------------------------------------------------------------- ;MINRETURN:TIME FOR SOUND TO TRAVEL 6" OUT AND 6" BACK = 885us ;(SPEED OF SOUND 13560"/s) MINRETURN MOV DELAYCOUNTER2,#6 MRA MOV DELAYCOUNTER1,#244 DJNZ DELAYCOUNTER1,$ DJNZ DELAYCOUNTER2,MRA RET ;;---------------------------------------------------------------------------- ;;RANGETICK:TIME FOR SOUND TO TRAVEL MAXIMUM RANGE (24') / 255 = 139us ;;(SPEED OF SOUND 13560"/s) ;RANGETICK MOV DELAYCOUNTER1,#229 ;VALUE WAS 230, BUT THIS IS ; ;ADJUSTED TO COMPENSATE FOR ; ;SURROUNDING INSTRUCTIONS IN LOOP ; ;WHICH CALLS THIS ROUTINE. ; DJNZ DELAYCOUNTER1,$ ; RET ;;---------------------------------------------------------------------------- ;RANGETICK:TIME FOR SOUND TO TRAVEL MAXIMUM RANGE (??') / 255 = ???us ;(SPEED OF SOUND 13560"/s) RANGETICK MOV DELAYCOUNTER1,#50 DJNZ DELAYCOUNTER1,$ RET ;---------------------------------------------------------------------------- ;XMITON:ENABLES TRANSMITTER DRIVERS XMITON SETB RP0 ;SET RP0 TO UPPER REGISTER BANK MOV RA,#XMITENABLE CLRB RP0 ;SET RP0 TO LOWER REGISTER BANK RET ;---------------------------------------------------------------------------- ;XMITOFF:DISABLES TRANSMITTER DRIVERS XMITOFF SETB RP0 ;SET RP0 TO UPPER REGISTER BANK MOV RA,#XMITDISABLE CLRB RP0 ;SET RP0 TO LOWER REGISTER BANK RET ;---------------------------------------------------------------------------- READTABLE MOV PCLATH,#LCDMESSAGES< ;TABLE = LCDMESSAGES MOV W,TABLEENTRY CALL LCDMESSAGES ;READ TABLE FROM LOCATION MESSAGE# ADDR ;CLRB PCLATH.3 CLR PCLATH MOV TABLEVALUE,W RET ;---------------------------------------------------------------------------- ORG 03E1H LCDMESSAGES JMP PC+W ;Mess# RETW '0','1','2','3','4','5','6','7','8','9';E0-9 1 RETW 'S','o','n','a','r','1',' ',' ',' ',' ';E10-19 2 RETW 'r','a','n','g','e',':',' ','-','-','-';E20-29 3 ;---------------------------------------------------------------------------- ;END OF LISTING
Mechanical ranging is old news, but it is seldom done really well. Here are a couple "better" ideas.
Bumpers don't give enough warning because they are generally simple on/off things that don't stick out very far. One of the most brilliant things I've ever seen was the design of a "sane" car that had a huge spring "bumper" that looped out in front of the car and extended a little out to each side. The attachment points on either side were hinged and then extended so that they crossed under the car. At that point, they intersected a "joystick" which ran up to the driver through a ball joint. I've drawn up a little picture and the red dot is the joystick. The left and right edges of the spring have rollers which are designed to follow a special curb at either side of each lane. When they are "squeezed" the result is that the stick is pushed forward, increasing the speed of the car. Contact with the front of the spring pulls the stick back, slowing the vehicle. Any misalignment of left to right pressure causes the car to steer to a corrective course and thereby follow the "curbs." Dead simple, hopefully reliable, and... proportional. It was designed by a little girl for her science fare entry and I've never been able to forget it. I wish I knew where she ended up.
For smaller applications, the connection points can be pots or other rotary encoders. The difference between the readings indicates front/back contact. The addition of the readings is proportional to the amount of left/right contact.
Huh? The idea here is to throw some small object and see if it bounces back. Won't that mess up the area? Not if you throw particles of the environment around you. "Throw" air. Look for the returning breeze. Or water, sand, etc... This is the same method that gives you that weird sense of solid objects close by when you are not able to see and the hair on your face or arms pick up the little currents of air that are bounding off the wall you will walk into just before you have time to stop. This is heightened the more skin exposed and can be quite accurate when leaving a pitch dark house out the back door without ones clothes. Don't ask.
It was first suggested to me by one of the few ladies on the PICList but the only implementation of this I have ever seen was an entry in a robot "firefighter" competition by an obviously brilliant engineer. He (sorry girls, it was a he) started off with the fact that the candle needed to be blown out. Rather than depend on accurate positioning, he realized that he could just "spit" air in all directions at the given height of the candle. So he mounted a whisper fan vertically and found an inverted cone-like baffle that would direct the air to all sides. After setting that up, he realized that the air from the top was being circulated back to the bottom faster when the bot was up near a wall. His bumpers became nothing more than flags and never contacted anything under normal operation. When he ran the 'bot we realized that another advantage of the proportional sensing of wall proximity allowed him to go much faster and round the corners without slowing down because he had some room between first sensing the wall and actually hitting it. The 'bot had no brains to speak of, it just turned away from any flag that dropped down. Sadly, the rules of the competition didn't allow the 'bot to just blow out the candle and keep going; the judges ruled that it had to actually sense the flame and this 'bot never had that ability! He did put out the candle faster than anyone else, just about every run.
See also:
Also known as a stud sensor. Good for short range sensing. They need to be
re-calibrated constantly so you need some other way of knowing that nothing
is in the area at all. I know of two versions:
In a word, unreliable except under very controlled conditions. They get used in bathrooms all the time to flush the toilets and turn on the sinks. In a nice SoCal restaurant, while exporting the byproduct of processing my pre-dinner drink, I kept hearing a sink turning on and off. On the way out I saw why: A high window was allowing sunlight to fall just on the inside of the sink at about the point that the sensor was looking. It would warm up, the sink would turn on, the water spray was enough to cool the sink and turn the water off again. Anyone who has used a TV remote from any distance should realize that IR is NOT a viable technology. If you must, see also:
file: /Techref/new/letter/news0310.htm, 43KB, , updated: 2024/1/22 18:33, local time: 2024/12/8 11:23,
18.97.9.170:LOG IN
|
©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://massmind.org/techref/new/letter/news0310.htm"> October 2003 MassMind Newsletter</A> |
Did you find what you needed? |
Welcome to massmind.org! |
Welcome to massmind.org! |
.