Simulation de process industriel

Denis Hulo

Simulation de process industriel dans un formulaire Access.

Niveau requis : confirmé.

Commentez cet article : Commentez ♪

- Titre : Simulation de process industriel

- Auteur : Denis Hulo

- Parution : 1 juin 2015

- Licence : Copyright ® 2015 Denis Hulo. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction

- II. Contexte

- III. Description du principe

- III-A. Formules mathématiques de base mises en œuvre

- III-B. Formules mathématiques généralisées

- IV. Rendu final de la simulation du process

- V. Les tables nécessaires

- V-A. La table T_Creneau

- V-B. La table T_Jour

- V-C. La table T_Machine

- VI. Les requêtes pour la partie simulation

- VI-A. La requête affichant les tranches horaires

- VI-A-1. La formule donnant les jours

- VI-A-2. La formule donnant les heures

- VI-A-3. La formule donnant les dates et heures

- VI-A-4. Fonction évaluant la date et l'heure de fin du process

- VI-B. La requête affichant la charge des machines

- VI-B-1. Mise en œuvre de la formule généralisée

- VI-B-1-a. Durée totale (i-1)

- VI-B-1-b. Durée maximum (i-1)

- VI-B-1-c. Durée totale (i)

- VI-B-1-d. Durée maximum (i)

- VI-B-1-e. Nombre de pièces en attente à l'indice i

- VI-B-1-f. Date et heure de fin du process

- VII. Le formulaire de simulation

- VII-A. La zone de liste affichant les horaires

- VII-B. Le graphique pour afficher la charge des machines

- VIII. Téléchargement

- IX. Remerciements

I - Introduction

Les process industriels impliquent souvent des calculs complexes et nécessitent donc un peu d'expérience pour appréhender le code mis en œuvre. Le but n'étant pas d'alourdir le propos avec des formules trop compliquées, je vais donc essayer de décrire un exemple simple de simulation d'un process industriel dans Ms Access, suivant une gamme de fabrication.

II - Contexte

Dans l'industrie, les machines peuvent être regroupées en ensembles autonomes de production spécialisés par type de produits qui utilisent les mêmes machines : ces ensembles s'appellent des îlots. Les flux de produits (matières) peuvent utiliser les postes de travail de l'îlot dans un ordre différent suivant leur gamme de fabrication, alors que dans une ligne de fabrication l'ordre est impératif.

Description d'un îlot de machines

Pour simplifier, on va ici considérer une gamme de fabrication composée de m machines placées en série et négliger les durées de transfert entre machines.

III - Description du principe

L'objectif est d'obtenir, à partir de formules mathématiques, le nombre de pièces en attente sur une machine quelconque ainsi que le total des pièces déjà usinées à un instant donné. Nous injecterons ces fonctions traduites en VBA dans des requêtes pour afficher et représenter la progression des pièces sur les différentes machines.

III-A - Formules mathématiques de base mises en œuvre

La durée de fabrication de n pièces qui passent sur m machines au total

duree_fabrication = (n-1)*duree_max + duree_total

- duree_max : durée de passage la plus longue entre les machines.

- duree_total : durée totale de passage sur les machines.

On en déduit :

Le nombre de pièces fabriquées sur m machines placées en série après une durée d

nbre_fabrique = ((d - duree_total) \ duree_max) + 1

C'est cette formule mathématique qui va nous servir de base pour nos calculs dans nos requêtes.

III-B - Formules mathématiques généralisées

La durée de passage de n pièces qui passent sur i machines disposées en série (i compris entre 1 et m)

duree_passage(i) = (n-1)*duree_max(i) + duree_total(i)

- duree_max(i) : durée de passage la plus longue entre les machines d'indice 1 à i.

- duree_total(i) : durée totale de passage sur les i machines.

En inversant la formule on obtient :

Le nombre de pièces passées sur les i machines, après une durée d

nbre_passe(i) = ((d - duree_total(i)) \ duree_max(i)) + 1

Nous utilisons ici la division entière, notée « \ » en VBA, pour obtenir un nombre entier de pièces.

On en déduit enfin :

Le nombre de pièces en attente sur la machine d'indice i, après une durée d

nbre_attente(i) = (((d - duree_total(i-1)) \ duree_max(i-1)) + 1) - (((d - duree_total(i)) \ duree_max(i)) + 1)

- duree_max(i-1) : durée de passage la plus longue entre les machines d'indice 1 à (i-1) ;

- duree_total(i-1) : durée totale de passage sur l'ensemble des (i-1) machines ;

- duree_max(i) : durée de passage la plus longue entre les machines d'indice 1 à i ;

- duree_total(i) : durée totale de passage sur les i machines.

Cette dernière formule va nous permettre de connaître, à un instant donné, le nombre de pièces en attente sur une machine quelconque et surtout, le nombre total de pièces déjà terminées en bout de gamme.

IV - Rendu final de la simulation du process

Voici le rendu du formulaire qui présente, pour chaque machine, le nombre de pièces en attente et donc la progression des pièces usinées.

Aperçu du formulaire de simulation

On constate que le programme permet de visualiser, pour chaque tranche horaire, le plan de charge de toutes les machines.

Voici les objets nécessaires pour aboutir à ce résultat.

V - Les tables nécessaires

Pour sauvegarder les durées d'usinage sur chaque machine ainsi que les jours et tranches horaires intervenant dans la simulation, nous aurons besoin de trois tables :

V-A - La table T_Creneau

Cette table contient la liste des créneaux horaires accompagnés de leur indice.

Nom du champ

Type de données

Description

Indice

Numérique

Indice du créneau horaire

Creneau

Texte

Créneau horaire

V-B - La table T_Jour

Elle permet d'enregistrer les indices des jours durant lesquels se déroule le processus industriel.

Nom du champ

Type de données

Description

Jour

Entier long

Numéro d'ordre du jour

V-C - La table T_Machine

Cette table permet de sauvegarder les noms des machines et les durées de passage des pièces qui peuvent être paramétrés.

Nom du champ

Type de données

Description

Indice

Entier long

Numéro d'ordre de la machine

Machine

Texte

Nom de la machine

Duree

Entier long

Durée de passage sur la machine

VI - Les requêtes pour la partie simulation

Afin de pouvoir afficher, pour chaque jour et chaque tranche horaire, le plan de charge simulé des machines, on a besoin de réaliser quelques requêtes.

VI-A - La requête affichant les tranches horaires

Cette requête paramétrée réalise le produit cartésien entre la table T_Creneau et T_Jour, pour afficher toutes les tranches horaires du process :

Aperçu de la requête affichant les horaires

On constate que la requête comprend, dans la partie encerclée, des champs calculés que nous allons détailler.

VI-A-1 - La formule donnant les jours

Le champ calculé affichant le(s) jour(s) pris en compte dans la simulation

DateJour: AjDate("j";[Jour]-1;ValDate([Forms]![F_Simuler_Process]![Date_Debut]))

- [Forms]![F_Simuler_Process]![Date_Debut] : paramètre donnant la date et l'heure du début du process.

VI-A-2 - La formule donnant les heures

Le champ calculé affichant les tranches horaires prises en compte dans la simulation

Horaire: AjDate("n";([Indice]-1)*Forms!F_Simuler_Process!Creneau;Forms!F_Simuler_Process!Horaire_Debut)

- [Forms]![F_Simuler_Process]![Creneau] : paramètre donnant la durée des tranches horaires.

- [Forms]![F_Simuler_Process]![Horaire_Debut] : paramètre donnant l'heure du début du process.

VI-A-3 - La formule donnant les dates et heures

Les dates et horaires pris en compte dans la simulation s'obtiennent en fonction du paramètre définissant le 1er jour et le 1er horaire :

Le champ calculé affichant les dates et heures prises en compte dans la simulation

DateHeure: CDate(AjDate("j";[Jour]-1;ValDate([Forms]![F_Simuler_Process]![Date_Debut])) & " " & AjDate("n";([Indice]-1)*[Forms]![F_Simuler_Process]![Creneau];[Forms]![F_Simuler_Process]![Horaire_Debut]))

VI-A-4 - Fonction évaluant la date et l'heure de fin du process

On évalue la date et l'heure de fin du processus à partir de la formule de base définie précédemment :

La durée de fabrication de n pièces qui passent sur m machines au total

duree_fabrication = (n-1)*duree_max + duree_total

La fonction VBA mise en œuvre pour ce calcul va permettre de filtrer la requête sur le champ date et heure :

Fonction donnant la date et l'heure de fin du processus

Public Function fin_process(ByVal nbre As Long, ByVal debut As Date, ByVal Horaire_Debut, ByVal Horaire_Fin, ByVal Creneau As Integer) As Date
' date et heure de fin du process en fonction du nombre de pièces, de la date de début du process,
' des heures de début et de fin dans la journée et du créneau horaire.
Dim rs As DAO.Recordset
Dim leSql As String
Dim d As Long, d1 As Long, d2 As Long
Dim dt As Date
Dim j As Integer
Dim m As Long

' requête affichant la durée totale du process en se basant sur la formule (n-1)*duree_max + duree_total.
leSql = "SELECT " & (nbre - 1) & "*Max([Duree])+Sum([Duree]) AS durée " & _
"FROM T_Machine;"

' le jeu d'enregistrement correspondant.
Set rs = CurrentDb.OpenRecordset(leSql, dbOpenForwardOnly)

' la durée totale.
d = rs!durée

rs.Close
Set rs = Nothing

d1 = DateDiff("s", TimeValue(debut), Horaire_Fin)

If d <= d1 Then ' si compris dans l'intervalle.
fin_process = DateAdd("s", d, debut)

Else ' sinon on décompose la durée.

d = d - d1
dt = CDate(Format(debut + 1, "dd/mm/yyyy") & " " & Format(Horaire_Debut, "hh:nn"))
m = DateDiff("s", Horaire_Debut, Horaire_Fin)
j = d \ m
dt = DateAdd("d", j, dt)
dt = DateAdd("s", d Mod m, dt)

fin_process = dt

End If

' renvoie la date et l'heure de fin du process.
fin_process = DateAdd("s", (Creneau * 60), fin_process)

End Function

VI-B - La requête affichant la charge des machines

Cette requête paramétrée réalise le produit cartésien entre la requête précédente R_Horaire2 et la table T_Machine, de manière à afficher toutes les tranches horaires du process et les quantités en attente sur chaque machine :

Aperçu de la requête finale

On remarque que la requête comprend dans la partie encerclée des champs calculés que nous allons détailler.

VI-B-1 - Mise en œuvre de la formule généralisée

Nous avons en fait injecté dans la requête au niveau du champ Nbre la formule généralisée vue précédemment :

La formule donnant le nombre de pièces en attente sur la machine d'indice i

nbre_attente(i) = (((d - duree_total(i-1)) \ duree_max(i-1)) + 1) - (((d - duree_total(i)) \ duree_max(i)) + 1)

À cet effet, nous avons évalué les différentes durées maximales et totales au moyen de fonctions de domaine.

VI-B-1-a - Durée totale (i-1)

La durée totale jusqu'à la machine d'indice (i-1)

Duree_Total1: SomDom("Duree";"T_Machine";"Indice<=" & ([T_Machine_1].[Indice]-1) & " or ( Indice=1)")

On choisit ici une fonction de domaine, dans la seconde version de l'exemple disponible en téléchargement nous utilisons une sous-requête à la place.

VI-B-1-b - Durée maximum (i-1)

La durée maximum jusqu'à la machine d'indice (i-1)

Duree_Max1: MaxDom("Duree";"T_Machine";"Indice<=" & ([T_Machine_1].[Indice]-1) & " or ( Indice=1)")

VI-B-1-c - Durée totale (i)

La durée totale jusqu'à la machine d'indice i

Duree_Total2: SomDom("[Duree]";"T_Machine";"Indice<=" & [T_Machine_1].[Indice])

VI-B-1-d - Durée maximum (i)

La durée maximum jusqu'à la machine d'indice i

Duree_Max2: MaxDom("Duree";"T_Machine";"Indice<=" & [T_Machine_1].[Indice])

Puis, on a inséré dans le champ nbre de la requête principale une fonction VBA qui est la traduction de la formule généralisée mentionnée plus haut.

VI-B-1-e - Nombre de pièces en attente à l'indice i

On a injecté la formule généralisée vue précédemment au niveau de la requête en utilisant une fonction VBA fnc_nbre :

Le champ calculé indiquant le nombre de pièces en attente sur une machine donnée

Nbre: VraiFaux(T_Machine_1.Indice=12;fnc_Nbre(Forms!F_Simuler_Process!Date_Debut;[DateHeure];Forms!F_Simuler_Process!Horaire_Debut;Forms!F_Simuler_Process!Horaire_Fin;[Duree_Total2];[Duree_Max2];Forms!F_Simuler_Process!Nbre_Pieces);(VraiFaux(T_Machine_1.Indice=1;Forms!F_Simuler_Process!Nbre_Pieces;fnc_Nbre(Forms!F_Simuler_Process!Date_Debut;[DateHeure];Forms!F_Simuler_Process!Horaire_Debut;Forms!F_Simuler_Process!Horaire_Fin;[Duree_Total1];[Duree_Max1];Forms!F_Simuler_Process!Nbre_Pieces)))-fnc_Nbre(Forms!F_Simuler_Process!Date_Debut;[DateHeure];Forms!F_Simuler_Process!Horaire_Debut;Forms!F_Simuler_Process!Horaire_Fin;[Duree_Total2];[Duree_Max2];Forms!F_Simuler_Process!Nbre_Pieces))

On utilise ici la fonction VraiFaux pour tester si on est en bout de gamme (l'indice égal à 12 est juste un indicateur de fin supérieur au nombre maximum de machines), dans ce cas, on calcule le nombre de pièces fabriquées. L'expression comprend également la fonction fnc_Nbre qui donne le nombre de pièces passées sur les i machines, après une durée d.

Les champs durées et date/heure définis précédemment :

- Duree_Max1 : durée maximum jusqu'à la machine d'indice (i-1) ;

- Duree_Total1 : durée totale jusqu'à la machine d'indice (i-1) ;

- Duree_Max2: durée maximum jusqu'à la machine d'indice (i) ;

- Duree_Total2 : durée totale jusqu'à la machine d'indice (i) ;

- DateHeure : date et heure prises en compte pour le calcul.

Les paramètres de la simulation (début et fin du process) qui sont des zones de texte situées sur le formulaire simulateur du process :

- Forms!F_Simuler_Process!Date_Debut : paramètre indiquant la date et l'heure de début de la simulation ;

- Forms!F_Simuler_Process!Horaire_Debut : paramètre indiquant l'heure de début du process ;

- Forms!F_Simuler_Process!Horaire_Fin : paramètre indiquant l'heure de fin du process.

La fonction VBA donnant le nombre de pièces en attente sur les différentes machines de la gamme de fabrication

Public Function fnc_Nbre(ByVal debut As Date, ByVal fin As Date, ByVal Horaire_Debut As Date, ByVal Horaire_Fin As Date, ByVal duree_total As Integer, ByVal duree_max As Integer, ByVal nbre As Long) As Long
' nombre de pièces passées sur la machine en fonction de la durée totale et de la durée max. jusqu'à cette machine.

Dim j As Integer
Dim d1 As Long, d2 As Long
Dim d As Long

j = DateDiff("d", debut, fin)

If j > 1 Then ' process sur plusieurs jours.
d = (j - 1) * DateDiff("s", Horaire_Debut, Horaire_Fin)
d1 = DateDiff("s", TimeValue(debut), Horaire_Fin)
d2 = DateDiff("s", Horaire_Debut, TimeValue(fin))
d = d + d1 + d2
ElseIf (j = 1) Then ' simulation sur 1 jour entier.
d1 = DateDiff("s", TimeValue(debut), Horaire_Fin)
d2 = DateDiff("s", Horaire_Debut, TimeValue(fin))
d = d1 + d2
Else ' process se déroulant dans la journée.
d = DateDiff("s", TimeValue(debut), TimeValue(fin))
End If

If (d >= duree_total) Then
fnc_Nbre = (d - duree_total) \ duree_max + 1 ' formule mathématique définie dans l'article.

If fnc_Nbre > nbre Then
fnc_Nbre = nbre
End If

Else
fnc_Nbre = 0
End If

End Function

VI-B-1-f - Date et heure de fin du process

On évalue la date et l'heure de fin du processus à partir de la formule de base définie précédemment :

La durée de fabrication de n pièces qui passent sur m machines au total

duree_fabrication = (n-1)*duree_max + duree_total

La fonction VBA mise en œuvre pour ce calcul est la suivante :

Fonction donnant la date et l'heure de fin du processus

Public Function fin_process(ByVal nbre As Long, ByVal debut As Date, ByVal Horaire_Debut, ByVal Horaire_Fin, ByVal Creneau As Integer) As Date
' date et heure de fin du process en fonction du nombre de pièces, de la date de début du process,
' des heures de début et de fin dans la journée et du créneau horaire.
Dim rs As DAO.Recordset
Dim leSql As String
Dim d As Long, d1 As Long, d2 As Long
Dim dt As Date
Dim j As Integer
Dim m As Long

' requête affichant la durée totale du process en se basant sur la formule (n-1)*duree_max + duree_total.
leSql = "SELECT " & (nbre - 1) & "*Max([Duree])+Sum([Duree]) AS durée " & _
"FROM T_Machine;"

' le jeu d'enregistrement correspondant.
Set rs = CurrentDb.OpenRecordset(leSql, dbOpenForwardOnly)

' la durée totale.
d = rs!durée

rs.Close
Set rs = Nothing

d1 = DateDiff("s", TimeValue(debut), Horaire_Fin)

If d <= d1 Then ' si compris dans l'intervalle.
fin_process = DateAdd("s", d, debut)

Else ' sinon on décompose la durée.

d = d - d1
dt = CDate(Format(debut + 1, "dd/mm/yyyy") & " " & Format(Horaire_Debut, "hh:nn"))
m = DateDiff("s", Horaire_Debut, Horaire_Fin)
j = d \ m
dt = DateAdd("d", j, dt)
dt = DateAdd("s", d Mod m, dt)

fin_process = dt

End If

' renvoie la date et l'heure de fin du process.
fin_process = DateAdd("s", (Creneau * 60), fin_process)

End Function

VII - Le formulaire de simulation

Nous allons décrire le formulaire qui présente la simulation du process sur les différentes machines de la gamme de fabrication.

Aperçu du formulaire de simulation

Le programme permet de visualiser pour chaque tranche horaire le plan de charge de toutes les machines.

VII-A - La zone de liste affichant les horaires

Sur la partie gauche du formulaire se trouve une zone de liste qui affiche l'ensemble des tranches horaires prises en compte dans la simulation du process. Elles sont sous la forme Jour/Heure.

VII-B - Le graphique pour afficher la charge des machines

Sur la plus grande partie du formulaire se trouve le graphique qui affiche le plan de charge des machines dont voici le SQL :

Code SQL du graphique placé sur le simulateur

PARAMETERS [Forms]![F_Simuler_Process]![Nbre_Pieces] Value;
TRANSFORM First(R_Horaire_Machine_Piece.Nbre) AS First_Nbre
SELECT R_Horaire_Machine_Piece.Machine FROM R_Horaire_Machine_Piece
GROUP BY R_Horaire_Machine_Piece.Machine
PIVOT R_Horaire_Machine_Piece.Machine In ("M1","M2","M3","M4","M5","M6","Total fait");

VIII - Téléchargement

Pour faciliter les tests et assurer sa portabilité, la base exemple n'utilisera pas de composants externes à Access (ActiveX ou autres).

La base exemple est au format Access 2000.

IX - Remerciements

Un grand Merci à toute l'équipe de Dvp et plus particulièrement à :

Pour ses remarques et conseils avisés :
. claudeleloup

Pour leur relecture :
. claudeleloup
. franouch
. Oppenheimer