Hallo Zusammen,
ich nutze gerade die Arduino IDE um mit Hilfe von Ethernet bzw ein ESP8266. Mich über Profinet mit der SPS zu unterhalten. Dies Funktioniert auch bis jetzt ganz gut.
Ich möchte aber auch Real/Float Werte an die SPS Übertragen und diese hat leider, da man nicht mit dem optimierten Speicherzugriff von Arduino auf die S7 Zugreifen kann Big Endian. Im Folgenden Code:
Ich habe auf der SPS Seite einen DB absolut Adressiert zum senden und empfangen.
Ich würde gerne auf Profinet bleiben und nicht via Modbus TCP arbeiten da es dann auf der SPS Seite kompliziert wird.
Ziel ist es Remote IO´s mit Arduino und ESP8266 zu erstellen und die Heizungssteuerung damit umzusetzen.
Auf der Arduino Seite ist ein OneWire Temperaturfühler von Dallas.
/*----------------------------------------------------------------------
Data Read Demo
Created 12 Dec 2016
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();
NodeMCU 1.0 ESP-12E ESP8266 supported
----------------------------------------------------------------------*/
// Wifi -> #define S7WIFI
// Cable -> #define S7WIRED
#include <ESP8266WiFi.h>
#include "Settimino.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS D4
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
// Uncomment next line to perform small and fast data access
#define BufferSize 64
// 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, 178, 210); // Local Address
IPAddress PLC(192, 168, 178, 200); // 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[] = "Homenet"; // Your network SSID (name)
char pass[] = "LabberOnkel"; // Your network password (if any)
IPAddress Gateway(192, 168, 178, 1);
IPAddress Subnet(255, 255, 255, 0);
int DBNum = 40; // This DB must be present in your PLC
byte Bufferrecv[BufferSize];
byte Buffersent[3];
// S7Client will create a WiFiClient as TCP Client
S7Client Client(_S7WIFI);
unsigned long Elapsed; // To calc the execution time
float Temperatur = 0.0;
union float2byte {
float f;
byte bytes[3];
} Convert;
//----------------------------------------------------------------------
// Setup : Init Ethernet and Serial port
//----------------------------------------------------------------------
void setup() {
sensors.begin(); // Start the Tempsensor Pin
// Open serial communications and wait for port to open:
Serial.begin(9600);
//--------------------------------------------- ESP8266 Initialization
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, pass);
WiFi.config(Local, Gateway, Subnet);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("Local IP address : ");
Serial.println(WiFi.localIP());
}
//----------------------------------------------------------------------
// Connects to the PLC
//----------------------------------------------------------------------
bool Connect()
{
int Result = Client.ConnectTo(PLC,
0, // Rack (see the doc.)
0); // 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 *Bufferrecv, int Length)
{
int i, cnt = 0;
pbyte buf;
if (Bufferrecv != NULL)
buf = pbyte(Bufferrecv);
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()
{
sensors.requestTemperatures(); // Send the command to get temperatures
Convert.f = sensors.getTempCByIndex(0);
int Sizercv, Resultrcv;
int Sizesent, Resultsent;
void *Targetrcv;
void *Targetsent;
Sizesent = 4;
Targetsent = &Convert.bytes;
Sizercv = BufferSize;
Targetrcv = &Bufferrecv; // Uses a larger buffer
// Connection
while (!Client.Connected)
{
if (!Connect())
delay(500);
}
Serial.print("Reading "); Serial.print(Sizercv); Serial.print(" bytes from DB"); Serial.println(DBNum);
// Get the current tick
MarkTime();
Resultrcv = Client.ReadArea(S7AreaDB, // We are requesting DB access
DBNum, // DB Number
0, // Start from byte N.0
Sizercv, // We need "Size" bytes
Targetrcv); // Put them into our target (Buffer or PDU)
if (Resultrcv == 0)
{
ShowTime();
Dump(Targetrcv, Sizercv);
}
else
CheckError(Resultrcv);
Serial.println("Sending");
Serial.print(" Byte1: ");
Serial.print(Convert.bytes[0],HEX);
Serial.print(" Byte2: ");
Serial.print(Convert.bytes[1],HEX);
Serial.print(" Byte3: ");
Serial.print(Convert.bytes[2],HEX);
Serial.print(" Byte4: ");
Serial.println(Convert.bytes[3],HEX);
Serial.print(" Float: ");
Serial.println(Convert.f);
Client.WriteArea(S7AreaDB, // We are requesting DB access
DBNum, // DB Number
64, // Start from byte N.0
Sizesent, // We need "Size" bytes
Targetsent); // Put them into our target (Buffer or PDU)
delay(3000);
}