Example ImpedanceAutoranging#

  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}