November 21, 2024, 08:24:36 PM

News:

Be sure to checkout our Vixen interfaces in the Library forum -- if you want PC automation at near zero cost, EFX-TEK and Vixen is a great combination of tools.


Need a small adjustment to this program....

Started by poorfamily, October 19, 2007, 07:17:48 PM

Previous topic - Next topic

poorfamily

Here is the code for my skeleton prop for this year.  Although the code is written for 3 servos I'm only using one at the moment which turns the head of the prop randomly.  Then, when the PIR is triggered, the Prop-1 sends a trigger to the Cowlacious 'Scary Terry' servo board and a 30 second sound file plays.  What I need to add is a 60 second delay after the 30 second sound file so the ST board doesn't trigger again right away.  But I want the random head turning to continue throughout.  Jon helped me adapt someone else's program and I'm not quite sure where to add the new code to 'deaden' the PIR for the 60 seconds after the end of the sound file. Any help?

' =========================================================================
'
'   File....... Random_Servos.bs1
'   Purpose.... Randomly turn 3 servos
'   Author..... Robert Hole (based on the work of Vern Graner)
'   Web.....    www.halloween.cindybob.com
'   Started.... 20 Mar 2006
'   Updated.... 22 Mar 2006
'
'   {$STAMP BS1}
'   {$PBASIC 1.0}
'
' =========================================================================


' -----[ Program Description ]---------------------------------------------
' Pan 3 servos left and right a random amount. How often a particular servo
' will be in motion is a function of the chance number. A higher number means
' less chance that a servo will be in motion.

' -----[ Revision History ]------------------------------------------------


' -----[ I/O Definitions ]-------------------------------------------------
SYMBOL  PIR             = PIN6
SYMBOL  Cowlacious      = PIN5
SYMBOL  Servo1          = 0                     ' Servo1 Pin #
SYMBOL  Servo2          = 1                     ' Servo2 Pin #
SYMBOL  Servo3          = 2                     ' Servo3 Pin #


' -----[ Constants ]-------------------------------------------------------

SYMBOL  Chance          = 199                   ' Set the chance of any servo being in motion.
SYMBOL  IsOn            = 1                     ' The higher the number the last chance.
SYMBOL  IsOff           = 0

' -----[ Variables ]-------------------------------------------------------

SYMBOL  lottery         = W0                    ' random number
SYMBOL  rUpdate         = W5                    ' random number
SYMBOL  update          = B8                    ' update or not varialbe
SYMBOL  pos1            = B2                    ' servo1 postion
SYMBOL  dest1           = B3                    ' servo1 destination
SYMBOL  pos2            = B4                    ' servo2 postion
SYMBOL  dest2           = B5                    ' servo2 destination
SYMBOL  pos3            = B6                    ' servo3 postion
SYMBOL  dest3           = B7                    ' servo3 destination
SYMBOL  pirDelay        = W4
SYMBOL  cTimer          = B0


' -----[ Initialization ]--------------------------------------------------

Reset:
  DIRS = %00100111                              ' Change if the servos are not on pins 0,1,2
  lottery = 1031                                ' Seed the random number
  rUpdate = 2302                                ' Seed the random number
  dest1=120                                     ' Center the servos. These
  pos1=120                                      '  numbers may need to changed
  dest2=150                                     '  depending on the servos used
  pos2=150                                      '  and any deviation caused when
  dest3=160                                     '  mounting the servos.
  pos3=160

'Center the servos
  FOR update=100 TO dest1
    PULSOUT Servo1, update
    PAUSE 20
  NEXT
  FOR update=100 TO dest2
    PULSOUT Servo2, update
    PAUSE 20
  NEXT
  FOR update=100 TO dest3
    PULSOUT Servo3, update
    PAUSE 20
  NEXT

' -----[ Program Code ]----------------------------------------------------
PAUSE 15000
Main:
  PAUSE 10                                      ' Speed, more pause = slower

Check_Timers:
  IF pirDelay = 0 THEN Check_PIR                ' okay to check PIR?
    pirDelay = pirDelay - 1                     ' no, update delay timer

  IF Cowlacious = IsOff THEN Check_Dest1        ' audio trigger off?
    cTimer = cTimer - 1                         ' update timer
    IF cTimer > 0 THEN Check_Dest1              ' timer still running
      Cowlacious = IsOff                        ' no, output off
      GOTO Check_Dest1

Check_PIR:
  IF PIR = IsOff THEN Check_Dest1
    Cowlacious = IsOn                           ' activate Cowlacious
    cTimer = 10                                 ' 10 x 20 ms = 200 ms
    pirDelay = 750

' =========
'  Servo 1
' =========

Check_Dest1:
  RANDOM lottery
  IF pos1 <> dest1 THEN Update_Pos1             ' If not at dest then update the servo position?
  RANDOM rUpdate                                ' At dest so randomly decide if the servo should
  update=rUpdate // chance                      '  go again.
  IF update<>1 THEN Check_Dest2:                ' No match so maintain current position
  dest1 = lottery // 250                        ' Match so get a new dest.
  dest1 = dest1 MIN 70                          ' Confine to minimum and maximum limits. These
  dest1 = dest1 MAX 180                         '  limits may need to be changed to suit your
                                                '  situation and taste. Experiment with different numbers.

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

  PULSOUT Servo1, pos1                           ' Move the servo

' =========
'  Servo 2
' =========

Check_Dest2:
  RANDOM lottery
  IF pos2 <> dest2 THEN Update_Pos2
  RANDOM rUpdate
  update=rUpdate // chance
  IF update<>2 THEN Check_Dest3:
  dest2 = lottery // 250
  dest2 = dest2 MIN 90
  dest2 = dest2 MAX 200


Update_Pos2:
  IF pos2 < dest2 THEN Go_CW2
  pos2 = pos2 - 2

Go_CW2:
  pos2 = pos2 + 1

  PULSOUT Servo2, pos2

' =========
'  Servo 3
' =========

Check_Dest3:
  RANDOM lottery
  IF pos3 <> dest3 THEN Update_Pos3
  RANDOM rUpdate
  update=rUpdate // chance
  IF update<>3 THEN Main:
  dest3 = lottery // 250
  dest3 = dest3 MIN 90
  dest3 = dest3 MAX 200


Update_Pos3:
  IF pos3 < dest3 THEN Go_CW3
  pos3 = pos3 - 2

Go_CW3:
  pos3 = pos3 + 1

  PULSOUT Servo3, pos3


  GOTO Main                                      ' Start again


  END


' -----[ Subroutines ]-----------------------------------------------------

JonnyMac

October 19, 2007, 08:47:42 PM #1 Last Edit: October 19, 2007, 08:52:23 PM by JonnyMac
Since you're only controlling one servo I simplified the program -- give this a try.  Remember, when you're working with *multi-tasking* programs like this that are running servos, you can't put in statements like PAUSE 15000 -- this will prevent the servo from being refreshed as needed.

' =========================================================================
'
'   File....... Random_Head.BS1
'   Purpose....
'   Author..... Robert Hole (based on the work of Vern Graner)
'   Web.....    www.halloween.cindybob.com
'   Started.... 20 Mar 2006
'   Updated.... 22 Mar 2006
'
'   {$STAMP BS1}
'   {$PBASIC 1.0}
'
' =========================================================================


' -----[ Program Description ]---------------------------------------------


' -----[ Revision History ]------------------------------------------------


' -----[ I/O Definitions ]-------------------------------------------------

SYMBOL  PIR             = PIN6
SYMBOL  Cowlacious      = PIN5
SYMBOL  Head            = 0                     ' head turn servo


' -----[ Constants ]-------------------------------------------------------

SYMBOL  IsOn            = 1
SYMBOL  IsOff           = 0


' -----[ Variables ]-------------------------------------------------------

SYMBOL  pos1            = B2                    ' head servo position
SYMBOL  dest1           = B3                    ' head servo destination
SYMBOL  cTimer          = B4                    ' timing for PIR signal

SYMBOL  pirDelay        = W3                    ' PIR hold-off delay
SYMBOL  audioTmr        = W4                    ' timer for audio event
SYMBOL  lottery         = W5


' -----[ Initialization ]--------------------------------------------------

Setup:
  DIRS = %0010001                               ' configure outputs

  lottery = 1031                                ' Seed the random number
  dest1 = 150                                   ' start at center

  FOR pos1 = 100 TO dest1
    PULSOUT Head, pos1
    PAUSE 20
  NEXT


Reset:
  pirDelay = 6000                               ' one-miniute PIR delay


' -----[ Program Code ]----------------------------------------------------

Main:
  PAUSE 10                                      ' loop pad

Check_Timers:
  IF audioTmr = 0 THEN Check_PIR_Delay          ' audio finished?
    audioTmr = audioTmr - 1                     '   no, update timer
    IF audioTmr = 0 THEN Reset                  '   if done, start hold-off

Check_PIR_Delay:
  IF pirDelay = 0 THEN Check_PIR                ' okay to check PIR?
    pirDelay = pirDelay - 1                     '   no, update delay timer

Check_The_Cow:
  IF Cowlacious = IsOff THEN Update_Head        ' audio trigger off?
    cTimer = cTimer - 1                         '   no, update timer
    IF cTimer > 0 THEN Update_Head              '   timer still running?
      Cowlacious = IsOff                        '     no, output off
      GOTO Update_Head

Check_PIR:
  IF audioTmr > 0 THEN Update_Head              ' skip if audio running
  IF PIR = IsOff THEN Update_Head               ' pir signal?
    Cowlacious = IsOn                           ' activate Cowlacious
    cTimer = 20                                 ' 20 x 10 ms = 200 ms
    audioTmr = 3000                             ' 3000 x 10 ms = 30 s


' ===========
'  Head Servo
' ===========

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

  GOTO Main                                     ' Start again


' -----[ Subroutines ]-----------------------------------------------------
Jon McPhalen
EFX-TEK Hollywood Office

poorfamily

Thanks as always for the quick, thorough response.  You guys really go above and beyond.  I loaded the program and the head movement is much better (although I'd like the servo turning a tad slower.  What line can I adjust?.)  But the PIR won't trigger.  I reloaded the original program and it worked fine with the older version.  I'm using one of your PIR's and it's hooked up to P6 with a three-wire servo cable.

JonnyMac

Sometimes you just have to start over -- and that's what I've done.  This is a fairly sophisticated program; when trying to maintain a servo and do other things with a Prop-1 things can get tricky.  I reconstructed the program as a state machine and it runs much better now; it even debounces the the PIR input.  I also added a movement divider to the servo updating to slow the head movement.  You can switch out the divider (I defined four) to change the movement speed (it's fairly slow with the 8x divider).

I've tested this pretty thoroughly (even connected a 'scope to check the servo update timing) -- I think it does what you want.  Enjoy.

' =========================================================================
'
'   File....... Random_Head_Advanced.BS1
'   Purpose....
'   Author..... Jon Williams, EFX-TEK
'               -- with contributions by Vern Graner and Robert Hole
'   Started....
'   Updated.... 20 OCT 2006
'
'   {$STAMP BS1}
'   {$PBASIC 1.0}
'
' =========================================================================


' -----[ Program Description ]---------------------------------------------


' -----[ Revision History ]------------------------------------------------


' -----[ I/O Definitions ]-------------------------------------------------

SYMBOL  PIR             = PIN6
SYMBOL  Cowlacious      = PIN5
SYMBOL  Head            = 0                     ' head turn servo


' -----[ Constants ]-------------------------------------------------------

SYMBOL  IsOn            = 1
SYMBOL  IsOff           = 0


' -----[ Variables ]-------------------------------------------------------

SYMBOL  moveDivider     = B0
SYMBOL   div2           =  BIT0
SYMBOL   div4           =  BIT1
SYMBOL   div8           =  BIT2
SYMBOL   div16          =  BIT3

SYMBOL  state           = B1                    ' program state
SYMBOL  pirCount        = B2                    ' for PIR debouncing
SYMBOL  pos1            = B3                    ' head servo position
SYMBOL  dest1           = B4                    ' head servo destination
SYMBOL  cTimer          = B5                    ' timing for PIR signal
SYMBOL  pirDelay        = W3                    ' PIR hold-off delay
SYMBOL  audioTmr        = W4                    ' timer for audio event
SYMBOL  lottery         = W5


' -----[ Initialization ]--------------------------------------------------

Setup:
  DIRS = %00100001                              ' configure outputs

  lottery = 1031                                ' Seed the random number
  dest1 = 150                                   ' start at center

  FOR pos1 = 100 TO dest1
    PULSOUT Head, pos1
    PAUSE 20
  NEXT

Reset:
  pirDelay = 3000                               ' one-miniute PIR delay
  state = 0


' -----[ Program Code ]----------------------------------------------------

Main:
  PAUSE 15                                      ' tuned for 20 ms loop

  BRANCH state, (PIR_Hold, PIR_Test, Audio_Start, Audio_Hold)

PIR_Hold:                                       ' inter-event delay
  pirDelay = pirDelay - 1                       ' update timer
  IF pirDelay > 0 THEN Update_Head              ' skip if not expired
    state = 1                                   '   else, update state
    pirCount = 0                                '   clear debounce timer
    GOTO Update_Head

PIR_Test:
  pirCount = pirCount + 1 * PIR                 ' update/clear PIR count
  IF pirCount < 10 THEN Update_Head             ' skip until valid signal
    state = 2                                   '   else, update state
    cTimer = 10                                 '   start cow timer
    GOTO Update_Head

Audio_Start:
  Cowlacious = IsOn                             ' activate audio player
  cTimer = cTimer - 1                           ' udpate start timer
  IF cTimer > 0 THEN Update_Head                ' skip until finished
    Cowlacious = IsOff                          '   remove start signal
    state = 3                                   '   update state
    audioTmr = 1500                             '   1500 x 20 ms = 30 sec
    GOTO Update_Head

Audio_Hold:
  audioTmr = audioTmr - 1                       ' update audio timer
  IF audioTmr > 0 THEN Update_Head              ' skip while audio running
    GOTO Reset                                  ' start over


' ===========
'  Head Servo
' ===========

Update_Head:
  moveDivider = moveDivider + 1                 ' update move divider
  IF div8 = 0 THEN Update_Servos                ' time for position update?
    moveDivider = 0                             ' yes, reset divider

  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                   ' check direction
  pos1 = pos1 - 2                               ' Move servo CCW

Go_CW1:
  pos1 = pos1 + 1                               ' Move servo CW


' ===============
' Update Servo(s)
' ===============

Update_Servos:
  PULSOUT Head, pos1                            ' Move the servo

  GOTO Main                                     ' Start again


' -----[ Subroutines ]-----------------------------------------------------
Jon McPhalen
EFX-TEK Hollywood Office

poorfamily

Wow Jon this latest version is perfect!  I'm not sure what all you did but I can only hope to someday be able to do this on my own.  Sometime between High School (1984) and now I've lost the ability to piece together computer code so I really struggle trying to put together these programs.  But I guess what I thought would be an easy program (run 1 servo randomly, when the PIR is triggered start a sound file, keep the PIR from triggering for a little while) can actually be a little tough on the Prop-1.

As you hear all the time, thanks for the outstanding help!


JonnyMac

As my pals in the Dallas Personal Robotics Group often say: Sometimes it's harder than it looks!

Now that you have working code, why not go through it an analyze what I've done? -- would be a good learning exercise and help you get back into the swing of coding.  PBASIC is quite capable, and this is one of those cases that prove it.  Remember, servo processing is NOT trivial as a servo wants to be updated every 20 milliseconds.

Anyway, I'm glad I could help.  I enjoy solving problems with embedded code and this was a good one.  Happy Halloween.
Jon McPhalen
EFX-TEK Hollywood Office