Welcome to the Parallax Discussion Forums, sign-up to participate.

This should be simple - More PBasic Train Logic

Posts: 134
edited 2017-10-25 - 14:57:40
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

• Posts: 1,071
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.
• Posts: 134
Tried : IF (Serstring(4) & 004) AND (Serstring(4) & 016) THEN Outs1 = Outs1 | 002

Doesn't work.

Thanks for the idea.

Greg
• Posts: 6,404
edited 2017-10-25 - 21:04:17
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.
• Posts: 134
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
• Posts: 1,071
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.
• Posts: 1,071
edited 2017-10-25 - 20:21:47
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.
• Posts: 1,071
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.
• Posts: 6,404
edited 2017-10-26 - 16:19:26
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.
• Posts: 6,290
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.
• Posts: 2,966
```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.
Press any key to continue, any other key to quit

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.
• Posts: 134
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
• Posts: 6,404
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.
• Posts: 2,966
nice one @Tracy

Mike
I am just another Code Monkey.
A determined coder can write COBOL programs in any language. -- Author unknown.
Press any key to continue, any other key to quit

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.
• Posts: 134
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