Arduino读取西门子PLC数据/S7协议通讯

S7协议是西门子公司工业设备专用通讯协议,有开源协议snap7开源库可以对数据进行读写,支持多个平台和语言甚至是Arduino板卡上,我这里分享下使用方法

Arduino读取西门子PLC数据/S7协议通讯_第1张图片 

 

材料

  • Arduino UNO (328P)

  • Ethernet拓展版 (W5100)

  • 西门子 S7-200 Smart一台

  • 网线/交换机

软件

  • STEP 7-MicroWIN SMART

  • Arduino IDE

步骤

  • 下载安装S7协议库 Settimino Homepage (Step7+Arduino)

  • 在ArduinoIDE上加载Settimino库:项目>加载库>添加zip库

  • ArduinoIDE上打开第三方库>Settimino> ReadDemo示例

  • 代码上改动  (代码的具体设置去看snap7官方API文档)

    • 示例支持多个板卡:esp32/esp8266/w5500/w5100,默认是esp32所以代码上要调整下

      1. 注释ESP32/8266的初始化,留下Ethernet的初始化

      2. 文本编辑器进入 ;注释#define M5STACK_LAN  ;取消注释#define ARDUINO_LAN

      3. UNO内存小,编译储存会不够,宏定义DO_IT_SMALL选择缓冲数据存储方式

    • 修改PLC IP和local IP 

    • 注意选对PLC的机架号和槽号,西门子不同系列PLC不同,200smart默认不需要设置

Arduino读取西门子PLC数据/S7协议通讯_第2张图片

 

  • 200smart 没有DB块,DBNum只有设置1

  • 通讯类型设置 SetConnectionType(3),S7不同模式对通讯影响不同,这里设置3,

 

  • 编译 下载到UNO,在STEP 7-MicroWIN上链接PLC在线修改变量,观察串口打印数据的是否变化

/*----------------------------------------------------------------------

Data Read Demo





Created  12 Dec 2016

Modified 10 Mar 2019 for Settimino 2.0.0

by Davide Nardella

------------------------------------------------------------------------

This demo shows how to read data from the PLC.

A DB with at least 1024 byte into the PLC is needed.

Specify its number into DBNum variable





- Both small and large data transfer are performed (see DO_IT_SMALL)

- During the loop, try to disconnect the ethernet cable.

  The system will report the error and will reconnect automatically

  when you re-plug the cable.

- For safety, this demo *doesn't write* data into the PLC, try

  yourself to change ReadArea with WriteArea.

- This demo uses ConnectTo() with Rack=0 and Slot=2 (S7300)

  - If you want to connect to S71200/S71500 change them to Rack=0, Slot=0.

  - If you want to connect to S7400 see your hardware configuration.

  - If you want to work with a LOGO 0BA7 or S7200 please refer to the

    documentation and change

    Client.ConnectTo(, , );

    with the couple

    Client.SetConnectionParams(, , );

    Client.Connect();

    

----------------------------------------------------------------------*/

#include "Platform.h"

#include "Settimino.h"





// Uncomment next line to perform small and fast data access

#define DO_IT_SMALL





// Enter a MAC address and IP address for your controller below.

// The IP address will be dependent on your local network:

byte mac[] = {

  0x90, 0xA2, 0xDA, 0x0F, 0x08, 0xE1 };





IPAddress Local(192,168,1,1); // Local Address

IPAddress PLC(192,168,1,31);   // PLC Address





// Following constants are needed if you are connecting via WIFI

// The ssid is the name of my WIFI network (the password obviously is wrong)

char ssid[] = "SKYNET-AIR";    // Your network SSID (name)

char pass[] = "yourpassword";  // Your network password (if any)

IPAddress Gateway(192, 168, 1, 1);

IPAddress Subnet(255, 255, 255, 0);





int DBNum = 1; // This DB must be present in your PLC

byte Buffer[1024];





S7Client Client;





unsigned long Elapsed; // To calc the execution time

//----------------------------------------------------------------------

// Setup : Init Ethernet and Serial port

//----------------------------------------------------------------------

void setup() {

    // Open serial communications and wait for port to open:

    Serial.begin(115200);

//--------------------------------Wired Ethernet Shield Initialization    

    // Start the Ethernet Library

    EthernetInit(mac, Local);

    // Setup Time, someone said me to leave 2000 because some

    // rubbish compatible boards are a bit deaf.

    delay(2000);

    Serial.println("");

    Serial.println("Cable connected");  

    Serial.print("Local IP address : ");

    Serial.println(Ethernet.localIP());  

}

//----------------------------------------------------------------------

// Connects to the PLC

//----------------------------------------------------------------------

bool Connect()

{

    int Result=Client.ConnectTo(PLC,

                                  0,  // Rack (see the doc.)

                                  1); // Slot (see the doc.)

    Serial.print("Connecting to ");Serial.println(PLC);  

    if (Result==0)

    {

      Serial.print("Connected ! PDU Length = ");Serial.println(Client.GetPDULength());

    }

    else

      Serial.println("Connection error");

    return Result==0;

}

//----------------------------------------------------------------------

// Dumps a buffer (a very rough routine)

//----------------------------------------------------------------------

void Dump(void *Buffer, int Length)

{

  int i, cnt=0;

  pbyte buf;

  

  if (Buffer!=NULL)

    buf = pbyte(Buffer);

  else  

    buf = pbyte(&PDU.DATA[0]);





  Serial.print("[ Dumping ");Serial.print(Length);

  Serial.println(" bytes ]===========================");

  for (i=0; i we need to disconnect

  if (ErrNo & 0x00FF)

  {

    Serial.println("SEVERE ERROR, disconnecting.");

    Client.Disconnect();

  }

}

//----------------------------------------------------------------------

// Profiling routines

//----------------------------------------------------------------------

void MarkTime()

{

  Elapsed=millis();

}

//----------------------------------------------------------------------

void ShowTime()

{

  // Calcs the time

  Elapsed=millis()-Elapsed;

  Serial.print("Job time (ms) : ");

  Serial.println(Elapsed);   

}

//----------------------------------------------------------------------

// Main Loop

//----------------------------------------------------------------------

void loop()

{

  int Size, Result;

  void *Target;

   

#ifdef DO_IT_SMALL

  Size=64;

  Target = NULL; // Uses the internal Buffer (PDU.DATA[])

#else

  Size=1024;

  Target = &Buffer; // Uses a larger buffer

#endif

  //Client.SetConnectionParams(Local,0x0100,0x0101);

  Client.SetConnectionType(3);

  // Connection

  while (!Client.Connected)

  {

    if (!Connect())

      delay(500);

  }

  

  Serial.print("Reading ");Serial.print(Size);Serial.print(" bytes from DB");Serial.println(DBNum);

  // Get the current tick

  MarkTime();

  Result=Client.ReadArea(S7AreaDB, // We are requesting DB access

                         DBNum,    // DB Number

                         0,        // Start from byte N.0

                         Size,     // We need "Size" bytes

                         Target);  // Put them into our target (Buffer or PDU)

  if (Result==0)

  {

    ShowTime();

    Dump(Target, Size);

  }

  else

    CheckError(Result);

    

  delay(1000);  

}

你可能感兴趣的:(工业自动化,单片机,单片机,网络协议)