Skip to main content

Integracja sztucznej inteligencji (AI) z programowaniem sterowników PLC rewolucjonizuje automatykę przemysłową, zwiększając efektywność, elastyczność oraz możliwości predykcyjne. Wykorzystanie narzędzi takich jak silnik skryptów Python w środowisku CODESYS oraz usług AI opartych na chmurze oferuje inżynierom nowatorskie podejścia do projektowania i zarządzania aplikacjami PLC.

Silnik skryptów Python w środowisku CODESYS

Silnik skryptów Python w środowisku CODESYS to zaawłansowane narzylędzie umożliwiające automatyzację różnorodnych zadań związanych z rozwojem oraz zarządzaniem projektami w środowisku CODESYS. Dzięki integracji skryptów IronPython, programiści mogą usprawniać procesy takie jak tworzenie projektów, konfiguracja urządzeń oraz generowanie kodu, co znacząco zwiększa efektywność i precyzję pracy.

Key functionalities accessible through the Python Script Engine include:

  • System: Access to general CODESYS functionalities, such as exiting the application and handling the user interface.
  • Projects: Management of projects, including loading, creating, saving, and closing projects.
  • Online: Online functions like logging into devices and applications, managing access data, performing network scans, and gateway management.
  • LibraryManager: Management of library repositories, including viewing, installation, and removal of libraries.
  • DeviceRepository: Handling of device repositories, including import and export of device descriptions.

Skrypty mogą być wykonywane bezpośrednio z interfejsu systemu CODESYS Development lub za pomocą wiersza poleceń, co pozwala na elastyczną integrację procesów automatyzacji z istniejącymi przepływami pracy.

Aby ułatwić tworzenie i edytowanie skryptów, CODESYS oferuje wtyczkę Python Editor. Narzędzie to zapewnia funkcje takie jak autouzupełnianie, podświetlanie składni, strukturyzacja kodu oraz inteligentne wcięcia, zwiększając tym samym produktywność podczas opracowywania rozwiązań automatyzacyjnych opartych na skryptach Pythona.

Dzięki wykorzystaniu silnika skryptowego Python, programiści mogą osiągnąć wyższy poziom automatyzacji i precyzji w zarządzaniu projektami w środowisku CODESYS, co przekłada się na bardziej wydajne i niezawodne procesy rozwoju.

Dla profesjonalistów z dziedziny automatyki przemysłowej precyzja oraz spójność są kluczowe. Silnik skryptowy Python w CODESYS oferuje zaawansowane możliwości automatyzacji powtarzalnych zadań, takich jak dodawanie urządzeń, tworzenie programów, importowanie bibliotek czy konfiguracja projektów — wszystko z chirurgiczną precyzją.

Domyślna ścieżka do plików stub silnika skryptowego to:

C:\Program Files\CODESYS 3.5.xx.xx\CODESYS\ScriptLib\Stubs\scriptengine

Ten folder zawiera wszystkie pliki stub języka Python niezbędne do interakcji ze skryptowym API środowiska CODESYS. Pliki te pełnią rolę interfejsu między twoim kodem Pythona a wewnętrznymi obiektami środowiska CODESYS.

Jak używać w VS Code

Aby włączyć funkcje takie jak autouzupełnianie kodu, podświetlanie składni oraz podpowiedzi typów podczas pisania skryptów CODESYS w Visual Studio Code, możesz zrobić następujące rzeczy:

Skopiuj folder scriptengine z domyślnej ścieżki:

C:\Program Files\CODESYS 3.5.xx.xx\CODESYS\ScriptLib\Stubs\scriptengine

Wklej go do katalogu twojego projektu Pythonowego, na przykład:

my-codesys-scripts/
├── scriptengine/
├── my_script.py

Takie ustawienie pozwala VS Code rozpoznać moduły specyficzne dla CODESYS, co pomaga efektywniej pisać, testować i debugować twoje skrypty automatyzacji — nawet poza środowiskiem CODESYS.

Przykładowe programy w silniku skryptowym Python do interakcji z CODESYS

Przykładowy program:

devId = None
devices = device_repository.get_all_devices("CODESYS Control Win V3")
for device in devices:
    devId = device.device_id
proj = projects.primary


# delete existing testdev device
existing = proj.find('testdev')
if len(existing) > 0:
    existing[0].remove()


# add device
proj.add('testdev', devId)
apps = proj.find('Application', True)
if len(apps) > 0:
    app = apps[0]
    tc = app.create_task_configuration()

Co robi skrypt

Ten skrypt służy do tego, aby:

  • Pobrać identyfikator urządzenia dla CODESYS Control Win V3,
  • Usunąć z projektu dowolne istniejące urządzenie o nazwie „testdev”,
  • Dodać nowe urządzenie, używając pobranego identyfikatora urządzenia,
  • Utworzyć konfigurację zadań (Task Configuration) dla aplikacji w projekcie.

Wyjaśnienie skryptu – linia po linii

devId = None

devices = device_repository.get_all_devices("CODESYS Control Win V3")

for device in devices:

    devId = device.device_id
  • Pobiera wszystkie dostępne urządzenia z repozytorium urządzeń (Device Repository) pasujące do typu „CODESYS Control Win V3”.
  • W pętli przechodzi przez wyniki i zapisuje identyfikator urządzenia (device_id) ostatniego pasującego urządzenia do zmiennej devId.

💡 W skryptach produkcyjnych zazwyczaj należy wybrać konkretną wersję lub urządzenie, zamiast brać ostatnie urządzenie bez dokładnej kontroli.

proj = projects.primary

Gets the currently opened CODESYS project — this is the project that the script will modify.

# delete existing testdev device

existing = proj.find('testdev')

if len(existing) > 0:

    existing[0].remove()
  • Przeszukuje projekt w celu znalezienia dowolnego urządzenia o nazwie testdev.
  • Jeśli zostanie znalezione, usuwa istniejące urządzenie, aby uniknąć duplikatów.
  • Dzięki temu skrypt jest idempotentny — bezpieczny do wielokrotnego uruchamiania.
# add device

proj.add('testdev', devId)

Adds a new device to the project with the name testdev, using the device_id fetched earlier.

apps = proj.find('Application', True)

if len(apps) > 0:

    app = apps[0]

    tc = app.create_task_configuration()
  • Przeszukuje projekt, aby znaleźć obiekt Application (z opcją recursive = True).
  • Jeśli zostanie znaleziony, pobiera pierwszy znaleziony obiekt i tworzy w nim konfigurację zadań (Task Configuration).
  • Konfiguracje zadań są potrzebne do definiowania zadań cyklicznych, takich jak MainTask lub VISU_TASK.

Podsumowanie

Ten skrypt:

  • Dynamicznie znajduje urządzenie CODESYS,
  • Zapewnia, że projekt nie zawiera duplikatów,
  • Czysto dodaje nowe urządzenie,
  • Przygotowuje projekt poprzez utworzenie nowej konfiguracji zadań – gotowej do dodawania programów.

Więcej przykładowych skryptów:

Dodanie urządzenia wraz z konfiguracją zadań

# add device with a task configuration
proj.add('PLC', devId)
apps = proj.find('Application', True)
if len(apps) > 0:
    tc = apps[0].create_task_configuration()


# add task
task = tc.create_task('Task')
task.pous.add('PLC_PRG')


# proj = projects.open("C:\Users\Administrator\Documents\PL Przepompownia AI\Untitled1.project")


# devId = None
# devices = device_repository.get_all_devices("CODESYS Control Win V3")
# for device in devices:
#     devId = device.device_id
# proj = projects.primary


# # add device
# proj.add('PLC', devId)
# apps = proj.find('Application', True)
# if len(apps) > 0:
#     tc = apps[0].create_task_configuration()


# # add task
# task = tc.create_task('Task')
# task.pous.add('PLC_PRG')

Utwórz POU

proj = projects.primary # current project


found = proj.find("Application", True)
app = found[0]


# Create FB
mypou = app.create_pou("MyPou")


# Change declaration of the FB
implementation = mypou.textual_declaration.replace("""FUNCTION_BLOCK MyPou
VAR_INPUT
   iValue : INT;
END_VAR
VAR_OUTPUT
END_VAR
VAR
END_VAR""")


# Change implementation of the FB
mypou.textual_implementation.replace("""iValue := iValue + 1;""")


# Add method to FB
dosomething = mypou.create_method("DoSomething", "INT")


# Change declaration of the method
dosomething.textual_declaration.replace("""METHOD DoSomething : INT
VAR_INPUT
   iVal1 : INT;
   iVal2 : INT;
END_VAR""")


# Change implementation of the method
dosomething.textual_implementation.replace("""DoSomething := iVal1 + iVal2;""")


# # Find the pou and delete it
# found = app.find("MyPou")
# if found and len(found) == 1:
#    found[0].remove()
# else:
#    print("POU 'MyPou' was not found")

Utwórz listę zmiennych globalnych i trwałych:

# Get the primary project or open a project
proj = projects.primary  # Use the currently open project


# Find the Application object
found = proj.find("Application", True)
app = found[0]


# Create a Global Variable List (GVL)
gvl = app.create_gvl("GVL_Process")


# Define the global variables in the GVL
gvl.textual_declaration.replace("""VAR_GLOBAL
    // System Configuration
    g_xSystemEnabled    : BOOL := TRUE;    // System enable flag
    g_xEmergencyStop    : BOOL := FALSE;   // Emergency stop status
    g_xMaintenanceMode  : BOOL := FALSE;   // Maintenance mode flag
   
    // Process Variables
    g_rTemperature      : REAL;            // Process temperature
    g_rPressure         : REAL;            // Process pressure
    g_rFlowRate         : REAL;            // Flow rate
    g_rLevel            : REAL;            // Tank level
   
    // Control Parameters
    g_rTempSetpoint     : REAL := 25.0;    // Temperature setpoint
    g_rPressSetpoint    : REAL := 2.5;     // Pressure setpoint
    g_rFlowSetpoint     : REAL := 100.0;   // Flow rate setpoint
    g_rLevelSetpoint    : REAL := 50.0;    // Level setpoint
   
    // Alarms
    g_xTempAlarm        : BOOL;            // Temperature alarm
    g_xPressAlarm       : BOOL;            // Pressure alarm
    g_xFlowAlarm        : BOOL;            // Flow rate alarm
    g_xLevelAlarm       : BOOL;            // Level alarm
   
    // Timers
    g_tCycleTime        : TIME := T#100MS; // Control cycle time
    g_tAlarmDelay       : TIME := T#5S;    // Alarm delay time
END_VAR""")


# Create a persistent Global Variable List
persistent_gvl = app.create_persistentvars("GVL_Settings")


# Define the persistent global variables
persistent_gvl.textual_declaration.replace("""VAR_GLOBAL PERSISTENT
    // System Settings
    p_xAutoStartEnabled : BOOL := TRUE;    // Auto-start on power up
    p_tStartupDelay     : TIME := T#30S;   // Startup delay time
   
    // Control Parameters
    p_rTempKp           : REAL := 1.5;     // Temperature controller P gain
    p_rTempKi           : REAL := 0.2;     // Temperature controller I gain
    p_rTempKd           : REAL := 0.1;     // Temperature controller D gain
   
    p_rPressKp          : REAL := 2.0;     // Pressure controller P gain
    p_rPressKi          : REAL := 0.3;     // Pressure controller I gain
    p_rPressKd          : REAL := 0.05;    // Pressure controller D gain
   
    p_rFlowKp           : REAL := 1.0;     // Flow controller P gain
    p_rFlowKi           : REAL := 0.15;    // Flow controller I gain
    p_rFlowKd           : REAL := 0.0;     // Flow controller D gain
   
    p_rLevelKp          : REAL := 3.0;     // Level controller P gain
        p_rLevelKi          : REAL := 0.25;    // Level controller I gain
    p_rLevelKd          : REAL := 0.1;     // Level controller D gain
   
    // Alarm Thresholds
    p_rTempHighLimit    : REAL := 80.0;    // Temperature high limit
    p_rTempLowLimit     : REAL := 5.0;     // Temperature low limit
    p_rPressHighLimit   : REAL := 5.0;     // Pressure high limit
    p_rPressLowLimit    : REAL := 0.5;     // Pressure low limit
    p_rFlowHighLimit    : REAL := 200.0;   // Flow high limit
    p_rFlowLowLimit     : REAL := 10.0;    // Flow low limit
    p_rLevelHighLimit   : REAL := 90.0;    // Level high limit
    p_rLevelLowLimit    : REAL := 10.0;    // Level low limit
END_VAR""")


# Create a constant Global Variable List
const_gvl = app.create_gvl("GVL_Constants")


# Define the constant global variables
const_gvl.textual_declaration.replace("""VAR_GLOBAL CONSTANT
    // System Constants
    c_iMaxDevices       : INT := 10;       // Maximum number of devices
    c_iMaxAlarms        : INT := 100;      // Maximum number of alarms
   
    // Physical Constants
    c_rGravity          : REAL := 9.81;    // Gravity acceleration (m/s²)
    c_rWaterDensity     : REAL := 1000.0;  // Water density (kg/m³)
    c_rAirDensity       : REAL := 1.225;   // Air density at sea level (kg/m³)
   
    // Conversion Factors
    c_rPa_To_Bar        : REAL := 0.00001; // Pascal to Bar conversion
    c_rBar_To_PSI       : REAL := 14.5038; // Bar to PSI conversion
    c_rLiter_To_M3      : REAL := 0.001;   // Liter to cubic meter conversion
   
    // Time Constants
    c_tMaxRunTime       : TIME := T#24H;   // Maximum continuous run time
    c_tMaintenanceInterval : TIME := T#720H; // Maintenance interval (30 days)
END_VAR""")


print("Global Variable Lists created successfully!")

Tryb symulacji:

# set device to simulation mode - this only check Simulation mark in the online tab
devs = proj.find('testdev') # type here project name up to Application
    devs[0].set_simulation_mode(True)


# alternatively check the sim is enabled beforehand and turn it on if not yet enabled


devs = proj.find('testdev')
if len(devs) > 0:
   # check if sim is enabled
   cur_sim_mode = devs[0].get_simulation_mode()
   print(cur_sim_mode)
   # enable sim conditionally
   if not cur_sim_mode:
      devs[0].set_simulation_mode(True)

Jeśli chcesz w pełni odkryć potencjał silnika skryptowego Python w CODESYS oraz dowiedzieć się, jak usprawnić automatyzację procesów dzięki wskazówkom Claude’a Sonneta, koniecznie zapoznaj się z częścią 2 tego artykułu. Znajdziesz tam informacje, jak zastosować zdobytą wiedzę w praktyce oraz wykorzystać zaawansowane możliwości tego narzędzia.

O autorze

Maciej Kurantowicz

Author Maciej Kurantowicz

Automatyk i programista, CEO & Founder w ControlByte

Więcej postów tego autora Maciej Kurantowicz