I recently built a new prop and am stuck a the coding phase.
a)Basically I would like a servo to randomly (if possible) turn between positions as if a patient on the table is confused as to where they are.
b)Then, when a mat switch is triggered, the servo sweeps side to side as if the patient is in pain and screaming. Then it would reset itself to the beginning.
I have a VMusic2 hooked up with 2 sound files (whimper, scream). RX is pin 15, TX is pin 14
I also have a RC-4 hooked up with 4 lights. 2 of the lights will be on when part 'a' is running. Then when part 'b' is triggered, the other two turn on. That is on pin 13.
The matswitch is on pin 12 and the servo is pin 8.
Any help is appreciated!
I have this question for about this part of your program
Quote
a)Basically I would like a servo to randomly (if possible) turn between positions as if a patient on the table is confused as to where they are.
Does the servo need to move when the prop is waiting to be triggered? Otherwise, I don't for see any other questions right now.
Yes, i would like it to bsnut
So, here is your program and may need to be tweaked a little bit to meet your need. It was based on VMusic program that Jon wrote, which was cut and pasted into your program.
One thing, I can say it was fun to write, all 3 hours worth. I thank Jon for his code it was a big help.
' =========================================================================
'
' File......Dotor Patient Prop.bs2
' Purpose...
' Author....
' E-mail....
' Started...
' Updated...
'
' {$STAMP BS2}
' {$PBASIC 2.5}
'
' =========================================================================
' -----[ Program Description ]---------------------------------------------
'a)Basically I would like a servo to randomly (IF possible) turn between
'positions as if a patient on the table is confused as to where they are.
'
'b)Then, when a mat switch is triggered, the servo sweeps side to side as
' IF the patient is in pain AND screaming. Then it would reset itself to
' the beginning.
'
'Have a VMusic2 hooked up with 2 sound files (whimper, scream).
'RX is PIN 15, TX is PIN 14
'
'I also have a RC-4 hooked up with 4 lights. 2 of the lights will be ON
'when part 'a' is running.
'
'Then when part 'b' is triggered, the other two turn on. That is on pin 13.
'
'The matswitch is on PIN 12 and the servo is PIN 8.
'
'
' -----[ Revision History ]------------------------------------------------
' -----[ I/O Definitions ]-------------------------------------------------
RX PIN 15 ' no ULN / SETUP = UP
TX PIN 14 ' no ULN / SETUP = UP
Sio PIN 13 ' no ULN / SETUP = UP
Trigger PIN 12 ' SETUP = DN / matswitch
Servo PIN 8 ' patient's head servo
' -----[ Constants ]-------------------------------------------------------
IsOn CON 1 ' for active-high in/out
IsOff CON 0
#SELECT $STAMP
#CASE BS2, BS2E, BS2PE
T2400 CON 396
T38K4 CON 6
#CASE BS2SX, BS2P
T2400 CON 1021
T38K4 CON 45
#CASE BS2PX
T2400 CON 1646
T38K4 CON 84
#ENDSELECT
SevenBit CON $2000
Inverted CON $4000
Open CON $8000
Baud CON Open + T38K4 ' fast baud for accessories
VolMax CON $00
VolMin CON $FE
Headcentered CON 750 ' head centered
Headleft CON 1000 ' head counterclockwise
Headright CON 500 ' head clockwise
Whimperlts CON %0011 ' whimper lts on RC-4 K1 and K2
Screamlts CON %1100 ' scream lts on RC-4 K3 and K4
Screamspeed CON 20 ' sets scream servo speed. change to meet
' your needs
Screamtime CON 2080 ' set "Screamtime" in millisecond to meet
' sound file run time
' -----[ Variables ]-------------------------------------------------------
lottery VAR Byte ' randomize lottery value for servo speed
timer VAR Byte
servopos VAR Byte ' servo position var
servospeed VAR Byte ' servo speed var
whimperspeed VAR Byte ' whimper speed based on lottery value
idx VAR Byte ' loop controller
theMP3 VAR Byte ' MP3 file pointer
char VAR Byte ' character value
eePntr VAR Word ' EEPROM memory pointer
mute VAR Byte
panCtrl VAR Word
muteLeft VAR panCtrl.BYTE0
muteRight VAR panCtrl.BYTE1
' -----[ Initialization ]--------------------------------------------------
Reset:
'OUTS = $0000 ' clear all outputs
'DIRS = $3FFF ' make P0-P13 outputs
SEROUT Sio, Baud, ["!RC4", %00, "X"] ' set RC-4 all off
PAUSE 2250 ' let VMUSIC power up
GOSUB VM_Stop ' stop if playing
GOSUB VM_Wait_Prompt
FOR servopos = 1 TO 150
PULSOUT Servo, Headcentered
PAUSE 20
NEXT
' -----[ Program Code ]----------------------------------------------------
Main:
timer = 0
Main_Preshow:
RANDOM lottery ' randomize lottery value
whimperspeed = lottery // 25 + 10 ' set whimperspeed 100 to 350
servospeed = whimperspeed ' set servospeed
SEROUT Sio, Baud, ["!RC4", %00, "S", Whimperlts] ' set whimper lts on
theMP3 = 0
GOSUB VM_Play
GOSUB VM_Wait_Start
FOR servopos = Headleft TO Headright STEP servospeed
PULSOUT Servo, servopos
PAUSE 10
NEXT
FOR servopos = Headright TO Headleft STEP servospeed
PULSOUT Servo, servopos
PAUSE 10
NEXT
DO WHILE (timer < 100) ' wait for 0.1s signal
PAUSE 5 ' loop pad
timer = timer + 5 * Trigger ' update timer
LOOP
IF Trigger = 0 THEN Main_Preshow ' do Main_Preshow if Trigger is false
Start_Show:
GOSUB VM_Stop ' stop VMusic if playing "whimper"
theMP3 = 1
GOSUB VM_Play
GOSUB VM_Wait_Start
SEROUT Sio, Baud, ["!RC4", %00, "S", Screamlts] ' set scream lts on
servospeed = Screamspeed
Scream:
timer = 0 ' reset "timer" to be reused
DO
FOR servopos = Headright TO Headleft STEP servospeed
PULSOUT Servo, servopos
PAUSE 10
NEXT
FOR servopos = Headleft TO Headright STEP servospeed
PULSOUT Servo, servopos
PAUSE 10
NEXT
timer = timer + 20
LOOP UNTIL (timer = 2080) '
GOTO Main
' -----[ Subroutines ]-----------------------------------------------------
VM_Wait_Prompt:
SERIN RX, Baud, [WAIT(">")]
RETURN
' -------------------------------------------------------------------------
' Pass file # (index in DATA table) to play in "theMP3"
VM_Play:
SEROUT TX, Baud, ["VPF "]
GOTO Play_MP3
' -------------------------------------------------------------------------
' Pass file # (index in DATA table) to play in "theMP3"
VM_Repeat:
SEROUT TX, Baud, ["VRF "]
' -------------------------------------------------------------------------
' Pass file # (index in DATA table) to play in "theMP3"
Play_MP3:
eePntr = (8 * theMP3) + Song_List
Send_Name: ' send file title
FOR idx = 1 TO 8 ' max is 8 characters
READ eePntr, char ' get a character
IF char = 0 THEN Finish_Cmd ' if 0, we're at end
SEROUT TX, Baud, [char]
eePntr = eePntr + 1
NEXT
Finish_Cmd:
SEROUT TX, Baud, [".MP3", CR] ' send extention + CR
RETURN
' -------------------------------------------------------------------------
VM_Wait_Start:
SERIN RX, Baud, [WAIT("T $")]
RETURN
' -------------------------------------------------------------------------
VM_Stop:
SEROUT TX, Baud, ["VST", CR]
RETURN
' -------------------------------------------------------------------------
' Pass mute level (0 = loudest, 254 = muted) in "mute"
VM_Mute:
mute = mute MAX VolMin ' limit per spec
' copy to pan register for future use
muteLeft = mute
muteRight = mute
SEROUT TX, Baud, ["VSV ", DEC mute, CR]
RETURN
' -------------------------------------------------------------------------
' Pass levels (0 = loudest, 254 = muted) in "muteLeft" and "muteRight"
'
' NOTE: The VPF/VRF commands seems to reset volume levels so you must use
' a pan command while the file is playing for it to work.
'
' NOTE: Over-use can result is unwanted audio "clicks" and "pops"
VM_Pan:
muteLeft = muteLeft MAX $FE ' limit per spec
muteRight = muteRight MAX $FE
SEROUT TX, Baud, ["VWR $0B", HEX4 panCtrl, CR]
RETURN
' -----[ User Data ]-------------------------------------------------------
' File names are stored on 8-byte boundaries -- this is very important for
' correct program operation. This strategy uses a little more EE space but
' is easier to update and maintain
Song_List DATA @$00, "whimper" ' theMP3 = 0
DATA @$08, "scream" ' theMP3 = 1
Wow! Thanks! I cant wait to get this loaded up to see it run!!
Yes, I would love see it work as well. But, I found minor mistake, that may not let your program work right and here it is. You don't need this code below and the way you fixed it, is do what I did below. Which is to comment it out. It should work after you do this.
'OUTS = $0000 ' clear all outputs
'DIRS = $3FFF ' make P0-P13 outputs
Here is my updated code. It works with sound now. I just had to add a line for the vmusic baud because the fast baud wasn't working. Also, the servo doesn't move at all when the show starts, it just turns to a position and doesn't move until triggered to scream and then it moves to another position.
Oh and the scream portion never returns to the main program after it is completed.
' =========================================================================
'
' File......Dotor Patient Prop.bs2
' Purpose...
' Author....
' E-mail....
' Started...
' Updated...
'
' {$STAMP BS2}
' {$PBASIC 2.5}
'
' =========================================================================
' -----[ Program Description ]---------------------------------------------
'a)Basically I would like a servo to randomly (IF possible) turn between
'positions as if a patient on the table is confused as to where they are.
'
'b)Then, when a mat switch is triggered, the servo sweeps side to side as
' IF the patient is in pain AND screaming. Then it would reset itself to
' the beginning.
'
'Have a VMusic2 hooked up with 2 sound files (whimper, scream).
'RX is PIN 15, TX is PIN 14
'
'I also have a RC-4 hooked up with 4 lights. 2 of the lights will be ON
'when part 'a' is running.
'
'Then when part 'b' is triggered, the other two turn on. That is on pin 13.
'
'The matswitch is on PIN 12 and the servo is PIN 8.
'
'
' -----[ Revision History ]------------------------------------------------
' -----[ I/O Definitions ]-------------------------------------------------
'RX PIN 15 ' no ULN / SETUP = UP
TX PIN 14 ' no ULN / SETUP = UP
Sio PIN 13 ' no ULN / SETUP = UP
Trigger PIN 12 ' SETUP = DN / matswitch
Servo PIN 8 ' patient's head servo
' -----[ Constants ]-------------------------------------------------------
IsOn CON 1 ' for active-high in/out
IsOff CON 0
#SELECT $STAMP
#CASE BS2, BS2E, BS2PE
T2400 CON 396
T38K4 CON 6
T9600 CON 84
#CASE BS2SX, BS2P
T2400 CON 1021
T38K4 CON 45
#CASE BS2PX
T2400 CON 1646
T38K4 CON 84
#ENDSELECT
SevenBit CON $2000
Inverted CON $4000
Open CON $8000
VMBaud CON Open + T9600 ' baud for vmusic
EFXBAud CON Open + T38K4 ' baud for rc4
VolMax CON $00
VolMin CON $FE
Headcentered CON 750 ' head centered
Headleft CON 800 ' head counterclockwise
Headright CON 500 ' head clockwise
Whimperlts CON %0011 ' whimper lts on RC-4 K1 and K2
Screamlts CON %1100 ' scream lts on RC-4 K3 and K4
Screamspeed CON 20 ' sets scream servo speed. change to meet
' your needs
Screamtime CON 13000 ' set "Screamtime" in millisecond to meet
' sound file run time
' -----[ Variables ]-------------------------------------------------------
lottery VAR Byte ' randomize lottery value for servo speed
timer VAR Byte
servopos VAR Byte ' servo position var
servospeed VAR Byte ' servo speed var
whimperspeed VAR Byte ' whimper speed based on lottery value
idx VAR Byte ' loop controller
theMP3 VAR Byte ' MP3 file pointer
char VAR Byte ' character value
eePntr VAR Word ' EEPROM memory pointer
mute VAR Byte
panCtrl VAR Word
muteLeft VAR panCtrl.BYTE0
muteRight VAR panCtrl.BYTE1
' -----[ Initialization ]--------------------------------------------------
Reset:
'OUTS = $0000 ' clear all outputs
'DIRS = $3FFF ' make P0-P13 outputs
SEROUT Sio, EFXBaud, ["!RC4", %00, "X"] ' set RC-4 all off
PAUSE 2500 ' let VMUSIC power up
GOSUB VM_Stop ' stop if playing
'GOSUB VM_Wait_Prompt
FOR servopos = 1 TO 150
PULSOUT Servo, Headcentered
PAUSE 20
NEXT
' -----[ Program Code ]----------------------------------------------------
Main:
timer = 0
Main_Preshow:
RANDOM lottery ' randomize lottery value
whimperspeed = lottery // 25 + 10 ' set whimperspeed 100 to 350
servospeed = whimperspeed ' set servospeed
SEROUT Sio, EFXBaud, ["!RC4", %00, "S", Whimperlts] ' set whimper lts on
theMP3 = 0
GOSUB VM_Repeat
'GOSUB VM_Wait_Start
FOR servopos = Headleft TO Headright STEP servospeed
PULSOUT Servo, servopos
PAUSE 10
NEXT
FOR servopos = Headright TO Headleft STEP servospeed
PULSOUT Servo, servopos
PAUSE 10
NEXT
DO WHILE (timer < 100) ' wait for 0.1s signal
PAUSE 5 ' loop pad
timer = timer + 5 * Trigger ' update timer
LOOP
IF Trigger = 0 THEN Main_Preshow ' do Main_Preshow if Trigger is false
Start_Show:
GOSUB VM_Stop ' stop VMusic if playing "whimper"
theMP3 = 1
GOSUB VM_Play
'GOSUB VM_Wait_Start
SEROUT Sio, EFXBaud, ["!RC4", %00, "S", Screamlts] ' set scream lts on
servospeed = Screamspeed
Scream:
timer = 0 ' reset "timer" to be reused
DO
FOR servopos = Headright TO Headleft STEP servospeed
PULSOUT Servo, servopos
PAUSE 10
NEXT
FOR servopos = Headleft TO Headright STEP servospeed
PULSOUT Servo, servopos
PAUSE 10
NEXT
timer = timer + 20
LOOP UNTIL (timer = 13000) '
GOTO Main
' -----[ Subroutines ]-----------------------------------------------------
VM_Wait_Prompt:
'SERIN RX, VMBaud, [WAIT(">")]
RETURN
' -------------------------------------------------------------------------
' Pass file # (index in DATA table) to play in "theMP3"
VM_Play:
SEROUT TX, VMBaud, ["VPF "]
GOTO Play_MP3
' -------------------------------------------------------------------------
' Pass file # (index in DATA table) to play in "theMP3"
VM_Repeat:
SEROUT TX, VMBaud, ["VRF "]
GOTO Play_MP3
' -------------------------------------------------------------------------
' Pass file # (index in DATA table) to play in "theMP3"
Play_MP3:
eePntr = (8 * theMP3) + Song_List
Send_Name: ' send file title
FOR idx = 1 TO 8 ' max is 8 characters
READ eePntr, char ' get a character
IF char = 0 THEN Finish_Cmd ' if 0, we're at end
SEROUT TX, VMBaud, [char]
eePntr = eePntr + 1
NEXT
Finish_Cmd:
SEROUT TX, VMBaud, [".MP3", CR] ' send extention + CR
RETURN
' -------------------------------------------------------------------------
VM_Wait_Start:
'SERIN RX, VMBaud, [WAIT("T $")]
RETURN
' -------------------------------------------------------------------------
VM_Stop:
SEROUT TX, VMBaud, ["VST", CR]
RETURN
' -------------------------------------------------------------------------
' Pass mute level (0 = loudest, 254 = muted) in "mute"
VM_Mute:
mute = mute MAX VolMin ' limit per spec
' copy to pan register for future use
muteLeft = mute
muteRight = mute
SEROUT TX, VMBaud, ["VSV ", DEC mute, CR]
RETURN
' -------------------------------------------------------------------------
' Pass levels (0 = loudest, 254 = muted) in "muteLeft" and "muteRight"
'
' NOTE: The VPF/VRF commands seems to reset volume levels so you must use
' a pan command while the file is playing for it to work.
'
' NOTE: Over-use can result is unwanted audio "clicks" and "pops"
VM_Pan:
muteLeft = muteLeft MAX $FE ' limit per spec
muteRight = muteRight MAX $FE
SEROUT TX, VMBaud, ["VWR $0B", HEX4 panCtrl, CR]
RETURN
' -----[ User Data ]-------------------------------------------------------
' File names are stored on 8-byte boundaries -- this is very important for
' correct program operation. This strategy uses a little more EE space but
' is easier to update and maintain
Song_List DATA @$00, "ambient" ' theMP3 = 0
DATA @$08, "scream" ' theMP3 = 1
You did a good job fixing the buad rate problem. But, if you look at my program and yours you can see the problem with the servo movement. This could be causing your problem with servo movement. The code, I used was from a book I have "Whats a Microcontroller".
These are the numbers that were used.
Headcentered = 750
Headleft = 1000
Headright = 500
I understand the servo position numbers were changed but I had a different servo I was testing with. Even with the numbers changed back, the servo doesn't randomly move side to side like I wanted it to. The code looks like it should move it but the servo moves to about 800-850 servo pos after starting and doesn't move again. Then when i trigger, the servo turns and tries to rotate clockwise til it can't go any farther and sits there and vibrates. It's so weird.
Also, the program doesn't reload...
I did some hard searching on the forums when got home from work and found a random servo movements that Jon did in 2007 (added in) and this is your program missing the Scream part and see if the random servo movement matches your needs. The only thing that is left do is Scream part of moving the servo back and forth and hope Jon jumps in on the Scream part.
' =========================================================================
'
' File......Dotor Patient Prop.bs2
' Purpose...
' Author....
' E-mail....
' Started...
' Updated...
'
' {$STAMP BS2}
' {$PBASIC 2.5}
'
' =========================================================================
' -----[ Program Description ]---------------------------------------------
'a)Basically I would like a servo to randomly (IF possible) turn between
'positions as if a patient on the table is confused as to where they are.
'
'b)Then, when a mat switch is triggered, the servo sweeps side to side as
' IF the patient is in pain AND screaming. Then it would reset itself to
' the beginning.
'
'Have a VMusic2 hooked up with 2 sound files (whimper, scream).
'RX is PIN 15, TX is PIN 14
'
'I also have a RC-4 hooked up with 4 lights. 2 of the lights will be ON
'when part 'a' is running.
'
'Then when part 'b' is triggered, the other two turn on. That is on pin 13.
'
'The matswitch is on PIN 12 and the servo is PIN 8.
'
'
' -----[ Revision History ]------------------------------------------------
' -----[ I/O Definitions ]-------------------------------------------------
RX PIN 15 ' no ULN / SETUP = UP
TX PIN 14 ' no ULN / SETUP = UP
Sio PIN 13 ' no ULN / SETUP = UP
Trigger PIN 12 ' SETUP = DN / matswitch
Head PIN 8 ' patient's head servo
' -----[ Constants ]-------------------------------------------------------
IsOn CON 1 ' for active-high in/out
IsOff CON 0
#SELECT $STAMP
#CASE BS2, BS2E, BS2PE
T2400 CON 396
T38K4 CON 6
T9600 CON 84
#CASE BS2SX, BS2P
T2400 CON 1021
T38K4 CON 45
#CASE BS2PX
T2400 CON 1646
T38K4 CON 84
#ENDSELECT
SevenBit CON $2000
Inverted CON $4000
Open CON $8000
VMBaud CON Open + T9600 ' baud for vmusic
EFXBAud CON Open + T38K4 ' baud for rc4s
VolMax CON $00
VolMin CON $FE
Headcentered CON 750 ' head centered
Headleft CON 1000 ' head counterclockwise
Headright CON 500 ' head clockwise
Whimperlts CON %0011 ' whimper lts on RC-4 K1 and K2
Screamlts CON %1100 ' scream lts on RC-4 K3 and K4
Screamspeed CON 20 ' sets scream servo speed. change to meet
' your needs
Screamtime CON 2080 ' set "Screamtime" in millisecond to meet
' sound file run time
' -----[ Variables ]-------------------------------------------------------
lottery VAR Byte ' randomize lottery value for servo speed
timer VAR Byte
pos1 VAR Byte ' head servo position var
dest1 VAR Byte ' head servo destination
'whimperspeed VAR Byte ' whimper speed based on lottery value
idx VAR Byte ' loop controller
theMP3 VAR Byte ' MP3 file pointer
char VAR Byte ' character value
eePntr VAR Word ' EEPROM memory pointer
mute VAR Byte
panCtrl VAR Word
muteLeft VAR panCtrl.BYTE0
muteRight VAR panCtrl.BYTE1
' -----[ Initialization ]--------------------------------------------------
Reset:
' OUTS = $0000 ' clear all outputs
' DIRS = $3FFF ' make P0-P13 outputs
SEROUT Sio, EFXBAud, ["!RC4", %00, "X"] ' set RC-4 all off
PAUSE 2250 ' let VMUSIC power up
GOSUB VM_Stop ' stop if playing
GOSUB VM_Wait_Prompt
' -----[ Program Code ]----------------------------------------------------
Main:
timer = 0
Main_Preshow:
SEROUT Sio, EFXBAud, ["!RC4", %00, "S", Whimperlts] ' set whimper lts on
theMP3 = 0
GOSUB VM_Play
GOSUB VM_Wait_Start
Update_Head:
RANDOM lottery
IF pos1 <> dest1 THEN Update_Pos1 ' at destination?
dest1 = lottery // 151 + 75 ' yes, reset (75 to 225)
Update_Pos1:
IF pos1 < dest1 THEN Go_CW1 ' Decide if the servo should move CW or CCW
pos1 = pos1 - 2 ' Move servo CCW
Go_CW1:
pos1 = pos1 + 1 ' Move servo CW
Update_Servos:
PULSOUT Head, pos1 ' Move the servo
IF Trigger = 0 THEN Main_Preshow ' do Main_Preshow if Trigger is false
Start_Show:
GOSUB VM_Stop ' stop VMusic if playing "whimper"
theMP3 = 1
GOSUB VM_Play
GOSUB VM_Wait_Start
SEROUT Sio, EFXBAud, ["!RC4", %00, "S", Screamlts] ' set scream lts on
Scream:
timer = 0 ' reset "timer" to be reused
DO
timer = timer + 20
LOOP UNTIL (timer = 2080) '
GOTO Main
' -----[ Subroutines ]-----------------------------------------------------
VM_Wait_Prompt:
SERIN RX, VMBaud, [WAIT(">")]
RETURN
' -------------------------------------------------------------------------
' Pass file # (index in DATA table) to play in "theMP3"
VM_Play:
SEROUT TX, VMBaud, ["VPF "]
GOTO Play_MP3
' -------------------------------------------------------------------------
' Pass file # (index in DATA table) to play in "theMP3"
VM_Repeat:
SEROUT TX, VMBaud, ["VRF "]
' -------------------------------------------------------------------------
' Pass file # (index in DATA table) to play in "theMP3"
Play_MP3:
eePntr = (8 * theMP3) + Song_List
Send_Name: ' send file title
FOR idx = 1 TO 8 ' max is 8 characters
READ eePntr, char ' get a character
IF char = 0 THEN Finish_Cmd ' if 0, we're at end
SEROUT TX, VMBaud, [char]
eePntr = eePntr + 1
NEXT
Finish_Cmd:
SEROUT TX, VMBaud, [".MP3", CR] ' send extention + CR
RETURN
' -------------------------------------------------------------------------
VM_Wait_Start:
SERIN RX, VMBaud, [WAIT("T $")]
RETURN
' -------------------------------------------------------------------------
VM_Stop:
SEROUT TX, VMBaud, ["VST", CR]
RETURN
' -------------------------------------------------------------------------
' Pass mute level (0 = loudest, 254 = muted) in "mute"
VM_Mute:
mute = mute MAX VolMin ' limit per spec
' copy to pan register for future use
muteLeft = mute
muteRight = mute
SEROUT TX, VMBaud, ["VSV ", DEC mute, CR]
RETURN
' -------------------------------------------------------------------------
' Pass levels (0 = loudest, 254 = muted) in "muteLeft" and "muteRight"
'
' NOTE: The VPF/VRF commands seems to reset volume levels so you must use
' a pan command while the file is playing for it to work.
'
' NOTE: Over-use can result is unwanted audio "clicks" and "pops"
VM_Pan:
muteLeft = muteLeft MAX $FE ' limit per spec
muteRight = muteRight MAX $FE
SEROUT TX, VMBaud, ["VWR $0B", HEX4 panCtrl, CR]
RETURN
' -----[ User Data ]-------------------------------------------------------
' File names are stored on 8-byte boundaries -- this is very important for
' correct program operation. This strategy uses a little more EE space but
' is easier to update and maintain
Song_List DATA @$00, "whimper" ' theMP3 = 0
DATA @$08, "scream" ' theMP3 = 1
Something has gone horribly wrong with that program! The sound never starts, which I don't know why it wouldn't. The servo goes haywire and tries to turn itself off the charts.
The pos1 and dest1 variables need to be set to Word for servo position numbers. I read that on here somewhere and after chagning them with the old program, the servo worked, just not as expected.
Also, I think the loop for the scream part is never reaching the GOTO Main statement. It's very weird.
What I suggest is take the code that we know that's works and place the servo that you can get to work you and place it just below where the VMusic code is. The bummer part is, I can't help you test your code, because I'm at my overnite electrical maintenance job and will try to help as much as I can when I am back home.
Here is the topic that Jon posted some code for random servo movement, that I gave you in my last post. http://www.efx-tek.com/php/smf/index.php?topic=354.msg1653#msg1653
BTW, I found this link in the Completed Projects section http://www.efx-tek.com/php/smf/index.php?board=12.0 for random servo movement code that can help you out with the servo code and this is the code link. http://www.spiderspreyground.com/howto/dk-toepincher/Quad-Servo-Seek-to-random-6.txt
OK, I finally got it right you. I didn't check my code. My bad, sorry.
The reason for the crazy servo movements. Because, I didn't SEED the variable "lottery", which is placed in the Initialization section of the program and done like this.
lottery = 1031
The reason for Seeding the variable "lottery" is to give the command RANDOM to max number to work with.
Attached is the random servo program that I just tested for you and it works as programmed. I suggest you to load it on your Prop-2 only. That way you can test it to see if is what you are looking for. When you are happy, paste it into your code as talked about in the above post and if you want you can use this for both whimper and scream parts of your program.
Here is some updated code to reflect the random servo movements. However, i'm not getting exactly the movement I want but it is pseudo random.
How does defining lottery = 1031 make it the max number? I'm confused by that and also the // modulus part. I've adjusted the numbers and depending on how high or low I make them that reflects which side of the servo the random movements are on. Right now, they are random on the 500 servopos side. It's throwing me for a loop.
The only problem with the code is that I get the startup, music plays, but no servo movement, no trigger works...Any idea?
Anyhow here's the code:
' =========================================================================
'
' File......Dotor Patient Prop.bs2
' Purpose...
' Author....
' E-mail....
' Started...
' Updated...
'
' {$STAMP BS2}
' {$PBASIC 2.5}
'
' =========================================================================
' -----[ Program Description ]---------------------------------------------
'a)Basically I would like a servo to randomly (IF possible) turn between
'positions as if a patient on the table is confused as to where they are.
'
'b)Then, when a mat switch is triggered, the servo sweeps side to side as
' IF the patient is in pain AND screaming. Then it would reset itself to
' the beginning.
'
'Have a VMusic2 hooked up with 2 sound files (whimper, scream).
'RX is PIN 15, TX is PIN 14
'
'I also have a RC-4 hooked up with 4 lights. 2 of the lights will be ON
'when part 'a' is running.
'
'Then when part 'b' is triggered, the other two turn on. That is on pin 13.
'
'The matswitch is on PIN 12 and the servo is PIN 8.
'
'
' -----[ Revision History ]------------------------------------------------
' -----[ I/O Definitions ]-------------------------------------------------
'RX PIN 15 ' no ULN / SETUP = UP
TX PIN 14 ' no ULN / SETUP = UP
Sio PIN 13 ' no ULN / SETUP = UP
Trigger PIN 12 ' SETUP = DN / matswitch
Servo PIN 8 ' patient's head servo
' -----[ Constants ]-------------------------------------------------------
IsOn CON 1 ' for active-high in/out
IsOff CON 0
#SELECT $STAMP
#CASE BS2, BS2E, BS2PE
T2400 CON 396
T38K4 CON 6
T9600 CON 84
#CASE BS2SX, BS2P
T2400 CON 1021
T38K4 CON 45
#CASE BS2PX
T2400 CON 1646
T38K4 CON 84
#ENDSELECT
SevenBit CON $2000
Inverted CON $4000
Open CON $8000
VMBaud CON Open + T9600 ' baud for vmusic
EFXBAud CON Open + T38K4 ' baud for rc4
VolMax CON $00
VolMin CON $FE
Headcentered CON 750 ' head centered
Headleft CON 1000 ' head counterclockwise
Headright CON 500 ' head clockwise
Whimperlts CON %0011 ' whimper lts on RC-4 K1 and K2
Screamlts CON %1100 ' scream lts on RC-4 K3 and K4
' -----[ Variables ]-------------------------------------------------------
lottery VAR Word ' randomize lottery value for servo speed
timer VAR Word
delay VAR Word
pos1 VAR Word
dest1 VAR Word
servopos VAR Word
idx VAR Byte ' loop controller
theMP3 VAR Byte ' MP3 file pointer
char VAR Byte ' character value
eePntr VAR Word ' EEPROM memory pointer
mute VAR Byte
panCtrl VAR Word
muteLeft VAR panCtrl.BYTE0
muteRight VAR panCtrl.BYTE1
' -----[ Initialization ]--------------------------------------------------
Reset:
SEROUT Sio, EFXBaud, ["!RC4", %00, "X"] ' set RC-4 all off
PAUSE 2500 ' let VMUSIC power up
GOSUB VM_Stop ' stop if playing
FOR pos1 = 500 TO 1000
PULSOUT Servo, pos1
PAUSE 20
NEXT
' -----[ Program Code ]----------------------------------------------------
Main:
timer = 0
lottery = 1031
dest1 = 500
Main_Preshow:
RANDOM lottery ' randomize lottery value
dest1 = lottery // 151 + 875
SEROUT Sio, EFXBaud, ["!RC4", %00, "S", Whimperlts] ' set whimper lts on
theMP3 = 0
GOSUB VM_Repeat
IF pos1 <> dest1 THEN Update_Pos1 ' are we there yet?
'dest1 = lottery // 375 + 700 ' scale to 100 - 200
dest1 = lottery // 151 + 875
Update_Pos1:
IF pos1 < dest1 THEN Go_CW1
pos1 = pos1 - 2
Go_CW1:
pos1 = pos1 + 1
Update_Servos:
PULSOUT Servo, pos1
PAUSE 15
DO WHILE (timer < 100) ' wait for 0.1s signal
PAUSE 5 ' loop pad
timer = timer + 5 * Trigger ' update timer
LOOP
IF Trigger = 0 THEN Main ' do Main_Preshow if Trigger is false
Start_Show:
GOSUB VM_Stop ' stop VMusic if playing "whimper"
theMP3 = 1
GOSUB VM_Play
SEROUT Sio, EFXBaud, ["!RC4", %00, "S", Screamlts] ' set scream lts on
timer = 0
Scream:
'timer = 0 ' reset "timer" to be reused
DO
FOR servopos = Headright TO Headleft STEP 20
PULSOUT Servo, servopos
PAUSE 10
NEXT
FOR servopos = Headleft TO Headright STEP 20
PULSOUT Servo, servopos
PAUSE 10
NEXT
timer = timer + 20
LOOP UNTIL (timer = 13000)
GOTO Main
' -----[ Subroutines ]-----------------------------------------------------
VM_Wait_Prompt:
'SERIN RX, VMBaud, [WAIT(">")]
RETURN
' -------------------------------------------------------------------------
' Pass file # (index in DATA table) to play in "theMP3"
VM_Play:
SEROUT TX, VMBaud, ["VPF "]
GOTO Play_MP3
' -------------------------------------------------------------------------
' Pass file # (index in DATA table) to play in "theMP3"
VM_Repeat:
SEROUT TX, VMBaud, ["VRF "]
GOTO Play_MP3
' -------------------------------------------------------------------------
' Pass file # (index in DATA table) to play in "theMP3"
Play_MP3:
eePntr = (8 * theMP3) + Song_List
Send_Name: ' send file title
FOR idx = 1 TO 8 ' max is 8 characters
READ eePntr, char ' get a character
IF char = 0 THEN Finish_Cmd ' if 0, we're at end
SEROUT TX, VMBaud, [char]
eePntr = eePntr + 1
NEXT
Finish_Cmd:
SEROUT TX, VMBaud, [".MP3", CR] ' send extention + CR
RETURN
' -------------------------------------------------------------------------
VM_Wait_Start:
'SERIN RX, VMBaud, [WAIT("T $")]
RETURN
' -------------------------------------------------------------------------
VM_Stop:
SEROUT TX, VMBaud, ["VST", CR]
RETURN
' -------------------------------------------------------------------------
' Pass mute level (0 = loudest, 254 = muted) in "mute"
VM_Mute:
mute = mute MAX VolMin ' limit per spec
' copy to pan register for future use
muteLeft = mute
muteRight = mute
SEROUT TX, VMBaud, ["VSV ", DEC mute, CR]
RETURN
' -------------------------------------------------------------------------
' Pass levels (0 = loudest, 254 = muted) in "muteLeft" and "muteRight"
'
' NOTE: The VPF/VRF commands seems to reset volume levels so you must use
' a pan command while the file is playing for it to work.
'
' NOTE: Over-use can result is unwanted audio "clicks" and "pops"
VM_Pan:
muteLeft = muteLeft MAX $FE ' limit per spec
muteRight = muteRight MAX $FE
SEROUT TX, VMBaud, ["VWR $0B", HEX4 panCtrl, CR]
RETURN
' -----[ User Data ]-------------------------------------------------------
' File names are stored on 8-byte boundaries -- this is very important for
' correct program operation. This strategy uses a little more EE space but
' is easier to update and maintain
Song_List DATA @$00, "ambient" ' theMP3 = 0
DATA @$08, "scream" ' theMP3 = 1
QuoteHow does defining lottery = 1031 make it the max
If you look in the Basic Stamp help file under random you will find this
about random
Quote
RANDOM generates pseudo-random numbers ranging from 0 to 65535.
They're called "pseudo-random" because they appear random, but are
generated by a logic operation that uses the initial value in Variable
to "tap" into a sequence of 65535 essentially random numbers.
If the same initial value, called the "seed", is always used, then
the same sequence of numbers is generated. The following example demonstrates this:
result VAR Word
Main:
result = 11000 ' set initial "seed" value
RANDOM result ' generate random number
DEBUG DEC ? result ' show the result on screen
GOTO Main
In this example, the same number would appear on the screen over and over again.
This is because the same seed value was used each time; specifically, the first line
of the loop sets result to 11000. The RANDOM command really needs a different seed value
each time. Moving the "Result =" line out of the loop will solve this problem, as in:
result VAR Word
Setup:
result = 11000 ' set initial "seed" value
Main:
RANDOM result ' generate random number
DEBUG DEC ? result ' show the result on screen
GOTO Main
END
Here, result is only initialized once, before the loop. Each time through the loop,
the previous value of result, generated by RANDOM, is used as the next seed value.
This generates a more desirable set of pseudo-random numbers.
In applications requiring more apparent randomness, it's necessary to "seed" RANDOM
with a more random value every time. For instance, in the example program
(See Editor Help File),RANDOM is executed continuously (using the previous resulting
number as the next seed value) while the program waits for the user to press a button.
Since the user can't control the timing of button presses very accurately, the results
approach true randomness.
And here is the on the MOdulus operator as well from the help file
Quote
The Modulus operator (//) returns the remainder left after dividing one value by another.
Some division problems don't have a whole-number result; they return a whole number and
a fraction. For example, 1000 / 6 = 166.667. Integer math doesn't allow the fractional
portion of the result, so 1000 / 6 = 166. However, 166 is an approximate answer, because
166 * 6 = 996. The division operation left a remainder of 4. The // (double-slash)
returns the remainder of a given division operation. Naturally, numbers that divide
evenly, such as 1000 / 5, produce a remainder of 0.
What you may want to do is lower the PAUSE command from this PAUSE 15 to this PAUSE 7
due to the fact it takes time for the SEROUT to transmit it's data to VMusic and RC-4
I noticed this maybe causing the problem with the trigger and you may want to comment
this code out.
DO WHILE (timer < 100) ' wait for 0.1s signal
PAUSE 5 ' loop pad
timer = timer + 5 * Trigger ' update timer
LOOP
Also you can try changing this code from this
IF Trigger = 0 THEN Main ' do Main_Preshow if Trigger is false
to this
IF Trigger = 0 THEN Run_Preshow ' do Run_Preshow if Trigger is false
and and add this label above the servo code
Run_Preshow:
IF pos1 <> dest1 THEN Update_Pos1 ' are we there yet?
Or, you try this with the servo code between DO WHILE..LOOP Statements for the preshow code.
DO WHILE (Trigger = 0)
'Insert servo code here
LOOP
QuoteHow does defining lottery = 1031 make it the max number?
It doesn't, it just provides a seed for the psuedo-random algorithm. We can make things random by running the RANDOM function inside a loop that is waiting for a trigger. With the trigger happening at some random time, we will be at a random place in the psuedo-random sequence.
The modulus operator works like this: it returns the remainder of a division. The way I think of it -- in this context -- is that it will always return a value between zero and the divisor minus one. For example, if I want a random time between 10 and 20 seconds I would do something like this:
RANDOM lottery
delay = lottery // 10001 + 10000
PAUSE delayThe first part of the delay equation will return a value between 0 and 10000 (10001 - 1); the second adds my minimum value.
Again, in order to add true randomness to the RANDOM function, you need to be calling RANDOM when waiting around for something to happen.
So the timing for the sound and the servo movement during the scream segment is off. I have tried adjusting the timer value and also the pause values for the servo's and it is either too short or just way too long. What's going on with that??
I don't have the parts to test your program but am going to write a version from scratch. Integerating servos is really tough because you have to refresh them every 20ms or so -- this creates complications for timing, etc. Do you know the duration of your sound file? I assume that as you're using two files but a single, digital output, the "wimpering" sound has been assigned to the AMBIENT.WAV track. Am I correct?
My scream sound file is 13 seconds long. The ambient track is the whimpering sound. I am using the vmusic2 again.
With the servo processing it's going to be really tough to watch for the end of the track so I will use timing instead. This is not an easy program; servos are never easy with a Prop-1 or Prop-2, and the VMUSIC is a nightmare of a product (which is why EFX-TEK refuses to actively support it -- it is only done when our customers are in a bind).
Sorry for the touble. I've used it on another prop and haven't had issues with it. Maybe i'm lucky?
Yes. I've had them work, too, mostly -- but when the fail it can be an enormous pain to get them back (I've had to crack them open to "re-flash" the program).
In wimper mode are you looking for random positions within your defined range (500 to 800) or just a random speed between those two endpoints?
In scream mode is the prop supposed to go between the extremes?
yes, random positions within the range...possibly like 600-900...
I just wanted the scream to be back and forth on the servo, not really too specific on the servo position. Maybe 90 degrees total for the max range.
Give this a try. Now... this is one of those "it's harder than it looks" programs. Dealing with servos using the Prop-1 and Prop-2 is very tough. This means that a state-machine is the best structure so that the servo gets updated every loop. Execution paths are based on the current program state and other conditions, and are padded such that each program loop is about 20ms (this drives the timing of everything).
As I said, I don't have the gear available on my desk to test. It compiles fine and I've looked it over very carefully.
Updated 31 OCT 2011, 2:40 PM PST
' =========================================================================
'
' File...... patient.bs2
' Purpose...
' Author....
' E-mail....
' Started...
' Updated...
'
' {$STAMP BS2}
' {$PBASIC 2.5}
'
' =========================================================================
' -----[ Program Description ]---------------------------------------------
' -----[ Revision History ]------------------------------------------------
' -----[ I/O Definitions ]-------------------------------------------------
RX PIN 15 ' no ULN / SETUP = UP
TX PIN 14 ' no ULN / SETUP = UP
Sio PIN 13 ' no ULN / SETUP = UP
Trigger PIN 12 ' SETUP = DN / matswitch
Servo PIN 8 ' patient's head servo
' -----[ Constants ]-------------------------------------------------------
IsOn CON 1 ' for active-high in/out
IsOff CON 0
#SELECT $STAMP
#CASE BS2, BS2E, BS2PE
T2400 CON 396
T38K4 CON 6
T9600 CON 84
#CASE BS2SX, BS2P
T2400 CON 1021
T38K4 CON 45
#CASE BS2PX
T2400 CON 1646
T38K4 CON 84
#ENDSELECT
SevenBit CON $2000
Inverted CON $4000
Open CON $8000
VMBaud CON Open + T9600 ' baud for vmusic
EFXBAud CON Open + T38K4 ' baud for rc4
VolMax CON $00
VolMin CON $FE
HeadCtr CON 750
HeadLf CON 800
HeadRt CON 500
WhimperLts CON %0011 ' whimper lts on RC-4 K1 and K2
ScreamLts CON %1100 ' scream lts on RC-4 K3 and K4
WhimperSpd CON 1 ' servo speed for whimpering
ScreamSpd CON 10 ' servo speed for screaming
ScreamTime CON 13000 ' duration of scream audio
TrHoldOff CON 15000 ' 15s trigger hold-off
' -----[ Variables ]-------------------------------------------------------
pos VAR Word ' present servo position
target VAR Word ' target servo position
state VAR Byte ' program state
lottery VAR Word ' random #
delay VAR Word ' general program delays
debounce VAR Byte ' trigger debounce
' -----[ Initialization ]--------------------------------------------------
Power_Up:
LOW Servo ' setup servo pin
pos = HeadCtr
delay = 2500
GOSUB Servo_Pause ' delay with servo
GOSUB VM_Stop ' stop if playing
lottery = 1031
Reset:
RANDOM lottery
target = lottery // (HeadLf - HeadRt + 1) + HeadRt
state = 0
OUTL = 0
HIGH state
' -----[ Program Code ]----------------------------------------------------
Main:
PULSOUT Servo, pos
RANDOM lottery
BRANCH state, [Setup, Holding, Whimpering, Screaming]
' set lights and start whimper sound
' -- serial transmissions consume ~18ms, hence no delay needed
Setup:
HIGH 0
SEROUT TX, VMBaud, ["VRF ambient.mp3", CR]
SEROUT Sio, EFXBaud, ["!RC4", %00, "S", WhimperLts]
delay = TrHoldOff
state = 1
OUTL = 0
HIGH state
GOTO Main
' in holding mode
' -- behaves like whimpering but ignores trigger input
Holding:
IF (delay > 20) THEN ' still in hold-off period?
delay = delay - 20 ' update
IF (pos = target) THEN ' if at target, make new one
RANDOM lottery
target = lottery // (HeadLf - HeadRt + 1) + HeadRt
ELSEIF (pos < target) THEN
pos = pos + WhimperSpd MAX target
ELSE
pos = pos - WhimperSpd MIN target
ENDIF
ELSE
delay = 0
debounce = 0
state = 2
OUTL = 0
HIGH state
ENDIF
PAUSE 18
GOTO Main
' watches for trigger while whimpering
Whimpering:
debounce = (debounce + 20) * Trigger
IF (debounce < 150) THEN ' still whimpering
IF (pos = target) THEN
RANDOM lottery
target = lottery // (HeadLf - HeadRt + 1) + HeadRt
ELSEIF (pos < target) THEN
pos = pos + WhimperSpd MAX target
ELSE
pos = pos - WhimperSpd MIN target
ENDIF
PAUSE 17
ELSE ' have valid trigger
SEROUT TX, VMBaud, ["VPF scream.mp3", CR]
SEROUT Sio, EFXBaud, ["!RC4", %00, "S", ScreamLts]
delay = ScreamTime
target = HeadLf
state = 3
OUTL = 0
HIGH state
ENDIF
GOTO Main
' move quickly between servo endpoints while screaming
Screaming:
IF (delay < 20) THEN ' done?
GOTO Reset ' yes, start over
ELSE
delay = delay - 20 ' update delay
IF (pos = target) THEN ' check/update target
IF (pos = HeadLf) THEN
target = HeadRt
ELSE
target = HeadLf
ENDIF
ELSEIF (pos < target) THEN
pos = pos + ScreamSpd MAX target
ELSE
pos = pos - ScreamSpd MIN target
ENDIF
ENDIF
GOTO Main
' -----[ Subroutines ]-----------------------------------------------------
' Replaces PAUSE -- keeps servo updated
Servo_Pause:
DO WHILE (delay > 20)
PULSOUT Servo, pos
PAUSE 19
delay = delay - 20
LOOP
PAUSE delay
RETURN
' -------------------------------------------------------------------------
VM_Stop:
SEROUT TX, VMBaud, ["VST", CR]
RETURN
' -------------------------------------------------------------------------
Thanks jon!
Here are some of the bugs ive found so far...
- after the scream, the program never resets and goes back to whimpering. The strobe light is stuck on scare.
-Also, the head never speeds up during the scream. it continues to randomly move and there is never a point where it speeds up.
- How long does the hold off period last?
- I have had to press the trigger twice for the scream to actually happen sound wise. The lights trigger but i'm not sure if they re-trigger the second time.
Do you have a Prop-1 Trainer that we can use to monitor the program state?
Oy not handy...If it werent 1/2 hour before trick or treating I would search for it ;D
No worries, snag the updated listing. I found that I had left out the state 3 update which would put it into scream servo mode and use the scream timing. If you can find a P1-T put in on the low group to show you what state the program is in. I also backed of the trigger hold-off (period where trigger is ignored) to 15s.
4 years later I have an update on this prop!
I finally got the chance to sit and work on it after getting married and moving twice! I'm all settled in my man cave and working on Halloween once again!!!!
I was taking a look at the code that was previously put up and I made it work perfectly!
Some changes that I had to make were:
-Played with the ScreamTime constant. 13000 (13 seconds, correct?) was nowhere near 13 seconds. It was more like 3 seconds. So I updated the number and kept loading the program back in and playing around. 52750 is the number that works absolutely perfectly. I don't know why it works, but it does!
-The ambient track kept playing even when the screaming was supposed to be playing. Easy fix there as I put a call to the VM_Stop subroutine immediately before the scream track was loaded.
-I played around with the relay lights and had to configure them to my needs. I did make a special plug setup for the RC-4 which I will post in that forum.
I took a video of the patient in action! I only have the strobe light from the main setup so I used woot! lights for the "spot" light placeholder. Here it is:
https://youtu.be/KzLEZaZNGPY (https://youtu.be/KzLEZaZNGPY)
I am slowly going to add some more tweaks to it to continue scaring the poop out of the kids!
Here is my updated code:
' =========================================================================
'
' File...... patient.bs2
' Purpose...
' Author....
' E-mail....
' Started...
' Updated...
'
' {$STAMP BS2}
' {$PBASIC 2.5}
'
' =========================================================================
' -----[ Program Description ]---------------------------------------------
' -----[ Revision History ]------------------------------------------------
' -----[ I/O Definitions ]-------------------------------------------------
RX PIN 15 ' no ULN / SETUP = UP
TX PIN 14 ' no ULN / SETUP = UP
Sio PIN 13 ' no ULN / SETUP = UP
Trigger PIN 12 ' SETUP = DN / matswitch
Servo PIN 8 ' patient's head servo
' -----[ Constants ]-------------------------------------------------------
IsOn CON 1 ' for active-high in/out
IsOff CON 0
#SELECT $STAMP
#CASE BS2, BS2E, BS2PE
T2400 CON 396
T38K4 CON 6
T9600 CON 84
#CASE BS2SX, BS2P
T2400 CON 1021
T38K4 CON 45
#CASE BS2PX
T2400 CON 1646
T38K4 CON 84
#ENDSELECT
SevenBit CON $2000
Inverted CON $4000
Open CON $8000
VMBaud CON Open + T9600 ' baud for vmusic
EFXBAud CON Open + T38K4 ' baud for rc4
VolMax CON $00
VolMin CON $FE
HeadCtr CON 750
HeadLf CON 800
HeadRt CON 500
K1Lt CON %0001 ' RC-4 K1
SpotLt CON %0010 ' RC-4 K2
K3Lt CON %0100 ' RC-4 K3
StrobeLt CON %1000 ' RC-4 K4
WhimperSpd CON 2 ' servo speed for whimpering
ScreamSpd CON 10 ' servo speed for screaming
ScreamTime CON 52750 ' duration of scream audio
TrHoldOff CON 15000 ' 15s trigger hold-off
' -----[ Variables ]-------------------------------------------------------
pos VAR Word ' present servo position
target VAR Word ' target servo position
state VAR Byte ' program state
lottery VAR Word ' random #
delay VAR Word ' general program delays
debounce VAR Byte ' trigger debounce
' -----[ Initialization ]--------------------------------------------------
Power_Up:
LOW Servo ' setup servo pin
pos = HeadCtr
delay = 2500
GOSUB Servo_Pause ' delay with servo
GOSUB VM_Stop ' stop if playing
lottery = 1031
Reset:
RANDOM lottery
target = lottery // (HeadLf - HeadRt + 1) + HeadRt
state = 0
OUTL = 0
HIGH state
' -----[ Program Code ]----------------------------------------------------
Main:
PULSOUT Servo, pos
RANDOM lottery
BRANCH state, [Setup, Holding, Whimpering, Screaming]
' set lights and start whimper sound
' -- serial transmissions consume ~18ms, hence no delay needed
Setup:
HIGH 0
SEROUT TX, VMBaud, ["VRF ambient.mp3", CR]
SEROUT Sio, EFXBaud, ["!RC4", %00, "S", SpotLt]
delay = TrHoldOff
state = 1
OUTL = 0
HIGH state
GOTO Main
' in holding mode
' -- behaves like whimpering but ignores trigger input
Holding:
IF (delay > 20) THEN ' still in hold-off period?
delay = delay - 20 ' update
IF (pos = target) THEN ' if at target, make new one
RANDOM lottery
target = lottery // (HeadLf - HeadRt + 1) + HeadRt
ELSEIF (pos < target) THEN
pos = pos + WhimperSpd MAX target
ELSE
pos = pos - WhimperSpd MIN target
ENDIF
ELSE
delay = 0
debounce = 0
state = 2
OUTL = 0
HIGH state
ENDIF
PAUSE 18
GOTO Main
' watches for trigger while whimpering
Whimpering:
debounce = (debounce + 20) * Trigger
IF (debounce < 150) THEN ' still whimpering
IF (pos = target) THEN
RANDOM lottery
target = lottery // (HeadLf - HeadRt + 1) + HeadRt
ELSEIF (pos < target) THEN
pos = pos + WhimperSpd MAX target
ELSE
pos = pos - WhimperSpd MIN target
ENDIF
PAUSE 17
ELSE ' have valid trigger
GOSUB VM_Stop
SEROUT TX, VMBaud, ["VPF scream.mp3", CR]
SEROUT Sio, EFXBaud, ["!RC4", %00, "S", StrobeLt]
delay = ScreamTime
target = HeadLf
state = 3
OUTL = 0
HIGH state
ENDIF
GOTO Main
' move quickly between servo endpoints while screaming
Screaming:
IF (delay < 20) THEN ' done?
GOTO Reset ' yes, start over
ELSE
delay = delay - 20 ' update delay
IF (pos = target) THEN ' check/update target
IF (pos = HeadLf) THEN
target = HeadRt
ELSE
target = HeadLf
ENDIF
ELSEIF (pos < target) THEN
pos = pos + ScreamSpd MAX target
ELSE
pos = pos - ScreamSpd MIN target
ENDIF
ENDIF
GOTO Main
' -----[ Subroutines ]-----------------------------------------------------
' Replaces PAUSE -- keeps servo updated
Servo_Pause:
DO WHILE (delay > 20)
PULSOUT Servo, pos
PAUSE 19
delay = delay - 20
LOOP
PAUSE delay
RETURN
' -------------------------------------------------------------------------
VM_Stop:
SEROUT TX, VMBaud, ["VST", CR]
RETURN
' -------------------------------------------------------------------------