Diff of /trunk/gpiomod/GPIOMods.library.md [000000] .. [r16]  Maximize  Restore

Switch to unified view

a b/trunk/gpiomod/GPIOMods.library.md
1
---
2
3
             This FB can be used to sample analog data by using two
4
 GPIO Pins:
5
 - one digital input
6
 - one digital output
7
8
 There are also other circuits out there, which only
9
 need one single GPIO. But they have the clear disadvantage
10
 that they need to reconfigure this GPIO constantly. Additionally
11
 you have to take care about the VRef, which you are using, as it
12
 will be pulled to ground by the GPIO acting as an output.
13
 You need to take care to not destroy your board with that. In the
14
 Circuit, recommended here, it is to my understanding much safer,
15
 as we simply use the digital output as our VRef. Therefore we can
16
 easily and safely pull it to ground.
17
18
 Wirering::
19
   Digital Output (VRef)
20
      v
21
   R1 (2,2kOhm) 
22
      v
23
   Transistor / Poti / LDR / ...
24
      |---> Input Pin
25
   C1 (1uF)
26
      v
27
     GND
28
29
 Scheduling:
30
 The accuracy of the measurement relies in some aspects on the scheduling.
31
 So it is recommended to schedule the task, which is driving this FB, as 
32
 frequent as possible. It is generally OK to combine this FB with the SoftPWM.
33
 Just the sampling accuracy will slightly vary, depending on the frequency
34
 of the PWM. 
35
36
~~~ST
37
FUNCTION_BLOCK SoftAIN
38
VAR_INPUT
39
    xInput: BOOL;
40
END_VAR
41
VAR_OUTPUT
42
    xOutput: BOOL;
43
    rVal: REAL;
44
END_VAR
45
VAR
46
    xSampling: BOOL;
47
    tStart: SYSTIME;
48
    tCurrent: SYSTIME;
49
    xInit: BOOL;
50
END_VAR
51
VAR
52
    ctDischarge: SYSTIME;
53
    crScale: REAL;
54
END_VAR
55
56
~~~
57
~~~ST
58
SysTimeGetUs(tCurrent);
59
IF xInit THEN
60
    xInit := FALSE;
61
    tStart := tCurrent;
62
END_IF
63
    
64
65
IF xSampling THEN
66
    // Reading the sampling pin, and measure the time
67
    IF xInput THEN
68
        /// capacitor is full, stop sampling, and discharge
69
        xSampling := FALSE;
70
        rVal := LWORD_TO_REAL(tCurrent - tStart) * crScale;
71
        tStart := tCurrent;
72
    END_IF
73
ELSE
74
    // Discharge the capacitor
75
    IF tCurrent - tStart > ctDischarge THEN
76
        // start sampling
77
        tStart := tCurrent;
78
        xOutput := TRUE;
79
    END_IF
80
END_IF
81
~~~
82
---
83
84
             This FB can be used to implement a Soft PWM, based
85
 on the scheduler of a Linux system.
86
87
 Note, that this function block should be used in a
88
 a high priority task. The interval of the task will
89
 constantly change.
90
91
~~~ST
92
FUNCTION_BLOCK SoftPWM
93
VAR_INPUT
94
    dwFrequ: DWORD;
95
    rDutyCycle: REAL;
96
END_VAR
97
VAR_OUTPUT
98
    xPWM: BOOL;
99
END_VAR
100
VAR
101
    hTask: SysTask.RTS_IEC_HANDLE;
102
    ulInterval: DWORD;
103
END_VAR
104
VAR
105
    cMinInterval: DWORD;
106
END_VAR
107
108
~~~
109
~~~ST
110
(* If current task is not, yet, determined, get it *)
111
IF hTask = SysTask.RTS_INVALID_HANDLE THEN
112
    SysTask.SysTaskGetCurrent(ADR(hTask));
113
END_IF
114
115
(* if task is determined, adjust next cycle *)
116
IF hTask <> SysTask.RTS_INVALID_HANDLE THEN
117
    IF xPWM THEN
118
        ulInterval := LREAL_TO_DWORD((LREAL#1000000 / DWORD_TO_LREAL(dwFrequ)) * rDutyCycle);
119
    ELSE
120
        ulInterval := LREAL_TO_DWORD((LREAL#1000000 / DWORD_TO_LREAL(dwFrequ)) * (LREAL#1 - rDutyCycle));
121
    END_IF
122
    
123
    (* if we are near the boundary values, we snap the output either to TRUE or FALSE *)
124
    IF ulInterval < cMinInterval THEN
125
        SysTask.SysTaskSetInterval(hTask, DWORD#1000000 / dwFrequ);
126
    ELSE        
127
        SysTask.SysTaskSetInterval(hTask, ulInterval);
128
        xPWM := NOT xPWM;
129
    END_IF
130
END_IF
131
132
133
134
~~~