December 03, 2024, 10:15:09 AM

News:

Got VSA?  Want to use your Prop-SX?  Now you can!  See the VSA section of the Library forum for Prop-SX code that works with VSA.


Updating Haunt Control Program to Increase Traffic Flow

Started by Spooky Dad, August 13, 2016, 09:44:27 PM

Previous topic - Next topic

Spooky Dad

August 13, 2016, 09:44:27 PM Last Edit: August 13, 2016, 09:46:36 PM by Spooky Dad
Hey EFX-TEK forum - I have an existing, working haunt control program (see attached file called "Spooky_Dad_Haunt_Serial) that I have been using for the past 5 years to control the haunted house I build in my garage.  JonnyMac helped me with the original programming to ensure that the props only activated in a specific sequence, which works great, but it restricts the amount of flow I get through my haunt, as it only allows one group at a time.

Scan_Sensors:
  triggers = %11111111                          ' enable all
  FOR idx = 1 TO 20                             ' debounce 100ms (20x5)
    RANDOM lottery                              ' stir random #
    PAUSE 5
    triggers = triggers & Sensors               ' scan sensor inputs
  NEXT

  IF (triggers = 0) THEN                        ' WAIT mode?
    wmTimer = wmTimer - 1
    IF (wmTimer = 0) THEN
      GOSUB PS_0
    ENDIF
  ELSE
    trMask = 1 << state                         ' set active trigger mask

    triggers = triggers & trMask                ' clear others
    IF (triggers <> %00000000) THEN             ' activated?
      state = state + 1

What I am looking for help with / suggestions on is how to modify the program (after about a 2 minute warm up cycle) to allow ANY of the 8 props to be triggered whenever their motion sensor sees a victim, as long as 60 seconds has passed since tripping last.  I have tried my best to modify the file (see attached file "Spooky_Dad_Haunt_Parallel").  Just looking for a sanity check, as I am very close to running out of programming space.

Scan_Sensors:
  triggers = %11111111                          ' enable all
  FOR idx = 1 TO 20                             ' debounce 100ms (20x5)
    RANDOM lottery                              ' stir random #
    PAUSE 5
    triggers = triggers & Sensors               ' scan sensor inputs
  NEXT

  IF (triggers = 0) THEN                        ' WAIT mode
    wmTimer = wmTimer - 1
    IF (wmTimer = 0) THEN
      GOSUB PS_0
    ENDIF
  ELSE

    FOR state = 0 TO 7
      trmask = 1 << state
      triggers = triggers & trMask
      IF triggers <> %000000000 THEN
        state = state + 1
        GOTO Scare
      ELSE
        state = state + 1
      ENDIF
    NEXT
    END

JonnyMac

Does the 60-second hold-off timing apply to *any* prop in the sequence, or is there a 60-second timer for each?
Jon McPhalen
EFX-TEK Hollywood Office

Spooky Dad


JonnyMac

I looked at your code and you don't have 8 bytes for timers.

Have you considered "upgrading" to an HC-8+? It has eight TTL inputs, eight outputs, and a serial connection that can talk to your DC-16. It also has and RS-485 port that you can use for controlling DMX-compatible devices.

And with 32K of memory... there's plenty of space for timers.
Jon McPhalen
EFX-TEK Hollywood Office

Spooky Dad

I was actually waiting for the HC-8s to come up before I bought the Prop-2.  I wasn't looking to upgrade this year.  Let me go back and see if there is a WORD variable that isn't be used.  If so, then I guess I just set the timer bytes based on the state, right?

I know that I am definitely pushing what the Prop-2 was designed for, but it has served me well over the past 5 years. 

JonnyMac

August 15, 2016, 08:46:38 PM #5 Last Edit: August 15, 2016, 08:59:16 PM by JonnyMac
The Prop-2 is not designed for anything specific, it's a general-purpose controller. Where you're running short is memory and RAM because you're trying to do many disparate things within one controller.

One way you could free up a lot of room is to purge the program of you debug statements -- you know that the program works and those are just taking a lot of room.

Another thing you could do is copy you wav files to the SFXnn.WAV naming convention and then call them as an index -- you can create constants that hold the index values so the program is still easy to read. For example:

W_SCREAM        CON      0
W_GHOST         CON      1
W_CHILD         CON      2
W_STARTLE       CON      3
W_ANGRY         CON      4
W_SHRIEK        CON      5
W_OWL           CON      6
W_SNAKES        CON      7
W_NONSPOOKY     CON      8
W_CHICKEN       CON      9
W_ECHAIR        CON     10


Now you can simplify the Play_WAV routine:

Play_WAV:
  SEROUT Sio, Baud, ["!AP16", %00, "PS", sfx, rpts]
  RETURN


I would suggest that you analyze your variables to see which must be persistent (saved between uses) and those that are transient and can be shared. Remember that the BS2 allows you to alias variables with multiple names -- this makes the program easier to read, but you need to ensure that the variable is transient and sharing between routines is okay.
Jon McPhalen
EFX-TEK Hollywood Office

Spooky Dad

Thanks JonnyMac!  Let me dive into this over the next couple of days.  Didn't mean anything disparaging about the Prop-2.  I love my EFX-Tek Haunt Brains.

Spooky Dad

I made the following changes, which I hope work, but need to be tested.  Got the EEPROM Map down to just 81% full (from 98%) and I think really cleaned up the variables (removed unused ones and right sized ones that remained).  Latest file attached.

1. I got rid of the Word variable of "status" for the AP-16.  Wasn't using it
2. Got rid of programming to check AP-16 status.  Wasn't using it.
3. Got rid of the Byte Variable "last".  Wasn't being used. 
4. Had some reset code from the previous prop that was spread among the code.  Consolidated into main.
5. Took out programming language (Snakes and Chandelier) that wasn't being used.
6. Changed the RC4 Byte variable to a Nib (Nibble).  Only needs to send four bits, right?
7. Also changed pntr to sfx and reduced to Nib since it is only handling up to 16 files. 
8. Same thing with rpts.  I won't be having a file repeat more than 3 times, so I changed it to Nib.
9. I think I got the code changed to take advantage of the SFXnn naming format.  Didn't know how to create an Index, so I brute forced it.
10. Got caught up on my documentation of the file and what things are doing / used for.

The thing that is remaining is not to allow any prop to go off (ideally) within 60 seconds from the last time it went off. Or any proxy for 60 seconds.  The problem is that I still do not have enough RAM to create 8 different Word-sized variables to track the actual time.  Any suggestions?  Racking my brains over here.

JonnyMac

Even if you had the RAM space I think you'd run out of program space processing those variable.

Here's another thought: Use byte variables and a course resolution. Before going to work for Parallax I created a product called HotWire (before the travel service was announced) that would track for inputs with 100ms resolution. If any of them exceeded their limit, the device would send a code to a pager using an internal modem.

The program was a bear. I had to use an oscilloscope and a free pin to do time tests on every code segment so that I could pad each possible path to 100ms (this took about a week).

With the HC-8+... boy, you could have a lot of fun and get millisecond-precision timing for all of your triggers.
Jon McPhalen
EFX-TEK Hollywood Office

Spooky Dad

Hey JonnyMac!  I don't have the time this haunt season to switch to an HC-8+.  Would have to be a next year thing as I about to start the actual build the first weekend in September.  Plus I need help on the conversion of the code.

But I have been thinking.  I was wondering if I could add another mask to the picture (NoTripMask) that I could combine with tirggers after trMask. NoTripMask = 11111111 would be the default.  I would then toggle the appropriate bit based on the state variable (don't know how yet) from a 1 to a 0, before I increment the state variable.

    FOR state = 0 TO 7
      trmask = 1 << state
      triggers = triggers & trMask
      triggers = triggers & NoTripMask
      IF triggers <> %000000000 THEN
        NoTripMask = 11111110 (what function would I use to just toggle the bit based on the current state, in this case state 0, to a zero???)
        state = state + 1
        GOTO Scare
      ELSE
        state = state + 1
      ENDIF
    NEXT
    END

Then, couldn't I just set a timing variable to count to 60 seconds (or whatever I pick) and once it has timed down, I would set NoTripMask back to all 1s.  Kind of crude, but I think it would at least give me some control.  Maybe I could even create two different timing variables to split the low bits and the upper bits a part.  What do you think?

JonnyMac

What, exactly, are you trying to accomplish with the new mask? Are you trying to ensure that no element will run until 60 seconds has elapsed since the last one was tripped?
Jon McPhalen
EFX-TEK Hollywood Office

Spooky Dad

Correct.  Trying to modify the approach you showed me for the trMask and Triggers by taking it one more step. 

I think I figured out a way of doing a pseudo counter for each prop with an 8 Nib Index labeled prpstop and creating a timer that counts up (NoTripTimer) and attempting to figure out the equivalent of 4 seconds by dividing NoTripTimer by the constant Regulator.  I know I will have to play around with the Regulator constant to figure out what 4 seconds is when my program is idle.  I have attached the latest file, but this is the relevant section of code.

The intent is to check the following conditions:  1) If a motion has tripped using Triggers ANDED with Sensors  2) Then to eliminate all other props using trMask and then 3) using another AND function with trStop to remove any props that have tripped within the last 60 seconds. 

Scan_Sensors:
  NoTripTimer = NoTripTimer + 1
  triggers = %11111111                          ' enable all
  FOR idx = 1 TO 20                             ' debounce 100ms (20x5)
    RANDOM lottery                              ' stir random #
    PAUSE 5
    triggers = triggers & Sensors               ' scan sensor inputs
  NEXT

  IF (triggers = 0) THEN                        ' WAIT mode
    DEBUG "The state is ", DEC state, ", Timer is ", DEC wmtimer, ", AND ", ? spookymode, CR, LF
    wmTimer = wmTimer - 1
    IF (wmTimer = 0) THEN
      GOSUB PS_0
    ENDIF
  ELSE
    FOR state = 0 TO 8
      trmask = 1 << state
      triggers = triggers & trMask
      triggers = triggers & trStop
      IF triggers <> %000000000 THEN
        ' need help here setting bit 1 of trStop to a zero
        trStop.LOWBIT(state) = 0
        prpstop(state) = 15
        state = state + 1
        GOTO Scare
      ELSE
        state = state + 1
      ENDIF
    NEXT
  ENDIF

' Going to check to see if NoTripTimer reaches equivalent of 4 seconds before decrementing the appropriate bit in the prpstop index
  FOR  state = 0 TO 7
      IF NoTripTimer > Regulator THEN
          IF prpstop(state) <> 0 THEN
            prpstop(state) = prpstop(state) - NoTripTimer/Regulator     'Trying to get NoTripTimer/Regulator to equal 1
          ELSE
            trStop.LOWBIT(state) = 1
          ENDIF
          NoTripTimer = 0
      ENDIF
  NEXT

  GOTO Main

Can you check my logic to see if this will get the trick done?  I know its not a precise as the HC-8+ would give me.  Upgrading to the HC-8+ is going to have to be a Christmas Holiday project for me. 

Spooky Dad

Hey EFX Board!  I have made progress on my updates, but still having a few challenges getting the logic to work.  The areas not working properly are...

1. ANDing triggers & sensors & trMask & trStop to make sure that only props that havn't been tripped recently work
      a. triggers is initially set to all 1s
      b . Sensors are the motions and seem to working
      c. trMask also seems to be working going through the FOR NEXT Loop
      d. I can set the bits of trStop using state
      e. I just can't get to a non-zero answer EXCEPT for the first input... none other work

  FOR state = 0 TO 7
    trmask = 1 << state
    triggers = triggers & trMask
    triggers = triggers & trStop
    IF triggers <> %000000000 THEN

2.  The second issue is that I am not updating my array properly (prpStop) and the logic to check to see if the value is greater than zero goes beyond zero and back to 15

IF NoTripTimer > Regulator THEN
      FOR  state = 0 TO 7
          IF prpstop(state) <> 0 THEN               'THIS IS NOT WORKING RIGHT!!!
            prpstop(state) = prpstop(state) - 1     'Trying to get NoTripTimer/Regulator to equal 4 seconds
          ELSE
            trStop.LOWBIT(state) = 1
          ENDIF
      NEXT
      NoTripTimer = 0
ENDIF

I'd really appreciate some help in reviewing the looping logic to both check for the triggers and then activate the right prop based on state and a GOTO Scare and how to properly cycle through prpstop array.  Latest file is attached.  So close I can taste it. 

Spooky Dad

Hey Support Team!  Any feedback on the updated program? 

Spooky Dad

Just checking in to see if I could answer any questions.  If I am asking for the impossible, I'd take that answer, too.