;; ALFI (Animatronic Lego Face for Interaction) Program ;; Version 3.5 ;; Final Version 5/24/2009 ;; By Edward Stumpf, Class of 2009 ;; Fixed eye lid range, fixed blinking to be every 5 seconds. menu 1 [run] global [ear-position mouth-position eye-position lids-position state rightLevel leftLevel levelDiff boredTime blinkTime] ;; ear-position: 1=up, 0=down ;; mouth-position: 1=open, 0=closed ;; eye-position: 2=left, 1=right, 0=center ;; lids-position: 2=up, 1=down, 0=center ;; state: 2=bored, 1=alert, 0=asleep ;; rightLevel is the level of the right light sensor ;; leftLevel is the level of the left light sensor ;; levelDiff is the difference between the two sensors ;; boredTime tracks what time it is for timing bored ;; blinkTime is used for blinks to run setrightLevel RL-sense setleftLevel LL-sense setlevelDiff (leftLevel - rightLevel) setup loop [ ifelse (and (LL-sense < (RL-sense + levelDiff + 4)) (LL-sense > (RL-sense + levelDiff - 4))) [ ;; either it sees something in the center range or it sleeps ;; either way, eyes center eye-center ifelse (and (LL-sense < (leftLevel + 4)) (RL-sense < (rightLevel + 4))) [ ;; both sensor are at base level ;; determine whether should be bored or asleep if (state = 1) [ ;; first change to bored sets timer go-bored setboredTime timer ] ifelse (or (and (state = 2) ((timer - boredTime) > 20000)) (state = 0)) [ ;; if bored for 20 seconds, transition to sleep ;; if already asleep, stay asleep (nap time) go-sleep ] [ ;; otherwise stay bored go-bored ] ] [ ;; sensors saw something, so be alert go-alert ] ] [ ;; something has been seen go-alert if (and (LL-sense > leftLevel) (LL-sense > (RL-sense + levelDiff))) [ ;; if the left input is greater than the right, look left eye-left ] if (and (RL-sense > rightLevel) (LL-sense < (RL-sense + levelDiff))) [ ;; if the right input is greater than the left, look left eye-right ] ] ] end to go-alert if (or (state = 0) (state = 2)) [ ;; was asleep / bored ear-up mouth-open lids-up setstate 1 setblinkTime timer ] ;; blink every 5 seconds if ((timer - blinkTime) > 5000) [ blink setblinkTime timer ] ;; random ear wiggle if ((random 60) = 0) [ ear-wiggle ] end to go-sleep if (state = 2) [ mouth-close ear-down wait 2 lids-down setstate 0 ] end to go-bored if (state = 1) [ lids-center eye-center ear-down mouth-close setstate 2 setblinkTime timer ] ;; blink every 5 seconds if ((timer - blinkTime) > 5000) [ blink setblinkTime timer ] ;; random yawn if ((random 80) = 0) [ yawn ] ;; random ear wiggle if ((random 100) = 0) [ ear-wiggle ] end to setup ;; starts off asleep setstate 0 seteye-position 0 ;; center setlids-position 1 ;; down setmouth-position 0 ;; closed setear-position 0 ;; down eye-motor setpower 1 ear-motor setpower 1 mouth-motor setpower 1 lids-motor setpower 1 end ;;;;;;;;;;;;;;;;;;; ;; Eye Functions ;; ;;;;;;;;;;;;;;;;;;; ;; eye-position: 2=left, 1=right, 0=center ;; thisway = left, thatway = right to eye-left if (eye-position = 0) [ ;; center to left break-beam-eye-this 25] if (eye-position = 1) [ ;; right to left break-beam-eye-this 50] seteye-position 2 end to eye-right if (eye-position = 0) [ ;; center to right break-beam-eye-that 25] if (eye-position = 2) [ ;; left to right break-beam-eye-that 50] seteye-position 1 end to eye-center if (eye-position = 2) [ ;; left to center break-beam-eye-that 25] if (eye-position = 1) [ ;; right to center break-beam-eye-this 25] seteye-position 0 end ;;;;;;;;;;;;;;;;;;; ;; Ear Functions ;; ;;;;;;;;;;;;;;;;;;; ;; ear-position: 1=up, 0=down to ear-wiggle if (state = 1) [ ;; alert wiggle ear-down ear-up ] if (state = 2) [ ;; bored wiggle ear-up wait 5 ear-down ] end to ear-up if (not(ear-position = 1)) [ ear-motor thisway on waituntil[ear-up-sense] ear-motor off setear-position 1] end to ear-down if (not(ear-position = 0)) [ ear-motor thatway on waituntil[ear-down-sense] ear-motor off setear-position 0] end ;;;;;;;;;;;;;;;;;;;;; ;; Mouth Functions ;; ;;;;;;;;;;;;;;;;;;;;; ;; mouth-position: 1=open, 0=closed to yawn mouth-open wait 10 mouth-close end to mouth-open if (not(mouth-position = 1)) [ mouth-motor thatway on waituntil[mouth-open-sense] mouth-motor off setmouth-position 1] end to mouth-close if (not(mouth-position = 0)) [ mouth-motor thisway on waituntil[mouth-close-sense] mouth-motor off setmouth-position 0] end ;;;;;;;;;;;;;;;;;;;; ;; lids Functions ;; ;;;;;;;;;;;;;;;;;;;; ;; lids-position: 2=up, 1=down, 0=center to blink if (state = 1) [ ;; alert full blink lids-down wait 2 lids-up ] if (state = 2) [ ;; bored half blink (think tired) lids-down wait 2 lids-center ] end to lids-up if (lids-position = 0) [ break-beam-lids-up 20 setlids-position 2] if (lids-position = 1) [ break-beam-lids-up 40 setlids-position 2] end to lids-down if (lids-position = 0) [ break-beam-lids-down 20 setlids-position 1] if (lids-position = 2) [ break-beam-lids-down 40 setlids-position 1] end to lids-center if (lids-position = 2) [ break-beam-lids-down 20 setlids-position 0] if (lids-position = 1) [ break-beam-lids-up 20 setlids-position 0] end ;;;;;;;;;;;;;;;;;;;;;; ;; Helper Functions ;; ;;;;;;;;;;;;;;;;;;;;;; ;; functions count the specified number of times the IR beam is broken to break-beam-eye-this :count eye-motor thisway on repeat :count [ waituntil[(eye-sense) > 50] waituntil[(eye-sense) < 50] ] eye-motor off end to break-beam-eye-that :count eye-motor thatway on repeat :count [ waituntil[(eye-sense) > 50] waituntil[(eye-sense) < 50] ] eye-motor off end to break-beam-lids-down :count lids-motor thisway on repeat :count [ waituntil[(lids-sense) > 50] waituntil[(lids-sense) < 50] ] lids-motor off end to break-beam-lids-up :count lids-motor thatway on repeat :count [ waituntil[(lids-sense) > 50] waituntil[(lids-sense) < 50] ] lids-motor off end ;;;;;;;;;;;;;;;;;; ;; Sensor Names ;; ;;;;;;;;;;;;;;;;;; to ear-up-sense output switch 7 end to ear-down-sense output switch 8 end to mouth-close-sense output switch 9 end to mouth-open-sense output switch 10 end to eye-emit output switch 14 end to eye-sense output sensor 0 end to lids-emit output switch 15 end to lids-sense output sensor 1 end to LL-sense ;; red block ;; left side (for robot) output sensor 6 end to RL-sense ;; yellow block ;; right side (for robot) output sensor 5 end ;;;;;;;;;;;;;;;;; ;; Motor Names ;; ;;;;;;;;;;;;;;;;; to ear-motor a, end to mouth-motor b, end to eye-motor c, end to lids-motor d, end