La machine à états est l’une des architectures fondamentales fréquemment utilisées par les développeurs de LabVIEW pour créer rapidement des applications. L’architecture de machine à états peut être utilisée pour implémenter des algorithmes de prise de décision complexes représentés par des diagrammes d’états ou des organigrammes. Une machine à états peut être implémentée à l’aide des fonctions natives LabVIEW ; aucun toolkit ou module supplémentaire n’est requis pour l’architecture.
Cet article explore la définition d’une machine à états, des exemples de cas d’usage, des exemples conceptuels d’une machine à états et des exemples de code d’une machine à états.
Une machine à états est une architecture de programmation qui permet un flux dynamique vers des états en fonction des valeurs des états précédents ou des entrées utilisateur.
Ce modèle est bien adapté aux applications qui peuvent être décrites comme une combinaison des éléments suivants :
Un état peut être défini comme l’état au sein du programme tout en exécutant la tâche globale du programme ; des exemples d’état peuvent être l’initialisation, l’attente, l’exécution d’un calcul, la vérification de l’état, etc.
Les instructions logiques aident à déterminer quand passer à un nouvel état et à quel état passer. Les événements peuvent être utilisés pour déclencher le passage d’un état à l’autre ; ils peuvent être des événements programmatiques ou définis par l’utilisateur, comme d’appuyer sur un bouton.
Chaque état d’une machine à états fait quelque chose d’unique et appelle d’autres états. La communication d’état dépend d’une condition ou d’une séquence. Pour traduire le diagramme d’états en une architecture de programmation LabVIEW, vous avez besoin de l’infrastructure suivante :
Les machines à états sont utilisées dans des applications où des états distincts existent. Chaque état peut conduire à un ou plusieurs états et peut également terminer le flux de processus. Une machine à états repose sur l’entrée utilisateur ou le calcul en état pour déterminer l’état à passer. Les applications requièrent un état « initialiser », suivi d'un état par défaut, dans lequel de multiples actions peuvent être effectuées. Les actions effectuées peuvent dépendre des entrées et des états précédents et actuels. Un état « d’arrêt » peut ensuite être utilisé pour effectuer des actions de nettoyage.
En plus de sa puissante capacité à implémenter des algorithmes de prise de décision, les machines à états sont également des formes fonctionnelles de planification d’applications. Au fur et à mesure que les applications se développent, le besoin d’une conception adéquate s’est également amélioré. Les diagrammes d’état et les organigrammes sont utiles et parfois essentiels pour le processus de conception. Les machines à états sont non seulement avantageuses pour la planification des applications, mais aussi faciles à créer.
Par exemple, les applications suivantes peuvent bénéficier du modèle Machine à états :
Il existe un autre modèle de conception qui peut être utilisé pour implémenter une interface utilisateur, le Gestionnaire de messages dans une file d’attente. Un gestionnaire de messages dans une file d’attente est une version plus sophistiquée de la machine à états et offre une flexibilité supplémentaire, mais il ajoute également une complexité supplémentaire.
La création d’une machine à états efficace nécessite que le concepteur (1) crée une liste d’états possibles. Avec cette liste, le concepteur peut (2) planifier comment chaque état est lié à un autre. Ensuite, le diagramme d’états peut (3) être traduit en architecture de programmation graphique LabVIEW.
Dans cet exemple, nous voulons générer une application qui tire un canon de façon continue sans le laisser chauffer dangereusement.
(1) Énumérer les états possibles
Pour commencer, nous créons une liste de tous les états possibles pour notre tâche. Pour accomplir la tâche de tirer le canon de façon continue, vous devrez :
(2) Mapper les relations entre les états dans un diagramme d’états
Ensuite, nous examinerons comment ces états sont liés les uns aux autres et nous créerons un diagramme d’états. Lors de la création du diagramme d’états, envisagez ce qui entraînerait le programme à passer d’un état à l’autre : est-ce une transition automatique ? Y a-t-il un déclenchement externe de l’utilisateur ? La transition est-elle basée sur le résultat d’un calcul ?
Par exemple, examinons les relations entre l’état d’initialisation et les autres états.
Notezque tout en réfléchissant à la façon dont les états sont liés entre eux, nous avons commencé à définir la logique permettant de passer entre ces états. La logique de programmation que nous utiliserons dans le code dépend (1) du nombre d’états de transition possibles et (2) du nombre d’entrées prises en compte dans la logique. Les options de transition de code sont discutées ci-dessous dans la section Exemples de code de transition.
Continuez à explorer comment les états se lient entre eux jusqu’à ce que vous disposiez d’un diagramme d’états complet. Le diagramme d’états comprendra tous les états et leurs relations (Figure 1). Notez que dans ce diagramme, les états (nœuds ovales) décrivent les actions effectuées lorsque le processus de contrôle est dans cet état, tandis que les transitions (flèches) décrivent simplement quand et comment le processus peut passer d’un état à l’autre.
Figure 1 : Diagramme d’états du tir d’un canon
La relation entre chaque état vous aidera à programmer la logique nécessaire pour passer d’un état à l’autre.
(3) Construire une machine à états dans LabVIEW
Après avoir défini les états et leur relation dans un diagramme d’états, vous pouvez traduire cela en architecture de codage dans LabVIEW (Figure 2). Le flux entre les états du diagramme d’états (Figure1) est implémenté par la boucle. Les états individuels sont remplacés par des conditions dans la structure Condition. Chaque état du diagramme représenté ci-dessus correspond à un sous-diagramme de la structure Condition. Chaque état :
Un registre à décalage sur la boucle While suit l’état actuel, qui est alimenté dans l’entrée de la structure Condition.
Figure 2 : Machine à états
Reportez-vous au projet échantillon Mesure à mono-déclenchement, disponible à partir de la boîte de dialogue Créer un projet, pour voir un exemple d'adaptation de ce modèle à une application de mesure.
1. Le code d'arrêt ne s'exécute que lorsque l'utilisateur veut arrêter l'application.
2. Le code d'arrêt s'exécute toujours jusqu'à la fin.
Consultez le tutorielModifier la machine à états simple LabVIEWpour commencer.
Avant de personnaliser ce modèle, posez-vous les questions suivantes :
Il existe différentes méthodes pour déterminer l’état vers lequel effectuer une transition, comme discuté ci-dessous.
Notez que bien que les exemples d’images montrent l’état « Init », ces possibilités de transition peuvent s’appliquer à n’importe quel état.
Biunivoque : Si vous passez toujours de l’état A à l’état B, il n’y a pas besoin de programmer de logique, il suffit de générer en sortie le nom de la condition suivante (Condition B) vers le registre à décalage.
Figure 3a : Un seul état de transition possible
Un à deux : Si vous pouvez passer de l’état A à l’état B ou à l’état C, vous pouvez utiliser une fonction Sélectionner pour évaluer l’état d’un indicateur. Vous devriez évaluer quelque chose qui détermine l’état vers lequel vous souhaitez passer. Par exemple, sur la Figure 3b, nous voyons que l’entrée utilisateur du bouton Stop détermine si nous avançons depuis l’état Démarrage ou si nous continuons vers l’état Arrêt.
Figure 3b : Deux états de transition possibles
Un à plusieurs utilisant des tableaux : Si vous avez plusieurs états vers lesquels vous pouvez passer, vous pouvez utiliser une zone booléenne associée à une constante énum pour programmer la transition. Par exemple, sur la figure 3c, un code est conduit où le résultat du code détermine la transition, dont la sortie est un tableau de booléens. Le tableau booléen correspond à une constante énum qui contient une liste d’états possibles vers lesquels on peut passer. En utilisant la fonction Indexer un tableau, l’indice du premier booléen « Vrai » dans le tableau de booléens est en sortie. Ensuite, à l’aide de la fonction Sous-ensemble d’un tableau, vous pouvez extraire la valeur appropriée de la constante énum à laquelle elle est corrélée.
Figure 3c
Astuce : Rappelez-vous que les tableaux sont indexés par 0 et les énums par 1. Pour corréler le tableau de booléens avec la constante énum, utilisez la fonction Incrément pour corriger cet offset :
Un à plusieurs utilisant une boucle While : Une autre option si vous avez plusieurs états de transition possibles est d’utiliser une boucle While dans une condition. Le code à l’intérieur de la boucle While continuera jusqu’à ce qu’un état booléen soit défini sur Vrai, déclenchant le bouton Stop. Cela permettra au code de s’exécuter efficacement jusqu’à ce qu’un événement de déclenchement se produise.
La Figure 3d illustre un état « Init » utilisant une boucle interne et une structure Condition pour passer à l’état suivant. La structure Condition interne contient un diagramme pour chaque transition qui quitte l’état actuel. Chaque condition de la structure Condition interne a deux sorties : une valeur booléenne, qui spécifie si la transition doit être prise ou non, et une constante énumération, qui spécifie l’état vers lequel la transition va. En utilisant l’indice de boucle comme entrée dans la structure Condition, ce code passe effectivement à travers chaque condition de transition un par un, jusqu’à ce qu’il trouve un diagramme avec une sortie booléenne « Vrai ». Une fois que la sortie booléenne « Vrai » est trouvée, la condition génère le nouvel état vers lequel la transition se dirige. Bien que cette méthode puisse sembler légèrement plus compliquée que les méthodes précédentes, elle offre la possibilité d’ajouter des noms aux transitions en « convertissant » la sortie de l’indice de la boucle en un type énuméré. Cet avantage vous permet d’ajouter une « documentation automatique » à votre code de transition.
Figure 3d
Redondance de code
Problème : La partie la plus difficile lors de la création d’une machine à états est de différencier les états possibles dans le diagramme d’états. Par exemple, dans le diagramme d’états de la machine à coke (Figure 4), nous aurions pu avoir des états de 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50 cent au lieu d’avoir un état « en attente de réponse » qui passe d’un état à l’autre en fonction du type de pièce tombé. Cela créerait 11 états différents avec exactement le même diagramme de condition. Le code redondant peut créer un gros problème dans une application plus grande.
Solution : Si différents états ont le même diagramme de condition, essayez de les combiner en un seul état. Par exemple, l’état « Attendre une réponse » est créé pour éviter la redondance de code.
Utilisation de l’énum
Problème : Les énums sont largement utilisées comme sélecteurs de condition dans les machines à états. Si l’utilisateur essaie d’ajouter ou de supprimer un état à partir de cet énum, les fils de liaison restants connectés aux copies de cet énum seront brisés. C’est l’un des obstacles les plus courants lors de l’implémentation des machines à états avec des énums.
Solution : Voici deux solutions possibles à ce problème :
1. Si toutes les énumérations sont copiées de l’énum modifié, les pauses disparaîtront.
2. Créez une nouvelle commande avec l’énum et sélectionnez « déf. de type » dans le sous-menu. En sélectionnant une déf. de type, toutes les copies d’énum seront automatiquement mises à jour si l’utilisateur ajoute ou supprime un état.
Si vous souhaitez en savoir plus sur les machines à états et d’autres architectures avancées dans LabVIEW, envisagez de suivre le cours de formation pour clients LabVIEW Fondamental 2.