M5Stack W5500 LAN Module
This module contains the W5500 chip with M5Base, and can easily realize Internet connection with TCP/IP Ethernet Controller. And HT3.96 connector 485Interface is also available. You can also connect to other circuits with its HT3.96 connector.
Please find more information from here:
https://docs.m5stack.com/en/base/lan_base
You can buy from here:
https://www.switch-science.com/catalog/3994/
Settimino Library
Settimino is used in this tutorial and you can use it to build the communication between Siemens PLC (S7-1200,1500,300,400,200,LOGO)and でArduino/ESP8266/ESP32.
http://settimino.sourceforge.net/
Installation
Please access this link to download the latest version of that library.
https://sourceforge.net/projects/settimino/files/
Ethernet2 Library
Ethernet2 Library can be used with W5500 Ethernet shields as Server/Client.(Please be careful that older than W5100, you can not use this library.)
Download Link:
https://www.arduino.cc/reference/en/libraries/ethernet2/
Implementation
You need to edit the Settimino.h first.
Because the M5 Stack LAN Module is used in my tutorial, you need to change some code in that file.Go to Line111 and import the M5Core2.h and Ethernet2.h .
Code
Here is the Code.
/*———————————————————————- M5Stack Sentron emulation Created 09 Mar 2019 by Davide Nardella ———————————————————————— This demo is only for M5Stack hardware. You need to define M5STACK_WIFI or M5STACK_LAN (see platform.h) ———————————————————————-*/ #include <Platform.h> #include <Settimino.h> //——————————————————————— // Defining USE_DISPLAY the display will be used for service messages //——————————————————————— #define USE_DISPLAY #ifdef USE_DISPLAY #define stdout M5.Lcd #else #define stdout Serial #endif //********************************************************************** // Connection Variables //********************************************************************** // 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 }; // Cabled Network (M5STACK_LAN defined in platform.h) IPAddress Local(192,168,0,10); // Local Address IPAddress Gateway(192, 168, 0, 1); IPAddress Subnet(255, 255, 255, 0); // WIFI Network (M5STACK_WIFI defined in platform.h) // Following constants are needed only 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[] = “password”; // Your network password (if any) // Remote Address IPAddress PLC(192,168,0,12); // PLC Address //********************************************************************** // Process Variables //———————————————————————- // We assume that DB100 contains 9 Reals starting from 0 // V1,V2,V3 Voltage // C1,C2,C3 Current // P1,P2,P3 Power //********************************************************************** int DBValues = 100; // DB containing Data int OFSValues = 0; // Offset of first value int SizeValues = 36; // 9 Reals = 36 Byte //********************************************************************** // Program Variables //********************************************************************** // Pages #define VOLTAGE 1 #define CURRENT 2 #define POWER 3 #define SERVICE 4 #define PageSwitchTime 4000 // Change Page every 4s if no button was pressed long Elapsed =0; int PageColors[4] = {TFT_GREEN, // Voltage page text color TFT_YELLOW, // Current page text color TFT_WHITE, // Power page text color TFT_WHITE}; // Error page text color // Leading int xl[3]={15, 15, 15}; int yl[3]={36, 108,180}; // Values int xv[3]={84, 84, 84}; int yv[3]={10, 82, 154}; // Umes int xu[3]={260,260,260}; int yu[3]={36, 108,180}; float V[3]={0.0,0.0,0.0}; // TENSION float C[3]={0.0,0.0,0.0}; // CURRENT float P[3]={0.0,0.0,0.0}; // POWER S7Client Client; int CurrentPage = -1; // To force the first switch //———————————————————————- // Checks the elapsed time //———————————————————————- bool IsElapsed(long Time) { long Delta=millis()-Elapsed; if (Delta<0) // Check millis() rollover (after 49 days) { Elapsed=millis(); Delta=0; } return Delta>=Time; } //———————————————————————- // Mark current time //———————————————————————- void MarkTime() { Elapsed=millis(); } //———————————————————————- // Switches to a selected page //———————————————————————- void SwitchTo(int Page) { if (Page!=CurrentPage) // Avoid unneeded redraw { PreparePage(Page,PageColors[Page-1]); MarkTime(); CurrentPage=Page; } } //———————————————————————- // Draw Sigma symbol (no font available to do it) //———————————————————————- void DrawSigma(int x, int y, int Color) { M5.lcd.drawLine(x,y,x+18,y,Color); M5.lcd.drawLine(x,y+1,x+18,y+1,Color); M5.lcd.drawLine(x,y,x+9,y+9,Color); M5.lcd.drawLine(x+1,y,x+10,y+9,Color); M5.lcd.drawLine(x,y+18,x+9,y+9,Color); M5.lcd.drawLine(x+1,y+18,x+10,y+9,Color); M5.lcd.drawLine(x,y+18,x+18,y+18,Color); M5.lcd.drawLine(x,y+17,x+18,y+17,Color); } //———————————————————————- // Prepares the page //———————————————————————- void PreparePage(int Page, int Color) { M5.Lcd.fillScreen(TFT_BLACK); M5.Lcd.setTextColor(Color, TFT_BLACK); if (Page==SERVICE) { M5.Lcd.setTextSize(2); m5.Lcd.setCursor(0,0); } else M5.Lcd.setTextSize(1); switch (Page){ case VOLTAGE: // Lead M5.Lcd.drawString(“L1”, xl[0], yl[0], 4); M5.Lcd.drawString(“L2”, xl[1], yl[1], 4); M5.Lcd.drawString(“L3”, xl[2], yl[2], 4); // Umes M5.Lcd.drawString(“V”, xu[0], yu[0], 4); M5.Lcd.drawString(“V”, xu[1], yu[1], 4); M5.Lcd.drawString(“V”, xu[2], yu[2], 4); break; case CURRENT: // Lead M5.Lcd.drawString(“L1”, xl[0], yl[0], 4); M5.Lcd.drawString(“L2”, xl[1], yl[1], 4); M5.Lcd.drawString(“L3”, xl[2], yl[2], 4); // Umes M5.Lcd.drawString(“A”, xu[0], yu[0], 4); M5.Lcd.drawString(“A”, xu[1], yu[1], 4); M5.Lcd.drawString(“A”, xu[2], yu[2], 4); break; case POWER: // Lead DrawSigma(xl[0], yl[0], Color); M5.Lcd.drawString(“S”, xl[0]+22, yl[0], 4); DrawSigma(xl[1], yl[1], Color); M5.Lcd.drawString(“P”, xl[1]+22, yl[1], 4); DrawSigma(xl[2], yl[2], Color); M5.Lcd.drawString(“Q1”, xl[2]+22, yl[2], 4); // Umes M5.Lcd.drawString(“kVA”, xu[0], yu[0], 4); M5.Lcd.drawString(“kW”, xu[1], yu[1], 4); M5.Lcd.drawString(“kvar”, xu[2], yu[2], 4); break; } } //———————————————————————- // Displays a single floating point value //———————————————————————- void WriteValue(int x, int y, float Value) { char sValue[6]={0,0,0,0,0,0}; dtostrf(Value, 6, 1, sValue); M5.Lcd.drawString(sValue, x, y, 7); } //———————————————————————- // Displays 3 values in accord to the current page //———————————————————————- void DisplayValues() { M5.Lcd.setTextColor(PageColors[CurrentPage-1], TFT_BLACK); switch (CurrentPage){ case VOLTAGE: for (int c=0;c<3;c++) WriteValue(xv[c],yv[c],V[c]); break; case CURRENT: for (int c=0;c<3;c++) WriteValue(xv[c],yv[c],C[c]); break; case POWER: for (int c=0;c<3;c++) WriteValue(xv[c],yv[c],P[c]); break; } } //———————————————————————- // Switches to next page //———————————————————————- void NextPage() { int Page=CurrentPage+1; if (Page>POWER) Page=VOLTAGE; SwitchTo(Page); } //———————————————————————- // Setup : Init Ethernet and Serial port //———————————————————————- void setup() { #ifdef M5STACK_LAN M5.begin(true, false, true); #endif #ifdef M5STACK_WIFI M5.begin(true, false, true); #endif // Open serial communications and wait for port to open: Serial.begin(115200); SwitchTo(SERVICE); // Service Page #ifdef S7WIFI //——————————————— ESPXX Initialization stdout.println(); stdout.println(“Connecting to “); stdout.println(ssid); WiFi.begin(ssid, pass); WiFi.config(Local, Gateway, Subnet); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print(“.”); } stdout.println(“”); stdout.println(“WiFi connected”); stdout.println(“Local IP address : “); stdout.println(WiFi.localIP()); delay(3000); // Just to see the message #else //——————————–Wired Ethernet Shield Initialization EthernetInit(mac, Local); delay(1000); stdout.println(“”); stdout.println(“Cable connected”); stdout.println(“Local IP address : “); stdout.println(Ethernet.localIP()); delay(3000); // Just to see the message #endif } //———————————————————————- // Connects to the PLC //———————————————————————- bool Connect() { int Result=1; SwitchTo(SERVICE); stdout.println(“Connecting to “); stdout.println(PLC); while (Result!=0) { Result=Client.ConnectTo(PLC, 0, // Rack (see the doc.) 1); // Slot (see the doc.) if (Result==0) { stdout.println(“”); stdout.println(“Connected, PDU Length = “); stdout.println(Client.GetPDULength()); delay(300); SwitchTo(VOLTAGE); } else { stdout.print(“.”); delay(500); } } return Result==0; } //———————————————————————- // Prints the Error number //———————————————————————- void CheckError(int ErrNo) { int LastPage = CurrentPage; SwitchTo(SERVICE); stdout.print(“Error No. 0x”); stdout.println(ErrNo, HEX); // Checks if it’s a Severe Error => we need to disconnect if (ErrNo & 0x00FF) { stdout.println(“SEVERE ERROR disconnecting”); Client.Disconnect(); } else { delay(1000); SwitchTo(LastPage); } } //———————————————————————- // Main Loop //———————————————————————- void loop() { // Connects (if needed) if (!Client.Connected) Connect(); int Result=Client.ReadArea(S7AreaDB, DBValues, // DB containing Sentron Data OFSValues, // Offset of first value SizeValues, // Data Packet size NULL); // Use internal buffer (PDU.DATA[]), small and faster if (Result==0) { V[0]=S7.FloatAt(0); // Voltage L1 V[1]=S7.FloatAt(4); // Voltage L2 V[2]=S7.FloatAt(8); // Voltage L3 C[0]=S7.FloatAt(12); // Current L1 C[1]=S7.FloatAt(16); // Current L2 C[2]=S7.FloatAt(20); // Current L3 P[0]=S7.FloatAt(24); // Sigma S P[1]=S7.FloatAt(28); // Sigma P P[2]=S7.FloatAt(32); // Sigma Q1 DisplayValues(); } else CheckError(Result); if (Result==0) { // Change page detection if (M5.BtnA.wasPressed()) SwitchTo(VOLTAGE); if (M5.BtnB.wasPressed()) SwitchTo(CURRENT); if (M5.BtnC.wasPressed()) SwitchTo(POWER); // Auto page switch to avoid display damage on long time if (IsElapsed(PageSwitchTime)) { NextPage(); } } delay(200); M5.update(); } |
Ping
You may use the ping command to check the connection first.
Configuration in Siemens Side.
Go to Protection & Security>Connection mechanisms>and Check the options of “Permit access with PUT/GET communication from remote partner”.
And also Open the Attributes of your DB and uncheck the option of Optimized block access.
You will see the offset field in the DB.
Result
Here is the result: