Saturday, December 13, 2014

Raspberry Pi getting data from a S7-1200 PLC


UPDATE: If you want the raspberry pi to be the s7 server go here
UPDATE 2: If you want to see communication with S7-200 go here
UPDATE 3: Video walkthrough on setup go here

I recently borrowed a S7-1200 PLC from work to see if I could get data from it using a Raspberry Pi. In my search for something I found that Snap7 was the best option.
Steps to getting it work
  1. Download and compile snap7 (http://sourceforge.net/projects/snap7/files/1.2.1/snap7-full-1.2.1.tar.gz/download)
  2. Download and install python library to use snap7 (https://pypi.python.org/pypi/python-snap7)


#download and compile snap7 for rpi

wget http://sourceforge.net/projects/snap7/files/1.2.1/snap7-full-1.2.1.tar.gz/download 
tar -zxvf snap7-full-1.2.1.tar.gz
cd snap7-full-1.2.1/build/unix
sudo make –f arm_v6_linux.mk all

#copy compiled library to your lib directories
sudo cp ../bin/arm_v6-linux/libsnap7.so /usr/lib/libsnap7.so
sudo cp ../bin/arm_v6-linux/libsnap7.so /usr/local/lib/libsnap7.so

#install python pip if you don't have it:
sudo apt-get install python-pip
sudo pip install python-snap7

You will need to edit the lib_location on common.py in the /usr/local/lib/python2.7/dist-packages/snap7/ directory
Add a line in the __init__ part of the Snap7Library class:
lib_location='/usr/local/lib/libsnap7.so' 
example below:


class Snap7Library(object):
    """
    Snap7 loader and encapsulator. We make this a singleton to make
    sure the library is loaded only once.
    """
    _instance = None
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = object.__new__(cls)
            cls._instance.lib_location = None
            cls._instance.cdll = None
        return cls._instance

    def __init__(self, lib_location=None):
        lib_location='/usr/local/lib/libsnap7.so' # add this line here
        if self.cdll:
            return
        self.lib_location = lib_location or self.lib_location or find_library('snap7')
        if not self.lib_location:
            msg = "can't find snap7 library. If installed, try running ldconfig"
            raise Snap7Exception(msg)
        self.cdll = cdll.LoadLibrary(self.lib_location)

Now you can write your client code :-)
Here's an example on how to connect and read an output Q0.0:
from time import sleep
import snap7
from snap7.util import *
import struct

plc = snap7.client.Client()
plc.connect("192.168.12.73",0,1)

area = 0x82    # area for Q memory
start = 0      # location we are going to start the read
length = 1     # length in bytes of the read
bit = 0        # which bit in the Q memory byte we are reading

byte = plc.read_area(area,0,start,length)
print "Q0.0:",get_bool(mbyte,0,bit)
plc.disconnect()



I created a helper class on my github here to make the syntax easier for people who are used to DAServer and Ladder:
https://github.com/SimplyAutomationized/raspberrypi/raw/master/S7-1200pi/S71200.py
Example on how to use it:
import S71200
from time import sleep
import snap7
from snap7.util import *
import struct

plc = S71200.S71200("192.168.21.65")
plc.writeMem('QX0.0',True) # write Q0.0 to be true, which will only turn on the output if it isn't connected to any rung in your ladder code
print plc.getMem('MX0.1') # read memory bit M0.1
print plc.getMem('IX0.0') # read input bit I0.0
print plc.getMem("FREAL100") # read real from MD100
print plc.getMem("MW20") # read int word from MW20
print plc.getMem("MB24",254) # write to MB24 the value 254
plc.plc.disconnect()



Let me know if there are questions. Hope I can help :-)
Also let me know if you can help me clean up my S71200.py helper class. I know it looks messy.

Follow me to get updates on a Raspberry pi Sensor the DA or OPC server can get data using S7 protocol.
+Simply Automationized
Check out my other SCADA posts

26 comments:

  1. sudo make –f arm_v6_linux.mk all when I am running this line, I got the error like this

    pi@raspberrypi:~/Downloads/snap7-full-1.2.1/build/unix $ sudo make –f arm_v6_linux.mk all
    make: *** No rule to make target '–f'. Stop.

    Please help me to overcome that error.thanks in advance.


    ReplyDelete
    Replies
    1. Hi, Please use the following instead:

      sudo make -f arm_v6_linux.mk

      Delete
    2. the "-f" should be written by yourself.

      Delete
  2. Don't copy the line, write yourself the line. (Sorry for my english, is very basic.)

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. I too have the same error for the line "sudo make –f arm_v6_linux.mk all"
    Help me to overcome this problem.

    ReplyDelete
    Replies
    1. you probably are using a Raspberry Pi 3.. which would be
      "sudo make -f arm_v7_linux.mk all"

      Delete
  5. This comment has been removed by the author.

    ReplyDelete
  6. Hello. I try fix allow above. But dont success. Can you help me!
    snap7.snap7exceptions.Snap7Exception: can't find snap7 library. If installed, try running ldconfig

    ReplyDelete
  7. i am not able to read address starting from "MW" of S71200 plc, but can read address starting from "MD" why is that so please help me.

    ReplyDelete






  8. How can i solve this problem
    In [19]: plc.connect("192.168.0.1",0,1)
    ---------------------------------------------------------------------------
    Snap7Exception Traceback (most recent call last)
    in ()
    ----> 1 plc.connect("192.168.0.1",0,1)

    /home/pi/.local/lib/python2.7/site-packages/snap7/client.pyc in f(*args, **kw)
    23 def f(*args, **kw):
    24 code = func(*args, **kw)
    ---> 25 check_error(code, context="client")
    26 return f
    27

    /home/pi/.local/lib/python2.7/site-packages/snap7/common.pyc in check_error(code, context)
    63 error = error_text(code, context)
    64 logger.error(error)
    ---> 65 raise Snap7Exception(error)
    66
    67

    Snap7Exception: TCP : Connection timed out

    ReplyDelete
  9. when i try to install the snap7 lib i get this error i this line $ tar -zxvf snap7-full-1.2.1.tar.gz
    tar (child): snap7-full-1.2.1.tar.gz : open impossible: Aucun fichier ou dossier de ce type
    tar (child): Error is not recoverable: exiting now
    tar: Child returned status 2
    tar: Error is not recoverable: exiting now
    what does it mean ?

    ReplyDelete
  10. hey , i installed the lib and when i tried to excute the code i got an error : no module named snap7 .
    how can i fix this ?

    ReplyDelete
  11. in case of [tar -zxvf snap7-full-1.2.1.tar.gz] it was not working for me. Then found out the downloaded filename was [download.tar.gz], i needed to use [tar -zxvf download.tar.gz], by using [cd] / [dir] command first check the name of downloaded file, then execute the [tar -zxvf] command.

    ReplyDelete
  12. How can i fix tis
    File "plc2.py", line 1, in
    import S71200
    File "/home/pi/s7/S71200.py", line 110, in
    plc = S71200('192.168.1.10') #,debug=True)
    File "/home/pi/s7/S71200.py", line 16, in __init__
    self.plc.connect(ip,0,1)
    File "/usr/local/lib/python2.7/dist-packages/snap7/client.py", line 25, in f
    check_error(code, context="client")
    File "/usr/local/lib/python2.7/dist-packages/snap7/common.py", line 66, in check_error
    raise Snap7Exception(error)
    snap7.snap7exceptions.Snap7Exception: TCP : Unreachable peer

    ReplyDelete
  13. i have 2 questions :
    first one : how can we find the IP address that you wrote in your code [plc.connect("192.168...")] ?
    and what is that IP address exactly ?
    second one : do we connent raspberry to plc via Ethernet ?
    Thanks

    ReplyDelete
    Replies
    1. The ip address is the ip address of plc... You can set it up with tia portal (siemens automation software).... 2. Yes the snap7 uses ethernet to comunicate with the plc. It connects via "pg interface" (siemens administration protocol)... Of course you can setup an access point and access the plc via WiFi...

      Delete
  14. how to get response ...on db_write or any write funtion.... that we know value write successfully in DBaddress????

    ReplyDelete
  15. Dear All,
    i am trying to communicate S71200 PLC with RaspberryPI using Python program.

    Following are the Pthon program and Error:
    import S71200
    from time import sleep
    import snap7
    from snap7.util import *
    import struct

    plc = S71200.S71200("192.168.43.2")
    #plc.writeMem('QX0.0',True) # write Q0.0 to be true, which will only turn on the output if it isn't connected to any rung in your ladder code
    print plc.writeMem('%DB1.QX4.0',False)# writing value
    print plc.getMem("%DB1.DBX4.0") # read
    print plc.getMem("%DB1.DBX8.0") # read
    print plc.getMem("%DB1.DBW20") # read
    plc.plc.disconnect()

    Error:
    >>> %Run Snap7_Example3.py
    Traceback (most recent call last):
    File "/home/pi/Desktop/Snap7_Example3.py", line 9
    print plc.writeMem('QX4.0',False)# writing value
    ^
    SyntaxError: invalid syntax
    >>>



    In SIEMENS TIA:
    Address is: %DB1.DBX4.0
    %DB1.DBX8.0
    %DB1.DBD.16


    Please advice

    ReplyDelete
    Replies
    1. Hi ReachRao,

      It seems you are using Python3. The error here is showing invalid syntax as from Python3 print "abcd" is not supported and data needs to be kept in brackets.
      For e.g. please change to print(plc.writeMem('QX4.0',False)) to resolve this error.

      Delete
  16. Thanks for a very detailed explaination, can you tell me were can i get the area for other plcs? or is it the same for all the S7 seires?

    ReplyDelete