Upload
others
View
2
Download
0
Embed Size (px)
Citation preview
Introduction partie 2
LabVIEW
ME 2e semestre
rev. 15.1
Christophe Salzmann���
Phot
o M
artin
Klim
as
Instrument virtuel
• Mimic un instrument réel
Front panel - diagram - connector pane 3
3 parties d'un VI
double function C2F (double deg_cel)
{ return deg_cel * 1.8 + 32;
}
4
Front panel
Diagram
Connector Pane
C2F.vi
Programmation
• LabVIEW se programme en liant des icones représentant des fonctions
• Les fils reliant les icones représentent les données
• L'ordre d'exécution est défini par la disponibilité des données à l'entrée d'une fonction
• Les éléments de l'interface utilisateur sont des contrôles et des indicateurs
• Les données "coulent" des contrôles vers les indicateurs
5
Flot de données et bloc
Une structure (loop, sequence, case, etc.) est l'équivalent d'un bloc { } en c:
Elle défini la portée (scope). Les données entrantes sont comme copiées dans des variables temporaires, et les données sortantes sont copiées depuis des variables internes temporaires.
temp. var.! Internal temp. var.!
A!
B!
C!D!
E!
int tmpA = A;
int tmpB = B;
int tmpC = n/a;
do {
E = D * tmpA;
tmpC = E + i;
} while (!tmpB);
C = tmpC;
6
Flot de données
LabVIEW va generer une erreur si vous essayez de connecter une sortie sur une entrée, Pourquoi ?
Causalité
Vous ne pouvez pas employer des données résultant d'un calcul courant pour effectuer ce calcul, i.e. vous ne pouvez pas mélanger des donnés courantes avec des données du futur!
7
Dataflow
LabVIEW utilise un feedback node pour décaler les données dans le temps d'une itération
Feedback node!
8
out (k)!
out (k-1)!
Les shifts registers permettent de mémoriser les données dans le temps
out (k)!
out (k-1)!
G data types • La couleur défini le type • L'épaisseur du trait défini les dimensions • Un point rouge indique une conversion automatique • Les conversions sont différentes du C/C++ , elles suivent la norme IEEE 754 • Une conversion de type peut être forcée
2.5 -> 2 3.5 -> 4
9
Rounding to the nearest Even integer: Pour les nombres qui sont exactement à mi-chemin entre deux entiers comme par ex. 2.5, 3.5, etc. ils sont arrondis à l'entier pair le plus proche. (pour évitez les erreurs systématiques) ex. 2.5 -> entier pair le plus proche -> 2 3.5 -> entier pair le plus proche -> 4
automatic conversion
G types – Tableau array
Tableau (Array) -> structure contenant des éléments du même type
• Arrays à plusieurs dimension (≤ 64) • Arrays de n'importe quels types composés • Arrays sont dynamiques, leur taille peut être
changée automatiquement durant l'exécution • La largeur des ‘[]’ indique sur les dimensions du
tableau • Ils existe un grand nombre de fonctions prédéfinies
travaillant sur les tableaux, ex. algèbre linéaire
Bool[];
long[];
long[][];
long[][][];
float[][][][][]..
struct[];
Str[];
waveform;
matrix; array indexes
array element
10
Array[0][0] = 1
G data types - cluster
Cluster-> structure avec des éléments de types différents
• Equivalent des struct en C/C++ • Le nombre d'éléments des clusters est fixe • La couleur des clusters indique si les éléments sont
de taille fixe (brun) ou non (rose) • Il est possible de mettre un Cluster dans un Cluster • Les éléments (champs) du Cluster peuvent être
accédés par leur nom (recommendé) ou leur position
struct {
double f;
char[] s;
bool b;
} c;
c.f = c.f + 0.5;
11
G - structures
for (i=0;i<N;i++) { } i:=0;
do { } while (cond; i++) switch(cond) { case: break; default } Sequence1;
#ifdef cond #endif Formula node
Mathscript node Event node
12
Exécute le contenu un nombre de fois donné • de 0 à9 ( - 1)
L'exécution peut être stopée (≥ LV 8.6) • Arrêt si est vrai
Boucle - for
for (i=0;i<N;i++)
{
…
}
…
…
for (i=0;i<N;i++)
{
…
if () break;
}
13
Exécute le contenu un nombre de fois donné i va de 0 à 9 Le dernier i (last i) vaut 9
Boucle - for
N=10;
for (i=0;i<N;i++)
{
i;
}
last_i = i;
14
0 1 9
9
Auto indexing La boucle for sauve en interne toutes les valeurs de i i va de 0 à 9 Le dernier i (last i) vaut 9 all_i = [0,1,2,3,4,5,6,7,8,9]
Boucle - indexing
N=10;
for (i=0;i<N;i++)
{
i;
all_i[i]=i;
}
last_i = i;
15
0 1
0 1 9
9 …
Auto indexing • nombre d'itérations definie par la taille du tableau d'entrée (in:3)
• auto indexing • no auto-indexing
• Accède au ième élément du tableau d'entrée
• out[] = {1, 2, 3} • e = 3 • = 2, = 3
Boucle – auto-indexing
for(i=0;
i<sizeof(in[]);
i++)
{
out[i] = in[i];
e = in[i];
}
16
1 2 3 1 2 3
1 2 3
Exécute le contenu jusqu'à ce que la condition soit valide (v ou F) • va de 0 à 3
• La boucle s'arrête après 4 itérations {0,1,2,3}
Loops - while
i = 0;
do {
…
}
while(!(3==i); i++);
…
17
Exécute le contenu jusqu'a ce que la condition soit atteinte • La boucle while est exécutée 7 fois • 5 < i est vrai quand i = 6 • va de 0 à 6
• out[] = {0,1,2,3,4,5,6}
Loops - while
i = 0;
do {
out[i]= i;
}
while(5 < i; i++);
18
Les fils sont évalués à l'entrée de la boucle, l'intérieur de la boucle est similaire à un bloc en c
• Stop1 est évalué une fois avant l'entrée dans la boucle • Stop2 est évalué à chaque itérations de la boucle
• La boucle s'arrête après une itérations si Stop1 est False • Si Stop1 est True, la boucle s'arrête quand Stop2 est False
Loops - while
tmp = Stop1;
do {
...
}
while( tmp & Stop2 );
19
Internal temp. var.!
Dataflow & Shift register
J!
int tmpJ_k_1 = 0; // default
// tmpJ_k_2 = 0;
int tmpJ, J, Stop;
do {
J = tmpJ_k_1;
tmpJ = i;
tmpJ_k_1 = tmpJ;
} while (!Stop);
tmp(k-1)! tmp(k)!
default!when k=0
J = 0,0,1,2,3, ...
Les shift registers sont des variables dépendantes du temps qui mémorisent la (les) valeur(s) précédente(s)
20
tmpL(k-1)!
Dataflow & Shift register
Si aucune valeur par défaut n'est définie (connectée) la dernière valeur est utilisée
L!
tmpL(k)!
NO default! =>!keep the value of the previous run!
L = 1
L = 2
double tmpL_k_1; // NO default
double tmpL, L;
do {
L = tmpL_k_1 + 1;
tmpL = L;
tmpL_k_1 = tmpL;
} while (!Stop);
L = 3
21
Shift registers (registres à décalage) • fixe la valeur pour l'itération i • récupère la valeur de l'itération i-1
Boucle – Shift register
for(i=0;
i<sizeof(in[]);
i++)
{
if (i==0)
out[i] = -1;
else
out[i] = in[i-1];
}
22
out[] = {-1, 1, 2}
• Les shift registers (registres à décalage) permettent de mémoriser les valeurs entre les itérations, c'est comme une variable locale
• S'ils ne sont pas initialisés, il garde la valeur de la dernière exécution ceci tant qu'ils restent en mémoire
• Ils peuvent être agrandis pour récupérer les k-n valeurs de la variable
Shift registers
i = 0;
do {
sr1[i]=sr1[i-1]+1;
if (i==0)
sr2[i] = 0;
else
sr2[i]=sr2[i-1]+1;
if (i<=2)
A[i]= 0;
else
A[i]=sr2[i-2];
}
while(i < 5; i++);
23
A[] = {0, 0, 0, 1, 2, 3, 4} 1st iteration
sr1 = 7 sr2 = 7
2nd iteration sr1 = 14 sr2 = 7
• Si la condition est True passer la valeur connectée à T
sinon passer la valeur connectée à F
• Si x vaut 5 -> S = “x is 5”, sinon S =“x different than 5”
Conditional - if
if (x==5)
S = “x is 5”;
else
S = “x different
than 5”;
24
• Les case structures sont similaires au switch en C/C++ • indique que tous les cas sont définis • indique que certains cas ne sont pas définis et que la valeur par défaut sera utilisée
• S= “one” quand x==1, and S=“default” pour toutes les autres valeurs de x • out = -1 or 0
Conditional - case
out = -1; //default val.
switch (x)
case 1:
S=“one”;
break;
case 0:
default:
S = “default”;
out = -1;
25
• Le type du case s'adapte automatiquement au format du fil connecté • Les cas (cases) peuvent contenir des intervalles avec “..” ou séparé par
des “,” • Chaque case exécute un bloc de code spécifique
• Quand x vaut [2,5,6,7,8,9,10] S= “2,5,6,7,8,9,10” out = x+1
Conditional - case
out = -1; //default val.
switch (x)
..<skipped>..
case 2:
case 5..10:
S = “2,5,6,7,8, \
9,10” ”;
out = x+1;
break
26
• Il est possible de forcer l'ordre d'exécution de LabVIEW à l'aide de séquences
• A éviter, car cela enlève à LabVIEW la possibilité de générer de code performant!
• Usage principal: mesure du temps d'exécution
• Dans l'exemple ci-dessus d = 4 [ms] sur un Mac
Sequence
t1=millisec();
for (i=0;i<1000000;i++)
sin(i)
t2=millisec();
d= t2 – t1;
27
• Les Flat sequences peuvent être empilées • Les résultat intermédiaires peuvent être sauvés dans des variables locales
Sequence
t1=millisec();
for (i=0;i<1000000;i++)
sin(i)
t2=millisec();
d= t2 – t1;
28
• Permet de définir un calcul sous la forme de texte • Expression node: une seule ligne de calcul • Formula node: lignes multiple, code proche du C
Expression/Formula node
DegF = DegC * 1.8 + 32;
expression node
formula node
29
• La syntaxe très proche du C • Le code est compilé et exécuté en un bloc • Le code ne peut pas être changé durant l'exécution, employer la toolbox
Gmath si vous avez besoin de changer votre code
• A=[1, 3, 2] with n=3 • S^2 = 36 • max=3
Formula node
int32 A[]={1, 3, 2};
int32 n= sizeof(A);
int32 tmp=0;
int32 i;
Max =0;
for (i=0;i<n;i++){
tmp+=A[i];
if (A[i]>Max)
Max = A[i];
}
S2=tmp*tmp;
S^2 = S2;
max = Max;
30
Virtual Instrument (VI)
• Le VI principal n'a rien de connecté sur le connector pane
• Les sous-VI (i.e. généralement des VI avec connector pane connecté) sont comme des fonctions en C.
- Des valeurs par défaut sont utilisées si rien n'est connecté, la connexion peut être rendue obligatoire
• Dans le diagram les VI sont identifiés via leur icône -> définir un icône représentatif de la fonction
• Les VIs sont identifié par leur noms (et chemin/path)
- Pour LabVIEW deux VIs avec le même nom sont "identiques"
- LabVIEW cherche sur votre disque les VIs manquants
- LabVIEW vous informe si le chemin/path de votre Vis à changé
31
Tableau array
Tableau (Array) -> structure contenant des éléments du même type
32
2D array
1D array
5D array
Tableau vide 0 est grisé 1 visible
Tableau vide 0s sont grisés 4 visibles
3 éléments 1 vide 4 visibles
Array functions
Initialize arrays
const dbl cst_array[2][3] =
{{1,2,3} , {4,5,6}};
dbl dbl_array [2][3] =
{{-1,-1,-1},{-1,-1,-1}};
dbl rnd_array[][];
for (r=0; r<2; r++)
for (c=0;c<3;c++)
rand_array[r][c]=rand();
33
How big an array ?
100’000’000 pts x 8 Bytes ~ 800 MBytes
• Utilisez quand c'est possible des primitives in-place qui ne travaillent directement sur les tableaux sans les copier • Check the Buffer Allocations, Tools»Profile»Show Buffer Allocations
34
Array functions
Les tableaux LabVIEW connaissent leur(s) taille(s) int A1[3] = {1,2,3};
elem = ArraySize(A1);
int A2[3] = {{1,2,3},
{4,5,6}};
row = Get(ArraySize(A2),0);
Colum = Get(ArraySize(A2),1);
int A3[3] = {1,2,3};
elem = ArraySize(A3);
A4= BuildArray(A3,4);
elem_1 = ArraySize(A4);
Les tableaux LabVIEW sont dynamiques
A4
A3
A2
A1
Build array 35
Array functions
int Array[6] = {{1,2,3},
{4,5,6}};
A = GetSubArray(Array,def,all,
1,3);
B = GetIndexArray(Array, 1, all);
e = GetIndexElem(Array, 1, 2);
f = GetIndexElem(Array, def, 2);
Accès aux éléments du tableau équivalent aux [ ] en c
grow
Unconnected inputs are set to default (see help window for default values)
B[]={4,5,6}
e = 6
f = 0
A[]={{2,3}, {5,6}}
0
1 3
36
Array functions
int Array[4] = {1,2,3,4};
Delete(Array,2,1,C,D);
Insert(C,1,9.0,E);
Replace(E,0,8.0,F);
Replace(F,3,7.0,F);
C[] = {1,4} D[] = {2,3} E[] = {1,9,4} F[] = {8,9,4}
delete
insert
replace
Delete/insert/replace array elements
37
Array functions
double Pos[] = {};
double Neg[] = {};
double _A[];
for (i=0; r<1000; i++)
_A[i]=rand() * 2 - 1;
for (j=0; j<size(_A),j++) {
if (_A[j]≥ 0)
AppendArray(Pos, _A[j]);
else
AppendArray(Neg, _A[j]);
Ex: sort in 2 arrays positive from negative values
_A[]
38
Array functions
double A[100];
double B[100];
double Neg[], Pos[];
Double T=0;
int i;
GenRand(100, &A);
Sort(A, &B);
for (i=0, i<SizeArray(B), i++){
if (B[i]<T) && (B[i+1]>=T))
break;
i++;
}
Split(B, i, &Neg, &Pos);
Ex: sort positive from negative values, alternative solution
39
Strings
typedef struct LVString {
long size;
char[] string;
}
• Les strings LabVIEW sont comme des string en c.
• Les strings peuvent être redimensionnée dynaminquement, LabVIEW se charge de la gestion de la mémoire, elles ont une taille limites de 232 ~4Millard de chars
• Les strings LabVIEW connaissent leur taille
• Un caractère est une string d'un élément, un caratère peut être représenté comme un unsigned 8bits Integer ou [U8].
• Les strings peuvent être employées comme des streams de bytes
40
String functions
String S[] = '\r';
String S[] = 'Hello World';
UInt8 A[] = {1,2,4,3};
String S[] = (String)A;
array of Bytes
A
normal
'\' code
password
hexadecimal
Initialize Strings
Display formats
41
String functions
Length = sizeof("Hello World");
S = S + "Hello " + "World";
strcat(S,"Hello ");
strcat(S,"World");
Length = 11
S = "Hello World"
S = "lo Wo"
S1 = "Hello"
S2 = "World"
S = "Hello World"
String Length!
Concatenate!
String Subset!
Match Pattern!
Search & Replace!
space
return 42
spaceß
S = StrSubset("Hello World",3,5);
S[2] = SplitStr("Hello World","\s");
S = ReplaceStr("Hello World","\s","\r");
String functions
sprintf(S,"Result :%d, %6f",
135,32.089);
S = "Result : 135, 32.089000"
Right – click la fonction Format into String pour éditer précisément le format de la conversion
String format will be automatically added to the node
Format Into String!
43
String functions
cin >> D >> S >> B >> I;
If (cin.fail()) ...
sscanf(S,"%f %[ A-Za-z] %s %d",
&D, S, &B, &i);
Error = "Scan From String (arg 4) in Strings.vi"
D = 3.14
S = "is pi"
B = FALSE
I = 0
Default values
Use %s for a single string (no delimiter like \s, \r, etc) otherwise specify the allowed characters in [], in the above example [\s A-Za-z]
'\s'
Error because the last two elements are inverted
Scan from String!
44
Right – click la fonction Format into String pour éditer précisément le format de la conversion
String functions
Double A = {{4.3, 5.6} {1.8, 2.2}};
String F = "%.3f";
S = ArrayToSpreadSheetStr(A,F);
String S = "4.3, 5.6\r1.8,2.2";
String F = "%d";
String D = ',';
A = SpreadSheetStrToArray(S,F,D);
S = "4.300 5.600
1.800 2.200"
A = {{ 4 6 }
{ 2 2 }}
delimiter!format!
format!
%d -> convert into integer
%.3f -> double with 3 digits after '.'
Array to Spreadsheet String!
Spreadsheet String to Array!
45
String functions
String LS = "long blabla before the interesting part that needs to be removed first!!\rtime: 12.1.2012 - 15:13\rc: green\ri: 123" MatchPattern(LS, "time:\s", NULL,NULL,After); MatchPattern(After, "c:\s", S,NULL,After2); MatchPattern(After2, "i:\s", C,NULL,After3); B = (C=="green");
atoi(After3,I)
S = "12.1.21012 -15:13"
Example of string parsing
Decimal String to number!
C = "green"
B = TRUE
I = 123
46
String functions
// -- c++ version -- string LS = "long blabla before the interesting part that needs to be removed first!!\rtime: 12.1.2012 - 15:13\rc: green\ri: 123" int P, I, B; string T,S,C; P = LS.find("time: "); T = LS.substr(P + 6,LS.size());
P = T.find("c: "); S = T.substr(0,P); T = T.substr(P + 3,T.size());
P = T.find("i: "); C = T.substr(0,P);
B = C.compare(0,5,"green"); T = T.substr(P+3,T.size());
I =atoi(T.c_str());
S = "12.1.21012 -15:13"
Example of string parsing
Decimal String to number!
C = "green"
B = TRUE
I = 123
47
Talking to the Unix OS
• System Exec fourni un accès aux fonctions de l'OS
• L'effet est similaire à l'entrée de commandes dans le terminal/CMD
• Les sorties standard (cout) et d'error (cerr) sont retournées
Standard result"
Standard error"
Applications Developer Library Network System Users … private sbin tmp usr var
48 Note: on Windows, prepend 'cmd /c to you call, ex: 'cmd /c dir C:'
Talking to the Unix OS
// -- myPrg.c --
#include <iostream>
using namespace std
int main (int argc, char* const argv[])
{
cout << "argv[1]: '"<<argv[1]<<"'\n";
cerr << "no error!\n";
return 0;
}
> cd my/vi/path
> ./myPrg 123
argv[1]: 123
no error!
>
argv[1]: 123
no error!
The VI directory"
Launch a program called "myPrg" with '123' as parameter.
The program and the calling VI are located in the same directory.
49