de:project_s7:s7_arduino_modbus_master

Differences

This shows you the differences between two versions of the page.

de:project_s7:s7_arduino_modbus_master [2022/04/21 15:01] ()
 1:  1:
 +====== S7-1500 und Arduino Modbus Verbindung (Arduino Server) ======
 +{{ :de:project_s7:s7_arduino_modbus_01.png?250|S7-1500 und Arduino Modbus Verbindung (Arduino Server)}}
 +{{:de:project_s7:de.png?16|deutsch}} Mit den Mikroprozessorlösungen von [[de:arduino:start|Arduino]] eröffnet sich eine neue Welt für Simatic-Anwendungen. Die Vielseitigkeit von Arduino-Sensoren kann durch ihren äußerst günstigen Preis ergänzt werden. Obwohl sich Simatic mit der IOT2040-Serie auch dieser Welt öffnet, ist es ein Schritt einfacher, Simatic direkt mit Arduino zu verbinden. Hierfür gibt es verschiedene Lösungen. Die Modbus-Verbindung wird in diesem Kapitel vorgestellt. Im folgenden Beispiel speichert Arduino die gesammelten Messdaten als Server. Die Daten werden Simatic als Client abgefragt. Arduino fasst in diesem Fall nur wenige Daten zusammen, der Schwerpunkt liegt auf der Modbus-Verbindung.
  
 +{{:de:project_s7:uk.png?16|english}} With [[de:arduino:start|Arduino]]'s microprocessor solutions, a new world opens up for Simatic applications. The versatility of Arduino sensors can be complemented by their extremely affordable price. Although Simatic also opens up to this world with the IOT2040 series, it is a degree easier to connect Simatic directly to Arduino. There are several solutions to this, the Modbus connection is presented in this chapter. In the example below, Arduino stores the collected measurement data as a server. The Simatic is queried data as a client. Arduino summarizes only a few data in this case, the focus is on the Modbus connection.
 +
 +{{:de:project_s7:hu.png?16|magyar}} Az [[hu:arduino:start|Arduino]] mikroprocesszoros megoldásaival egy új világ nyílik a Simatic alkalmazásai előtt. Az Arduino szenzorok sokoldalúságát azok rendkívül kedvező árával lehet kiegészíteni. Habár a Simatic is nyit erre a világra az IOT2040-es sorozattal, egy fokkal egyszerűbb közvetlenül összekötni az Arduinoval a Simatic-ot. Erre több megoldás is adódik, ebben a fejezetben a Modbus kapcsolat kerül bemutatásra. A lenti példában az Arduino a begyüjtött mérésadatokat szerverként tárolja. Az adatokat a Simatic kliensként kérdezi le. Az Arduino ezesetben csak néhány adatot összegez, a hangsúly a Modbus kapcsolaton van.
 +
 +|{{:de:project_s7:s7_arduino_modbus_01.png?250|}}|{{:de:project_s7:s7_arduino_modbus_03.png?250|}}|{{:de:project_s7:s7_arduino_modbus_02.png?250|}}|
 +|Simatic-Arduino Verbindung|TIA Portal Sicht \\ Klicken Sie auf das Bild, um es zu vergrößern.|Arduino Serial Monitor \\ Klicken Sie auf das Bild, um es zu vergrößern|
 +===== Simatic S7-1500, als Client (master) =====
 +
 +{{:de:project_s7:de.png?16|deutsch}} Von der S7-Seite aus kann auf die Register des Arduino zugegriffen werden, indem die Standardfunktion "**modbusClient**" aufgerufen wird. Die erforderlichen Einstellungen finden Sie im mitgelieferten (herunterladbaren) Programm.
 +
 +{{:de:project_s7:uk.png?16|english}} From the S7 the registers of the Arduino can be accessed by calling the standard "**modbusClient**" function. The required settings can be found in the supplied (downloadable) program.
 +
 +{{:de:project_s7:hu.png?16|magyar}} Az S7 oldalról a standard "**modbusClient**" funkció hívásával lehet az Arduino regisztereit elérni. A mellékelt (letölthető) programban megtalálhatók a szükséges beállítások.
 +
 +<WRAP center round download 80%>
 +**SCL-Programm download : **  {{:de:project_s7:callarduinomodbus.scl|callArduinoModbus.scl}} \\  \\  
 +Der Quellcode enthält eine Beschreibung eines scl-Codes (siehe Quellcode unten). Der Code kann im TIA-Portal geöffnet und übersetzt werden.
 +</WRAP>
 +
 +From file (from 2020.10.30) **{{dlcounter>file?de:project_s7:callarduinomodbus.scl}}** downloads.
 +
 +<hidden Klicken Sie hier, um den Code anzuzeigen - Click here to view the code>
 +<code pascal>
 +FUNCTION_BLOCK "callArduinoModbus"
 +{ S7_Optimized_Access := 'TRUE' }
 +VERSION : 0.1
 +   VAR 
 +      modbusParameter {InstructionName := 'TCON_IP_v4'; LibVersion := '1.0'; S7_SetPoint := 'False'} : TCON_IP_v4 := (64, 16#1, 16#0B, true, ([16#C0, 16#A8, 16#00, 16#2A]), 502, 503);
 +      modbusClient {InstructionName := 'MB_CLIENT'; LibVersion := '4.1'; S7_SetPoint := 'False'} : MB_CLIENT;
 +      modbusTime {InstructionName := 'TON_TIME'; LibVersion := '1.0'} : TON_TIME;
 +      modbusTrig { S7_SetPoint := 'True'} : Bool;
 +      timeOn : Bool;
 +      rec : Array[0..9] of Word;
 +      done : Bool;
 +      busy : Bool;
 +      error : Bool;
 +      status : Word;
 +      temp : Word;
 +   END_VAR
 +
 +
 +BEGIN
 + // communication between Simatic S7-1500 and Arduino Mega over Modbus (holding registers)
 + // Server-slave: Arduino Mega (with "heartbeat" and test-informations in holding registers
 + // client-master: S7-1500
 + // code: Vamos, 2020 -- ob121.com
 +
 +
 + // read in sec raster
 + #modbusTime(IN := NOT (#modbusTrig),
 +             PT := t#500ms,
 +             Q => #modbusTrig);
 +
 + // trigger for modbus read
 + IF #modbusTrig THEN
 +     IF #timeOn THEN
 +         #timeOn := false;
 +     ELSE
 +         #timeOn := true;
 +     END_IF;
 + END_IF;
 +
 + // call modbus client
 + #modbusClient(REQ:=#timeOn,
 +               DISCONNECT:= FALSE,
 +               MB_MODE:=0,
 +               MB_DATA_ADDR:=40001,
 +               MB_DATA_LEN:=6,
 +               DONE=>#done,
 +               BUSY=>#busy,
 +               ERROR=>#error,
 +               STATUS=>#status,
 +               MB_DATA_PTR:=#rec,
 +               CONNECT:=#modbusParameter);
 +
 + // monitor for Arduino informations
 + #temp := #rec[0];   // heart beat (sec tick)
 + #temp := #rec[1];   // humidity (/100, 0..100%, 2..5% accuracy)
 + #temp := #rec[2];   // temperature (/100,  -40..80 °C, 0,5% accuracy) 
 + #temp := #rec[3];   // heat index (/100, °C)
 + #temp := #rec[4];   // light intensity (0..1024)
 + #temp := #rec[5];
 +
 + // 0000: Instruction executed without errors.
 + // 0001: Connection established.
 + // 0003: Connection terminated.
 + // 7000: #no job active AND no connection established (REQ=0, DISCONNECT=1).
 + // 7001: Connection establishment triggered.
 + // 7002: Intermediate call. Connection is being established.
 + // 7003: Connection is being terminated.
 + // 7004: Connection established AND monitored. No job processing active.
 + // 7005: data is being sent.
 + // 7006: data is being received.
 + // 80BB: Invalid value at ActiveEstablished parameter
 + // 80C8: #no response OF the server in the defined period.
 + // 8187: the MB_HOLD_REG parameter has an Invalid Pointer. Data area is too small.
 + // 8380: received Modbus frame has incorrect format OR too few bytes were received.
 + // 8381: Function code is NOT supported.
 + // 8382: the length OF the Modbus frame in the frame header does NOT match the number OF received bytes.
 + // 8383: #error reading OR writing data OR access outside the address area
 + // 8384: Invalid exception code received.
 + // 8385: Diagnostics code NOT supported.
 + // 8386: received function code does NOT match the one sent originally.
 + // 8387: the protocol ID OF the Modbus TCP frame received BY the server is NOT "0".
 + // 8388: the Modbus server sent a different data length than was requested.
 + // 8389: Invalid data area definition
 + // 80B6: Invalid connection type, only TCP connections are supported.
 + // 80BB: Invalid value at ActiveEstablished parameter
 + // 8188: the MB_MODE parameter has an Invalid value.
 + // 8189: Invalid addressing OF data at the MB_DATA_ADDR parameter.
 + // 818A: Invalid data length at the MB_DATA_LEN parameter.
 + // 818B: the MB_DATA_PTR parameter has an Invalid Pointer.
 + // 818C: Timeout at parameter BLOCKED_PROC_TIMEOUT OR RCV_TIMEOUT
 + // 8200: A different Modbus request is currently being processed via the PORT.
 +
 +END_FUNCTION_BLOCK
 +</code>
 +</hidden>
 +
 +===== Arduino Mega, als Server (slave) =====
 +{{:de:project_s7:de.png?16|deutsch}} Für die Modbus Server-Funktion verwendet [[de:arduino:start|Arduino]] die Standard-Modbus-Bibliothek. Die Verwendung der Bibliothek ist speicherintensiv, daher reicht Uno für die Funktion nicht aus. Es muss die Mega-Karte verwendet werden (Ein Vergleich von Uno und Mega finden Sie [[de:arduino:start#einige_arduino-board-vergleiche|hier]]). Die Verbindung funktioniert über Ethernet (Modbus TCP), daher sollten Sie die Ethernet-schild verwenden. Die folgenden Bibliotheken sind für die Modbus-Verbindung erforderlich:
 +
 +{{:de:project_s7:uk.png?16|english}} For the Modbus Server function, [[de:arduino:start|Arduino]] uses the standard Modbus library. Using the library is memory intensive, so Uno is not enough for the function, the Mega card must be used (a comparison of Uno and Mega can be found [[de:arduino:start#einige_arduino-board-vergleiche|here]]). The connection works over Ethernet (Modbus TCP), so you should use the Ethernet shield. The following directories are required for the Modbus connection:
 +
 +{{:de:project_s7:hu.png?16|magyar}} A Modbus Server funkcióhoz az [[hu:arduino:start|Arduino]] a standard Modbus könyvtárat használja. A könyvtár alkalmazása memóriaigényes, így az Uno nem elégséges a funkcióhoz, a Mega kártyát kell alkalmazni (az Uno és a Mega összehasonlítása [[hu:arduino:start#nehany_arduino_board_oesszevetese|itt]] található). A kapcsolat Etherneten működik (Modbus TCP), ezért az Ethernet shield-et érdemes használni. Az alábbi könyvtárak szükségesek a Modbus kapcsolathoz:
 +
 +- https://github.com/arduino-libraries/ArduinoModbus \\
 +- https://github.com/arduino-libraries/ArduinoRS485 \\
 +
 +{{ :de:project_s7:s7_arduino_modbus_04.png?600 |Arduino Mega, als Server (slave)}}
 +==== Arduino-Messungen ====
 +{{:de:project_s7:de.png?16|deutsch}} Arduino stellt Simatic im obigen Beispiel einige Messungen zur Verfügung:
 +
 +  * Temperatur: DHT22-Sensormessung (-40..80 ° C, 0,5% Genauigkeit, teilbar durch 100)
 +  * Luftfeuchtigkeit (0..100%, 2..5% Genauigkeit, teilbar durch 100)
 +  * Wärmeempfindungsindex (abgeleitet von Temperatur und Luftfeuchtigkeit, teilbar durch 100)
 +  * Lichtintensität (0..1024, Fotosensor GL5506)
 +  * Anwesenheitssignal (heart-beat, sein Wert ändert sich alle 2 Sekunden)
 +
 +Anschlussbelegung der Messungen: DHT22: Pin 9, Photosensor: A5.
 +
 +{{:de:project_s7:uk.png?16|english}} Arduino makes some measurements available to Simatic in the example above:
 +
 +  * temperature: DHT22 sensor measurement (-40..80 ° C, 0.5% accuracy, divisible by 100)
 +  * humidity (0..100%, 2..5% accuracy, divisible by 100)
 +  * heat sensation index (derived from temperature and humidity, divided by 100)
 +  * light intensity (0..1024, GL5506 photo sensor)
 +  * presence signal (heart-beat, its value changes every 2 seconds)
 +
 +Port assignment of measurements: DHT22: pin 9, photosensor: A5.
 +
 +{{:de:project_s7:hu.png?16|magyar}} Az Arduino a fenti példában néhány mérést tesz elérhetővé a Simatic számára:
 +
 +  * hőmérséklet: A DHT22 szenzor mérése  ( -40..80 °C, 0,5% pontosság, 100-zal osztandó)   
 +  * páratartalom (0..100%, 2..5% pontosság, 100-zal osztandó) 
 +  * hőérzet index (a hőmérsékletből és páratartalomból származik, 100-zal osztandó)
 +  * világítás-intenzitás (0..1024, GL5506 fotoszenzor)
 +  * jelenlét-jel (heart-beat, 2 másodpercenként változik az értéke) 
 +
 +Mérések port-kiosztása: DHT22: pin 9, fotoszenzor: A5.
 +
 +==== Arduino Software ====
 +
 +Libraries: \\
 +- https://github.com/arduino-libraries/ArduinoModbus \\
 +- https://github.com/arduino-libraries/ArduinoRS485 \\
 +- https://github.com/adafruit/DHT-sensor-library \\
 +- https://github.com/adafruit/Adafruit_Sensor \\
 +
 +<WRAP center round download 80%>
 +
 +**Arduino-Programm download : **  {{:de:project_s7:modbus_server_mega.ino |modbus_server_mega.ino}} \\  \\  
 +Der Quellcode enthält eine Beschreibung eines Arduino-Codefile (siehe Quellcode unten). Der Code kann im Arduino geöffnet und übersetzt werden.
 +</WRAP>
 +
 +<hidden Klicken Sie hier, um den Code anzuzeigen - Click here to view the code>
 +<code c>
 +// Modbus Server Mega board 
 +// Test for Simatic s7-1500 Modbus connections
 +// Vamos Sandor - 2020 - ob121.com
 +// https://www.ob121.com/doku.php?id=de:project_s7:s7_arduino_modbus_master
 +
 +#include <Ethernet.h>
 +#include <ArduinoModbus.h>
 +#include <DHT.h>
 +
 +#define DHTPIN 9 
 +
 +// Uncomment whatever type you're using!
 +//#define DHTTYPE DHT11   // DHT 11
 +#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
 +//#define DHTTYPE DHT21   // DHT 21 (AM2301)
 +
 +DHT dht(DHTPIN, DHTTYPE);
 +
 +word hum, temp, heatidx, lightint;
 +bool _2s;
 +unsigned long TimeAct, TimePrev, HoldingResult, InputResult, HeartBeat, i, StartingAddr;
 +long Cmd;
 +
 +EthernetServer EthServer(502);
 +ModbusTCPServer modbusTCPServer;
 +
 +void setup() {
 +  // Ethernet Settings
 +  byte mac[] = { 0x4E, 0xA0, 0xBE, 0x3F, 0xFE, 0x0F };  // Define MAc address
 +  byte ip[] = { 192, 168, 0, 42 };                      // Define IP address
 +  byte subnet[] = { 255, 255, 255, 0 };                 // Define SubNEt mask
 +
 +  // initialize the ethernet device
 +  Ethernet.begin(mac, ip, subnet);                      // Assign MAC, IP, and subnet mask
 +  Serial.begin(9600);
 +  EthServer.begin();          // start listening for clients
 +  modbusTCPServer.begin();    // start listening for clients
 +  dht.begin();                // start dht
 +  
 +  // Define Holding register:
 +  HoldingResult = modbusTCPServer.configureHoldingRegisters(0, 100);
 +  InputResult = modbusTCPServer.configureInputRegisters(0, 100);
 +
 +  Serial.print("Holding Reg init result =");
 +  Serial.print(HoldingResult);
 +  Serial.print("\n");
 +
 +  Serial.print("Input Reg init result =");
 +  Serial.print(InputResult);
 +  Serial.print("\n");
 +
 +  Serial.print("Modbus server address=");
 +  Serial.println(Ethernet.localIP());
 +  Serial.print("\n");
 +}
 +
 +void loop() {
 +  // Modbus server accept incoming connections
 +  EthernetClient client = EthServer.available();
 +
 +  if (client.connected()) {
 +    modbusTCPServer.accept(client);
 +    // poll for Modbus TCP requests, while client connected
 +    modbusTCPServer.poll();
 +    // Serial.print("poll");
 +  }
 +
 +  //---------------------------------------------------------------------------------
 +  // TIME  clock 2s
 +  TimeAct = millis();     // Millis value between  0 and  655535
 +
 +  _2s = false;
 +  if (  ( (TimeAct > TimePrev) and (TimeAct - TimePrev) > 2000) or ((TimeAct < TimePrev) and (65535 - TimePrev + TimeAct) > 2000 )  ) {
 +    _2s = true;
 +    TimePrev = TimeAct;
 +  }
 +  //---------------------------------------------------------------------------------
 +  // HeartBeat
 +  if (_2s) {
 +    HeartBeat++;
 +    if (HeartBeat > 255) {
 +      HeartBeat = 0;
 +    }
 +    Serial.print("HeartBeat=");
 +    Serial.println(HeartBeat);
 +    Serial.print("\n");
 +    dht22();                // call dht sensor  
 +    light();                // call photosensor
 +  }
 +  //---------------------------------------------------------------------------------
 +  // Modbus server  :
 +
 +  // holding register 40001: heartbeat (FC3)
 +  modbusTCPServer.holdingRegisterWrite(0x00, HeartBeat);  // heart beat 2sec
 +  modbusTCPServer.holdingRegisterWrite(0x01, hum);        // humidity (/100, 0..100%, 2..5% accuracy)
 +  modbusTCPServer.holdingRegisterWrite(0x02, temp);       // temperature (/100,  -40..80 °C, 0,5% accuracy) 
 +  modbusTCPServer.holdingRegisterWrite(0x03, heatidx);    // heat index (/100, °C)
 +  modbusTCPServer.holdingRegisterWrite(0x04, lightint);   // light intensity (0..1024)
 +  modbusTCPServer.holdingRegisterWrite(0x05, 5);          // res
 +  modbusTCPServer.holdingRegisterWrite(0x06, 6);          // res
 +
 +}
 +
 +void dht22() {
 +  float h = dht.readHumidity();
 +  float t = dht.readTemperature();  
 +  float f = dht.readTemperature(true);
 +  // Check if any reads failed and exit early (to try again).
 +  if (isnan(h) || isnan(t) || isnan(f)) {
 +    Serial.println(F("Failed to read from DHT sensor!"));
 +    hum = 0;         // in errorcase: 0
 +    temp = 0;        // in errorcase: 0
 +    heatidx = 0;     // in errorcase: 0
 +    return;
 +  }
 +
 +  // Compute heat index in Fahrenheit (the default)
 +  float hif = dht.computeHeatIndex(f, h);
 +  // Compute heat index in Celsius (isFahreheit = false)
 +  float hic = dht.computeHeatIndex(t, h, false);
 + 
 +  Serial.print(F("Humidity: "));
 +  Serial.print(h);
 +  Serial.print(F(" Temperature: "));
 +  Serial.print(t);
 +  Serial.print(F("°C "));
 +  Serial.print(f);
 +  Serial.print(F("°F  Heat index: "));
 +  Serial.print(hic);
 +  Serial.print(F("°C "));
 +  Serial.print(hif);
 +  Serial.println(F("°F"));  
 +
 +  h = h * 100.0;
 +  t = t * 100.0;
 +  hic = hic * 100.0;
 +
 +  hum = (word) h;
 +  temp = (word) t;
 +  heatidx = (word) hic; 
 +}
 +
 +void light() {
 +  // light sensor (photosensor): GL5506 (light resisitance (10 lux): 2-6 KOhm,
 +  // dark resistance 0.15 MOhm
 +  
 +  int val = analogRead(5);             // read from A5
 +  Serial.print("Light intensity : " );
 +  Serial.println(val); 
 +  lightint = (word) val;
 +}
 +
 +</code>
 +</hidden>
 +
 +{{page>de:project_s7:foot}}
  • de/project_s7/s7_arduino_modbus_master.txt
  • 2022/04/21 15:01
  • ()