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 | ~~~ |