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

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

 

 

材料

  • Arduino UNO (328P)

  • Ethernet拓展版 (W5100)

  • 西门子 S7-200 Smart一台

  • 网线/交换机

软件

  • STEP 7-MicroWIN SMART

  • Arduino IDE

步骤

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

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

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

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

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

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

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

    • 修改PLC IP和local IP 

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

 

  • 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(<IP>, <Rack>, <Slot>);

    with the couple

    Client.SetConnectionParams(<IP>, <LocalTSAP>, <Remote TSAP>);

    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<Length; i++)

  {

    cnt++;

    if (buf[i]<0x10)

      Serial.print("0");

    Serial.print(buf[i], HEX);

    Serial.print(" ");

    if (cnt==16)

    {

      cnt=0;

      Serial.println();

    }

  }  

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

}

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

// Prints the Error number

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

void CheckError(int ErrNo)

{

  Serial.print("Error No. 0x");

  Serial.println(ErrNo, HEX);

  

  // Checks if it's a Severe Error => 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);  

}

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然,下面是一个简单的例子,展示了如何使用ESP32通过S7协议西门子PLC进行读取和写入通信。 首先,你需要安装 `S7Comm` 库,它是一个用于与西门子PLC通信的ESP32库。你可以在 Arduino 库管理器中搜索并安装该库。 接下来,使用以下代码示例: ```cpp #include <S7Comm.h> // 定义PLC连接参数 const char* ipAddress = "192.168.0.100"; // PLC的IP地址 int rack = 0; // PLC的机架号 int slot = 2; // PLC的插槽号 // 创建S7Comm对象 S7Client plc; void setup() { Serial.begin(115200); // 初始化PLC连接 if (plc.ConnectTo(ipAddress, rack, slot) == 0) { Serial.println("PLC连接成功"); } else { Serial.println("PLC连接失败"); while (1); } } void loop() { // 读取PLC的M0.0位状态 bool m0_0; if (plc.ReadBit(S7AreaDB, 0, 0, m0_0) == 0) { Serial.print("M0.0位状态:"); Serial.println(m0_0 ? "高" : "低"); } else { Serial.println("读取M0.0位失败"); } // 写入PLC的M1.0位状态为高 bool m1_0 = true; if (plc.WriteBit(S7AreaDB, 1, 0, m1_0) == 0) { Serial.println("写入M1.0位成功"); } else { Serial.println("写入M1.0位失败"); } delay(1000); } ``` 在上述代码中,我们首先定义了PLC的连接参数,包括PLC的IP地址、机架号和插槽号。然后,在 `setup()` 函数中,我们初始化了PLC连接,并检查连接是否成功。 在 `loop()` 函数中,我们使用 `ReadBit()` 函数读取PLC的M0.0位状态,并使用 `WriteBit()` 函数将PLC的M1.0位状态设置为高。你可以根据自己的需求修改读写的数据区域和地址。 记得在 Arduino IDE 中选择正确的开发板和端口,然后编译并上传代码到ESP32开发板。打开串口监视器,你将能够看到与PLC的通信状态和读写结果。 希望这个简单的例子能帮助到你!如有任何问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值