Bonjour,
Comme promis, voilà un petit tutoriel pour faire une gestion de recettes sur automate SIEMENS S7-300 et +.
C'est une méthode parmis d'autres, celle-ci est ma façon de faire et a été largement éprouvée sur le terrain
Définition:
Une recette est un jeu de paramètres (une structure de données) qui permet de personnaliser un process en fonction d'un type de produit (par exemple).
Principe:
Il faut avoir une banque (table) de X recettes dans l'automate.
Par un moyen de sélection quelconque (un pupitre IHM, un bouton sélecteur ...), on désigne la recette à utiliser parmis les X, c'est la recette de travail.
La recette:
Il faut commencer par créer une structure de données.
Il s'agit de créer un UDT (User Defined Type = Type Défini par l'Utilisateur) pour définir notre structure.
Voilà un exemple en images:
Lorsque la boite de dialogue apparait, donnez un numéro à l'UDT (ou laissez celui que STEP7 vous propose) ainsi qu'un nom. Ici dans l'exemple c'est UDT1 - Recette
Voila un exemple de recette. Ici elle fait 14 octets de longueur. A vous de personnaliser selon vos besoins
La banque de recette:
Il faut créer un tableau pour contenir X recettes.
A ne pas faire : faire un bloc DB par recette, donc au total X blocs DB.
Un DB vide consomme déjà 38 octets (pour l'entete que l'automate a besoin)
Si vous avez 50 recettes à stocker, vous perdez 1900 octets pour rien ; et comme la mémoire des automates se compte en Ko et non en Mo ....
Sans compter le temps que vous passez pour créer ces X blocs DB.
Ca peut peut-etre valoir le coup d'utiliser cette méthode si la recette est conséquente en taille > 1 Ko par ex
A faire : créer un seul DB qui va contenir un tableau de X structures
L'exemple en images :
Pour faire une banque de 50 recettes par exemple.
De cette manière, lorsque vous souhaitez accéder à une valeur de la banque par programme, il faut adresser la variable comme ceci :
Code : Tout sélectionner
"Banque de recettes".Recettes[7].Temps_OP110
L'indexage:
Notre soucis maintenant est de récupérer une recette quelconque depuis la banque et la transférer dans notre recette de travail.
Il faut commencer par déclarer cette recette de travail.
On doit la mettre dans un DB, parmis vos autres données par exemple. (je n'ai pas réussi à la mettre parmis les variables globales (les mémentos), l'éditeur de mnémoniques me refusant le type UDT pour un mémento ... toutefois on peut le faire mais sans y attribuer un mnémonique ... j'y reviendrais par la suite)
Il suffit de déclarer la variable de type UDTxx (xx=1 dans notre exemple)
Cette recette de travail a un emplacement bien connu, donc facile d'accès par programme.
Il nous faut maintenant une fonction de ce type :
Ou nous aurons en entrée, un numéro de DB qui est celui de la banque de recettes, un indice de recette souhaitée et un emplacement de destination qui est notre recette de travail.
Un code d'erreur en retour pour savoir si tout c'est bien passé.
Dans mon exemple, ma recette de travail a été créé dans un DB "Var Process"
Si on aurait voulu utiliser des mémentos, on aurait pu mettre ça en destination:
Code : Tout sélectionner
P#M100.0 BYTE 14
l'inconvenient c'est qu'on ne peut pas utiliser les mnémoniques, donc c'est pas propre .... à éviter
Reste à écrire cette fonction "Charger Recette".
L'utilisation du langage LIST est indispensable.
Et le fonctionnement des automates SIEMENS nous facilite pas la tache, car il faut manipuler des pointeurs, des variables de type ANY ... de quoi faire fuir les débutants
Préliminaires:
Cette partie apporte des détails pour la programmation d'une fonction de type "Charger Recette".
Vous n'avez pas besoin de connaitre ces détails pour l'utiliser. Vous pouvez considérer cette fonction comme une "boite noire".
Si vous etes curieux, lisez ce qui suit sinon passez directement à la partie suivante qui donne directement le code de la fonction.
Pour spécifier un emplacement de destination, il faut manipuler une variable de type ANY.
Le type ANY est une sorte de pointeur mais avec une indication de taille en plus.
Elle est utilisée notamment en paramètre pour la fonction SFC20 (BLKMOV) dont nous aurons besoin.
Le type ANY se décompose ainsi : (syntaxe du C )
Code : Tout sélectionner
struct ANY
{
BYTE id; // ID qui doit etre égal à B#16#10 pour dire que c'est un type ANY
BYTE unit; // unité de longueur: B#16#2 = octet / B#16#4 = mot
WORD length; // nombre d'unités pour la longueur
WORD dbindex; // numéro du DB (0 = mémoire globale = mémento)
DWORD pointer; // pointeur du type P#....
};
Dans notre fonction, nous allons utiliser la fonction systeme SFC20 (BLKMOV) pour copier notre recette d'un emplacement a un autre. Cette fonction prend deux types ANY en parametre. Le ANY en source et le ANY en destination.
Il faut donc que nous renseignons ces deux parametres. Pour la destination c'est facile, c'est une entrée de la fonction "Charger Recette". Mais pour la source, il va falloir faire du calcul.
Pour le ANY de la source:
id = B#16#10
unit = B#16#2 = on ne traite que les octets
length = on le récupère du ANY de la destination
dbindex = c'est un parametre d'entrée de la fonction "Charger recette"
pointeur = (Numéro recette-1) * taille recette (length) à convertir en pointeur
La fonction "Charger Recette":
Voici le source de la fonction "Charger Recette":
Code : Tout sélectionner
FUNCTION "Charger Recette" : VOID
TITLE =
VERSION : 0.1
VAR_INPUT
Numero_DB_Banque : INT ; //Numéro du DB ou se trouve la banque de recettes
Numero_Recette : INT ; //Numéro de la recette
Destination : ANY ; //Emplacement de destination
END_VAR
VAR_OUTPUT
Erreur : INT ; //Code d'erreur
END_VAR
VAR_TEMP
T_AR1 : DWORD ; //Sauvegarde de la valeur de AR1
T_AR2 : DWORD ; //Sauvegarde de la valeur de AR2
Source : ANY ; //Emplacement source
Dest : ANY ; //Emplacement destination
END_VAR
BEGIN
NETWORK
TITLE =
TAR1 #T_AR1; // sauvegarde de la valeur de AR1
TAR2 #T_AR2; // sauvegarde de la valeur de AR2
NETWORK
TITLE =Copie de la variable Destination vers Dest
L P##Destination;
LAR1 ; // AR1 = Destination
L B [AR1,P#1.0]; // type de variable ANY
L B#16#2; // type octet
==I ;
SPB copy; // on ne supporte que le type octet
L W#16#80FF; // code d'erreur
T #Erreur;
SPA fin; // fin de la fonction
copy: LAR2 P##Dest; // AR2 = Dest
L W [AR1,P#0.0];
T LW [AR2,P#0.0]; // 1er mot
L W [AR1,P#2.0];
T LW [AR2,P#2.0]; // 2eme mot
L W [AR1,P#4.0];
T LW [AR2,P#4.0]; // 3eme mot
L W [AR1,P#6.0];
T LW [AR2,P#6.0]; // 4eme mot
L W [AR1,P#8.0];
T LW [AR2,P#8.0]; // 5eme et dernier mot
NETWORK
TITLE =Création de la source
LAR1 P##Source; // AR1 = Source (AR2 = Dest)
L B#16#10;
T LB [AR1,P#0.0]; // ID pour dire que c'est un type ANY
L B#16#2;
T LB [AR1,P#1.0]; // transfert en octets
L LW [AR2,P#2.0];
T LW [AR1,P#2.0]; // nombre d'octets à tranférer
L #Numero_DB_Banque;
T LW [AR1,P#4.0]; // DB à adresser
L #Numero_Recette; // indice de la recette
L 1;
-D ; // car l'indice commence à 1 et non 0
L LW [AR2,P#2.0]; // taille d'une recette
*D ; // multiplication
SLD 3; // conversion en pointeur
L P#DBX 0.0;
+D ; // ajout de la base
T LD [AR1,P#6.0]; // pointeur
NETWORK
TITLE =Copie de données
CALL "BLKMOV" (
SRCBLK := #Source,
RET_VAL := #Erreur,
DSTBLK := #Dest);
NETWORK
TITLE =
fin: LAR1 #T_AR1; // restitution de la valeur de AR1
LAR2 #T_AR2; // restitution de la valeur de AR2
END_FUNCTION
Attention qd meme de mettre des valeurs correctes en parametre d'entrée
L'indice de recette doit etre supérieur ou égal à 1 (1 pour la premiere recette, 2 pour la seconde ...)
Le code d'erreur est =0 si tout c'est bien passé
Sinon réferez vous à la liste des codes d'erreur de la fonction SFC20.
Pour ceux qui ne savent pas integrer un source LIST, voici l'archive complete du tutoriel:
http://rapidshare.com/files/69452621/Tutoriel.zip.html
Il reste a voir comment faire pour modifier ces recettes depuis un pupitre par ex.
Ca sera un prochain post
@+