1// Copyright [2017] Zurich Instruments AG
2
3#include <cstdlib>
4#include <ctime>
5#include <iostream>
6
7#include "ziAPI.h"
8#include "ziUtils.hpp"
9
10
11int main()
12{
13 /* This examplte demonstrates how to perform a manually triggered autoranging
14 for impedance while working in manual range mode. The Impedance Analyzer (IA)
15 option is needed to run this example. Connect the Impedance Testfixture and
16 attach a 1kOhm resistor. */
17
18 // Define the device address of the device to run the example on.
19 const char* deviceAddress = ziUtilsGetEnv("LABONE_DEVICE", "dev3123");
20 printf("ENV LABONE_DEVICE=%s\n", deviceAddress);
21
22 // Address of the data server.
23 const char* dataServer = ziUtilsGetEnv("LABONE_SERVER", "localhost");
24
25 // Port of the data server.
26 const uint16_t port = 8004;
27
28 // Over which interface the connection to the
29 // device should be established. Can be either
30 // - 1: "1GbE" - Ethernet
31 // - 2: "USB" - USB
32 // - 3: "PCIe" - PCIe
33 const char* deviceInterface = "1GbE";
34
35 ZIConnection conn = nullptr;
36
37 if (isError(ziAPIInit(&conn)))
38 {
39 return 1;
40 }
41
42 ziAPISetDebugLevel(0);
43 ziAPIWriteDebugLog(0, "Logging enabled.");
44
45 try
46 {
47 checkError(
48 ziAPIConnectEx(conn, dataServer, port, ZI_API_VERSION_6, nullptr));
49 checkError(
50 ziAPIConnectDevice(conn, deviceAddress, deviceInterface, nullptr));
51 ziApiServerVersionCheck(conn);
52 char nodePath[1024];
53
54 /* Create a base instrument configuration: disable all outputs, demods and
55 * scopes. */
56 snprintf(nodePath, sizeof(nodePath), "/%s/demods/*/enable", deviceAddress);
57 checkError(ziAPISetValueI(conn, nodePath, 0));
58 snprintf(nodePath, sizeof(nodePath), "/%s/demods/*/trigger", deviceAddress);
59 checkError(ziAPISetValueI(conn, nodePath, 0));
60 snprintf(
61 nodePath, sizeof(nodePath), "/%s/sigouts/*/enables/*", deviceAddress);
62 checkError(ziAPISetValueI(conn, nodePath, 0));
63 snprintf(nodePath, sizeof(nodePath), "/%s/scopes/*/enable", deviceAddress);
64 checkError(ziAPISetValueI(conn, nodePath, 0));
65 snprintf(nodePath, sizeof(nodePath), "/%s/imps/*/enable", deviceAddress);
66 checkError(ziAPISetValueI(conn, nodePath, 0));
67 /* Perform a global synchronisation between the device and the data server:
68 Ensure that the settings have taken effect on the device
69 before setting the next configuration. */
70 checkError(ziAPISync(conn));
71
72 int64_t imp_index = 0;
73 ZIIntegerData curr_index, volt_index;
74 snprintf(
75 nodePath,
76 sizeof(nodePath),
77 "/%s/imps/%" PRId64 "/current/inputselect",
78 deviceAddress,
79 imp_index);
80 checkError(ziAPIGetValueI(conn, nodePath, &curr_index));
81 snprintf(
82 nodePath,
83 sizeof(nodePath),
84 "/%s/imps/%" PRId64 "/voltage/inputselect",
85 deviceAddress,
86 imp_index);
87 checkError(ziAPIGetValueI(conn, nodePath, &volt_index));
88 double man_curr_range = 10e-3;
89 double man_volt_range = 10e-3;
90
91 /* Now configure the instrument for this experiment.The following channels
92 and indices work on all devices with IA option.The values below may be
93 changed if the instrument has multiple IA modules. */
94 snprintf(
95 nodePath,
96 sizeof(nodePath),
97 "/%s/imps/%" PRId64 "/enable",
98 deviceAddress,
99 imp_index);
100 checkError(ziAPISetValueI(conn, nodePath, 1));
101 snprintf(
102 nodePath,
103 sizeof(nodePath),
104 "/%s/imps/%" PRId64 "/mode",
105 deviceAddress,
106 imp_index);
107 checkError(ziAPISetValueI(conn, nodePath, 0));
108 snprintf(
109 nodePath,
110 sizeof(nodePath),
111 "/%s/imps/%" PRId64 "/auto/output",
112 deviceAddress,
113 imp_index);
114 checkError(ziAPISetValueI(conn, nodePath, 1));
115 snprintf(
116 nodePath,
117 sizeof(nodePath),
118 "/%s/imps/%" PRId64 "/auto/bw",
119 deviceAddress,
120 imp_index);
121 checkError(ziAPISetValueI(conn, nodePath, 1));
122 snprintf(
123 nodePath,
124 sizeof(nodePath),
125 "/%s/imps/%" PRId64 "/freq",
126 deviceAddress,
127 imp_index);
128 checkError(ziAPISetValueD(conn, nodePath, 500));
129 snprintf(
130 nodePath,
131 sizeof(nodePath),
132 "/%s/imps/%" PRId64 "/auto/inputrange",
133 deviceAddress,
134 imp_index);
135 checkError(ziAPISetValueI(conn, nodePath, 0));
136 snprintf(
137 nodePath,
138 sizeof(nodePath),
139 "/%s/currins/%" PRId64 "/range",
140 deviceAddress,
141 curr_index);
142 checkError(ziAPISetValueD(conn, nodePath, man_curr_range));
143 snprintf(
144 nodePath,
145 sizeof(nodePath),
146 "/%s/sigins/%" PRId64 "/range",
147 deviceAddress,
148 volt_index);
149 checkError(ziAPISetValueD(conn, nodePath, man_volt_range));
150 checkError(ziAPISync(conn));
151
152 /* After setting the device in manual ranging mode we want to trigger
153 manually a one time auto ranging to find a suitable range. Therefore, we
154 trigger the auto ranging for the current input as well as for the voltage
155 input. */
156 snprintf(
157 nodePath,
158 sizeof(nodePath),
159 "/%s/currins/%" PRId64 "/autorange",
160 deviceAddress,
161 curr_index);
162 checkError(ziAPISetValueI(conn, nodePath, 1));
163 snprintf(
164 nodePath,
165 sizeof(nodePath),
166 "/%s/sigins/%" PRId64 "/autorange",
167 deviceAddress,
168 volt_index);
169 checkError(ziAPISetValueI(conn, nodePath, 1));
170
171 bool finished = false;
172 ZIIntegerData voltRangingState, currRangingState;
173 std::cout << "Start auto ranging. This takes a few seconds.\n";
174 time_t t_start = time(NULL);
175 /*The auto ranging takes some time.We do not want to continue before the
176 best range is found. Therefore, we implement a loop to check if the auto
177 ranging is finished. */
178 while (!finished)
179 {
180 sleep(500);
181 snprintf(
182 nodePath,
183 sizeof(nodePath),
184 "/%s/currins/%" PRId64 "/autorange",
185 deviceAddress,
186 curr_index);
187 checkError(ziAPIGetValueI(conn, nodePath, &currRangingState));
188 snprintf(
189 nodePath,
190 sizeof(nodePath),
191 "/%s/sigins/%" PRId64 "/autorange",
192 deviceAddress,
193 volt_index);
194 checkError(ziAPIGetValueI(conn, nodePath, &voltRangingState));
195 finished = (currRangingState | voltRangingState) == 0;
196 }
197
198 std::cout << "Auto ranging finished after " << difftime(time(NULL), t_start)
199 << "s.\n";
200 double auto_curr_range, auto_volt_range;
201 snprintf(
202 nodePath,
203 sizeof(nodePath),
204 "/%s/currins/%" PRId64 "/range",
205 deviceAddress,
206 curr_index);
207 checkError(ziAPIGetValueD(conn, nodePath, &auto_curr_range));
208 snprintf(
209 nodePath,
210 sizeof(nodePath),
211 "/%s/sigins/%" PRId64 "/range",
212 deviceAddress,
213 volt_index);
214 checkError(ziAPIGetValueD(conn, nodePath, &auto_volt_range));
215 std::cout << "Current range changed from " << man_curr_range << "A to "
216 << auto_curr_range << "A.\n";
217 std::cout << "Voltage range changed from " << man_volt_range << "V to "
218 << auto_volt_range << "V.\n";
219
220 ziAPIDisconnect(conn);
221 }
222 catch (std::runtime_error& e)
223 {
224 char extErrorMessage[1024] = "";
225 ziAPIGetLastError(conn, extErrorMessage, 1024);
226 fprintf(stderr, "Error: %s\ndetails: %s\n", e.what(), extErrorMessage);
227 return 1;
228 }
229
230 ziAPIDestroy(conn);
231 return 0;
232}