10 REM LINE FOLLOWER 20 REM Nigel Hunter 30 REM (c) CET 1983 Published by BBC Publications 40 REM version 2.0 50 : 60 port = &FE60 70 ?&FE62 = 15 80 PROCmotors_on 90 : 100 ON ERROR IF ERR=17 GOTO 190 ELSE REPORT:PRINT" at line ";ERL:END 110 : 120 MODE7 130 PROCoff 140 PROCsetup 150 PROCcharacters 160 PROCtitle(8) 170 PROCspace7 (23) 180 : 190 MODE7 200 PROCoff 210 PROCmenu 220 IF answer$ = "3" THEN MODE 7 : PROCcomplete : END 230 CLS 240 PROCsensor_choice 250 PROCoptimum 260 MODE5 270 PROCoff 280 PROCscreen_display 290 PROCrun 300 PROCend 310 MODE 7 320 PROCcomplete 330 PRINT 340 END 350 : 360 : 370 : 380 DEF PROCcharacters 390 VDU 23,224,24,60,126,255,24,24,24,24 400 VDU 23,225,16,48,112,255,255,112,48,16 410 VDU 23,226,8,12,14,255,255,14,12,8 420 ENDPROC 430 : 440 DEF PROCdelay (count) 450 LOCAL delay 460 FOR delay = 1 TO count : NEXT 470 ENDPROC 480 : 490 DEF PROCmove1 (direction,distance) 500 LOCAL I 510 pulse = (direction OR 2) 520 FOR I = 1 TO distance 530 ?port = direction : PROCdelay (speedcontrol) 540 ?port = pulse : PROCdelay (2) 550 NEXT I 560 ENDPROC 570 : 580 DEF PROCend 590 REM Switches motors off, resets cursor, EDIT & ESCAPE keys, buffers, and PRINT format 600 PROCmotors_off 610 PROCon 620 *FX 4 630 *FX 229 640 *FX 15 650 @% = 10 660 ENDPROC 670 : 680 DEF PROCmanual 690 LOCAL I$ 700 PRINT TAB(22,17) FNsensor1 710 REM flush buffers 720 *FX 15,0 730 REPEAT 740 I$ = FNwait 750 REM Detect arrow keys 760 *FX 4,1 770 IF INKEY (uparrow) THEN PROCmove3 (forward,uparrow) 780 IF INKEY (downarrow) THEN PROCmove3 (backward,downarrow) 790 IF INKEY (leftarrow) THEN PROCmove3 (left,leftarrow) 800 IF INKEY (rightarrow) THEN PROCmove3 (right,rightarrow) 810 PRINT TAB(22,17) FNsensor1 820 UNTIL INKEY(space) 830 ENDPROC 840 : 850 DEF PROCmenu 860 CLS 870 PRINT TAB(0,1) CHR$(130) "BBC Buggy" 880 PRINT TAB(4,5) CHR$(134) "Choose the type of line you";TAB(4,7) CHR$(134) "wish the Buggy to follow:" 890 PRINT TAB(8,11);"1 White line";TAB(8,13);"2 Black line";TAB(8,15);"3 Exit from program" 900 PRINT TAB(4,19) " Your choice? "; : answer$ = FNinput (1,"1,2,3") 910 IF answer$ = "1" THEN RESTORE 2270 ELSE RESTORE 2280 920 READ A$,B$,light,A,B,device$ 930 ENDPROC 940 : 950 DEF PROCmotors_off 960 ?port = 8 970 ENDPROC 980 : 990 DEF PROCmotors_on 1000 ?port = 0 1010 ENDPROC 1020 : 1030 DEF PROCmove2 (direction,angle) 1040 LOCAL counter 1050 counter = 0 1060 pulse = (direction OR 2) 1070 REPEAT 1080 ?port = direction : PROCdelay (speedcontrol) 1090 ?port = pulse : PROCdelay (4) 1100 counter = counter + 1 1110 UNTIL counter = angle OR FNsensor1 > optimum 1120 ?port = 0 1130 ENDPROC 1140 : 1150 DEF PROCmove3 (direction,key) 1160 LOCAL pulse 1170 pulse = (direction OR 2) 1180 REPEAT 1190 ?port = direction : PROCdelay(4) 1200 ?port = pulse : PROCdelay(2) 1210 PRINT TAB(22,17) FNsensor1 1220 UNTIL INKEY(key) = FALSE 1230 ENDPROC 1240 : 1250 DEF PROCoptimum 1260 REM flush buffers 1270 *FX 15,0 1280 PRINT TAB(5,13) CHR$ 134 "Drive the Buggy onto the" 1290 PRINT TAB(5,14) CHR$ 134 "background." 1300 PROCcentre ("Press SPACE to record reading",21) 1310 PROCcentre ("Level = ",17) 1320 PROCmanual 1330 level2 = FNsensor1 1340 REM flush buffers 1350 *FX 15,0 1360 PRINT TAB(5,13) CHR$ 133 "Drive the Buggy to the " 1370 PRINT TAB(5,14) CHR$ 133 "start of the " A$ " Line." 1380 PROCcentre ("Press SPACE to record reading",21) 1390 PROCmanual 1400 level1 = FNsensor1 1410 PRINT TAB(5,13) CHR$ 131 "The levels are recorded." 1420 PROCcentre (CHR$ 131 + "Ready to follow the " + A$ + " line.",14) 1430 PROCcentre ("",17) 1440 PROCcentre ("",21) 1450 PROCspace7 (23) 1460 optimum = INT(level2+(3/4*(level1-level2))+0.5) 1470 ENDPROC 1480 : 1490 DEF PROCrun 1500 VDU 19,2,A,0,0,0 : PRINT TAB(10,25) CHR$(224) 1510 PROCdelay (500) 1520 REPEAT 1530 VDU 19,2,A,0,0,0 : PRINT TAB(10,25)CHR$(224) 1540 PROCmove1 (forward,travel) 1550 PRINT TAB(10,20) FNsensor1 1560 IF FNsensor1 < optimum THEN PROCturn 1570 PRINT TAB(10,20) FNsensor1 1580 UNTIL end 1590 ENDPROC 1600 : 1610 DEF PROCturn 1620 VDU 19,2,B,0,0,0 1630 angle=35 : maxangle=70 : sensor=0 : direction=store 1640 PROCdelay(50) 1650 REPEAT 1660 REPEAT 1670 IF direction = right THEN PRINT TAB(10,25) CHR$(226) ELSE PRINT TAB(10,25) CHR$(225) 1680 PROCmove2 (direction,angle) 1690 PRINT TAB(10,20) " " ; TAB(10,20) FNsensor1 1700 IF FNsensor1 > optimum THEN sensor = 1 1710 IF sensor THEN UNTIL sensor : UNTIL sensor : store = direction : ENDPROC 1720 IF direction = right THEN direction = left : PRINT TAB(10,25) CHR$(226) ELSE direction = right : PRINT TAB(10,25) CHR$(225) 1730 angle = 2 * angle 1740 UNTIL angle > maxangle OR sensor 1750 PROCmove2 (direction,angle/4) : REM turn to centre 1760 maxangle=500 1770 UNTIL angle > maxangle 1780 end = 1 1790 ENDPROC 1800 : 1810 DEF PROCscreen_display 1820 PRINT TAB(4,1) "Line Follower" 1830 REM Lower window (text) 1840 VDU 28,0,30,19,19 : COLOUR 129 : CLS 1850 PROCoff 1860 REM upper window (graphics) 1870 MOVE 560,100 : DRAW 560,300 1880 DRAW 760,300 : DRAW 760,100 1890 DRAW 560,100 1900 VDU 24,540;480;780;720; : GCOL0,129 : CLG 1910 VDU 24,560;500;760;700; : GCOL0,130 : CLG : GCOL0,3 1920 VDU 26 1930 PRINT TAB(2,26) A$ TAB(14,26) B$ 1940 PRINT TAB(4,28) level1 ; TAB(16,28) level2 ; TAB(10,20) optimum 1950 PROCdelay (500) 1960 ENDPROC 1970 : 1980 DEF PROCsensor_choice 1990 PROCtitle(3) 2000 PRINT TAB(5,10) "This uses the " device$ " mounted" 2010 PRINT TAB(5,11) "on the front of the Buggy." 2020 ENDPROC 2030 : 2040 DEF FNsensor1 = ADVAL(light) DIV 1000 2050 : 2060 DEF PROCsetup 2070 REM Detect arrow keys 2080 *FX 4,1 2090 REM keyboard INKEY values 2100 uparrow = -58 : forward = 0 2110 downarrow = -42 : backward = 5 2120 leftarrow = -26 : left = 4 2130 rightarrow = -122: right = 1 2140 nokey = -129: space = -99 2150 REM other variables 2160 end =0 : store = left 2170 travel = 12 2180 speedcontrol= 10 2190 @%=02 2200 ENDPROC 2210 : 2220 DEF PROCtitle (line%) 2230 PROCdouble(CHR$(130)+" LINE FOLLOWER ",-1,line%) 2240 ENDPROC 2250 : 2260 : 2270 DATA White,Black,1,7,0,LDR 2280 DATA Black,White,2,0,7,BCR 2290 : 2300 : 2310 : 2320 REM Utilities 2330 : 2340 DEF FNcentre (text$) =19-LEN(text$) DIV 2 2350 : 2360 DEF PROCcentre (text$,line%) 2370 PRINT TAB(1,line%) SPC 38 2380 PRINT TAB(FNcentre(text$),line%) text$ 2390 ENDPROC 2400 : 2410 DEF PROCcomplete 2420 CLS 2430 PROCdouble (CHR$ 131 +"Mission completed.",-1,10) 2440 PROCend 2450 ENDPROC 2460 : 2470 DEF PROCdouble (text$,X,Y) 2480 IF X<0 THEN X = FNcentre (text$) 2490 PRINT TAB(X-1,Y ) CHR$(141) ; text$ 2500 PRINT TAB(X-1,Y+1) CHR$(141) ; text$ 2510 ENDPROC 2520 : 2530 DEF PROCoff VDU 23;11,0;0;0;0 : ENDPROC 2540 DEF PROCon VDU 23;11,255;0;0;0: ENDPROC 2550 : 2560 DEF FNinput (length,allowed$) 2570 LOCAL input$,ascii 2580 PRINT STRING$(length,"."); STRING$(length,CHR$ 8); 2590 PROCon:*FX 15 2600 REPEAT ascii = ASC FNwait 2610 IF ascii = 127 AND LEN(input$) >0 THEN input$ = LEFT$(input$,LEN(input$)-1) : VDU ascii 2620 IF INSTR(allowed$,CHR$ ascii) AND LEN(input$)13 AND ascii<>127 THEN ascii = 7 2630 IF ascii = 13 AND LEN(input$)<1 THEN ascii = 7 2640 IF ascii = 127 THEN VDU 46,8 ELSE VDU ascii 2650 UNTIL ascii = 13 : PRINT : PROCoff 2660 =input$ 2670 : 2680 DEF PROCspace7 (line%) 2690 LOCAL I$ 2700 PROCcentre ("Press the SPACE BAR to continue.",line%) 2710 *FX 15 2720 REPEAT I$ = FNwait : UNTIL INKEY(space) 2730 REPEAT UNTIL INKEY(nokey) 2740 PRINT TAB(5,23); SPC(38) 2750 ENDPROC 2760 : 2770 : 2780 DEF FNwait 2790 LOCAL I$ 2800 *FX 4,1 2810 REPEAT 2820 I$=INKEY$(10000) 2830 IF I$="" THEN PROCmotors_off ELSE PROCmotors_on 2840 UNTIL I$<>"" 2850 *FX 4 2860 =I$ 2870 :