Analogausgänge

Mit Hilfe der LIBAD4 Bibliothek ist es sehr einfach, einen Analogausgang auf eine bestimmte Spannung zu setzen. Dazu öffnet das Beispiel Messsystem (ad_open), gibt dann die Werte an verschiedenen Ausgängen aus (ad_analog_out) und zuletzt wird das Messsystem wieder geschlossen (ad_close). Natürlich würde in einem realen Programm das Messsystem nur einmal am Beginn des Programms geöffent und am Ende wieder geschlossen werden.

Der Sourcecode des Beispiels befindet sich im LIBAD4 SDK im Verzeichnis examples/analog_out (und dort jeweils in den Verzeichnissen ccs und vb für C/C++, C# und Visual Basic™ .Net). Wie alle Beispiele, verzichtet auch dieses aus Gründen der Einfachheit auf eine solide Fehlerbehandlung...

Das Beispiel verwendet die Routine write_analog_outputs() um den Aufruf der LIBAD4 Funktionen ad_open()ad_analog_out() und ad_close() zu zeigen. An diese Routine wird der Name des Messgeräts (driver), die Nummer des Messbereichs (range), die Nummern der zu messenden Eingänge (chav) und die auszugebenden Spannungswerte (voltagev) übergeben. Die C/C++ Variante übergibt zusätzlich noch die Anzahl der Kanäle (chac). Alle Argumente werden in main() von der Kommandozeile gewonnen, entsprechend aufbereitet und dann an write_analog_outputs() übergeben.

Der erste Parameter auf der Kommandozeile wird in driver übergeben und legt das Messsystem fest. Beispielsweise öffnet "usb-ad:@100" das USB-AD mit der Seriennumer 100. Ausführliche Hinweise zu den notwendigen Namen für die verschiedenen Messsysteme finden Sie im LIBAD4 Handbuch in Kapitel 6, Messsysteme.

Dieser Name wird von write_analog_outputs() direkt an ad_open() weitergegeben. Der Rückgabewert von ad_open() ist ein Handle, der das geöffnete Messsystem repräsentiert und an alle Funktionen der LIBAD4 übergeben werden muss. Im Fehlerfall wird -1zurückgegeben.

Der Parameter range definiert den Messbereich und wird in main() durch das optionale Kommandzeilenargument -r <range> bestimmt. Per default steht dieser Wert auf 0 und wählt damit beispielsweise den +/- 5V Messbereichs eines USB-AD aus. Die einzelnen Messbereiche der verschiedenen Messsysteme sind auch in Kapitel 6 des LIBAD4 Handbuchs beschrieben.

Die restlichen Argumente auf der Kommandzeile werden von main() in Zahlen konvertiert und in die Felder chav[] und voltagev[] geschrieben. In einer Schleife über alle Kanäle übergibt write_analog_outputs() diese Werte dann an ad_analog_out() um die Spannung am Analogausgang einzustellen. Dabei spezifiert das erste Argument (adh) das Messsystem (wie von ad_open() geliefert), das zweite Argument den Kanal (bestehend aus dem Kanaltyp AD_ANLOG_OUTPUT und der Nummer des Kanals chav[i]) und das dritte Argument den Messbereich (range). Als letztes Argument wird voltagev[i] übergeben, mit dem die Ausgangsspannung festgelegt wird. Die Funktion gibt im Fehlerfall einen Wert ungleich null zurück, wobei diese Fehlernummer immer einer Fehlernummer des Hostrechners entspricht (also z.B. unter Windows wird eine Fehlernummer aus <winerror.h> zurückgegeben).

Nach dem Schleifenende wird das Messsystem mit ad_close() wieder geschlossen.

/* 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