'Combot revision 3 'Combat robot for Justin's botshow by DLC 9/18/99 'Fully subsumptive architecture using FSMs for better response times ' 'What is a subsumtion architecture? In a nutshell it is a collection 'of behaviours that are totally independent, have zero coupling to 'each other and do not share state. In an ideal world, all of the 'behaviours would be running simultaneously. However, the Stamp II 'does not support multitasking, so rather than have any one function 'or behaviour monopolize the processor for its entire process I have 'made all behaviours Finite State Machines (FSM for short). This 'allows all of these rather simple behaviours to get a "slice" of 'time and release the processor for the next one in line in such a 'manner that things happen rather quickly in order, that closely 'resembles concurrency. I do this by having each behaviour save 'its current state so that it can come back to it and act on its 'time slice. I have located the routines in the main loop in such 'a manner as to allow a heirarchy of priority based on position. 'Namely, the behaviours closest to the "act" function will have 'priority over those further up the line. This isn't that difficult 'to do, check this code over if you don't believe it. Notice that 'having zero coupling also makes the programming much simpler, and 'allows for interesting behavioural patterns to show through that 'have NOT been pre-programmed! 'General constants and variables SPKR con 0 'speaker I/O port i var byte 'temporary variable detect var byte 'IRPD holder seed var word 'random word seed 'servo constants and variables SC con 2 'I/O port of TTT servo chip N2400 con 396 '8N1 2400 non-inverted serial drive var word 'motor variable, both wheels ldrive var drive.byte1 'left drive parts rdrive var drive.byte0 SRIGHT con 64 'servo 1 on TTT servo chip SLEFT con 0 'servo 0 on TTT servo chip servo var byte 'general servo value holder 'Wheel movement routine variables lright var byte 'last right wheel value used lleft var byte 'last left... 'servo attack arm routine variables ARM con 128 'servo 2 on TTT servo chip 'Motor movement values f con $0101 'forward bu con $3f3f 'reverse st con $1919 'stop (mostly) tl con $1901 'turn left fl con $1605 'turn left going forward tr con $0119 'turn right fr con $0617 'turn right going forward rl con $2f10 'rotate left rr con $102f 'rotate right 'Seek FSM constants and vars sDur var byte 'duration, times through FSM sDir var word 'seek direction 'Chase FSM constants and vars 'detect = in14*2 + in15 'Bumper vars and constants bDur var byte 'duration, times through FSM bDir var word 'actual direction to go 'i = in3 for bumper status 'watchEdge vars and constants RCT con 13 'edge detect sensor I/O port weDur var byte 'duration, times through FSM weDir var word 'direction to go eValue var word 'current CDS detector value leValue var word 'first (calibrated) CDS value 'Die FSM vars and constants 'uses i = in0 for value 'armAtk FSM vars and constants atDur var byte 'duration, times through FSM atDir var word 'direction to go atCen var byte 'at center flag 'uses i= in14*2 + in15 Startup: 'initialize variables, servos, and sensors sDur =0 atDur =0 bDur =0 weDur =0 eValue =0 high SC 'make sure serout is high gosub stopWheels 'turn off drive wheels gosub caledgedet 'calibrate edge detector gosub stoparms 'reset arms now gosub setupmotors 'get motors ready gosub startWheels 'and enable wheels freqout SPKR, 100,2000 'announce "I'm alive and ready" pause 500 'wait for a half second main: 'This is the main loop gosub seek 'wander mode gosub chase 'subsumes seek gosub bumper 'subsumes seek and chase gosub watchEdge 'subsumes seek, chase and bumper gosub act 'do what won above gosub die 'subsume all functions gosub armAtk 'independent, die will subsume this goto main end 'need this to keep Stamp in line! '=============================== '= Robotic Behaviours = '=============================== seek: 'wander, seeking enemy if sDur <> 0 then seDec 'do this if sDur is 0 random seed 'random direction i = seed & %111 'mask off for 0-7 only lookup i,[f,tr,tl,f,rr,f,fr],sDir random seed 'random direction and duration sDur = seed & %111111 'mask for 64 choices sDur = sDur + 20 'a bit more duration seDec: 'sDur <>0, so do something sDur = sDur - 1 'we have been here drive = sDir return chase: 'enemy found, go get it! detect = in14*2 + in15 'look at IRPD branch detect,[cdone,cleft,cright,cfront] cfront: drive = f goto cdone cleft: drive = tl goto cdone cright: drive = tr cdone: return bumper: 'bumped them, backup and charge again if bDur <> 0 then bDec 'only act if i = in3 'get bumper status if i <> 0 then bdone 'only act if bumper = 0 (hit) bDir = bu bDur = 50 bDec: 'we are acting on a bumper hit bDur = bDur - 1 'we have acted drive = bDir bDone: return watchEdge: 'look for "end of the world" if weDur <> 0 then weDec 'only do this if we aren't already high RCT pause 1 rctime RCT,1,eValue 'we now have a look-see if eValue < leValue then weOK weDur = 80 'times through this FSM weDir = bu 'backup weDec: if weDur >40 then weDec2 weDir = rr 'rotate away weDec2: weDur = weDur - 1 drive = weDir weOK: return die: 'look for kill switch and maybe die i = in0 'get status of kill button if i <> 0 then dOK gosub stopwheels 'Oh man! we got hit gosub stoparms freqout SPKR,500,8000 freqout SPKR,1000,800 stop 'GAME OVER dOK: return act: 'This runs the servo wheels servo = SLEFT + ldrive 'get left motor value if servo = lleft then doRight serout SC,N2400,[servo] 'only do this if different lleft = servo 'new last value doRight: servo = SRIGHT + rdrive if servo = lright then aDone serout SC,N2400,[servo] 'only do this if different lright = servo 'new last value aDone: return armAtk: 'muscle the arms around now if atDur <> 0 then atCurrent detect = in14*2 + in15 'IRPD value if detect <> 3 then atNosee atDur = 60 'duration of a swing atDir = 08 + ARM 'arm servo serout SC,N2400,[atDir] atCen = 0 'reset centered flag atCurrent: if atDur > 30 then atDec atDir = 52 + ARM 'swing the other way serout SC,N2400,[atDir] atDec: atDur = atDur - 1 goto atDone atNosee: if atCen = 1 then atDone atDir = 31 + ARM 'center arms serout SC,N2400,[atDir] atCen = 1 'set centered flag atDone: return '-------------------------------- '- Routines used above - '-------------------------------- stopwheels: 'stops wheels from moving serout SC,N2400,[00] return startwheels: 're-starts wheels serout SC,N2400,[$40] return stoparms: 'centers and stops the arms servo = 31 + 128 serout SC,N2400,[servo] 'center attack arms return setupmotors: i = $19 + SLEFT 'set motors to stop and enable them serout SC,N2400,[i] i = $19 + SRIGHT serout SC,N2400,[i] return caledgedet: 'calibrate line sensor high RCT 'charge sensor cap pause 1 rctime RCT,1,leValue 'get normal "light" value leValue = leValue + 45 'bias for "dark" boundry return