Single bit energized test

mikeexplorer

Supporting Member
Join Date
Nov 2018
Location
Scranton,PA
Posts
179
I am trying to find a better (cleaner) way to code this. In this example B3:45 should only have 1 bit on in its 0-3 range. It is a selection of what area the code will execute on. In this case it is 4 bits I am checking so these lines of code do work. In a program I am planning to write next I will need to test up to 8 bits (only one on) to detect only one train in a mainline block.



In this sample code, if more then one bit is on, it simply sets an alarm code indicating a selection error.



Any suggestions?


Mike
 
If you wanted you could make an alarm bit on a different rung... example B3:45/5 (if not used) would be true IF anyone of the 4 bits are true then if N7:36 was NEQ 0 and B3:45/5 was true you would MOVe 37 to N7:49

Or doing a compare of a word like Lare said when looking at more than 4 bits, 8 would be a lot for one rung, you can also use a bit MASK and if greater than 1 you could make your logic true.

In this example B3:45 should only have 1 bit on in its 0-3 range

I did notice some of your logic is duplicated, just because your bits are reversed they are still the same and you would be doing the move twice for no reason, so if you leave it as is you can delete some of the logic.
 
As geniusintraining said, you could simplify your contact count significantly because you are checking for the same condition multiple times.

Another way to approach this it to look at the negative case. If the value is NOT equal to zero it needs to be one of the single-bit binaries (1, 2, 4, 8, 16, 32, 64, 128). If the value is NOT zero and NOT one of these numbers you have a problem.

Keith
 
[Update: this is the same thing that Keith suggested, and he got it up here first]


I am trying to find a better (cleaner) way to code this...Any suggestions?


Hi Mike,

The image (below) is cleaner.

Caveat: clean to me anyway, but then I'm a bitboy and breathe this stuff; not everyone would consider this anything less than obfuscation ;).

Possibly also slightly better from a CPU standpoint

My last two rungs replace your first four now, and with straightforward modifications* will replace your sixteen rungs later.


More ideas below; let us know what you come up with, and don't be concerned about choosing one of "us" over the other: I for one, and I am sure many others here, appreciate you project.


* The MVM mask in rung 0001 (ffffh); twelve more NEQs in rung 0002 (blecch, but better than twelve more NEQs in each of sixteen rungs, eh?).

Alternatives

The XICs on rungs 0011 through 0014 could be ORed via branches, so all that resides on one rung, and then there is only one [NEQ N7:36 0] and one [MOV 37 N7:49], but that is not much better.

Better than multiple branches on one rung, move whatever logic you end up into a separate routine that gets called from the main routine, which reduces the use of vertical real estate in the main routine.


It could also be done with a loop (e.g. Lary's bitsum approach), in which case you would not need to MVM (or CPW) B3:45 to an INT, and the code can be modified from handling four bits to sixteen by changing only one INT (i.e. the loop counter). A loop would be a close second, but that's my own bias: I have never seen any mishaps caused by a loop.


You could do some fun stuff in the loop, like

  • XIC bit 0 (INT 1) and ANDing with -2 (65534 = 65535-1);
  • XIC bit 1 (INT 2) AND with -3 (65533 = 65535 - 2;
  • ...;
  • XIC bit 15 (UINT 32768) and 32767 (= 65535 - 32768)
  • The ANDed value would be generated on the fly (e.g. XOR -1 bit];
  • If the XIC is true, the AND result should be 0;
  • This is almost certainly obfuscatory though.

xxx.png
 
Last edited:
Here is Lary's suggestion in a loop; this is by no means the only and/or best way to implement the loop internals, but overall the loop is probably one of the cleanest approaches, at least in terms of vertical real estate (always a critical resource).


It also applies across varying numbers of bits as the project expands e.g. you can code it for sixteen* now and it will work without change as those as-yet-unused, twelve more significant bits are added to the project.


* or even 32 bits or more: B3:45/[N7:253] works as it might in C-style, even if N7:253 goes beyond 15 e.g. if N7:253 is 32, then it B3:45/[N7:253] an indirect reference to bit B3:47/0.

Screenshot from 2020-06-13 10-09-32.png
 
Last edited:
One way I simplify alarms and conditions is to check if things are OK, then set an OK bit.

Then, you only need one rung to MOV 37 checking each mode and each OK bit.

Capture.JPG
 
There is more than one way to skin a cat (no offence to animal lovers)

Not really tried it but the logic seems ok

Alarm.png
 
Parky,

That works the same, and I have done similar myself.

However, when I check modes throughout the entire program I usually check my MODE_xxx_OK bit for each output enable in each mode.

I also usually have a single rung that checks Power, K1/MCR On, E-Stop clear, and other 'main' conditions and set an ALLOW_RUN bit to check throughout the program.
 
The more I look at this, the more I think it belongs in a (sub-)routine: the main reasons are the [NEQ N7:36 0] instructions duplicated in so many rungs.


That test could either make optional the call to the routine, [NEQ N7:36 0 JSR U:n], or the call could be unconditional and the inverse test could be used to return early from the routine, [EQU N7:36 0 RET], after some initialization (e.g. [MOV 0 N7:49]).
 
Last edited:
Continuing the "more than one way" theme, even unrolling the loop for four or eight bits seems like an improvement; see the last active rung in the attached PDF.
 
Last edited:
Teasing

I think Parky's first solution is good enough to solve his problem but what if there were 32 bits and only one can be set? Then Parky's solution is not very good.

What bothers me about the forum needs to rediscover things every few years. This problem or one similar to it has been solved before. I used many bit hack routines for writing chess or Othello programs decades ago.
 

Similar Topics

Hi, I've got a Micro820 that I am using to create some menus and handle an alarm buzzer for a Panelview 800 HMI. I also need it to communicate...
Replies
4
Views
2,083
I'm writing a function block using Omron CX-Programmer for a CJ2M CPU. The FB is for interfacing with Slice I/O counter cards. The counter cards...
Replies
17
Views
9,692
Hi all, I have an application where the plant PLC is communicating via Ethernet/IP to 3 different field PLC's. The Field PLC's are all Micrologix...
Replies
6
Views
3,413
Hi, I'm talking to a ControlLogix PLC using CIP over E/IP, and I'm having trouble accessing single bits inside another type (such as an integer)...
Replies
5
Views
3,867
Hi all, someone knows if is possible in SCL extract the single bit of a WORD or DOUBLE WORD defined as VAR_TEMP?? In other word I'd like to...
Replies
2
Views
7,051
Back
Top Bottom