# Premier exemple pas à pas

On va implémenter le grafcet suivant, permettant d'allumer une lampe depuis un intérrupteur de type bouton poussoir.

![Premier Grafcet à implémenter dans HomeIO avec c#](/files/-M-K2UJH5_a6svmYqbvA)

## Définir les équations

En applications les règles vue en cours avec M. Riera, vous pouvez déterminer les équations.

### Calcul des fonctions de transition

{% hint style="info" %}
Rappel de la règle : $$F T1(t)=X\_{n-1}(t-1).R1(t)$$&#x20;
{% endhint %}

$$
ft1 = X1. \uparrow bp \\
ft2 = X2. \uparrow bp
$$

### Calcul des étapes

{% hint style="info" %}
Rappel de la règle : $$Xi(t) = FTpred\_i(t) + Xi(t-1).\overline{FTsucc\_i(t)}$$&#x20;
{% endhint %}

$$
X1=ft2+X1.\overline{ft1} \\
X2=ft1+X2.\overline{ft2}
$$

### Calcul des sorties

$$
Allumer\_la\_lampe = X2
$$

## Rappel du fonctionnement du cycle API

![Cycle API à reproduire](/files/-M-K4nRckqDrSZ76Xug-)

## Mise en place dans C\#

Dans C# (ou tout autre langage de programmation), le cycle API est en fait une boucle, qui se répète, sans fin, toutes les *x* ms (peut dépendre de l'automate que l'on souhaiterait simuler), afin de simuler le cycle d'un API.

A l'intérieur de cette boucle, le programme doit réaliser les différentes opérations du cycle :

1. Sauvegarder l'état précédent
2. Lire les entrées
3. Calculer les fonctions de transitions
4. Calculer les étapes
5. Calculer les sorties
6. Ecrire les sorties

### Quelques éléments en C\#

#### Récupérer une entrée depuis HomeIO

L'extrait de code ci-dessous permet de récupérer l'état d'un capteur (ou d'une entrée en général) et de le sauvegarder dans une variable.

```csharp
bool bp = MemoryMap.Instance.GetBit(adresseDuComposant, MemoryType.Input).Value;
```

On peut procéder de manière similaire pour récupérer l'état d'une sortie, et ensuite pouvoir le modifier.

```csharp
MemoryBit lampe = MemoryMap.Instance.GetBit(adresseDuComposant, MemoryType.Output);
//lampe contient l'adresse. Pour accéder à la valeur, il faut utiliser la propriété Value;
```

### Traduction des différentes étapes du cycle

Considérons que le code ci-après se trouve dans une méthode nommée : `runCycleApi()`

{% hint style="danger" %}
Les extraits de code ci-après suppose que les déclarations sont effectuées. Le code ne concerne que la méthode qui est exécutée cycliquement par le *timer*.
{% endhint %}

#### Etape 1. Sauvegarde des états précédents

```csharp
this.bpPrec = this.bp;
```

#### Etape 2. Lecture des entrées

La lecture des entrées implique de mettre à jour la memory map qui est en cache. Cette mise à jour ne se fait qu'en début de cycle pour récupérer l'état du système, et en fin de cycle pour écrire les sorties.

```csharp
MemoryMap.Instance.Update();
this.bp = MemoryMap.Instance.GetBit(adresseDuComposant, MemoryType.Input).Value;
```

#### Etape 3. Calcul des fonctions de transition

Il est souvent nécessaire de manipuler des fronts (montant ou descendant) afin de traiter la donnée des entrées.

Le calcul d'un front montant peut se faire de la manière suivante :

```csharp
this.front = ! this.bpPrec && this.bp;
```

{% hint style="info" %}
Il serait très judicieux de définir une méthode pour calculer les fronts sur des exemples plus complexes
{% endhint %}

Les équations des fonctions de transition se calculent donc avec les lignes suivantes :

```csharp
this.ft1 = this.X1 && this.front;
this.ft2 = this.X2 && this.front;
```

ft1, ft2, X1 et X2 sont des variables représentant les éléments du Grafcet. Les étapes (Xn) sont initialisées à **false**, sauf les étapes initiales qui doivent être à **true** pour pouvoir exécuter le Grafcet.

#### Etape 4. Calcul des étapes

La traduction des équations en C# donne :

```csharp
this.X1 = this.ft2 || this.X1 && ! this.ft1;
this.X2 = this.ft1 || this.X2 && ! this.ft2;
```

#### Etape 5. Calcul des sorties

En fonction des actions associées aux étapes.

```csharp
this.lampe.Value = X2; //on active la lampe que sur l'étape 2
```

#### Etape 6. Mise à jour des sorties

Il faut maintenant mettre à jour HomeIo en synchronisant le cache et la memory map:

```csharp
MemoryMap.Instance.Update();
```

#### On répète le cycle

Si tout le code précédent est dans une méthode, on peut répéter ce cycle dans un time avec la méthode suivante, associée à un timer dans votre projet :

```csharp
private void timer1_Tick(object sender, EventArgs e)
{
    runCylceApi();
}
```

Ce timer doit se déclencher soit de manière automatique au chargement, soit sur un bouton de votre interface, au choix. Il est nécessaire d'initialiser aussi l'état du grafcet (étape initiale à vraie `this.X1 = true`)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://cours.davidannebicque.fr/but-info/premier-exemple-pas-a-pas.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
