Example ImpedanceUserCompensation#

  1/// Example illustrating the use of the LabOne C API and the Impedance Module to
  2/// perform a short-open user compensation with an MFIA device.
  3#include <chrono>
  4#include <iostream>
  5#include <string>
  6#include <thread>
  7
  8#include "ziAPI.h"
  9#include "ziUtils.hpp"
 10
 11/// Translate C API result codes into C++ exceptions
 12void handleError(ZIConnection conn, ZIResult_enum resultCode)
 13{
 14  if (resultCode == ZI_INFO_SUCCESS)
 15  {
 16    return;
 17  }
 18  char* errorDescription;
 19  ziAPIGetError(resultCode, &errorDescription, nullptr);
 20  constexpr size_t maxErrorLength = 1000;
 21  char errorDetails[maxErrorLength];
 22  errorDetails[0] = 0;
 23  ziAPIGetLastError(conn, errorDetails, maxErrorLength);
 24  auto message = std::string{"LabOne C API error "} +
 25                 std::to_string(resultCode) + ": " + errorDescription +
 26                 "\nDetails: " + errorDetails;
 27  throw std::runtime_error(message);
 28}
 29
 30int main()
 31{
 32  const char* serverHost = ziUtilsGetEnv("LABONE_SERVER", "localhost");
 33  const char* deviceAddress = ziUtilsGetEnv("LABONE_DEVICE", "dev3123");
 34  const char* deviceInterface = ziUtilsGetEnv("LABONE_INTERFACE", "1GbE");
 35
 36  // Instrument connection
 37  std::cout << "-- Connecting to instrument ..." << std::endl;
 38  ZIConnection conn = nullptr;
 39  handleError(conn, ziAPIInit(&conn));
 40
 41  handleError(
 42      conn, ziAPIConnectEx(conn, serverHost, 8004, ZI_API_VERSION_6, nullptr));
 43  handleError(
 44      conn, ziAPIConnectDevice(conn, deviceAddress, deviceInterface, nullptr));
 45
 46  ziApiServerVersionCheck(conn);
 47
 48  const auto pathBase = std::string{"/"} + deviceAddress + "/";
 49
 50  // Instrument settings
 51  std::cout << "-- Setting up instrument ..." << std::endl;
 52  {
 53    // clang-format off
 54    const auto impIndex = 0;
 55    const auto pathBaseImp = pathBase + "imps/" + std::to_string(impIndex) + "/";
 56    handleError(conn, ziAPISetValueI(conn, (pathBaseImp + "enable").c_str(), 1));
 57    handleError(conn, ziAPISetValueI(conn, (pathBaseImp + "mode").c_str(), 0));
 58    handleError(conn, ziAPISetValueI(conn, (pathBaseImp + "auto/output").c_str(), 1));
 59    handleError(conn, ziAPISetValueI(conn, (pathBaseImp + "auto/bw").c_str(), 1));
 60    handleError(conn, ziAPISetValueD(conn, (pathBaseImp + "freq").c_str(), 1000.0));
 61    handleError(conn, ziAPISetValueI(conn, (pathBaseImp + "auto/inputrange").c_str(), 1));
 62    handleError(conn, ziAPISetValueD(conn, (pathBaseImp + "output/amplitude").c_str(), 0.3));
 63    handleError(conn, ziAPISetValueD(conn, (pathBaseImp + "output/range").c_str(), 1.0));
 64    handleError(conn, ziAPISetValueI(conn, (pathBaseImp + "model").c_str(), 0));
 65    handleError(conn, ziAPISync(conn));
 66    // clang-format on
 67  }
 68
 69  // User compensation setup
 70  std::cout << "-- Setting up module for user compensation ..." << std::endl;
 71  ZIModuleHandle impedance;
 72  handleError(conn, ziAPIModCreate(conn, &impedance, "impedanceModule"));
 73  handleError(conn, ziAPIModExecute(conn, impedance));
 74  {
 75    // clang-format off
 76    handleError(conn, ziAPIModSetString(conn, impedance, "device", deviceAddress));
 77    handleError(conn, ziAPIModSetDoubleData(conn, impedance, "freq/start", 1000.0));
 78    handleError(conn, ziAPIModSetDoubleData(conn, impedance, "freq/stop", 5000000.0));
 79    handleError(conn, ziAPIModSetIntegerData(conn, impedance, "freq/samplecount", 20));
 80
 81    // Important: this allows everything to pass, in case the short is much higher than 0 Ohm.
 82    handleError(conn, ziAPIModSetIntegerData(conn, impedance, "validation", 0));
 83
 84    // Short-only mode.
 85    handleError(conn, ziAPIModSetIntegerData(conn, impedance, "mode", 1));
 86
 87    // Add additional open, note this is the case for 21.08 onwards. otherwise the old mode 3 is short-open.
 88    handleError(conn, ziAPIModSetIntegerData(conn, impedance, "openstep", 1));
 89    // clang-format on
 90  }
 91
 92  // Short compensation
 93  {
 94    std::cout << "-- Short compensation ..." << std::endl;
 95    handleError(conn, ziAPIModSetIntegerData(conn, impedance, "step", 0));
 96    handleError(conn, ziAPIModSetIntegerData(conn, impedance, "calibrate", 1));
 97
 98    for (;;)
 99    {
100      std::this_thread::sleep_for(std::chrono::milliseconds{200});
101
102      double progress;
103      handleError(conn, ziAPIModProgress(conn, impedance, &progress));
104      std::cout << "Short compensation progress: " << 100 * progress
105                << " %          \r" << std::flush;
106
107      ZIIntegerData finished;
108      handleError(conn, ziAPIModFinished(conn, impedance, &finished));
109      if (finished)
110      {
111        break;
112      }
113
114      // Wait until first calibration step succeeded. The calibration step is
115      // bit-encoded in the 'status' node.
116      ZIIntegerData status;
117      handleError(conn, ziAPIModGetInteger(conn, impedance, "status", &status));
118      if ((status & 0b01) != 0)
119      {
120        break;
121      }
122    }
123
124    std::cout << std::endl;
125    char message[1000];
126    unsigned int messageLength = 0;
127    handleError(
128        conn,
129        ziAPIModGetString(
130            conn,
131            impedance,
132            "message",
133            message,
134            &messageLength,
135            sizeof(message)));
136    std::cout << "Message: " << message << std::endl << std::endl;
137  }
138
139  std::cout << std::endl
140            << "Please change from short into open now. Then press [Enter] to "
141               "continue."
142            << std::endl;
143  std::cin.get();
144
145  // Open compensation
146  {
147    std::cout << "-- Open compensation ..." << std::endl;
148    handleError(conn, ziAPIModSetIntegerData(conn, impedance, "step", 1));
149    handleError(conn, ziAPIModSetIntegerData(conn, impedance, "calibrate", 1));
150
151    for (;;)
152    {
153      std::this_thread::sleep_for(std::chrono::milliseconds{200});
154
155      double progress;
156      handleError(conn, ziAPIModProgress(conn, impedance, &progress));
157      std::cout << "Open compensation progress: " << 100 * progress
158                << " %          \r" << std::flush;
159
160      ZIIntegerData finished;
161      handleError(conn, ziAPIModFinished(conn, impedance, &finished));
162      if (finished)
163      {
164        break;
165      }
166
167      // Wait until second calibration step succeeded.
168      ZIIntegerData status;
169      handleError(conn, ziAPIModGetInteger(conn, impedance, "status", &status));
170      if ((status & 0b10) != 0)
171      {
172        break;
173      }
174    }
175
176    std::cout << std::endl;
177    char message[1000];
178    unsigned int messageLength = 0;
179    handleError(
180        conn,
181        ziAPIModGetString(
182            conn,
183            impedance,
184            "message",
185            message,
186            &messageLength,
187            sizeof(message)));
188    std::cout << "Message: " << message << std::endl << std::endl;
189  }
190
191  // Save and load compensation file
192  {
193    // clang-format off
194    std::cout << "-- Save and load compensation file" << std::endl;
195    handleError(conn, ziAPIModSetIntegerData(conn, impedance, "todevice", 1));
196    handleError(conn, ziAPISetValueI(conn, (pathBase + "system/impedance/calib/internal/store").c_str(), 1));
197    handleError(conn, ziAPIModSetString(conn, impedance, "filename", "testcal"));
198    handleError(conn, ziAPIModSetIntegerData(conn, impedance, "save", 1));
199
200    // Wait for data to be saved ('save' node returns to 0)
201    for(;;) {
202      ZIIntegerData save;
203      handleError(conn, ziAPIModGetInteger(conn, impedance, "save", &save));
204      if (save == 0) {
205        break;
206      }
207      std::this_thread::sleep_for(std::chrono::milliseconds{100});
208    }
209
210    // Use this to apply the just finished short-open compensation
211    handleError(conn, ziAPIModSetIntegerData(conn, impedance, "load", 1));
212    // clang-format on
213  }
214
215  std::cout << "Short-Open user compensation complete." << std::endl;
216
217  // Cleanup
218  handleError(conn, ziAPIModClear(conn, impedance));
219  handleError(conn, ziAPIDestroy(conn));
220}