channel: Fix to-physical setup in AnalogChannel._get_converter
[pycomedi.git] / doc / synchronized_analog_IO.txt
1 Import required modules.
2
3 >>> from numpy import arange, linspace, zeros, sin, pi, float32
4 >>> from pycomedi.device import Device
5 >>> from pycomedi.subdevice import StreamingSubdevice
6 >>> from pycomedi.channel import AnalogChannel
7 >>> from pycomedi.chanspec import ChanSpec
8 >>> from pycomedi.constant import (AREF, CMDF, INSN, SUBDEVICE_TYPE, TRIG_SRC,
9 ...     UNIT)
10 >>> from pycomedi.utility import inttrig_insn, Reader, Writer
11
12 Open a device.
13
14 >>> device = Device('/dev/comedi0')
15 >>> device.open()
16
17 Get your I/O subdevices (alternatively, use `device.subdevice()` to
18 select the subdevice directly by index).
19
20 >>> ai_subdevice = device.find_subdevice_by_type(SUBDEVICE_TYPE.ai,
21 ...     factory=StreamingSubdevice)
22 >>> ao_subdevice = device.find_subdevice_by_type(SUBDEVICE_TYPE.ao,
23 ...     factory=StreamingSubdevice)
24
25 Generate a list of channels you wish to control.
26
27 >>> ai_channels = [
28 ...     ai_subdevice.channel(i, factory=AnalogChannel, aref=AREF.diff)
29 ...     for i in (0, 1, 2, 3)]
30 >>> ao_channels = [
31 ...     ao_subdevice.channel(i, factory=AnalogChannel, aref=AREF.diff)
32 ...     for i in (0, 1)]
33
34 Configure the channels.
35
36 >>> for chan in ai_channels + ao_channels:
37 ...     chan.range = chan.find_range(unit=UNIT.volt, min=-10, max=10)
38
39 Use the subdevice flags to determine data types.
40
41 >>> ai_dtype = ai_subdevice.get_dtype()
42 >>> ao_dtype = ao_subdevice.get_dtype()
43
44 Allocate buffers (with channel data interleaved).
45
46 >>> n_samps = 100
47 >>> ai_buffer = zeros((n_samps, len(ai_channels)), dtype=ai_dtype)
48 >>> ao_buffer = zeros((n_samps, len(ao_channels)), dtype=ao_dtype)
49
50 Initialize output buffer.
51
52 >>> midpoint = int(ao_channels[0].get_maxdata()/2)
53 >>> bitrange = float(midpoint/2)
54 >>> ao_buffer[:,0] = midpoint+bitrange*sin(2*pi*arange(n_samps)/(n_samps-1.0))
55 >>> ao_buffer[:,1] = linspace(0, midpoint, n_samps)
56 >>> ao_buffer[-1,:] = midpoint
57
58 Get rough commands.
59
60 >>> frequency = 1000.0  # Hz
61 >>> scan_period_ns = int(1e9 / frequency)  # nanosecond period
62 >>> ai_cmd = ai_subdevice.get_cmd_generic_timed(
63 ...     len(ai_channels), scan_period_ns)
64 >>> ao_cmd = ao_subdevice.get_cmd_generic_timed(
65 ...     len(ao_channels), scan_period_ns)
66
67 Setup multi-scan run triggering.
68
69 >>> ai_cmd.start_src = TRIG_SRC.int
70 >>> ai_cmd.start_arg = 0
71 >>> ai_cmd.stop_src = TRIG_SRC.count
72 >>> ai_cmd.stop_arg = n_samps
73 >>> ao_cmd.start_src = TRIG_SRC.ext
74 >>> ao_cmd.start_arg = 18  # NI card AI_START1 internal AI start signal
75 >>> ao_cmd.stop_src = TRIG_SRC.count
76 >>> ao_cmd.stop_arg = n_samps
77
78 Add channel lists.
79
80 >>> ai_cmd.chanlist = ai_channels
81 >>> ao_cmd.chanlist = ao_channels
82
83 Test the commands.
84
85 >>> ai_subdevice.cmd = ai_cmd
86 >>> ao_subdevice.cmd = ao_cmd
87 >>> for i in range(3):
88 ...     rc = ai_subdevice.command_test()
89 ...     if rc == None: break
90 ...     print i, rc
91 >>> for i in range(3):
92 ...     rc = ao_subdevice.command_test()
93 ...     if rc == None: break
94 ...     print i, rc
95
96 Start the commands.
97
98 >>> ao_subdevice.command()
99 >>> ai_subdevice.command()
100
101 Start the reader and writer threads.
102
103 >>> writer = Writer(ao_subdevice, ao_buffer)
104 >>> writer.start()
105 >>> reader = Reader(ai_subdevice, ai_buffer)
106 >>> reader.start()
107
108 Arm the AO command.
109
110 >>> device.do_insn(inttrig_insn(ao_subdevice))
111 1
112
113 Trigger AI aquisition, which in turn triggers the AO.
114
115 >>> device.do_insn(inttrig_insn(ai_subdevice))
116 1
117
118 Join the reader and writer threads when they finish.
119
120 >>> writer.join()
121 >>> reader.join()
122
123 >>> ai_buffer  # doctest: +SKIP
124 array([[32669, 27117, 24827, 23111],
125        [33711, 27680, 25273, 23453],
126 ...
127        [31627, 24590, 22482, 22045],
128        [32668, 25381, 22937, 22189]], dtype=uint16)
129
130 array([[32342, 31572, 30745, 31926],
131        [33376, 31797, 30904, 31761],
132 ...
133        [31308, 24246, 22215, 21824],
134        [32343, 25044, 22659, 21959]], dtype=uint16)
135
136 Use a converter to convert these to physical values
137
138 >>> converters = [c.get_converter() for c in ai_channels]
139 >>> ai_physical = zeros(ai_buffer.shape, dtype=float32)
140 >>> for i,c in enumerate(converters):
141 ...     ai_physical[:,i] = c.to_physical(ai_buffer[:,i])
142 >>> ai_physical  # doctest: +SKIP
143 array([[ -3.00602727e-02,  -1.72442210e+00,  -2.42328525e+00,
144          -2.94697499e+00],
145        [  2.87937731e-01,  -1.55260551e+00,  -2.28717470e+00,
146          -2.84260321e+00],
147 ...
148        [ -3.48058283e-01,  -2.49561310e+00,  -3.13893342e+00,
149          -3.27229714e+00],
150        [ -3.03654540e-02,  -2.25421524e+00,  -3.00007629e+00,
151          -3.22835135e+00]], dtype=float32)
152 >>> [c.range.unit for c in ai_channels]
153 [<_NamedInt volt>, <_NamedInt volt>, <_NamedInt volt>, <_NamedInt volt>]
154
155 Close the device when you're done.
156
157 >>> device.close()