summaryrefslogtreecommitdiff
path: root/exp/FB_INC_DECODER.EXP
diff options
context:
space:
mode:
authorpux <pux@pux.dom>2021-01-07 19:39:17 +0100
committerpux <pux@pux.dom>2021-01-07 19:39:17 +0100
commit39765e002e71a2dd54e932469877acfc1b6fcb67 (patch)
tree83456425ad35e8c47894dee6660bd9ed574ebfdd /exp/FB_INC_DECODER.EXP
parentbbbba6c698a73fc1a6bd00f7a07c89ba19ce38c5 (diff)
downloadlib61131aux-39765e002e71a2dd54e932469877acfc1b6fcb67.tar.gz
lib61131aux-39765e002e71a2dd54e932469877acfc1b6fcb67.tar.bz2
lib61131aux-39765e002e71a2dd54e932469877acfc1b6fcb67.zip
add *.exp; (this is redundant information, just to be able to diff later on)HEADmaster
Diffstat (limited to 'exp/FB_INC_DECODER.EXP')
-rw-r--r--exp/FB_INC_DECODER.EXP133
1 files changed, 133 insertions, 0 deletions
diff --git a/exp/FB_INC_DECODER.EXP b/exp/FB_INC_DECODER.EXP
new file mode 100644
index 0000000..2433c18
--- /dev/null
+++ b/exp/FB_INC_DECODER.EXP
@@ -0,0 +1,133 @@
+
+(* @NESTEDCOMMENTS := 'Yes' *)
+(* @PATH := '' *)
+(* @OBJECTFLAGS := '0, 8' *)
+(* @SYMFILEFLAGS := '2048' *)
+FUNCTION_BLOCK FB_INC_DECODER
+VAR_INPUT
+ IN_xChA : BOOL; (* Channel A *)
+ IN_xChB : BOOL; (* Channel B, 90-degree rotated to Channel A *)
+ IN_xReset : BOOL; (* Reset counter to 0 *)
+
+ IN_xEnPosWindow : BOOL; (* TRUE if you want to overflow the counting at min/max values below *)
+ IN_diMinVal : DINT;
+ IN_diMaxVal : DINT;
+END_VAR
+VAR_OUTPUT
+ OUT_diActVal : DINT;
+END_VAR
+VAR_OUTPUT PERSISTENT
+ OUT_pdiActVal : DINT;
+END_VAR
+VAR
+ rtChA : R_TRIG;
+ rtChB : R_TRIG;
+ ftChA : F_TRIG;
+ ftChB : F_TRIG;
+ xFirstCycle : BOOL;
+END_VAR
+
+(*
+
+Incremental Encoder Decoder FB
+Author: mo
+Date: 2019-02
+
+ alternative OSCAT implementation (faulty!) below:
+
+ <OSCAT>
+ axb := cha XOR chb;
+
+ (* create pulses for channel a *)
+ clka := cha XOR edgea;
+ edgea := cha;
+
+ clkb := chb XOR edgeb;
+ edgeb := chb;
+
+ (* create pulses for both channels *)
+ clk := clka OR clkb;
+
+ (* set the direction output *)
+ IF axb AND clka THEN dir := TRUE; END_IF;
+ IF axb AND clkb THEN dir := FALSE; END_IF;
+
+ (* increment or decrement the counter *)
+ IF clk AND dir THEN cnt := cnt + 1; END_IF;
+ IF clk AND NOT dir THEN cnt := cnt -1; END_IF;
+
+ (* reset the counter if rst active *)
+ IF rst THEN cnt := 0; END_IF;
+ </OSCAT>
+
+=> problem here is: if your first pulse is e.g. a rising edge on CHb
+ with a high signal on CHa, it will increment cnt, but in the FALSE
+ direction instead of the TRUE direction. so your first pulse might count
+ into the wrong direction!
+
+
+This implementation accounts for all possible transitions.
+You can use OUT_diActVal or the persistent Version OUT_pdiActVal if your hardware
+is not moving while powered off to avoid reference runs at each restart of the PLC.
+
+ 1 |----| |----| |-
+A 0 _| |____| |____|
+
+ 1 |----| |----| |-
+B 0 _| |____| |____|
+
+*)
+
+(* @END_DECLARATION := '0' *)
+rtChA(clk:=IN_xChA);
+rtChB(clk:=IN_xChB);
+ftChA(clk:=IN_xChA);
+ftChB(clk:=IN_xChB);
+
+(* don't evaluate the changing edges when PLC starts up *)
+IF xFirstCycle THEN
+ IF (rtChA.Q AND NOT IN_xChB)
+ OR (ftChA.Q AND IN_xChB)
+ OR (rtChB.Q AND IN_xChA)
+ OR (ftChB.Q AND NOT IN_xChA)
+ THEN
+ OUT_diActVal := OUT_diActVal + 1;
+ OUT_pdiActVal := OUT_pdiActVal + 1;
+ END_IF
+
+ IF (rtChA.Q AND IN_xChB)
+ OR (ftChA.Q AND NOT IN_xChB)
+ OR (rtChB.Q AND NOT IN_xChA)
+ OR (ftChB.Q AND IN_xChA)
+ THEN
+ OUT_diActVal := OUT_diActVal - 1;
+ OUT_pdiActVal := OUT_pdiActVal - 1;
+ END_IF
+END_IF
+
+IF IN_xReset THEN
+ OUT_diActVal := 0;
+ OUT_pdiActVal := 0;
+END_IF
+
+IF IN_xEnPosWindow THEN
+ IF OUT_diActVal < IN_diMinVal THEN
+ OUT_diActVal := IN_diMaxVal - 1;
+ END_IF
+
+ IF OUT_diActVal >= IN_diMaxVal THEN
+ OUT_diActVal := IN_diMinVal;
+ END_IF
+
+ (* for persistent counter *)
+ IF OUT_pdiActVal < IN_diMinVal THEN
+ OUT_pdiActVal := IN_diMaxVal - 1;
+ END_IF
+
+ IF OUT_pdiActVal >= IN_diMaxVal THEN
+ OUT_pdiActVal := IN_diMinVal;
+ END_IF
+END_IF
+
+xFirstCycle := TRUE;
+END_FUNCTION_BLOCK
in each repos: see "about"-tab (if existing) for more details / README.
mailto contact at omeckman dot net
all timestamps in UTC (German winter time: UTC+01:00, summer time: UTC+02:00)
dark theme is a modded version of: https://gist.github.com/Yoplitein/f4b671a2ec70c9e743fa