This should be simple - More PBasic Train Logic

G McMurryG McMurry Posts: 132
edited October 25 in BASIC Stamp Vote Up0Vote Down
Maybe someone can help me with this little piece of logic.

I currently use the following method of "bit checking" to identify a "switch" input contained in a byte, then set a particular "relay" output contained in another byte as follows:

SerString(4) is an array containing some serial commands. Outs1 is a 74hc595 output register (classic BS2)

IF Serstring(4) & 004 THEN Outs1 = Outs1 | 002 'if the 3rd bit of Serstring(4) is on then turn on the 2nd bit of Outs1

This works fine...

Now I would like to check 2 bits of SerString(4) at the same time so that both bits must be on for the same function.

IF Serstring(4) & 004 AND Serstring(4) & 016 THEN Outs2 = Outs2 | 002 'if the 3rd and 5th bit of Serstring(4) are both on then turn on the 2nd bit of Outs1

This does not work. I basically get no output. Why? Seems simple enough.

However, even if it does, what I really want to do is make sure Serstring(4) & 004 is ON AND Serstring(4) 016 is OFF to get Outs2 | 002.

What this will do for me is it will keep me from Starting my Engine [Serstring(4) bit 4 is the Start Switch] while the Power Relay that engages the motors [Outs2 bit 2] is on. If the Engine revs up, it can cause my train to suddenly run forward. Its like in your car when you cannot start the car unless it is in park.

Any thoughts?

Greg

Comments

  • 14 Comments sorted by Date Added Votes
  • Might be a order issue. Try putting the Serstring(4) & 004 in parenthesis. and the other one.
    Re-inventing the wheel is not a waste of time if, when you are done, you understand why it is round.
    Cool, CA, USA 95614
  • Tried : IF (Serstring(4) & 004) AND (Serstring(4) & 016) THEN Outs1 = Outs1 | 002

    Doesn't work.

    Thanks for the idea.

    Greg
  • Tracy AllenTracy Allen Posts: 6,103
    edited October 25 Vote Up0Vote Down
    Could be a type but & 016 would be bit 16, not bit 6.

    IF Serstring(4) & 20 = 20 THEN Outs2 = Outs2 | 002

    should also work to mask bits 4 and 6 together.

    Oops, typed original message with brain out of gear.
  • Serstring(4) is: 020 MSB 00010100 LSB

    I only want to look at the two bits ( 4 and 16) for this. The others can change at anytime.

    IF Serstring(4) & 004 THEN Outs2 = Outs2 | 2 'works
    IF Serstring(4) & 016 THEN Outs2 = Outs2 | 2 'works
    IF Serstring(4) & 004 AND Serstring(4) & 016 THEN Outs2 = Outs2 | 2 'doesn't work

    Greg
  • If
    IF (Serstring(4).Bit2 = 1) AND (Serstring(4).Bit4 = 1) THEN Outs2.Bit1 = 1
    
    doesn't work, then I have a profound misunderstanding of basic.
    Re-inventing the wheel is not a waste of time if, when you are done, you understand why it is round.
    Cool, CA, USA 95614
  • tomcrawfordtomcrawford Posts: 754
    edited October 25 Vote Up0Vote Down
    Of course, the above doesn't work because you cannot use .BITx with an array. You have to either find a way to alias a variable to SerString(4) or you have to move SerString(4) to a simple variable.
    Serstring   VAR    BYTE(5)
    Simple      VAR    BYTE
    Simple = Serstring(4)
    If (Simple.BIT2 = 1) AND (Simple.BIT4 = 1) THEN whatever
    
    I actually fired up a BS-2 and tried the above.
    Re-inventing the wheel is not a waste of time if, when you are done, you understand why it is round.
    Cool, CA, USA 95614
  • Another approach would be
    If ((Serstring(4) & %0001000) = %0001000) AND ((Serstring(4) & %00000010) = %00000010) THEN
    

    You can never have too many parenthesis.
    Re-inventing the wheel is not a waste of time if, when you are done, you understand why it is round.
    Cool, CA, USA 95614
  • Tracy AllenTracy Allen Posts: 6,103
    edited October 26 Vote Up0Vote Down
    IF Serstring(4) & 20 = 20 THEN Outs2 = Outs2 | 002
    should work, same as
    IF Serstring(4) & %10100 = %10100 THEN Outs2 = Outs2 | 002

    For aliasing, you could define an implicit array:
    Serstring VAR byte
    Serstring1 VAR byte
    Serstring2 VAR byte
    Serstring3 VAR byte
    Serstring4 VAR byte
    
    You can still refer to it in array syntax:
    Serstring(4) implicitly refers to the same location in ram as Serstring4
    but you can also use the .bit syntax.
    IF Serstring4.bit4 & Serstring4.bit6 THEN ...
    
    That becomes non-zero (TRUE) iff both bits are set.
  • Here's another way that's very obvious:
      IF (serstring(4) & %00010100 = %00010100) THEN...
    
    Personally, I prefer using binary values for masks.
    Jon McPhalen
    Hollywood, CA
    It's Jon or JonnyMac -- please do not call me Jonny.
  • how about
    IF Serstring(4) & 004 THEN
        IF Serstring(4) & 016 THEN
            Outs2.Bit1 = 0
        ELSE
             Outs2.Bit1 = 1 ' since you want 016 LOW as far I could follow
        ENDIF
    ELSE
        Outs2.Bit1 = 0
    ENDIF
    

    Enjoy!

    Mike
    I am just another Code Monkey.

    A determined coder can write COBOL programs in any language. -- Author unknown.

    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this post are to be interpreted as described in RFC 2119.
  • All this was great food for thought. At least one of them works now. I shall review:

    I have buttons/switches on Serstring(4) 004 and 016. I have a relay on Outs1 002

    I don't want Serstring(4) 004 to activate Outs1 002 unless Serstring(4) 016 is on [actually off].

    I have been trying this with the following code with no success.

    IF (Serstring(4) & 004) AND (Serstring(4) & 016) THEN Outs1 = Outs1 | 002 It does not work at all. Nether 004 or 016 will change the state of Outs1 002.

    I would like to not use up any more variables such as in a couple of the suggestions. I have a working version of this logic that does use additional variables. I need to clean up my code and work as the Serstring(x) variables directly. I am running out of space. So I jumped on to the suggested binary version(s):

    IF ((Serstring(4) & %0000100) = %0000100) AND ((Serstring(4) & %00010000) = %00010000) THEN
    ' Outs1 = Outs1 | 002 'Set Start if Pwr off


    This line does work, but if you recall, I really need Serstring(4) 004 to be ON and Serstring(4) 016 to be OFF before turning Outs1 002 ON. Serstring(4) is the Starter Switch and Serstring(4) 016 is the Main Power Relay. Outs1 002 is the Starter Motor. I don't want the Starter to turn over if the Main Power Relay is engaged. This can be dangerous just like Starting your car in Drive. It could take off unpredictably.

    This leaves msrobots's new and non-binary suggestion:

    IF Serstring(4) & 004 THEN
    IF Serstring(4) & 016 THEN
    Outs1.BIT2 = 0
    ELSE
    Outs1.BIT2 = 1 ' since you want 016 LOW as far I could follow
    ENDIF
    ELSE
    Outs2.BIT1 = 0
    ENDIF


    This code works! It allows the ultimate operation of my Starter to be disallowed if the PWR Relay is ON.

    Seems like a lot of code, so I will mess with it a little to see if everything is necessary. In the beginning of my loop, I zero everything out so maybe I don't need the last Else Outs2.Bit1 = 0. I will experiment

    Thanks to all for the help on this problem. It has been a great learning experience for me.

    "Cruz Control" is around the corner now. Its a little difficult to test Cruz without actually loading it on the Locomotive, so I need to go out to the Railroad and give it a spin.

    I have another piece of control logic in Cruz that needs some control exceptions as well. I can use the above technique for that also. For example, we don't want the system to go into "Cruz" if the Power Relay is ON either. The engine would keep speeding up providing no MPH Feedback to Cruz which would cause RPM runaway.

    I should also provide an exception for when the Train is in Reverse or the Brakes are on. These control logic should be simple using what I have learned here. All without having to introduce additional variables.

    Mission Accomplished!

    Greg
  • You said, "'if the 3rd and 5th bit of Serstring(4) are both on then turn on the 2nd bit of Outs1"
    and somehow msrobots figured out that "both on" means that the third bit needs to be high=1 and the 5th bit low=0.

    IF Serstring(4) & %10100 = %00100 THEN Outs2 = Outs2 | 002
    Outs2 goes high if and only if bit value 4 is high and bit value 16 is low. %10100 is the mask and %00100 is the target value.
  • nice one @Tracy

    Mike
    I am just another Code Monkey.

    A determined coder can write COBOL programs in any language. -- Author unknown.

    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this post are to be interpreted as described in RFC 2119.
  • Sorry Tracy and Thanks,

    In an earlier post I mentioned that my ultimate goal was to look for 4 high and 16 low, but using the method I was trying, I couldn't even get 4 high and 16 high to trigger my desired output. You have taught me a different way to look at this.

    I just tried your code and it works fine, and is in line with what I was trying to do originally.

    Thanks for the followup.

    Thanks Everyone (again)

    Greg
Sign In or Register to comment.