Een aparte pagina met uitleg en voorbeelden vind je HIER. In het engels, want deze pagina is de meest populaire die we hebben met dagelijks bezoeken vanuit alle uithoeken van de wereld.
U E 0.0
FP M 1.0
SPBN m001
UN A 4.0
= A 4.0
m001: NOP 0
Met dank aan Joop B uit Weert.
X(
U M 20.0 //of b.v een ingang
FP M 20.1 // flank positief merker
)
X M 20.2 // troggle merker of b.v. een uitgang.
= M 20.2
UN T 2
L S5T#500MS //pauzetijd
SE T 1 //puls
U T 1
L S5T#500MS //pulstijd
SE T 2
U T 1
= M 1.0 //puls pauze bitje. Kan natuurlijk ook gewoon T 1 gebruiken
Een 100 serie CPU van VIPA heeft twee potmeters in het front. Heel handig om te gebruiken in je programma om een timer mee in te stellen. De tijdbasisbitjes bepalen op de counts voor bv 0.01s, 0.1s, 1s of 1min is. Even proberen doet wonderen.
FUNCTION FC 1 : VOID
TITLE =
VERSION : 0.1
BEGIN
NETWORK
TITLE =
//S5T maken voor 0-1s
//potmeter 0 = PEW 128
//potmeter 1 = PEW 130
//MW 100:
//xxTT.1111.2222.3333 (S5 timer formaat)
//x = nvb
//TT = tijdbasis
//1111 = bcd 100-tal
//2222 = bcd 10-tal
//3333 = bcd 1-tal
L PEW 128; //potmeter laden
T MW 100; //en opslaan in mw100
L 999;
<I ; //controleren of niet te groot
SPB m001;
T MW 100; // anders 999 maken
m001: L MW 100;
ITB ; //bcd van maken
SRW 4; //4 schuiven (=delen door 10)
T MW 100; // anders timer tot 10s
R M 100.4; //tijdbasisbitje 0
R M 100.5; //tijdbasisbitje 1
END_FUNCTION
Uit een oud programma gemaakt om te testen. Later niet meer gecontroleerd.
opmerking: de gebruikte methode om te controleren of het een negatieve waarde is klopt wel. Het naderhand botweg terugzetten van dat bit is natuurlijk fout!
FUNCTION FC 103 : VOID
TITLE =
//Funtie FC103 haalt alle analoge inputs binnen en schrijft de waarden weg
//op de woorden beginnnend met het startadr_bit.
//bv:
//startadr_bit is M100.0
//dan staat val ch0 in mw100
// ch1 in mw102
// ch2 in mw104
// ch3 in mw106
// ch4 in mw108 (PT100)
VERSION : 0.1
VAR_OUTPUT
STARTADR_bit : BOOL ;
END_VAR
VAR_TEMP
WOORD : WORD ;
BIT : BOOL ;
ADR_PTR : DWORD ;
END_VAR
BEGIN
NETWORK
TITLE =
//Ch0..Ch3 kunnen gewoon direct uitgelezen worden.
//bereik loopt dan van pos/neg 0-27648 (0h-6c00h)
//pointer in adresregister 1 schrijven
L P##STARTADR_bit;
LAR1 ;
NETWORK
TITLE =
//ch 0
//
//teken bepalen
//kladbit is '1' als waarde
//negatief is.
L PEW 752;
UW W#16#8000;
T #WOORD;
//
L #WOORD;
L 0;
<>I ;
= #BIT;
//------------------------------
// waarde bepalen en wegschrijven
L PEW 752;
SLW 1;
SRW 5;
T W [AR1,P#0.0];
// sign terugzetten
U #BIT;
= [AR1,P#0.7];
NETWORK
TITLE =
//ch 1
//teken bepalen
//kladbit is '1' als waarde
//negatief is.
L PEW 754;
UW W#16#8000;
T #WOORD;
//
L #WOORD;
L 0;
<>I ;
= #BIT;
//------------------------------
// waarde bepalen en wegschrijven
L PEW 754;
SLW 1;
SRW 5;
T W [AR1,P#2.0];
// sign terugzetten
U #BIT;
= [AR1,P#2.7];
NETWORK
TITLE =
//ch 2
//teken bepalen
//kladbit is '1' als waarde
//negatief is.
L PEW 756;
UW W#16#8000;
T #WOORD;
//
L #WOORD;
L 0;
<>I ;
= #BIT;
//------------------------------
// waarde bepalen en wegschrijven
L PEW 756;
SLW 1;
SRW 5;
T W [AR1,P#4.0];
// sign terugzetten
U #BIT;
= [AR1,P#4.7];
NETWORK
TITLE =
//ch 3
//teken bepalen
//kladbit is '1' als waarde
//negatief is.
L PEW 758;
UW W#16#8000;
T #WOORD;
//
L #WOORD;
L 0;
<>I ;
= #BIT;
//------------------------------
// waarde bepalen en wegschrijven
L PEW 758;
SLW 1;
SRW 5;
T W [AR1,P#6.0];
// sign terugzetten
U #BIT;
= [AR1,P#6.7];
NETWORK
TITLE =
//ch4
//de weggeschreven waarde is te temperatuur in de
//eenheid zoals met step7 geconfigureerd in units
//van 0.1 graad of 0.1 Kelvin
//------------------------------
// waarde wegschrijven
L PEW 760;
T W [AR1,P#8.0];
END_FUNCTION
Een kort programma om meetwaardes te middelen, eigenlijk bedacht voor S5. Omdat S5 niet bekent staat om z'n geweldige floating point eigenschappen is dit een mooie oplossing van Peter. Uiteraard ook bruikbaar in S7. M 0.4 is een flank van bv een timer.
U M 0.4
SPBN NTEL
L MW 10 //> JOUW GEMETEN WAARDE VAN DE SENSOR
L MW 40
+I
T MW 40
NTEL: U M 0.4
ZV Z 1
L z 1
L 16
>=I
SPBN NGEM
SET
R Z 1
L MW 40
SRW 4
T MW 50 //>> GEMIDDELDE WAARDE OVER 16 METINGEN
L 0
T MW 40
NGEM: NOP 0
Op een machine een slagen/minuutteller dmv een sensor op een tandwiel. Niet zo fraai, werkt wel en iedereen snapt het. Ook belangrijk.
NETWORK
TITLE =snelheid
//os'en tellen
U E 1.7; telingang
UN M 10.5; hulpbit
= M 10.4; one shot opgaande flank
U E 1.7; telingang
= M 10.5; hulpbit
//
UN E 1.7; telingang
UN M 10.7; hulpbit
= M 10.6; one shot neergaande flank
UN E 1.7; telingang
= M 10.7; hulpbit
//
//door gebruik te maken van op- en neergaande flank
//verhogen we het "oplossend" vermogen van de teller
//
UN M 10.4; one shot opgaande flank
UN M 10.6; one shot neergaande flank
SPB m004;
L DB100.DBW 12; telregister
+ 1;
T DB100.DBW 12; telregister
//
//uitrekenen snelheid
//afhankelijk van aantal telnokken en tijdbasis (m10.0)
//
m004: UN M 10.0; one shot (1x per seconde)
SPB m005;
L DB100.DBW 12; telregister
L 2;
*D ;
T DB100.DBW 10; snelheid
//
//telregister terug op nul zetten
L 0;
T DB100.DBW 12;
//
//einde sprong en laadistructie voor debugging
m005: L DB100.DBW 10;
FUNCTION FC 101 : VOID
TITLE =
//Bouwsteen is alleen getest op CPU 313 C
//Ch0..Ch3 loopt van 27648 tot -27648 (6C00h..9400h)normaal.
//Ch4 hoeft niet bewerkt te worden: hierin staat de waarde in
//graden C/F of Kelvin, in units van 0,1 graad of Kelvin.
AUTHOR : DREIJER
VERSION : 0.1
VAR_INPUT
IN_ADR : WORD ;
MAXVAL : INT ;
ZEROVAL : INT ;
END_VAR
VAR_OUTPUT
ANA_OUT : WORD ;
ERROR : BOOL ;
END_VAR
VAR_TEMP
FACTOR : WORD ;
SHIFT : WORD ;
RANGE : WORD ;
END_VAR
BEGIN
NETWORK
TITLE =unipolair
//aantal delen uitrekenen
L #MAXVAL;
L #ZEROVAL;
-I ;
T #RANGE;
//
//verhouding input/output
L 27648;
L #RANGE;
/I ;
T #FACTOR;
L #ZEROVAL;
T #SHIFT;
//
//input in pointer zetten
// L #ANA_ADR
// T #INREG
//
//output berekenen
// L PEW [#INREG]
L #IN_ADR;
L #FACTOR;
*I ;
L #SHIFT;
-I ;
T #ANA_OUT;
END_FUNCTION
De beste manier om een hoek te bepalen is niet met een binair gecodeerde encoder maar met grey code, dit omdat er per overgang maar 1 bit tegelijk veranderd. Omzetten van grey naar binair kan met onderstaande code. Normaal gezien geeft dit een afwijking: de greycode uit een encoder is meest „gekapte grey” om ervoor te zorgen dat er bij de overgang naar 0 graden ook maar 1 bit veranderd. Dit is een vaste offset die hier in het programma eenvoudig bijgeprogrammeerd kan worden natuurlijk.
Het voorbeeld is 4 bits, te weinig in de meeste gevallen, uitbreiding is echter wel heel erg simpel.
U #grey_3 = #bin_3 U #grey_2 UN #bin_3 O UN #grey_2 U #bin_3 = #bin_2 U #grey_1 UN #bin_2 O UN #grey_1 U #bin_2 = #bin_1 U #grey_0 UN #bin_1 O UN #grey_0 U #bin_1 = #bin_0
omschrijving
Datum en tijd gebruiken in een 300.
niet gecontroleerd!
FUNCTION FC 6 : VOID TITLE = VERSION : 0.1 VAR_TEMP Datum_Tijd : DATE_AND_TIME ; RV : INT ; Datum_Tijd_Nieuw : DATE_AND_TIME ; Fout_SFC : INT ; END_VAR BEGIN NETWORK TITLE = Lezen klok CALL SFC 1 ( RET_VAL := #RV, CDT := #Datum_Tijd); NOP 0; NETWORK TITLE = tijd naar integer L LB 3; BTI ; L 100; *I ; L LB 4; BTI ; +I ; T MW 28; NETWORK TITLE = Dag bepalen L LW 6; L W#16#F; UW ; T MB 27; NETWORK TITLE = U( ; L MW 28; L 300; >=I ; ) ; U( ; L MW 28; L 500; <I ; ) ; = M 50.0; NETWORK TITLE = U( ; L MW 28; L 715; >=I ; ) ; U( ; L MW 28; L 1230; <I ; ) ; = M 50.1; NETWORK TITLE = U( ; L MW 28; L 1346; >=I ; ) ; U( ; L MW 28; L 1711; <I ; ) ; = M 50.2; NETWORK TITLE = U( ; L MW 28; L 2200; >=I ; ) ; U( ; L MW 28; L 2300; <I ; ) ; = M 50.3; END_FUNCTION
Unidrive settings staan in FC 80
Saven van de configuratie in de unidrive, erg belangrijk:
1. Save Menu 1 through Menu 19 by setting #x.00 = 1000 and press the red ”reset” button on the Unidrive.
2. Save the Menu 20 values by setting #17.19 = 1 (resets itself back to zero).
3. Activate this configuration by setting #x.00 = 1070 and press the red ”reset” button on the Unidrive.
Hier word vooral punt 2 nogal eens vergeten!
DATA_BLOCK DB 80
TITLE =
VERSION : 0.1
STRUCT
Schrijf_naar_ct_1620 : DWORD ;
Schrijf_naar_ct_1621 : DWORD ;
Schrijf_naar_ct_1622 : DWORD ;
Schrijf_naar_ct_1623 : DWORD ;
Schrijf_naar_ct_1624 : DWORD ;
Schrijf_naar_ct_1625 : DWORD ;
Schrijf_naar_ct_1626 : DWORD ;
Schrijf_naar_ct_1627 : DWORD ;
Lees_vanaf_ct_1620 : DWORD ;
Lees_vanaf_ct_1621 : DWORD ;
Lees_vanaf_ct_1622 : DWORD ;
Lees_vanaf_ct_1623 : DWORD ;
Lees_vanaf_ct_1624 : DWORD ;
Lees_vanaf_ct_1625 : DWORD ;
Lees_vanaf_ct_1626 : DWORD ;
Lees_vanaf_ct_1627 : DWORD ;
END_STRUCT ;
BEGIN
Schrijf_naar_ct_1620 := DW#16#0;
Schrijf_naar_ct_1621 := DW#16#0;
Schrijf_naar_ct_1622 := DW#16#0;
Schrijf_naar_ct_1623 := DW#16#0;
Schrijf_naar_ct_1624 := DW#16#0;
Schrijf_naar_ct_1625 := DW#16#0;
Schrijf_naar_ct_1626 := DW#16#0;
Schrijf_naar_ct_1627 := DW#16#0;
Lees_vanaf_ct_1620 := DW#16#0;
Lees_vanaf_ct_1621 := DW#16#0;
Lees_vanaf_ct_1622 := DW#16#0;
Lees_vanaf_ct_1623 := DW#16#0;
Lees_vanaf_ct_1624 := DW#16#0;
Lees_vanaf_ct_1625 := DW#16#0;
Lees_vanaf_ct_1626 := DW#16#0;
Lees_vanaf_ct_1627 := DW#16#0;
END_DATA_BLOCK
FUNCTION FC 80 : VOID
TITLE =
//Setting CT memorygroup 16 SP Unidrive
//
//01 = 403
//02 = 3.00
//03 = 11 (profibusadres)
//04 = 5
//05 = 16
//06 = 157
//07 = 200
//08 = OFF
//09 = ON
//10 t/m 19 = leesdata
//20 t/m 29 = schrijfdata
//30 = OFF
//31 = Off
//32 = OFF
//33 = OFF
//34 = OFF
//35 = 9158049 (versienummer)
//36 = OFF
//37 = OFF
//38 = 0
//39 = 16
//40 = 16
//41 = 0
//42 = 0
//43 = 0
//44 = 0
//45 = 0
//46 = 0
//47 = 0
//48 = 0
//49 = 0
//50 = 0
//51 = 0
//
//Na wijziging eerst 16.00 op 1000 zetten en daarna de rode knop bedienen.
//Na wijziging eerst 16.00 op 1070 zetten en daarna de rode knop bedienen.
//
//CT data via DB 80
VERSION : 0.1
BEGIN
NETWORK
TITLE =
//DB 80 koppelen aan CT-data
//SCHRIJVEN NAAR CT
//Ct adres 16.20
L DB80.DBD 0;
T AD 80;
//Ct adres 16.21
L DB80.DBD 4;
T AD 84;
//Ct adres 16.22
L DB80.DBD 8;
T AD 88;
//Ct adres 16.23
L DB80.DBD 12;
T AD 92;
//Ct adres 16.24
L DB80.DBD 16;
T AD 96;
//Ct adres 16.25
L DB80.DBD 20;
T AD 100;
//Ct adres 16.26
L DB80.DBD 24;
T AD 104;
//Ct adres 16.27
L DB80.DBD 28;
T AD 108;
//LEZEN VANAF CT
//Ct adres 16.10
L ED 80;
T DB80.DBD 32;
//Ct adres 16.11
L ED 84;
T DB80.DBD 36;
//Ct adres 16.12
L ED 88;
T DB80.DBD 40;
//Ct adres 16.13
L ED 92;
T DB80.DBD 44;
//Ct adres 16.14
L ED 96;
T DB80.DBD 48;
//Ct adres 16.15
L ED 100;
T DB80.DBD 52;
//Ct adres 16.16
L ED 104;
T DB80.DBD 56;
//Ct adres 16.17
L ED 108;
T DB80.DBD 60;
END_FUNCTION
omschrijving
FUNCTION FC 10 : VOID
TITLE =
VERSION : 0.1
VAR_INPUT
Sorteer_DB : BLOCK_DB ;
DB_lengte : WORD ;
END_VAR
VAR_TEMP
kladvariabele : WORD ;
teller : WORD ;
klaar : BOOL ;
END_VAR
BEGIN
NETWORK
TITLE =
AUF #Sorteer_DB;
M002: LAR1 P#DBX 0.0;
SET ;
S #klaar;
L #DB_lengte;
L 1;
-I ;
Lus: T #teller;
L W [AR1,P#0.0];
L W [AR1,P#2.0];
<=I ;
SPB M003;
L W [AR1,P#0.0];
T #kladvariabele;
L W [AR1,P#2.0];
T W [AR1,P#0.0];
L #kladvariabele;
T W [AR1,P#2.0];
SET ;
R #klaar;
M003: TAR1 ;
L 16;
+D ;
LAR1 ;
L #teller;
LOOP Lus;
UN #klaar;
SPB M002;
BE ;
END_FUNCTION
Een eenvoudige PID regeling. Getest op een 500W sealbek van een verpakkingsmachine. De bouwsteen is nog niet helemaal voltooid (zie onderin) Bij de variabelen declaraties staan tussen de []haakjes voorbeelden van geldige invoeren, tussen {}haakjes de gebruikte eenheden. Er zitten per ongeluk enkele commentaren in het Nederlands tussen.
FUNCTION_BLOCK FB 2
TITLE =
VERSION : 0.1
VAR_INPUT
procesval : INT ; //proces value [MW202]{1/10deg}
setpoint : INT ; //setpoint [MW200][1200]{1/10deg}
GAIN : REAL ; //gain [1.5]
RESETRATE : REAL ; //resetrate [0.1]
DERIVATIVE : REAL ; //derivative [40.0]
direct : BOOL ; //0 for heating [FALSE]
auto : BOOL ; //auto [M100.0][TRUE]
tim : TIMER ; //cycle timer [T100]
cycl : S5TIME ;
END_VAR
VAR_OUTPUT
Output : INT ; //output for PWM [MW20]{1/10%}
Err_D : INT ; //for adjusting [MW22]
END_VAR
VAR
PVD : REAL ;
PVLAST : REAL ;
ERR : REAL ;
FEEDBACK : REAL ;
temp_cycl : BOOL ;
END_VAR
VAR_TEMP
OUTTEMP : REAL ;
PV : REAL ;
SP : REAL ;
TEMP0 : BOOL ;
out_conv : DINT ;
END_VAR
BEGIN
NETWORK
TITLE =
// timer voor de cyclustijd
UN #temp_cycl;
L #cycl;
SE #tim;
U #tim;
= #temp_cycl;
UN #temp_cycl;
SPB eind;
NETWORK
TITLE =
L #procesval;
ITD ;
DTR ;
T #PV;
L #setpoint;
ITD ;
DTR ;
T #SP;
NETWORK
TITLE =
//1. IF AUTO = true THEN
U #auto;
SPBN auto;
//2. PV_D = PV +(PV - PV_last) * Derivative
L #PV;
L #PVLAST;
-R ;
L #DERIVATIVE;
*R ;
L #PV;
+R ;
T #PVD;
//3. PV_last = PV
L #PV;
T #PVLAST;
//4. ERR = SP - PV_D
L #SP;
L #PVD;
-R ;
T #ERR;
//5. IF Direct = true THEN Err =0 Err //Change sign if direct.
U #direct;
SPBN dir;
L 0;
L #ERR;
-R ;
T #ERR;
//6. ENDIF
dir: NOP 0;
//ERR naar buiten brengen voor afregelen
L #ERR;
RND ;
T #Err_D;
//7. out_temp = Err * Gain + Feedb //Calc gain time the error and add
// the feedback.
L #ERR;
L #GAIN;
*R ;
L #FEEDBACK;
+R ;
T #OUTTEMP;
//8. IF Out_Temp > 100 THEN Out_Temp =100 //Limit output
L #OUTTEMP;
L 1.000000e+003;
>R ;
SPBN gr;
T #OUTTEMP;
gr: NOP 0;
//9. IF Out_Temp < 0 THEN Out_Temp =0 // 0 and 100 percent.
L #OUTTEMP;
L 0;
<R ;
SPBN kl;
T #OUTTEMP;
kl: NOP 0;
//10. Out = Out_Temp // The final output
L #OUTTEMP;
RND ;
T #out_conv;
T #Output;
//11. Feedback = Feedback +(Out - Feedback) * ResetRate
L #OUTTEMP;
L #FEEDBACK;
-R ;
L #RESETRATE;
*R ;
L #FEEDBACK;
+R ;
T #FEEDBACK;
//12. ELSE
auto: NOP 0;
//------------------------------moet nog
//13. PV_last = PV //While loop in manual, stay ready for bumpless switch
// to Auto.
//14. Feedback = Out
//15. ENDIF
eind: NOP 0;
END_FUNCTION_BLOCK
Een grove PWM, niet volmaakt, maar werkend getest op bovenstaande PID
FUNCTION_BLOCK FB 3
TITLE =
VERSION : 0.1
VAR_INPUT
input : INT ; //PWM value[MW20][450]{1/10%}
t_pulse : TIMER ; //pulse timer [T20]
t_pause : TIMER ; //pause timer [T21]
END_VAR
VAR_OUTPUT
output : BOOL ; //output [M24.0]
END_VAR
VAR
pulse : S5TIME ;
pause : S5TIME ;
END_VAR
BEGIN
NETWORK
TITLE =
L #input;
L 10;
/I ;
ITB ;
T #pulse;
L 1000;
L #input;
-I ;
L 10;
/I ;
ITB ;
T #pause;
UN #t_pause;
L #pause;
SE #t_pulse;
U #t_pulse;
L #pulse;
SE #t_pause;
U #t_pulse;
= #output;
END_FUNCTION_BLOCK
omschrijving
code