Siemens S7 shift register query

Ock

Member
Join Date
Nov 2008
Location
Lancashire
Posts
5
I am having some difficulty understanding some code written by Italian contractors to track product along a conveyor via a shift register. There is one network that is causing confusion and I tend to think that it is some form of indirect addressing:

L #Pos_out (DB35.DBW6) contains the INT value 4
T #Index temporary DWord

A L [#Index] ** What does this do? **
= #OUT M31.5 (memory bit that drives my O/P)

My assumption is that the code in question sets M31.5 when the shift register has clocked product along the conveyor to a position determined by the content of DB35.DBW6 but I cannot understand how the instructions ...

A L [#Index]
= #OUT

... work because DB35.DBW6 is an INT?

In other words, if DB35.DBW6 has a value of 4, how does this set M31.5 high?
 
#Index is used as a Pointer Double Word. The bits are as below:

wwww wwww xxxx xyyy yyyy yyyy yzzz

w = memory area
x = not used
y = word address
z = bit address

If 4 is loaded into that index, then you will be pointing to 0.4, if the 4 was shifted left by 3 (normal standard for pointing to words/bytes), then it would be 4.0.

The memory area was left clear so the following line

A L [#Index]

declares the memory area to be 'L', local flag area (TEMP area)., so if index = 4, this would be like

A L 0.4

So the program must be placing the indexed data into the local flag area, maybe as a Load/Transfer type instruction.with a bit shift thrown in.



EDIT:

When you are in the program editor (opened a block), select help, then contents, a help manual; appears. Go to the apendix area A3 describes all the data types and how they are made up.
 
Last edited:
More confusion ...

I understand the way in which the pointer monitors a particular bit (in network 4) much better now. The way in which the 32 bit shift register has been created though is causing me much confusion now. If I clock in a single bit using M115.0 AND M115.1 then subsequently shift using M115.0 the bit moves to the left on each shift pulse from M115.0

Bit M116.7 moves to Bit M117.0 then M117.1 and so on as I would expect but the real problem comes shifting from M117.7 to M118.0 because M116.0 also becomes ON at the same time as M118.0 giving me a ghost bit in my register every 16 cycles.

Sorry for the length of it but the code is as follows:

Network 1

L 0
T MD 134
T MD 138
T MD 142
T MD 146

L MD 116
T MD 130

Network 2

A M 115.0
A M 115.1
S M 130.0

Network 3

A M 115.0
JCN m001

L MD 130
SRD 24
T MD 134

L MD 130
SLD 8
SRD 16
T MD 138

L MD 130
SLD 16
SRD 8
T MD 142

L MD 130
SLD 24
T MD 146

L MD 134
L MD 138
OD
L MD 142
OD
L MD 146
OD
T MD 130

SLD 1
T MD 130

L MD 130
SRD 24
T MD 134

L MD 130
SRD 16
SLD 8
T MD 138

L MD 130
SRD 8
SLD 16
T MD 142

L MD 130
SLD 24
T MD 146

L MD 134
L MD 138
OD
LD MD 142
OD
L MD 146
OD
T MD 130

NOP 0 m001

Network 4

L 4
T #Index

A L [#Index]
= M 115.7

Network 5

L 4
L 1
+I
T #Index

A M115.4
R L [#Index]


Network 6

L MD 130
T MD 116

:confused:
 
Please create a library, insert an S7 Program and copy the block to the library and post the archived library. There are no local data accesses prior to N/W 4 so maybe you can explain how valid data has made its way into the local data area ?
 
For a start MD116 = MB116, 117, 118 and 119.

MB116 will be the MSB and 119 the LSB.

Shifting MD116 left by 1 would include M117.7 moving into M116.0 and shifting right would see M116.0 go into M117.7.

What I am saying is at no time would M116.7 go to M117.0 on a single shift. SRD 15 would achieve that.

L MD 130
SRD 24
T MD 134

would leave MB's 134, 135 and 136 = zero and MB137 = MB130. Which would mean MD134 = 0 0 0 MB130

L MD 130
SLD 8
SRD 16
T MD 138 = 0 0 MB131 MB132

L MD 130
SLD 16
SRD 8
T MD 142 = 0 MB132 MB133 0

L MD 130
SLD 24
T MD 146 = MB133 0 0 0

L MD 134 = 0 0 0 MB130
L MD 138 = 0 0 MB131 MB132
OD
L MD 142 = 0 MB132 MB133 0
OD
L MD 146 = MB133 0 0 0
OD
T MD 130 = MB130 MB131 MB132 MB133

As Simon says, would need to know more about the logic to understand why this is done.
 
I think that Peter has given us a hint at why this is being done. It's a byte swapping exercise, probably for visulisation purposes or to compensate for the fact that some other code was written to expect the bytes in a different order.

Interestingly, the code could be re-written without all the shifting and "ORing" instructions as follows:

Code:
L MW 130
T MW 134
T MW 136
L MW 135
T MW 140
L MW 132
T MW 134
T MW 136
L MW 135
T MW 138
L MD 138
T MD 130
Nick
 
Ok. Sorry for any confusion but here's what I have done so far which may or may not make things a little clearer ...

In an effort to understand the movement of data (far too long winded writing it bit by bit on paper) I re-assigned the local area data to the MD addresses and monitored them on a single scan basis using PLC SIM.

The code appears to work in exactly the same way in both formats with M115.7 being set when M116.4 is set in line with the pointer in Network 4.

Now, although you are correct in stating that at no time would M116.7 go to M117.0 on a single shift, the long winded code in Network 3 achieves exactly that as it is simply moving the bytes around to achieve the 32 bit shift register function.

As I said earlier, a ghost bit appears where L0.0 (M130.0) is set despite the conditions in Network 2 not being satisfied so I can't explain how valid data has made its way into the local data area. That is my issue that I am seeking help on.

I have included the original block and the block which calls it in their original formats.

Thanks again for all your help ...
 
... the long winded code in Network 3 achieves exactly that as it is simply moving the bytes around to achieve the 32 bit shift register function.

The long winded code does not just move the bytes around, it moves them around and combines some of them resulting in your ghost bit - is this what is supposed to happen ?

Using a specific bit pattern makes it a lot easier to debug this tangled mess.

spag.jpg
 
Looking at the code I guess its trying to move a bit at a time from across MB116, then 117, then 118, 119 and out.

Your right in that if M117.7 is on, then after all the shifts then M116.0 and M118.0 are both on.

I also tried starting with M117.7 and M118.7 on and ended up with bit 1 in every byte on. :confused:

Is this what is supposed to happen?

What it means of course is once you start shifting bits, it will never empty out. Well never tried a test as I don't have a PLC at home.
 
I'd change the DINT temp's to Bytes and add another temp byte and code as follows:

Code:
      LAR1  P##BYTE_1

      L     #DD_Shift
      T     LD [AR1,P#0.0]

      A     #Impulso_shift
      JCN   OVER

      L     #BYTE_4
      SLW   9
      SRW   8
      T     #BYTE_4

      L     #BYTE_3
      SLW   9
      JZ    B3

      T     #xbyte
      L     1
      L     #BYTE_4
      OW    
      T     #BYTE_4
      L     #xbyte

B3:   SRW   8
      T     #BYTE_3

      L     #BYTE_2
      SLW   9
      JZ    B2

      T     #xbyte
      L     1
      L     #BYTE_3
      OW    
      T     #BYTE_3
      L     #xbyte

B2:   SRW   8
      T     #BYTE_2

      L     #BYTE_1
      SLW   9
      JZ    B1

      T     #xbyte
      L     1
      L     #BYTE_2
      OW    
      T     #BYTE_2
      L     #xbyte

B1:   SRW   8
      T     #BYTE_1

      AN    #Impulso_set
      ON    #Load
      JC    OVER

      L     1
      OW    
      T     #BYTE_1

OVER: LAR1  P##BYTE_1

      L     LD [AR1,P#0.0]
      T     #DD_Shift
can't test it but think its close
 
Thanks very much for all your help with this one folks, I have now found the cause of the problem and a suitable solution too. :p

The error lies in the original code and it's only when operations have started to run the line differently due to a reduction in manpower has the fault become apparent.



The purpose of Network 3 is simply to rearrange the order of Bytes MB130 through MB133 from

MB130 | MB131 | MB132 | MB133

to

MB133 | MB132 | MB131 | MB130

then shift entire double word one place to the left before restoring the bytes back into their original order from

MB133 | MB132 | MB131 | MB130

to

MB130 | MB131 | MB132 | MB133


Now the problem is that if we take:

MB130 | MB131 | MB132 | MB133

and perform the following ...

L MD 130
SLD 8
SRD 16
T MD 138

we find:

zero | zero | MB131 | MB132

but what we need is:

zero | zero | MB131 | zero

This is similar later in the Network with:

L MD 130
SRD 16
SLD 8
T MD 138


The solution to the first part is to change it to:

L MD 130
SLD 8
SRD 24
SLD 8
T MD 138

which will result in:

zero | zero | MB131 | zero

Modified code now looks like this:

Network 3

A M 115.0
JCN m001

L MD 130
SRD 24
T MD 134

L MD 130
SLD 8
SRD 24
SLD 8
T MD 138

L MD 130
SRD 8
SLD 24
SRD 8
T MD 142

L MD 130
SLD 24
T MD 146

L MD 134
L MD 138
OD
L MD 142
OD
L MD 146
OD
T MD 130

SLD 1
T MD 130

L MD 130
SRD 24
T MD 134

L MD 130
SLD 8
SRD 24
SLD 8
T MD 138

L MD 130
SRD 8
SLD 16
SRD 8
T MD 142

L MD 130
SLD 24
T MD 146

L MD 134
L MD 138
OD
LD MD 142
OD
L MD 146
OD
T MD 130

NOP 0 m001

...

Thanks again everyone (y)
 
Here's FC47 re-coded. The CAD instruction is provided for swapping the byte order. I've eliminated the direct referencing of L data by using an address register.

Code:
FUNCTION "FC47" : VOID
TITLE =Shift
VERSION : 0.1
 
VAR_INPUT
  Impulso_set : BOOL ; //Impulso per impostare il primo bit dello shift registro
  Load : BOOL ; //Bit di presenza da caricare (eventualmente fisso ON)
  Impulso_shift : BOOL ; //Impulso per shift DD
  Impulso_reset : BOOL ; //Impulso di reset del bit testato (eventualmento fisso a OFF)
  Pos_out : INT ; //Posizione del bit da testare
END_VAR
VAR_OUTPUT
  OUT : BOOL ; //Bit testato
END_VAR
VAR_IN_OUT
  DD_Shift : DWORD ; //Doppia word ausiliaria per shift registro
END_VAR
VAR_TEMP
  DD_aux : DINT ; 
END_VAR
BEGIN
NETWORK
TITLE =Azzera variabili interne
      L     #DD_Shift; 
      T     #DD_aux; // temporary variable
      LAR1  P##DD_aux; 
NETWORK
TITLE =Carica il registro a scorrimento
      A     #Impulso_set; 
      A     #Load; 
      S      [AR1,P#0.0]; 
NETWORK
TITLE =Shift del registro a scorrimento
      A     #Impulso_shift; 
      JCN   m001; 
      L     #DD_aux; 
      CAD   ; 
      SLD   1; 
      CAD   ; 
      T     #DD_aux; 
m001: NOP   0; 
NETWORK
TITLE =Genera uscita
      L     #Pos_out; 
      +AR1  ; 
      A      [AR1,P#0.0]; 
      =     #OUT; 
NETWORK
TITLE =Resetta il bit utilizzato
      A     #Impulso_reset; 
      R      [AR1,P#0.1]; 
NETWORK
TITLE =Aggiornamento del registro a scorrimento I/O
      L     #DD_aux; 
      T     #DD_Shift; 
END_FUNCTION
 
Last edited:

Similar Topics

Good morning (EST), I am trying to implement the code below in on an S7-1200. It's barely half a dozen instructions, but I am stuck; I have not...
Replies
26
Views
5,735
Hi everyone I am completely new to using shift registers and am a bit stuck, my shift register works as should, it is for an overhead conveyor...
Replies
55
Views
15,725
Hi Guys, I am installing a vision system on a conveyor to inspect fill volumes and cap defects on an Eye drop bottling line. The idea is to...
Replies
12
Views
7,746
I'm wondering if there is a standard FC for a bit shift register. What i want: bit shift register of 64 bits Clock input to shift all bits 1...
Replies
16
Views
22,517
Hi folks, this is for you Shift Register guys. Can anyone see anything fundamentally wrong with the attached code? i've used this bit of code...
Replies
4
Views
2,320
Back
Top Bottom