ARDUINO™ "HACK" PLC SIEMENS™ QUA MẠNG ETHERNET

DẪN NHẬP

Hôm nay cuối tuần, mình sẽ dành thời gian làm một PLC & ARDUINO DEMO KIT và chia sẻ với các bạn cách kết nối Arduino với PLC S7-300 thông qua Ethernet, và thậm chí Read/Write vào PLC S7-300™ ở chế độ bảo mật cao nhất của CPU. Sau khi đọc bài viết này, các kỹ sư tự động có lý do để phải dè chừng khi tự dưng thấy một anh chàng điện tử cầm một Arduino có gắn Ethernet Shield và đang lúi húi kết nối vào hệ thống mạng Ethernet của nhà máy.....winkwinkwink....

Thực tế, mình cũng có tham khảo một số thư viện có thể đảm nhận việc giao tiếp này, ví như:

  • MQTT library block written in Siemens SCL for S7-300 PLC with CP343-1.

Source link: https://github.com/RoanBrand/MQTT-Siemens-S7-300

  • Settimino ARDUINO™ / NodeMCU™ Ethernet communication library for S7 Siemens™ PLC.

Source link: http://settimino.sourceforge.net/

Mình sẽ dùng thư viện settimino kiểm tra giao tiếp giữa Arduino & PLC vì cảm thấy nó pro hơn, có hướng dẫn rõ ràng & dễ hiểu. Để có được thử nghiệm này, các bạn phải có kiến thức nhất định về PLC Siemens và cũng phải tiêu tốn kha khá tiền đấy….laugh....

I. GIỚI THIỆU

Tác giả Dave Nardella (người Ý, Trưởng phòng quản lý phần mềm công ty MASMEC SPA) là tác giả của 2 thư viện rất hay về giao tiếp giữa các vi xử lý ARM Linux/ MIPS và PLC Siemens S7 ™:

1.1. THƯ VIỆN SNAP7

Snap7 là thư viện giao tiếp Ethernet đa nền tảng, mã nguồn mở, dùng để truyền nhận dữ liệu qua Ethernet gữa PLC của Siemens (từ LOGO 0BA7/0BA8, S7-200/300/400 cho đến các thế hệ mới như CPUs 1200/1500) và Raspberry PI (1 and 2) , BeagleBone Black, pcDuino, CubieBoard, UDOO and ARDUINO YUN. 

Link thư viện: http://snap7.sourceforge.net/.

1.2. THƯ VIỆN SETTIMINO

Settimino cũng là một thư viện Ethernet mã nguồn mở để kết nối ARDUINO ™ / ESP8266 NodeMCU (NodeMCU 1.0 ESP-12E ESP8266) với các PLC Siemens S7 ™. Nó được tác giả viết lại từ Snap7 để tương thích với nền tảng của Arduino.

Link thư viện settimino: http://settimino.sourceforge.net/.

1.3. THAM KHẢO VỀ PLC SIEMENS™ 

Các bạn có thể tham khảo tại website của Siemens: https://www.siemens.com

II. PHẦN CỨNG

2.1. LIST THIẾT BỊ PLC & ARDUINO DEMO KIT

No.
Items
Specification
Q’ty
Remarks
1
Load supply voltage 120/230 VAC : 24 VDC/5A
1
Nguồn 24VDC
2
DI24/DO16; AI5/AO2 integrated; 4 pulse outputs (2.5kHz); 4 channel counting and measuring with incremental encoders 24V (60kHz); integrated positioning function.
1
CPU 314C-2DP tích hợp sẵn nhiều I/O.
3
SIMATIC NET, CP 343-1 LEAN COMMUNICATION PROCESSOR FOR CONNECTING SIMATIC S7-300 TO IND. ETHERNET.
 
 
4
L=160MM
1
Đủ để gắn các card PLC
5
 
1
 
6
 
1
 
7
W5100
1
 
8
Cáp mạng LAN
Mỗi sợi dài 2~3m
3
Bấm sẵn 2 đầu
9
Dây điện (m)
1.5/2.5mm
3
 
10
CB
 
1
AC vào

Lưu ý quan trọng về Ethernet Shield

Giá trị điện trở tại khung đỏ hình chữ nhật hình dưới phải là 49R9 hay 510 (khoảng 50~51 ohm), có một số Ethernet Shield ghi 511 (510 ohm). Mình bị dính 1 con với điện trở 511 nên không thể kết nối được với PLC & cuối cùng phải tìm mua con khác mới kết nối được. Nếu bạn có một Ethernet Shield đang được sử dụng, hãy kiểm tra lại điện trở trên cũng như độ ổn định của nó.

2.2. SƠ ĐỒ MẠCH & CẤU HÌNH PHẦN CỨNG

Giải thích cấu hình

  • Ở cấu hình trên, Snap7 ClientDemo là tùy chọn nếu trong máy PC đã cài đặt Simatic Manager.
  • Trong chương trình Arduino IDE, sử dụng ConnectTo() xác định IP_Address, Rack, Slot cho kết nối đầu tiên, chức năng này thiết lập các thông số nội bộ và kết nối với PLC.
Configuration
MAC_Address
IP_Address
Rack
Slot
Remarks
CPU S7-300
Siemens default
192,168,0,71
0
2
Với CPU300: Rack=0, Slot=2.
Arduino Uno
0x90, 0xA2, 0xDA, 0x0F, 0x08, 0xE11
192,168,0,70
-
-

 

  • Trong chương trình STEP 7, IP_Address của PLC (CP343-1) phải là địa chỉ đã khai báo trong chương trình Arduino: 192.168.0.71. Xem chi tiết theo hình.

  • ARDUINO & PLC DEMO KIT thực tế:

III. CHƯƠNG TRÌNH

3.1. THƯ VIỆN SETTIMINO

Các bạn tải về tại link: https://sourceforge.net/projects/settimino/files/, trong đó bao gồm: thư viện, hướng dẫn chi tiết sử dụng thư viện và chương trình mẫu.

Trong file hướng dẫn, các bạn lưu ý đến thuật ngữ “Big-Endian” và “Little-Endian” để diễn tả sự khác nhau về cách đọc và ghi dữ liệu giữa ARDUINO ™ (Little -Endian ) và PLC Siemens S7 ™ (Big -Endian ).

  • Big –Endian: từ MSB --> LSB, ví dụ DWORD 0x4C21112F được lưu trữ trong PLC Siemens S7 ™ như sau:

0x4C

0x21

0x11

0x2F

  • Little –Endian: từ LSB --> MSB, cùng DWORD như trên nhưng ARDUINO ™ sẽ được lưu trữ ngược lại:

0x2F

0x11

0x21

0x4C

Trên trang STDIO: https://www.stdio.vn/articles/read/10/little-endian-va-big-endian, tác giả Rye Nguyen nói rất rõ về cấu trúc dữ liệu này và có cả chương trình chuyển đổi qua lại giữa Little-Endian và Big-Endian.

3.2. CHƯƠNG TRÌNH PLC

  • Mình dùng STEP 7 Professional 2010 V5.5 để cấu hình phần cứng & viết chương trình cho PLC. Các bạn chuyên ngành tự động hóa sẽ rất am hiểu về nó…..
  • Các bạn cũng có thể dùng SIMATIC WinCC làm hệ thống HMI/SCADA để điều khiển PLC Siemens S7 ™ hoặc ARDUINO ™.
  • Settimino có thể truy cập trực tiếp vào các dòng PLC Siemens có tích hợp sẵn Ethernet (như CPU 315-2 PN/DP, CPU412-2 PN/DP, CPU414-3 PN/DP…) hay thông qua Card Ethernet rời CP343 (cho CPU S7-300), CP443 (cho CPU S7-400). Mình đang thử nghiệm ở trường hợp dùng CP343 + CPU S7-300.

 

CPU

 

300

400

WinAC

1200

1500

LOGO

S7200

DB Read/Write

O

O

O

O(1)

O(1)

 

O(2)

 

O(2)

EB Read/Write

O

O

O

O

O

AB Read/Write

O

O

O

O

O

MK Read/Write

O

O

O

O

O

TM Read/Write

O

O

O

-

-

-

-

CT Read/Write

O

O

O

-

-

-

-

Get DB Size

O

O

O

-

-

-

-

DB Get

O

O

O

-

-

-

-

Control Run/Stop

O

O

O

-

-

-

-

3.3. CHƯƠNG TRÌNH ARDUINO

a. Đọc vào Data Block của PLC

  • Sơ lược về chương trình DBGetDemo:
    • Trong PLC, chúng ta tạo ra DB2 (Data Block) chứa 100 bytes với các giá trị được gán ban đầu theo thứ tự từ 0 ~ 99.
    • Chương trình DBGetDemo sẽ đọc giá trị 100 Bytes của DB2 (Data Block) ở trên và hiển thị ở Serial Monitor.
    • Trong lúc Arduino đọc DB2 từ PLC, chúng ta dùng chức năng FORCE trong PLC để thay đổi giá trị của 2 bytes (DB2.DBB0 & DB2.DBB1) trong DB2 để kiểm tra xem  Arduino có đọc đúng hay không? Chi tiết các bạn có thể xem tại:

  • Chương trình DBGetDemo
/*----------------------------------------------------------------------
 DB Get Demo

 Created 19 Nov 2013
 by Davide Nardella
 
------------------------------------------------------------------------
This demo shows how to upload an entire DB from the PLC without
knowing its size in advance.
A DB1 with not more than 1024 byte into the PLC is needed.

- 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 <SPI.h>
#include <Ethernet.h>
#include "Settimino.h"

// 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, 0xE11 };
  
IPAddress Local(192,168,0,70); // Local Address
IPAddress PLC(192,168,0,71);   // PLC Address

byte Buffer[512];

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(9600);
     while (!Serial) {
      ; // wait for serial port to connect. Needed for Leonardo only
    }
    // Start the Ethernet Library
    Ethernet.begin(mac, Local);
    // Setup Time, someone said me to leave 2000 because some 
    // rubbish compatible boards are a bit deaf.
    delay(2000); 
    Serial.println(Ethernet.localIP());
}
//----------------------------------------------------------------------
// Connects to the PLC
//----------------------------------------------------------------------
bool Connect()
{
    int Result=Client.ConnectTo(PLC, 
                                  0,  // Rack (see the doc.)
                                  2); // 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() 
{
  
  uint16_t Size;
  int Result;
  Size = sizeof(Buffer);
  
  // Connection
  while (!Client.Connected)
  {
    if (!Connect())
      delay(500);
  }
  
  Serial.println("Uploading DB2"); 
  // Get the current tick
  MarkTime();
  Result=Client.DBGet(2,       // DB Number = 1
                      &Buffer, // Our Buffer
                      &Size);  // In input contains our buffer size
                               // As output contains the data read
  if (Result==0)
  {
    ShowTime();
    Dump(&Buffer, Size);
  }
  else
    CheckError(Result);
    
  delay(500);  
}

b. Ghi vào Data Block của PLC ở mức bảo mật Level 3

  • ​​Sơ lược về chương trình:
    • Bật Security Level 3 (Read/Write Protection) trong cấu hình CPU300 - Sau đó Complie & Download to Module.
    • Trong PLC, chúng ta tạo ra DB1 (Data Block) chứa 1,090 bytes với KNOW_HOW_PROTECT (nói chung là DB này bị khóa theo thuật ngữ của Siemens).
    • Chương trình WriteDemo sẽ ghi giá trị mong muốn vào 2 bytes DB1.DBB0 & DB1.DBB1 của DB1 (Data Block) đang được lưu trong PLC.
    • Thay đổi các giá trị muốn ghi trong chương trình Arduino và kiểm tra online DB1 của PLC ? 
  • Chương trình tham khảo:

Chi tiết các bạn có thể xem tại: 

VI. LỜI KẾT

  • Riêng với PLC S7-300 ở thử nghiệm này, Sap7/Settimino hầu như có thể thực hiện việc đọc/ghi vào PLC mà không phụ thuộc vào Mức độ bảo mật (Protection Level). Vấn đề bảo mật này chắc chắn là gây ra rất nhiều khó khăn cho các kỹ sư tự động khi làm việc với CPU của Siemens™.
  • Arduino không tương thích với môi trường công nghiệp: khói bụi, hơi ẩm, nhiệt độ ... và khó có thể đáp ứng yêu cầu về độ ổn định như PLC. Nhưng ít nhiều, đây cũng là một hướng cho các bạn làm IoT/ Smart Home dùng các CPU Siemens thế hệ mới có tích hợp sẵn cổng Ethernet, giá cả phải chăng, kết hợp với Arduino.
  • Qua bài viết này, nếu các bạn có cơ hội làm việc trên các dòng PLC khác, hãy thử giao tiếp bằng Arduino và cùng chia sẻ với mọi người....yes....Và sau cùng đừng quên Rate node cho bài viết này nhé. heart.
Youtube: 
Arduino Read PLC Data Block
Arduino Write to PLC Data Block with Security Protection
Những hình ảnh về dự án: 
Bài viết truyền cảm hứng: 
lên
19 thành viên đã đánh giá bài viết này hữu ích.
Các dự án được truyền cảm hứng

Select any filter and click on Apply to see results

Các bài viết cùng tác giả

KẾT NỐI PROFIBUS-DP GIỮA ARDUINO VÀ PLC

Hôm nay, tôi xin chia sẻ cách Arduino giao tiếp với PLC thông qua kết nối Profibus-DP. Với kết quả đạt được, chúng ta có thể thực hiện một số dự án IoT hoặc IIoT với sự kết hợp giữa PLC và Arduino cộng với các SHIELD mở rộng của của Arduino với chi phí thấp.

Dưới đây là một số thử nghiệm mà tôi đã áp dụng giao tiếp Profibus-DP cho Arduino Mega 2560 + PLC Siemens S7-300

lên
18 thành viên đã đánh giá bài viết này hữu ích.

Phương pháp Charlieplexing và LoLShield VU Meter

Phương pháp Charliplexing là gì? Mình sẽ giới thiệu sơ lược về nó và hướng dẫn các bạn làm một board LoLShield (Lots of Lights Shield). Với LoLShield, mục tiêu chúng ta là điều khiển 126 đèn led đơn được xếp thành ma trận 9x14 bằng phương pháp Charliplexing để tiết kiệm chân Arduino và thiết kế sao nó thành Shield cắm thẳng lên Arduino

lên
14 thành viên đã đánh giá bài viết này hữu ích.