Shop OBEX P1 Docs P2 Docs Learn Events
WAITPEQ with a time limit? — Parallax Forums

WAITPEQ with a time limit?

doggiedocdoggiedoc Posts: 2,241
edited 2014-09-05 07:52 in Propeller 1
I am trying to figure out how to control a process with a switch and WAITPEQ is the obvious solution. I need a failsafe approach such as a time limit that the routine will wait but at the moment I'm at a loss as to how to structure it. Any chance this is possible?

Here's the method so far (no failsafe yet.)
PUB OpenDoor  

  OUTA [RELAY_PIN] := ON
  pause(250)
  HB25.SetMotorS(1840,1500)
  'pause(2910)
  waitpeq(%1,|<UPPER_SWTCH_PIN,0)
  
  HB25.SetMotorS(1500,1500)
  pause(250)
  doorState := OPEN
  OUTA [RELAY_PIN] := OFF
          

Comments

  • Heater.Heater. Posts: 21,230
    edited 2014-09-03 06:49
    Sadly there is no way to wait on pins with a time out.

    You are going to have to pole that by reading INA and testing for the pins state, and reading CNT and testing for the time limit, in a repeat loop. Which ever one happens first sets some status and gets you out of the loop.

    Provided that is fast enough for your application the only downside is that WAITxxx consumes a lot less power whist it is waiting than a polling loop.
  • electromanjelectromanj Posts: 270
    edited 2014-09-03 06:56
    Hi Doc. I was trying to mess around with something similar a few months back, and here is what I came up with.
    CON
            _clkmode = xtal1 + pll16x                                              
            _xinfreq = 5_000_000
    VAR
      long stack[1000]
      byte flag           
      long  timercog
    Pub init
      dira[0] := 0
      dira[14] := 1
      switchcheck
    Pub switchcheck
      cognew(timer,@stack[200])  'start timer
      flag := 0
      repeat
        if ina[0] := 1           'if switch is on, turn on relay
          outa[14] := 1
          timerReset             'reset the timer
        if ina[0] := 0           'if switch is off turn off relay
          outa[14] := 0
          timerReset             'reset timer
        if flag == 1             'if timer has timed out turn off relay
          outa[14] := 0
    Pub timer
      timercog := cogid           'if timer is allowed to run out, set flag to 1
      flag := 0
      repeat 60
        waitcnt(clkfreq*10+cnt)  
      flag := 1                    
    pub timerReset
      cogstop(timercog)
      cognew(timer,@stack[200])   'restart the timer  
    
    V.
  • doggiedocdoggiedoc Posts: 2,241
    edited 2014-09-03 07:04
    Thanks traVis and Heater - I may have come up with a solution:

    What about this:
    PUB OpenDoor 
    
      OUTA [RELAY_PIN] := ON
      pause(250)
      HB25.SetMotorS(1840,1500)   'turns on motor for door
      repeat 400
        pause(10)
        if UPPER_SWTCH_PIN == 1   'tests for switch engagement by door
          HB25.SetMotorS(1500,1500)   'and turns off if so
          doorState := OPEN
          OUTA [RELAY_PIN] := OFF
          abort                                       'exits method
      HB25.SetMotorS(1500,1500)     'otherwise times out after about 4 seconds
      doorState := OPEN
      OUTA [RELAY_PIN] := OFF
              
    

    The loop has a finite delay of about 4 seconds built in and checks pin state each pass, if high turns off motor and relay, sets the doorState parameter and aborts the method.

    Think that will work? I can't test it from here.
  • jonesjones Posts: 281
    edited 2014-09-03 10:35
    Heater. wrote: »
    Sadly there is no way to wait on pins with a time out.
    Being basically a rookie I hesitate to jump in, but I think there is a way. Since WAITxxx compares a 32-bit mask on INA with a 32-bit state, you can watch as many pins as you like. If you have a pin to spare, you can set a counter to slow NCO and have the WAITxxx watch the counter output as well as the pin you're interested in. Reset the counter before the WAITxxx statement, then if the counter output changes first the WAITxxx still terminates. You can test the counter pin to see if it was a timeout. I'm about as far from guru status as one can be, but that's worked for me. I also use PropBasic instead of Spin, but the WAITxxx statements work the same, I think. It also provides a way that you can abort a wait condition in one cog by toggling a pin with another cog. I've used it both ways. The downside is that it wastes a pin.
  • Heater.Heater. Posts: 21,230
    edited 2014-09-03 10:51
    jones,

    Yes indeed. As you say it uses up a pin. And a counter. That might be quite acceptable in many cases.

    Another way would be to start a COG with the code that waits on pins. Then after a time out kill the COG. Seriously wasteful of hardware resources.
  • pik33pik33 Posts: 2,366
    edited 2014-09-03 11:08
    If you have another cog, use it as a watchdog. One cog doing waitpeq, another waitcnt. This of course costs 2 cogs, but then they will use less current doing waitxxx than one cog doing a loop
  • richaj45richaj45 Posts: 179
    edited 2014-09-03 11:27
    Maybe a timer interrupt is what is needed?

    And we thought interrupts were bad.
    cheers,
    rich
  • Mike GreenMike Green Posts: 23,101
    edited 2014-09-03 11:37
    I believe the Prop II design includes a pin wait instruction that has a timeout. A timer interrupt doesn't really fix things. You have to be very careful about the case where the pin state changes at the same time (system clock cycle) as the timer times out. The Prop II instruction reports which action terminated the instruction which is what you need.
  • Heater.Heater. Posts: 21,230
    edited 2014-09-03 11:52
    richaj45,
    And we thought interrupts were bad.
    Yes we did. And we still think so. After many years of messing with them.

    What we want to write in a high level language in this case is something like:
    wait
        pins = someState:
            // Do whatever we should do
            // when that happens
        time = someTime:
            // Do whatever we should so
            // if it does not happen in time
    

    No interrupts there. (Yes interrupts may be there under the hood but not necessarily)

    One could even throw other events in there that might need waiting on, like messages from other COGS for example.

    That's before we start talking about the multi tasking that we are told we need interrupts for.

    In that case what we would like to write is something like:
    par
        someProcess
        someOtherProcess
    
  • jonesjones Posts: 281
    edited 2014-09-03 12:01
    Heater. wrote: »
    jones,

    Yes indeed. As you say it uses up a pin. And a counter. That might be quite acceptable in many cases.

    Another way would be to start a COG with the code that waits on pins. Then after a time out kill the COG. Seriously wasteful of hardware resources.
    True enough usually, but not always. I have an OSD application where main tests for the presence of incoming vertical sync and activates a red LED if vertical sync (and thus incoming video) is lost. In another cog, there are WAITxxx statements that watch for vertical sync and the line connected to the red LED. Loss of video aborts that wait so the cog doesn't hang up and can respond to the loss of video. Since I need a 'loss of video' indicator anyway, no extra hardware was used. Like anything else, sometimes you can do something, and sometimes you can't.
  • doggiedocdoggiedoc Posts: 2,241
    edited 2014-09-03 19:46
    Thanks all for the replies. In the end I abandoned WAITPEQ and went with a finite timed loop that tests the pin each pass and exits accordingly.

    Here's the method:
    PUB OpenDoor 
    
      OUTA [RELAY_PIN] := ON
      pause(500)
      HB25.SetMotorS(1840,1500)
        repeat 55
          if INA[UPPER_SWTCH_PIN] == 1
           pause(300) 
           HB25.SetMotorS(1500,1500)
           doorState := OPEN
           OUTA [RELAY_PIN] := OFF
           'pst.Str(String("Success!! ",13))
           return
          pause(100) 
      HB25.SetMotorS(1500,1500)    
      doorState := OPEN
      OUTA [RELAY_PIN] := OFF
      'pst.Str(String("Fail ",13))
      statusLED(1)                  'trigger alarm
              
    
  • base2designbase2design Posts: 78
    edited 2014-09-04 11:36
    Adding on to the "use another pin + counter", I found a snippet on the web at http://wardyprojects.blogspot.com/2014/03/propeller-hacking-waitpeq-timeout.html that seems to be a working example.
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2014-09-04 13:08
    doc the only thing I see if you code that could potentially be an issue is the pause statement. Not sure of the details of the pulse width or speed of the motor versus this switch, but in the micro world 100 ms is a long time. Is the pause required while waiting for the input?
  • doggiedocdoggiedoc Posts: 2,241
    edited 2014-09-04 14:51
    Chris, the pauses are part of the overall time limit for switch engagement - and to allow relay/motor response.
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2014-09-04 17:01
    But the one in your repeat 55 loop that is executed every pass through the loop pauses the code for 100 ms every pass through. Perhaps that is desired. Normally you wouldn't want a pause while testing for a pin state if there's a possibility it could be missed. If it is a switch that is possible.
  • doggiedocdoggiedoc Posts: 2,241
    edited 2014-09-04 18:04
    Yes. The pause(100) is inside the repeat 55 loop but outside the if INA... loop. So until INA[LOWER_SWTCH_PIN] goes HIGH the repeat loop overhead is only about 100 microseconds. The pause(300) only executes when condition is met.
  • SavageCircuitsSavageCircuits Posts: 256
    edited 2014-09-04 18:42
    That Chris Savage doesn't know what he's talking about. =)

    Okay so if your pulse comes in during the pause(100) it would be missed by the IF INA evaluation. That is what I meant. Since nothing is happening there except a test for the state of the pin, you wouldn't want a delay in that loop. =)
  • doggiedocdoggiedoc Posts: 2,241
    edited 2014-09-05 03:10
    @Savage///Circuits --You're thinking 'micro' pulse. This is a 'macro' pulse in that we're waiting for a mechanical switch to be engaged by a slow moving object (the door). Precision is not an issue in this case but I completely understand your point.


    Doc

    PS - that Chris Savage guy is not all that bad :nerd:
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2014-09-05 07:52
    Thanks doc! I'm glad you got my back! And glad you see what I meant. :cool:
Sign In or Register to comment.