Shop OBEX P1 Docs P2 Docs Learn Events
Help with timing, parallel processes between two BS2's — Parallax Forums

Help with timing, parallel processes between two BS2's

BlakeBlake Posts: 74
edited 2010-03-10 04:27 in BASIC Stamp
Hey, I am fairly inexperienced at pbasic and electrical engineering in general. I was wondering if anyone had any tips or tricks to using one basic stamp to time operations and another to execute code based on this timing. I looked briefly into using a 555 timer in astable mode, but I was unable to get the pulse period I wanted easily. I have a feeling a propeller chip would be a better option for this, but I already have two bs2's lying around.

In the following code the first stamp keeps time and sends a signal to the second stamp every X seconds. The second stamp activates a motor which spits out a coin from a machine. The machine has an optical interrupt which senses when a coin has left the machine. I put in the "counter" variable so that if the machine is unable to spit out a coin before the next pulse from the first stamp, the second stamp activates the motor until two coins are spit, etc. The "coin" variable is so that the bs2 doesn't count the same coin blocking the interrupt twice (or hundreds of times) because the stamp is cycling through its code numerous times before the coin has had a chance to leave the interrupt.

Every so often, this code fails. I think it must have to do with the timing between the stamps, the second stamp missing a pulse signal or getting the same one twice, etc.

So, is there a better way to do this?

Thanks for any help,
Blake

first stamp:
' {$STAMP BS2}
' {$PBASIC 2.5}

'first stamp, performs timing.

LOW 0  'pin to send signal to second bs2

main:
PAUSE 3505
HIGH 0
PAUSE 5
LOW 0
GOTO main




second stamp:
' {$STAMP BS2}
' {$PBASIC 2.5}

'second stamp, performs actions.

'input (blue line) from opd917BZ
INPUT 0
'input from timer bs2
INPUT 7

counter VAR Byte
coin VAR Byte

main:
counter = 0
LOW 5
GOTO start

start:
DEBUG DEC counter

IF (IN7 = 1) THEN           'if there is a signal from timer
  counter = counter +1    'add one to count
  GOTO motoron                  'turn on motor

ELSEIF (IN0 = 0) THEN     'if coin rolls through interrupt
  GOTO evalmotoroff        'decide whether to turn off motor

ELSEIF (IN0 = 1) THEN    'if there is no coin in interrupt
  coin = 0                       ' set coin present variable to 0

ENDIF

GOTO start



evalmotoroff:
IF (coin = 0) THEN    'if this is the first cycle since coin has been interrupted
coin = 1                  'set coin present to 1. this will null future coin present cycles until interrupt is again clear. 
counter = counter - 1    'subtract one from coin counter
GOTO turnoff             'begin motor turn off
ENDIF
GOTO start

turnoff:           
IF (counter = 0) THEN    'if first cycle
LOW 5     'deactivate motor relay   
GOTO start
ENDIF
GOTO start

motoron:
HIGH 5    'trigger motor relay
GOTO start

Post Edited (Blake) : 3/9/2010 2:16:24 AM GMT

Comments

  • BlakeBlake Posts: 74
    edited 2010-03-09 03:00
    Okay, I read the above FAQ and Mike Green states (about parallel processing):
    Mike Green said...

    2) It can't really. There's only one processor in the Stamp, so it can only do one thing at a time. You can attach additional processors to a Stamp and you can network several Stamps together, but, if you want to do two things at the same time, you need something like the Propeller that can really do several things at the same time. It's possible to combine two programs together so two functions are interleaved and the Stamp appears to be doing several things at the same time. The BoeBot works somewhat that way in that servos require control pulses about 50 times a second. The Stamp in the BoeBot can read sensors and do some decision making in between the servo pulses since there's about 17ms left in the 20ms interval before another servo control pulse has to be generated.

    But, my code does work (most of the time). I think it just needs to be refined. I think my question about a better way still has merits... I think mine needs to work in a similar way to the BoeBot.
  • Mike GreenMike Green Posts: 23,101
    edited 2010-03-09 04:11
    The reason your code doesn't work sometimes is that the 2nd Stamp is occasionally busy when it "should" be listening for a pulse from the 1st Stamp. In order for this scheme to work, you need, at the very least, a flip-flop between the 1st Stamp and the 2nd Stamp that gets set by the 1st Stamp and sensed and reset by the 2nd Stamp. This flip-flop essentially remembers that X seconds have gone by and the 1st Stamp has signalled to the 2nd Stamp that this has happened. The flip-flop will remember this until the 2nd Stamp has a chance to notice and act on the signal. Once the 2nd Stamp has noticed, it can reset the flip-flop to be ready for the next signal.
  • Tracy AllenTracy Allen Posts: 6,662
    edited 2010-03-09 16:24
    A quick way to achieve the memory action that Mike suggests is to tie a 0.01uF capacitor from the trigger pin to ground (pin 0 on the timer Stamp, pin 7 on the listening Stamp). On the timer Stamp, the HIGH 0 instruction charges the capacitor, but instead of LOW 0, do INPUT 0. The 5 volt charge will be stored on the capacitor, a dynamic memory, for many seconds, provided the circuit has no significant external leakage. On the listening Stamp, PBASIC at its leisure sees the capacitor charged high, executes its subroutine, and then does a LOW 7 : INPUT 7 sequence. That resets the cycle.

    Another way to do it is to make the high pulse on the timer Stamp much longer, but use code on the listening Stamp to detect the 0-->1 transition instead of just the high level. If it detects just the IN7=1, there is danger that it will execute the code more than once for one trigger, as you have already observed. The transition code requires a couple of bit variables to detect the change:
    oldTrig VAR bit
    newTrig VAR bit
    upTrig VAR bit
    oldTrig = IN7
    ' ...
    start:
      ' ...
      newTrig = IN7
      upTrig=newTrig ^ oldTrig & newTrig  ' 1 on 0-->1 transition, otherwise 0
      oldTrig=newTrig
      IF uptrig THEN ' .... do the stuff
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Tracy Allen
    www.emesystems.com

    Post Edited (Tracy Allen) : 3/9/2010 4:29:21 PM GMT
  • ercoerco Posts: 20,256
    edited 2010-03-09 17:13
    Tracy: Your cap idea is wonderful, simple, almost free, and bookmark-worthy.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ·"If you build it, they will come."
  • BlakeBlake Posts: 74
    edited 2010-03-10 02:40
    Thanks for the help! Tracy's post was really helpful and I ended up implementing the capacitor switch idea. I agree with erco, really simple and a great idea. One problem I've run into, unrelated, is that sometimes my machine spits out two coins at once before the stamp can turn off the motor, which ends up causing the counter variable to go negative. This causes the machine to never stop because a negative number is greater than zero. I have solved this with a "if counter = 0 OR counter > 25 THEN counter = 0" (because it will never get higher than 25 and to "reset" the variable).

    Here's my updated code (again thanks everyone, especially Tracy):

    Timing Stamp:
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    'first stamp, performs timing.
    
    LOW 0  'pin to send signal to second bs2
    
    main:
    PAUSE 3500
    HIGH 0
    INPUT 0
    GOTO main
    
    



    Listening/Acting Stamp:
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    
    'second stamp, listens, performs actions.
    
    'input (blue line) from opd917BZ
    INPUT 0
    'input from timer bs2
    INPUT 7
    
    counter VAR Byte
    coin VAR Byte
    
    main:
    counter = 0
    LOW 5
    GOTO start
    
    start:
    DEBUG DEC counter
    
    IF (IN7 = 1) THEN         'if there is a signal from timer
      LOW 7
      INPUT 7
      counter = counter +1    'add one to count
      HIGH 5                  'trigger motor relay
      GOTO start              'turn on motor
    
    ELSEIF (IN0 = 0) THEN     'if coin rolls through interrupt
      GOTO evalmotoroff       'decide whether to turn off motor
    
    ELSEIF (IN0 = 1) THEN    'if there is no coin in interrupt
      coin = 0               ' set coin present variable to 0
    
    ENDIF
    GOTO start
    
    evalmotoroff:
    IF (coin = 0) THEN    'if this is the first cycle since coin has been interrupted
    coin = 1                  'set coin present to 1. this will null future coin present cycles until interrupt is again clear.
    counter = counter - 1  ' subtract 1 from counter
    GOTO decideoff
    ENDIF
    GOTO start
    
    decideoff:
    IF (counter = 0 OR counter > 25) THEN 'if counter is zero or negative
    counter = 0            'make sure counter is zeroed
    LOW 5                  'turn off motor
    GOTO start
    ENDIF
    GOTO start
    
    
  • Tracy AllenTracy Allen Posts: 6,662
    edited 2010-03-10 04:27
    I'm glad you liked the capacitor trick. I've used that often to latch the occurrence of short lived events until the Stamp could get around to seeing them. I dry weather and with clean wiring, its amazing how long a capacitor can hold a pin at one level or the other. Nevertheless, I can't claim to have invented memory as charge stored on a capacitor!

    Blake, another way to deal with the negative issue is to nip it in the bud in the counter instruction:
    counter = counter - 1 ' subtract 1 from counter
    counter = counter MIN 1 - 1 ' subtract 1 from counter, but never go negative.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Tracy Allen
    www.emesystems.com
Sign In or Register to comment.