Analog Outputs

It is very simple to set an analog output on a certain voltage with the help of LIBAD4 library. Therefore the example opens the measurement system (ad_open), then denotes the values to the various outputs (ad_analog_out) and at last closes the measurement system again (ad_close). Evidently the measurement system would be opened just once at the start of the program and closed at the end in a real program.

You will find the source code of the example in LIBAD4 SDK in the directory examples/analog_out (and in there in the according directories c, cs and vb for C/C++, C# and Visual Basic™.Net). Like all examples, this one does away with a proper error treatment due to simplicity of handling…

The example provides the routine read_analog_outputs() showing how to use the LIBAD4 functions ad_open(), ad_analog_out() and ad_close(). The name of the measurement device (driver), the number of the measurement range (range), the number of input channels to be measured (chav) and the voltage value (voltagev) that needs to be stated, are passed on to the routine. In addition the C/C++ code passes on the number of channels (chac). All arguments are retrieved from the command line in main(), processed accordingly and passed on to read_analog_outputs().

The first parameter on the command line gets passed in driver and denotes the measurement system. The "usb-ad:@100" for example opens the USB-AD with the serial number 100. You will find detailed descriptions for the necessary names of the different measurement systems in the LIBAD4 manual in chapter 6, measurement systems.

read_analog_outputs() passes this name directly to ad_open(). The return value of ad_open() is a handle, representing the opened measurement system and has to be passed to all functions of the LIBAD4. In case of an error -1 will be returned.

The parameter range defines the measurement range and will be denoted in main() by the optional command line argument -r <range>. This value defaults to 0 and thereby selects for example the measurement range +/- 5V of a USB-AD. The individual measurement ranges of the various measurement systems are also described in chapter 6 of the LIBAD4 manual.

main() fills the array chav[] and voltagev[] by converting the remaining arguments of the command line to numbers. The function write_analog_outputs() processes the array in a loop and calls ad_analog_out() for each channel to ad_analog_out() to tune the voltage of an analog output. The function measures the voltage of an analog input and gets passed to the measurement system (as returned by aad_open()) as first parameter (adh). The second argument specifies the channel (channel type AD_ANLOG_OUTPUT and channel index chav[i]) and the third argument specifies the measurement range (range). The last argument required is the variable voltagev[i], in which the output voltage is denoted. On error the function returns a non-zero error code. This error code corresponds to the host computer's operating system (for example in Windows an error number is returned from <winerror.h>).

The measurement system will be closed at the end of the loop ad_close().

/* Libad Analog Output Example
 *
 * Example showing how to set the voltage at some analog outputs
 * using bmcm's LIBAD4.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "libad.h"
/* Set analog output(s).
 */
void
write_analog_outputs (const char *driver, int range, int chac, int chav[], float voltagev[])
{
  int32_t adh;
  int i;
  /* Open DAQ system.
   */
  adh = ad_open (driver);
  if (adh == -1)
    {
      printf ("failed to open %s: err = %d\n", driver, errno);
      return;
    }
  /* Set analog output to some voltage.
   */
  for (i = 0; i < chac; i++)
    {
      int rc;
      rc = ad_analog_out (adh, AD_CHA_TYPE_ANALOG_OUT | chav[i], range, voltagev[i]);
      if (rc == 0)
        printf ("cha %2d: %7.3f V\n", chav[i], voltagev[i]);
      else
        printf ("error: failed to write cha %d: err = %d\n", chav[i], rc);
    }
  /* Close DAQ system again.
   */
  ad_close (adh);
}
/* Show usage.
 */
void
usage ()
{
  printf ("usage: analog_out <driver> [ -r <range> ] [<cha1>,] <voltage1> .. [<chan>,] voltagen\n"
          "  <driver>       string to pass to ad_open()\n"
          "                 - will prompt for name\n"
          "  <range>        range number of analog output\n"
          "  <cha1..n>      number of analog output to set\n"
          "  <voltage1..n>  output voltage\n");
}
/* Main entry point.
 */
int
main (int argc, char *argv[])
{
  if (argc > 1)
    {
      char *name, *p, tmp[80];
      int i, start, range, chac, chav[16];
      float voltagev[16];
      /* First command line argument is the DAQ's name.
       * If "-" is passed, then let's read the name from
       * the console.
       */
      name = argv[1];
      if (strcmp (argv[1], "-") == 0)
        {
          printf ("data acquisition system to open: ");
          fgets (tmp, sizeof(tmp), stdin);
          p = strchr (tmp, '\n');
          if (p)
            *p = 0;
          name = tmp;
        }
      /* Range defaults to 0 but may get overridden by
       * -r on the command line.
       */
      start = 2;
      range = 0;
      if (argc > 3)
        {
          if (strcmp (argv[start], "-r") == 0)
            {
              range = atoi (argv[start+1]);
              start += 2;
            }
        }
      /* Convert remaining command line arguments into channel
       * numbers and voltages. Add those to the appropriate array.
       */
      chac = 0;
      for (i = start; i < argc; i++)
        {
          char *delim;
          delim = strchr (argv[i], ',');
          if (delim)
            {
              chav[chac] = atoi (argv[i]);
              voltagev[chac] = (float) atof (delim+1);
            }
          else
            {
              chav[chac] = 1;
              voltagev[chac] = (float) atof (argv[i]);
            }
          chac++;
          if (chac >= 16)
            break;
        }
      /* Set analog outputs accordingly.
       */
      write_analog_outputs (name, range, chac, chav, voltagev);
      if (strcmp (argv[1], "-") == 0)
        {
          printf ("press return to continue...\n");
          fgets (tmp, sizeof(tmp), stdin);
        }
      return 0;
    }
  else
    {
      usage ();
      return 1;
    }
}
// Libad Analog Output Example
//
// Example showing how to set the voltage at some analog outputs
// using bmcm's LIBAD4.
using System;
using LIBAD4;
static class Example
{
  // Set analog output(s).
  static void
  write_analog_outputs (string driver, int range, int[] chav, float[] voltagev)
  {
    // Open DAQ system.
    int adh = LIBAD.ad_open (driver);
    if (adh == -1)
      {
        Console.WriteLine ("failed to open {0}: err = {1}", driver, LIBAD.errno);
        return;
      }
    // Set analog output to some voltage.
    for (int i = 0; i < chav.Length; i++)
      {
        int rc;
        rc = LIBAD.ad_analog_out (adh, LIBAD.AD_CHA_TYPE_ANALOG_IN | chav[i], range, voltagev[i]);
        if (rc == 0)
          Console.WriteLine ("cha {0,2}: {1,7:##0.000} V", chav[i], voltagev[i]);
        else
          Console.WriteLine ("error: failed to write cha {0}: err = {1}", chav[i], rc);
      }
    // Close DAQ system again.
    LIBAD.ad_close (adh);
  }
  // Show usage.
  static void
  usage ()
  {
    Console.WriteLine ("usage: analog_out <driver> [ -r <range> ] [<cha1>,] <voltage1> .. [<chan>,] voltagen");
    Console.WriteLine ("  <driver>       string to pass to ad_open()");
    Console.WriteLine ("                 - will prompt for name");
    Console.WriteLine ("  <range>        range number of analog input");
    Console.WriteLine ("  <cha1..n>      number of analog output to set");
    Console.WriteLine ("  <voltage1..n>  output voltage");
  }
  // Main entry point.
  static int
  Main (string[] argv)
  {
    if (argv.Length > 0)
      {
        // First command line argument is the DAQ's name.
        // If "-" is passed, then let's read the name from
        // the console.
        string name = argv[0];
        if (argv[0] == "-")
          {
            Console.Write ("data acquisition system to open: ");
            name = Console.ReadLine ();
          }
        // Range defaults to 0 but may get overridden by
        // -r on the command line.
        int start = 1;
        int range = 0;
        if (argv.Length > 2)
          {
            if (argv[start] == "-r")
              {
                range = int.Parse (argv[start+1]);
                start += 2;
              }
          }
        // Convert remaining command line arguments into channel
        // numbers and voltages. Add those to the appropriate array.
        int[] chav = new int[argv.Length - start];
        float[] voltagev = new float[argv.Length - start];
        for (int i = start; i < argv.Length; i++)
          {
            int delim = argv[i].IndexOf (',');
            if (delim >= 0)
              {
                chav[i - start] = int.Parse (argv[i].Substring (0, delim));
                voltagev[i - start] = float.Parse (argv[i].Substring (delim+1));
              }
            else
              {
                chav[i - start] = 1;
                voltagev[i - start] = float.Parse (argv[i]);
              }
          }
        // Set analog outputs accordingly.
        write_analog_outputs (name, range, chav, voltagev);
        if (argv[0]== "-")
          {
            Console.WriteLine ("press return to continue...");
            Console.ReadLine ();
          }
        return 0;
      }
    else
      {
        usage ();
        return 1;
      }
  }
}
' Libad Analog Output Example
'
' Example showing how to set the voltage at some analog outputs
' using bmcm's LIBAD4.
Imports System
Imports LIBAD4
Module Example
  ' Set analog output(s).
  Sub write_analog_outputs (driver As String, range As Integer, ByVal chav As Integer(), ByVal voltagev As Single())
    ' Open DAQ system.
    Dim adh As Integer
    adh = LIBAD.ad_open (driver)
    If adh = -1 Then
      Console.WriteLine ("failed to open {0}: err = {1}", driver, LIBAD.errno)
      Exit Sub
    End If
    ' Set analog output to some voltage.
    For i = 0 To chav.Length-1
      Dim rc As Integer
      rc = LIBAD.ad_analog_out (adh, LIBAD.AD_CHA_TYPE_ANALOG_IN or chav(i), range, voltagev(i))
      If rc = 0 Then
        Console.WriteLine ("cha {0,2}: {1,7:##0.000} V", chav(i), voltagev(i))
      Else
        Console.WriteLine ("error: failed to write cha {0}: err = {1}", chav(i), rc)
      End If
    Next
    ' Close DAQ system again.
    LIBAD.ad_close (adh)
  End Sub
  ' Show usage.
  Sub Usage
    Console.WriteLine ("usage: analog_out <driver> [ -r <range> ] [<cha1>,] <voltage1> .. [<chan>,] voltagen")
    Console.WriteLine ("  <driver>       string to pass to ad_open()")
    Console.WriteLine ("                 - will prompt for name")
    Console.WriteLine ("  <range>        range number of analog input")
    Console.WriteLine ("  <cha1..n>      number of analog output to set")
    Console.WriteLine ("  <voltage1..n>  output voltage")
  End Sub
  ' Main entry point.
  Sub Main (ByVal argv As String())
    If argv.Length > 0 Then
      ' First command line argument is the DAQ's name.
      ' If "-" is passed, then let's read the name from
      ' the console.
      Dim name As String
      name = argv(0)
      If argv(0) = "-" Then
        Console.Write ("data acquisition sytem to open: ")
        name = Console.ReadLine ()
      End If
      ' Range defaults to 0 but may get overridden by
      ' -r on the command line.
      Dim start, range As Integer
      start = 1
      range = 0
      If argv.Length > 2 Then
        If argv(start) = "-r" Then
          range = Int32.Parse (argv(start+1))
          start = start + 2
        End If
      End If
      ' Convert remaining command line arguments into channel
      ' numbers and voltages. Add those to the appropriate array.
      Dim chav(argv.Length-1 - start) As Integer
      Dim voltagev(argv.Length-1 - start) As Single
      For i = start To argv.Length-1
        Dim delim As Integer
        delim = argv(i).IndexOf (",")
        If delim >= 0 Then
          chav(i - start) = Int32.Parse (argv(i).SubString (0, delim))
          voltagev(i - start) = Single.Parse (argv(i).SubString (delim+1))
        Else
          chav(i - start) = 1
          voltagev(i - start) = Single.Parse (argv(i))
        End If
      Next
      ' Set analog outputs accordingly.
      write_analog_outputs (name, range, chav, voltagev)
      If argv(0) = "-" Then
        Console.WriteLine ("press return to continue...")
        Console.ReadLine ()
      End If
      Environment.Exit (0)
    Else
      Usage
      Environment.Exit (1)
    End If
  End Sub
End Module