titanspark76

Bit shift

12 posts in this topic

I need a way to transfer the last 8 bits of a register to the 1st 8 bits of a different register. Using WAND I can isolate the data I want, but having trouble finding a good solution to shift them. Example

1001001011111111 ---->0000000010010010. Thank you for any suggestions.

Share this post


Link to post
Share on other sites

Many PLCs have an instruction to do this.  Some have instructions you can use to shift bits around within a word, and other have commands which can take apart a 16 bit word into 2 separate words with 8 bits loaded to each.

Until you tell us which PLC, we can't answer you.

Share this post


Link to post
Share on other sites

I would guess that you in the first place have the 8 bits as higher 8 bits and that you need them to be the 8 lower bits. Then you would use SHR (ShiftRight). In a different scenario use SHL (ShiftLeft). Both will clear the remaining bits.

It takes two inputs: 1. Input = the 8 bits you have just masked out, 2. Input = the number of positions to shift to the right (8 in your example).

It's a very basic instruction so it's pretty much available in all the PLC's.

Share this post


Link to post
Share on other sites

Didn't realize I forgot the PLC type (Q03CPU). Let me be a little more clear in what I'm trying to accomplish. I'm trying to isolate sections of an Ascii string. I need to isolate the 1st 3 digits into a group of registers and the final 5 in a different data register. By doing the below I've had no problem isolating the 1st 3 digits. Let's say D0-D3 is the original 8 character string and the string is 12345678.

l l sm400-----------------------------(DAND D0 HFFFFFF D10)

By monitoring D10-D11 I can see 123 (good)

But the last 5 digits I haven't had much luck. As in my original post I was thought after doing another dand instruction with HFF000000 to mask the 1st 3 digits if I could shift them it would display correctly. I took kaare's suggestion and display the 4 digit , but now cannot get the remainder to display. This is what I've currently tried for the last 5 digits

---------(DAND D0 HFF000000 D20)

| | M0------(SFRP D21 K8)

| | M1 -----------(MOV D21 D30)

| | M2-----------(BMOV D0 D31 K2)

 

When I try to do an ascii display (proface) which does show up the 8 character display correctly when monitoring D0-D3. Now when monitoring D30-d32 I'm only seeing 4 instead of the desired 45678.

Share this post


Link to post
Share on other sites

Doesn't Q have a SWAP command to switch the order of the high and low bytes?

Share this post


Link to post
Share on other sites

In D10 to D11 you have NULL,3,2,1 (from MSB to LSB of the double) extracted from D0 and D1.

To extract only the 4 you are just looking at the "34" word so you can do it with WAND (single word AND). If you ---WAND D1 HFF00 D20 and ---SWAP D20, you will have NULL,4 in D20. 

----(BMOV D2 D21 k2 ) will give you 8,7 6,5 NULL,4 in D20 to D22.

If you want to get rid of the NULL between 4 and 5 you can

---WAND H0FF D21 D30

---SFL D30 k8

--- + D30 D20 D30

to give you 5,4 in D30.

If you masked and shifted the rest of D21 and D22 in the same way into D31 and D32, it should give you the result you're looking for.

Share this post


Link to post
Share on other sites

@Crossbow: Yes, the Q-series has a SWAP command, but I don't think that's what the original poster is looking for.

@Luke.S: After a very brief look at your code I think it might work, expect your last instruction "+ D30 D20 D30". This will add the data instead of and the data. I think you might be aiming for WAND instead of +, or am I wrong?

@titanspark76: Why do you need to convert/bitshift the string in the PLC? Doesn't Proface have any features to implement this in an easier way?

Share this post


Link to post
Share on other sites

@kaare_t I think a WAND of D30 D20 (H0034 & H3500) would just return H0000.

My idea is to put the "5" to the left of the "4" in the same word with binary addition. This will XOR the bits so if a 1 is there it will be kept as a 1 in that position. Because there are no 1s being XORed together in this case there won't be any carries.

Share this post


Link to post
Share on other sites

@Luke.S: Yes, you are absolutely correct regarding returning 0 when using WAND. I actually never used + for this (I've always used WOR, or just XOR) but it turns out that this will work just fine - just tested it. Nice clarification!

Share this post


Link to post
Share on other sites

@kaare_t Yeah I learnt this stuff at university but when you've done it many times and you know it works you just use it without thinking. But it certainly is good to have to justify what you're thinking every know and again.

I think decimal addition holds up to the same principle too. E.g. if I have 10 (1x10^1+0x10^0)and I want to put 2 (0x10^1+2x10^0) in the "empty" space on the right, 10+2=12 works.

But you're right, using OR instructions is probably a simpler way to do it. I'll try using them next time. Anyway, I think this is going a bit off topic sorry..

Edited by Luke.S

Share this post


Link to post
Share on other sites

Thanks for the help. I went a little different route than I originally was (I'm simply adding an Ascii space for the 1st digit), but used some of the ideas posted or they at least got me to thinking of a different way. (if you see a way to simplify it more I'm open to suggestions). I'm going to start requiring my customers to use an even # of digits in all their barcodes :-)

@kaare_t I actually don't need it to display on a proface HMI. I have to give an IT guy a set of data registers where they can scan for this information. Since the server isn't setup I was hoping if I could get it displayed on the HMI properly it should work for them. Basically below is the code I'm using now. With D0 being the original data

l l sm400-----------------------------(DAND D0 HFFFFFF D10)  (this gives me the 1st 3 digits needed)

And lets say for the final 5 digits I want to display in D20-D22

l l sm400-----------------------------(DAND D0 HFF000000 D30)

--------------------------------------------(MOV D31 D20)

---------------------------------------------(OUT D20.5)    (This gives me an Ascii space that I'm hoping is acceptable)

---------------------------------------------(BMOV D2 D21 K2)

 

Share this post


Link to post
Share on other sites
21 hours ago, titanspark76 said:

I have to give an IT guy a set of data registers where they can scan for this information. Since the server isn't setup I was hoping if I could get it displayed on the HMI properly it should work for them

Well, if you are basically free to choose I would go with binary encoding but that's just my opinion... Easier to chunk for the PLC... What kind of server setup do you have?

Regarding the ASCII 'space' that's a pretty regular way of doing it since many controllers won't accept 'null' in the string. E.g. many printers (not all though) require you to fill 'null' with 'space'...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now