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.

Introduction
La programmation API, c'est bien plus que l'assemblage de blocs logiques. En plus de 12 ans en tant que programmeur API, j'ai vu d'innombrables projets API – beaucoup avec des problèmes typiques :
- Noms de variables illisibles comme
M0.0,DB1.DBX0.0ou%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.
Pourquoi des bonnes pratiques en programmation API ?
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.
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
Bonne pratique 1 : Utiliser systématiquement les standards IEC 61131-3
L'IEC 61131-3 est la norme internationale pour la programmation API : elle définit de manière uniforme les langages, les types de données et les types de blocs. Son intérêt pratique : un code conforme à la norme reste lisible pour le programmeur suivant.
Aperçu des 5 langages de programmation
| Norme (CEI) | Siemens | Utilisation | Limites |
|---|---|---|---|
| LD – Ladder Diagram | KOP | Verrouillages, logique simple | Illisible au-delà d'une cinquantaine de réseaux |
| FBD – Function Block Diagram | FUP | Régulation, logique de flux de données | Difficile à maintenir pour les grands programmes |
| IL – Instruction List | AWL | Uniquement code existant | Classé obsolète depuis 2013 |
| ST – Structured Text | SCL | Algorithmes, calculs, bibliothèques | Moins parlant pour les purs verrouillages |
| SFC – Sequential Function Chart | GRAPH | Commandes 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.
Programmation structurée : la pyramide

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.
Bonne pratique 2 : Établir des conventions de nommage
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
Préfixes standardisés (Notation hongroise)
| Préfixe | Type de données | Exemple |
|---|---|---|
b | BOOL | bMotorRun, bAlarmActive |
i | INT | iCounter, iTemperature |
r | REAL | rSpeed, rPressure |
s | STRING | sAlarmText, sRecipeName |
dt | DATE_TIME | dtStartTime, dtLastMaintenance |
t | TIME | tDelayStart, tCycleTime |
udi | UDINT | udiPartCounter, udiTotalProduction |
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.
Bonne pratique 3 : Utiliser correctement les blocs fonctionnels vs fonctions
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;
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
);
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.
Les 4 états

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.
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.
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"
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 :
- Créer une branche feature :
git checkout -b feature/new-conveyor-logic - Committer les modifications :
git commit -m "Add conveyor start delay 2s" - Créer une Pull Request (GitHub, GitLab)
- Revue de code par un second programmeur
- Merge dans
develop - Tests sur l'API de développement
- Branche release →
main
Bonne pratique 6 : Commentaires et documentation
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;
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.
Bonne pratique 7 : Tests et simulation
Simulation avec PLCSIM
Siemens PLCSIM Advanced permet de tester les programmes API sans matériel physique :
Workflow :
- Développer le programme API dans TIA Portal
- Démarrer PLCSIM Advanced et charger le projet
- Définir et vérifier les variables via la table de surveillance
- 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
Bonne pratique 8 : Optimisation des performances
Surveiller la charge CPU
Tueurs de performance fréquents :
- Trop de temporisateurs/compteurs → Utilisez des tableaux au lieu de variables individuelles
- Opérations sur les chaînes dans les cycles temps réel → Déplacez-les vers des tâches de priorité inférieure
- 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;
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
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.
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
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
.gitignoreconfiguré - Simulation avec PLCSIM préparée
- Processus de revue de code établi
- Documentation (en-têtes FB, architecture système) créée
Infographie : Bonnes pratiques API en un coup d'œil

Ressources complémentaires
- Standard IEC 61131-3 : PLCopen.org
- Bonnes pratiques Siemens TIA Portal : Siemens Support
- NAMUR NE 107 : NAMUR.net
- Git pour API : PlcGit Documentation
À propos de l'auteur : David Prybisch est programmeur API depuis plus de 12 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 région Saar-Lor-Lux comme pour des clients en Suisse.