engineering

Programmation API : 8 bonnes pratiques de code maintenable

Guide pour un code API propre et maintenable avec Siemens TIA Portal : conventions de nommage, structure FB/FC, alarmes NAMUR, Git et tests en simulation.

David Prybisch
15 min read
Programmation API : 8 bonnes pratiques de code maintenable

1.Introduction

La programmation API, c'est bien plus que l'assemblage de blocs logiques. En plus de 10 ans en tant qu'ingénieur en automatisation, j'ai vu d'innombrables projets API – beaucoup avec des problèmes typiques :

  • Noms de variables illisibles comme M0.0, DB1.DBX0.0 ou %MW100
  • Mélange incohérent de langages de programmation – LD, FBD, IL et SCL mélangés dans le même projet
  • Absence de documentation – le programmeur original a quitté l'entreprise depuis longtemps

Dans cet article, je partage les bonnes pratiques essentielles pour des programmes API maintenables avec Siemens TIA Portal.

2.Pourquoi des bonnes pratiques en programmation API ?

2.1.Le problème : le code legacy

Scénario typique de ma pratique :

Un constructeur de machines appelle : "Notre installation est à l'arrêt. Pouvez-vous nous aider ?"

Sur place, la désillusion :

  • Noms de variables comme M0.0, DB1.DBX0.0, %MW100 – personne ne sait ce qu'ils représentent
  • LD, FBD, IL et SCL mélangés dans le même projet
  • Pas de commentaires, pas de structure
  • Le programmeur original a quitté l'entreprise il y a des années

La recherche de pannes prend beaucoup trop de temps car personne ne s'y retrouve dans le code.

2.2.La solution : une programmation professionnelle

Des programmes API structurés et maintenables apportent des avantages clairs :

  • Recherche de pannes plus rapide grâce à des noms de variables explicites
  • Temps d'intégration réduit pour les nouveaux programmeurs
  • Moins d'arrêts machine grâce à une meilleure gestion des erreurs

3.Bonne pratique 1 : Utiliser systématiquement les standards IEC 61131-3

L'IEC 61131-3 est la norme internationale pour la programmation API et obligatoire pour les machines certifiées CE.

3.1.Aperçu des 5 langages de programmation

Norme (CEI)SiemensUtilisationLimites
LD – Ladder DiagramKOPVerrouillages, logique simpleIllisible au-delà d'une cinquantaine de réseaux
FBD – Function Block DiagramFUPRégulation, logique de flux de donnéesDifficile à maintenir pour les grands programmes
IL – Instruction ListAWLUniquement code existantClassé obsolète depuis 2013
ST – Structured TextSCLAlgorithmes, calculs, bibliothèquesMoins parlant pour les purs verrouillages
SFC – Sequential Function ChartGRAPHCommandes séquentielles (GRAFCET)Surcharge pour la logique simple

Erreur répandue : SCL et ST sont le même langage — SCL est l'implémentation Siemens du Structured Text. Les citer séparément revient à compter un langage deux fois, en omettant l'IL.

En détail : Quel langage convient à quelle tâche, comment les appellations normatives se rattachent aux noms Siemens et pourquoi SCL et ST sont le même langage — voir l'article dédié Les 5 langages de programmation API selon la CEI 61131-3.

3.2.Programmation structurée : la pyramide

Structure de programme API : Architecture hiérarchique des blocs de OB1 via FC_SystemControl aux blocs fonctionnels et blocs de données

OB1 (Main)
  └── FC_SystemControl (Modes de fonctionnement)
       ├── FB_PackMLStateMachine (Commande séquentielle)
       │    ├── FB_MotorControl (Partie d'installation)
       │    ├── FB_ValveControl (Partie d'installation)
       │    └── FB_ConveyorControl (Partie d'installation)
       └── FC_AlarmHandler (Utilitaire)

Règle : Chaque niveau a exactement UNE responsabilité claire.

4.Bonne pratique 2 : Établir des conventions de nommage

4.1.Le problème : le chaos des noms de variables

Exemple négatif (de la pratique) :

// ❌ MAUVAIS
M0.0    // Qu'est-ce que c'est ?
DB1.DBX0.0   // Quel moteur ?
%MW100  // Température ? Pression ?

Exemple positif :

// ✅ BON
bMotorPumpMainRun : BOOL;  // Moteur pompe principale en marche
iTemperatureTank1 : INT;   // Température réservoir 1 en °C
rPressureSetpoint : REAL;  // Consigne de pression en bar

4.2.Préfixes standardisés (Notation hongroise)

PréfixeType de donnéesExemple
bBOOLbMotorRun, bAlarmActive
iINTiCounter, iTemperature
rREALrSpeed, rPressure
sSTRINGsAlarmText, sRecipeName
dtDATE_TIMEdtStartTime, dtLastMaintenance
tTIMEtDelayStart, tCycleTime
udiUDINTudiPartCounter, udiTotalProduction

4.3.Entrées/Sorties avec préfixe

// Entrées : ix (Input X)
ixMotorFeedbackRun : BOOL AT %I0.0;  // "x" = Bool
iwTemperatureSensor : WORD AT %IW0;   // "w" = Word

// Sorties : qx (Output X)
qxMotorStart : BOOL AT %Q0.0;
qwValvePosition : WORD AT %QW0;

La cohérence est reine : Décidez en équipe d'UNE convention et documentez-la.

En détail : Pourquoi un tableau de préfixes ne fait pas encore un standard — et ce que le contrat d'interface, la bibliothèque versionnée et la voie d'exception y changent — voir l'article dédié Standards de codage API : des conventions de nommage à la bibliothèque versionnée.

5.Bonne pratique 3 : Utiliser correctement les blocs fonctionnels vs fonctions

5.1.Blocs fonctionnels (FB) - Avec état

Quand les utiliser ?

  • Parties d'installation avec état (moteur, vanne, convoyeur)
  • Gestionnaires d'alarmes
  • Machines d'état

Exemple : Commande de moteur

FUNCTION_BLOCK FB_MotorControl
VAR_INPUT
  bStart : BOOL;        // Commande de démarrage
  bStop : BOOL;         // Commande d'arrêt
  bFeedback : BOOL;     // Retour moteur en marche
END_VAR

VAR_OUTPUT
  qxStart : BOOL;       // Sortie démarrage moteur
  bRunning : BOOL;      // État : moteur en marche
  bAlarm : BOOL;        // Défaut actif
END_VAR

VAR
  tDelayStart : TON;    // Temporisation au démarrage
  tTimeoutFeedback : TON; // Timeout pour le retour
  bAlarmLatched : BOOL; // Défaut mémorisé
END_VAR

// Logique du programme ici...
END_FUNCTION_BLOCK

Appel :

// Dans OB1 ou FC
dbMotorPumpMain(
  bStart := bSystemRun AND NOT bEmergencyStop,
  bStop := bSystemStop OR bEmergencyStop,
  bFeedback := ixMotorPumpMainFeedback
);
qxMotorPumpMainStart := dbMotorPumpMain.qxStart;

5.2.Fonctions (FC) - Sans état

Quand les utiliser ?

  • Calculs sans état
  • Mises à l'échelle
  • Opérations mathématiques
  • Fonctions utilitaires

Exemple : Mise à l'échelle de température

FUNCTION FC_ScaleTemperature : REAL
VAR_INPUT
  iwRawValue : INT;  // Valeur brute du capteur (0-27648)
  rMinTemp : REAL;   // Température minimale (ex. -50°C)
  rMaxTemp : REAL;   // Température maximale (ex. +150°C)
END_VAR

// Mise à l'échelle 0-27648 → rMinTemp à rMaxTemp
FC_ScaleTemperature := rMinTemp +
  (REAL#iwRawValue / 27648.0) * (rMaxTemp - rMinTemp);
END_FUNCTION

Appel :

rTemperatureTank1 := FC_ScaleTemperature(
  iwRawValue := iwTempSensor1,
  rMinTemp := -50.0,
  rMaxTemp := 150.0
);

6.Bonne pratique 4 : Gestion des erreurs selon NAMUR NE 107

NAMUR NE 107 est le standard industriel pour l'auto-surveillance et le diagnostic dans l'industrie de process. Il s'est également établi dans la construction mécanique.

6.1.Les 4 états

États de diagnostic NAMUR NE 107 : Fonctionnement normal, Maintenance requise, Vérification de fonction, Défaillance

6.2.Implémentation avec FB_AlarmHandler

FUNCTION_BLOCK FB_AlarmHandler
VAR_INPUT
  bTrigger : BOOL;          // Déclencheur d'alarme
  eAlarmLevel : INT;        // 1=Info, 2=Warning, 3=Error, 4=Critical
  sAlarmText : STRING[80];  // Texte d'alarme
END_VAR

VAR_OUTPUT
  bAlarmActive : BOOL;      // Alarme active
  bAckRequired : BOOL;      // Acquittement requis
END_VAR

VAR
  bAlarmLatched : BOOL;     // Alarme mémorisée
  dtTimestamp : DATE_TIME;  // Horodatage de l'alarme
END_VAR

// Logique : Mémoriser l'alarme, définir l'horodatage, acquitter si nécessaire
IF bTrigger AND NOT bAlarmLatched THEN
  bAlarmLatched := TRUE;
  dtTimestamp := CURRENT_TIMESTAMP();
  bAlarmActive := TRUE;

  // Logging vers IHM/SCADA
  // ...
END_IF;

bAckRequired := bAlarmLatched AND eAlarmLevel >= 3;
END_FUNCTION_BLOCK

Bonne pratique : Un gestionnaire d'alarmes central collecte toutes les alarmes et les communique de manière groupée à l'IHM.

7.Bonne pratique 5 : Versionnage avec Git

Oui, Git fonctionne aussi pour le code API ! Depuis TIA Portal v18, l'intégration est devenue nettement plus simple.

7.1.Configuration : TIA Portal avec Git

1. Activer le Multiuser Engineering

TIA Portal → Projet → Propriétés → Multiuser Engineering → Activer

2. Enregistrer le projet au format compatible Git

# .gitignore pour TIA Portal
*.ap18
*.zap18
__OPNB*
*.bak

3. Initialiser le dépôt Git

git init
git add .
git commit -m "Initial commit: TIA Portal project setup"

7.2.Stratégie de branchement pour les projets API

main (Code de production)
  ├── develop (Développement)
  │    ├── feature/motor-control-update
  │    ├── feature/add-safety-logic
  │    └── bugfix/alarm-text-typo
  └── hotfix/critical-emergency-stop-bug

Workflow :

  1. Créer une branche feature : git checkout -b feature/new-conveyor-logic
  2. Committer les modifications : git commit -m "Add conveyor start delay 2s"
  3. Créer une Pull Request (GitHub, GitLab)
  4. Revue de code par un second programmeur
  5. Merge dans develop
  6. Tests sur l'API de développement
  7. Branche release → main

8.Bonne pratique 6 : Commentaires et documentation

8.1.Commentaires de code : la règle des 3 lignes

Mauvais :

// ❌ Évident, n'apporte rien
bMotorRun := TRUE;  // Démarrer le moteur

Bon :

// ✅ Explique POURQUOI, pas QUOI
// Temporisation 2s pour la montée en pression du circuit hydraulique
// (Voir exigence REQ-HYD-012)
tDelayStart(IN := bStartRequest, PT := T#2S);
qxMotorStart := tDelayStart.Q;

8.2.Standards de documentation

Pour chaque FB/FC :

(*
  Nom : FB_MotorControl
  Version : 1.2.0
  Auteur : David Prybisch
  Date : 2025-11-22

  Description :
    Commande de moteur standardisée avec temporisation de démarrage,
    surveillance du retour et mémorisation des défauts.

  Historique des modifications :
    v1.2.0 - 2025-11-22 - Ajout de la surveillance de timeout
    v1.1.0 - 2025-10-15 - Intégration des alarmes NAMUR
    v1.0.0 - 2025-09-01 - Première version
*)
FUNCTION_BLOCK FB_MotorControl
// ...
END_FUNCTION_BLOCK

Diagrammes UML pour l'architecture système :

Utilisez des outils comme PlantUML ou Microsoft Visio pour visualiser l'architecture globale.

En détail : Ce que doit contenir une documentation d'installation complète, les 12 points qui comptent à la remise et comment reconstituer une documentation d'existant perdue — voir l'article dédié Documentation API : ce qu'elle doit contenir.

9.Bonne pratique 7 : Tests et simulation

9.1.Simulation avec PLCSIM

Siemens PLCSIM Advanced permet de tester les programmes API sans matériel physique :

Workflow :

  1. Développer le programme API dans TIA Portal
  2. Démarrer PLCSIM Advanced et charger le projet
  3. Définir et vérifier les variables via la table de surveillance
  4. Tester systématiquement les commandes séquentielles

Avantages :

  • Détecter les erreurs tôt – au bureau plutôt que chez le client
  • Les nouveaux programmeurs peuvent tester sans risque
  • Valider les modifications avant la mise en service

10.Bonne pratique 8 : Optimisation des performances

10.1.Surveiller la charge CPU

Tueurs de performance fréquents :

  1. Trop de temporisateurs/compteurs → Utilisez des tableaux au lieu de variables individuelles
  2. Opérations sur les chaînes dans les cycles temps réel → Déplacez-les vers des tâches de priorité inférieure
  3. Calculs complexes dans OB1 → Utilisez des interruptions cycliques (OB35)

Exemple : Gestion des temporisateurs par tableau

// ❌ MAUVAIS : 100 temporisateurs individuels
VAR
  tMotor1 : TON;
  tMotor2 : TON;
  // ... 98 autres temporisateurs
END_VAR

// ✅ BON : Tableau de temporisateurs
VAR
  atMotorTimers : ARRAY[1..100] OF TON;
END_VAR

// Appel en boucle
FOR i := 1 TO 100 DO
  atMotorTimers[i](IN := abMotorStart[i], PT := T#2S);
  aqxMotorStart[i] := atMotorTimers[i].Q;
END_FOR;

10.2.Optimisation mémoire avec les multi-instances

Problème : Chaque instance FB consomme son propre DB (DB d'instance).

Solution : Multi-instances pour les blocs récurrents.

// FB_ConveyorLine contient 10x FB_MotorControl en multi-instance
FUNCTION_BLOCK FB_ConveyorLine
VAR
  Motor1 : FB_MotorControl;  // Multi-instance
  Motor2 : FB_MotorControl;
  // ...
END_VAR

// Créer UNE SEULE instance de FB_ConveyorLine
dbConveyorLine : FB_ConveyorLine;  // Économise 90% de mémoire vs 10 FB séparés

11.Ce que le code propre fait gagner au dépannage

Toutes les bonnes pratiques précédentes se révèlent payantes lorsqu'une installation est à l'arrêt et qu'il faut trouver la panne sous pression. Celui qui programme de manière structurée ne cherche pas les pannes – il les circonscrit : symptôme → bloc concerné → chemin du signal → cause racine. Si chaque partie d'installation est encapsulée dans son propre FB au nom explicite, vous savez immédiatement où chercher, au lieu de fouiller des milliers de réseaux dans OB1.

C'est précisément le bénéfice concret de la séparation FC/FB, des conventions de nommage et de la hiérarchie claire des chapitres précédents : ils transforment des heures de tâtonnement en une recherche ciblée de quelques minutes.

En détail : La démarche complète – les cinq étapes de la vue des alarmes jusqu'au bloc, les bons outils TIA Portal, pourquoi le forçage n'est presque jamais la réponse et les cinq classes de défauts les plus fréquentes – figure dans l'article dédié Dépannage des programmes API : la cause en 5 étapes.

12.Conclusion : La programmation API professionnelle est rentable

L'investissement dans des programmes API structurés et maintenables est rentable à plusieurs niveaux :

  • Recherche de pannes plus rapide grâce à des noms de variables explicites et une structure claire
  • Temps d'intégration réduit pour les nouveaux programmeurs
  • Moins d'arrêts machine grâce à une meilleure gestion des erreurs
  • Maintenance simplifiée sur toute la durée de vie de l'installation

12.1.Checklist pour votre prochain projet API

  • Conventions de nommage convenues et documentées avec l'équipe
  • Structure de programme hiérarchique planifiée (diagramme UML)
  • Standards IEC 61131-3 respectés
  • Gestion des alarmes selon NAMUR NE 107 implémentée
  • Dépôt Git créé et .gitignore configuré
  • Simulation avec PLCSIM préparée
  • Processus de revue de code établi
  • Documentation (en-têtes FB, architecture système) créée

13.Infographie : Bonnes pratiques API en un coup d'œil

Infographie bonnes pratiques de programmation API : Checklist pour des programmes API structurés et maintenables

14.Ressources complémentaires


À propos de l'auteur : David Prybisch est programmeur API depuis plus de 10 ans. Il accompagne les constructeurs de machines dans la programmation structurée avec Siemens TIA Portal, les revues de code et la mise en service – dans la Grande Région comme pour des clients en Suisse.

Tags

SPS-ProgrammierungTIA PortalIEC 61131-3SiemensBest PracticesCode QualityNAMUR NE 107SCLAutomatisierung

Des questions sur votre projet d'automatisation ?

En tant qu'ingénieur en automatisation basé à Stadtbredimus, Luxembourg, j'offre des consultations initiales gratuites pour les entreprises de la Grande Région Saar-Lor-Lux.

David Prybisch · API · IHM · Mise en service

Related Articles

Questions fréquentes

Sollte ich Funktionsbausteine (FB) oder Funktionen (FC) verwenden?

Verwenden Sie Funktionsbausteine (FB) für zustandsbehaftete Logik (z.B. Motorsteuerung mit Störungsspeicher, Ventilsteuerung mit Feedback) und Funktionen (FC) für zustandslose Berechnungen (z.B. Skalierung, mathematische Operationen). FBs haben einen Instanz-Datenbaustein und behalten Werte zwischen Aufrufen – ideal für Anlagenteile. FCs sind Speicher-effizienter für wiederkehrende Berechnungen ohne Zustand.

Wie strukturiere ich große SPS-Programme am besten?

Nutzen Sie eine hierarchische Struktur: (1) Hauptprogramm (OB1) ruft nur Ablaufsteuerungen auf, (2) Ablaufsteuerungen (z.B. PackML-Zustände) koordinieren Anlagenteile, (3) Anlagenteile (Motoren, Ventile) sind als FB mit Standardinterface implementiert, (4) Utility-Funktionen (Skalierung, Alarme) in FC ausgelagert. Verwenden Sie Multiinstanzen, um Speicher zu sparen. Dokumentieren Sie die Struktur in einem UML-Diagramm.

Was sind die wichtigsten Namenskonventionen für SPS-Code?

Etablierte Best Practices: (1) Präfixe für Datentypen (bMotorRun für Bool, iTemperature für Int), (2) Pascal Case für Bausteine (FB_MotorControl), (3) Prefix für E/A (ixInputName, qxOutputName), (4) Sprechende Namen statt Abkürzungen (bMotorPumpMainRun statt bMPMR), (5) Konsistente Sprache (entweder DE oder EN, niemals gemischt). Tools wie Siemens Code Quality Check helfen bei der Einhaltung.

Wie implementiere ich professionelle Fehlerbehandlung in SPS-Code?

Best Practice ist ein zentraler Alarm-Baustein nach NAMUR NE 107 mit 4 Ebenen: (1) Fehler (Error) - Anlage stoppt, (2) Warnung (Warning) - Anlage läuft, Wartung erforderlich, (3) Info (Message) - Statusmeldungen, (4) Out of Service - Bauteil deaktiviert. Nutzen Sie die Siemens ProDiag-Bibliothek oder erstellen Sie einen FB_AlarmHandler, der Störungen mit Zeitstempel im HMI anzeigt und per OPC UA an übergeordnete Systeme meldet.

Kann ich Git für SPS-Projekte verwenden?

Ja, und Sie sollten! TIA Portal v18+ unterstützt Git-Integration über Multiuser Engineering. Speichern Sie TIA-Projekte im Openness-Format (XML-basiert), das Git-freundlich ist. Verwenden Sie .gitignore für Binary-Dateien. Commit-Messages sollten Änderungen klar beschreiben (z.B. 'Add motor start delay in FB_MotorControl'). Branching-Strategie: Feature-Branches für neue Funktionalität, Hotfix-Branches für kritische Fehler. Tools wie PlcGit erleichtern Diff-Visualisierung.

Was ist der Unterschied zwischen SCL und AWL in der SPS-Programmierung?

SCL (Structured Control Language) ist eine höhere Programmiersprache ähnlich Pascal/C, ideal für komplexe Berechnungen, Schleifen und Datenverarbeitung. AWL (Anweisungsliste) ist eine Low-Level-Sprache ähnlich Assembler, die direkten Registerzugriff ermöglicht. Empfehlung: Verwenden Sie SCL für 80% des Codes (bessere Lesbarkeit, einfachere Wartung) und AWL nur für zeitkritische Optimierungen oder Legacy-Systeme. TIA Portal bietet beide Sprachen, moderne Projekte setzen fast ausschließlich auf SCL.

Wie lange dauert es, SPS-Programmierung zu lernen?

Mit Grundkenntnissen in Programmierung: 3-6 Monate für solide Basics, 1-2 Jahre für professionelles Niveau. Lernpfad: (1) IEC 61131-3 Grundlagen (2 Wochen), (2) TIA Portal Bedienung (1 Monat), (3) Erstes Projekt mit Mentor (2-3 Monate), (4) Vertiefung Safety, HMI, Netzwerke (6+ Monate). Wichtig: Theorie allein reicht nicht – praktische Erfahrung an echten Anlagen ist unverzichtbar. Siemens SCE bietet kostenlose Schulungsunterlagen.

Welche SPS-Programmiersprache sollte ich als Anfänger lernen?

Starten Sie mit LAD (Kontaktplan) für einfache Logik – es ist visuell und intuitiv für Elektriker. Parallel dazu SCL (Structured Control Language) lernen für komplexere Aufgaben. SCL ist die Zukunft: kompakter, besser lesbar, und näher an modernen Programmiersprachen. FBD (Funktionsbausteindiagramm) ist gut für Regelungstechnik. SFC (Ablaufsprache) für Sequenzen. Tipp: Beherrschen Sie SCL + LAD, dann sind Sie für 95% aller Projekte gewappnet.