Analogeingänge

Mit Hilfe der LIBAD4 Bibliothek ist es sehr einfach, die aktuelle Spannung eines Analogeingangs zu messen. Dazu öffnet das Beispiel Messsystem (ad_open), liest dann die Werte an verschiedenen Eingängen aus (ad_analog_in) 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öffnet und am Ende wieder geschlossen werden.

Der Sourcecode des Beispiels befindet sich im LIBAD4 SDK im Verzeichnis examples/analog_in (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 read_analog_inputs() um den Aufruf der LIBAD4 Funktionen ad_open()ad_analog_in() und ad_close() zu zeigen. An diese Routine wird der Name des Messgeräts (driver), die Nummer des Messbereichs (range) und die Nummern der zu messenden Eingänge (chav) ü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 read_analog_inputs() ü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 read_analog_inputs() 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 das Feld chav[] geschrieben. In einer Schleife über alle Kanäle übergibt read_analog_inputs() diese Werte dann an ad_analog_in(), mit der die Spannung eines Analogeingangs gemessen wird. Dabei spezifiert das erste Argument (adh) das Messsystem (wie von ad_open() geliefert), das zweite Argument den Kanal (bestehend aus dem Kanaltyp AD_ANLOG_INPUT und der Nummer des Kanals chav[i]) und das dritte Argument den Messbereich (range). Als letztes Argument wird die Variable voltage übergeben, in die ad_analog_in() den gemessenen Spannungswert schreibt. 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 Input Example
 *
 * Example showing how to read the voltage at some analog inputs
 * using bmcm's LIBAD4.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "libad.h"
/* Read analog input(s).
 */
void
read_analog_inputs (const char *driver, int range, int chac, int chav[])
{
  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;
    }
  /* Read voltage at analog inputs.
   */
  for (i = 0; i < chac; i++)
    {
      float voltage;
      int rc;
      rc = ad_analog_in (adh, AD_CHA_TYPE_ANALOG_IN | chav[i], range, &voltage);
      if (rc == 0)
        printf ("cha %2d: %7.3f V\n", chav[i], voltage);
      else
        printf ("error: failed to read cha %d: err = %d\n", chav[i], rc);
    }
  /* Close DAQ system again.
   */
  ad_close (adh);
}
/* Show usage.
 */
void
usage ()
{
  printf ("usage: analog_in <driver> [ -r <range> ] <cha1> .. <chan>\n"
          "  <driver>     string to pass to ad_open()\n"
          "               - will prompt for name\n"
          "  <range>      range number of analog input\n"
          "  <cha1>       number of first analog input to read\n"
          "  <chan>       number of last analog input to read\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];
      /* 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 numbers and add those to the channel array.
       */
      chac = 0;
      for (i = start; i < argc; i++)
        {
          chav[chac] = atoi (argv[i]);
          chac++;
          if (chac >= 16)
            break;
        }
      /* Measure analog inputs and print results
       * to the console.
       */
      read_analog_inputs (name, range, chac, chav);
      if (strcmp (argv[1], "-") == 0)
        {
          printf ("press return to continue...\n");
          fgets (tmp, sizeof(tmp), stdin);
        }
      return 0;
    }
  else
    {
      usage ();
      return 1;
    }
}
// Libad Analog Input Example
//
// Example showing how to read the voltage at some analog inputs
// using bmcm's LIBAD4.
using System;
using LIBAD4;
static class Example
{
  // Read analog input(s).
  static void
  read_analog_inputs (string driver, int range, int[] chav)
  {
    // Open DAQ system.
    int adh = LIBAD.ad_open (driver);
    if (adh == -1)
      {
        Console.WriteLine ("failed to open {0}: err = {1}", driver, LIBAD.errno);
        return;
      }
    // Read voltage at analog inputs.
    for (int i = 0; i < chav.Length; i++)
      {
        float voltage = 0;
        int rc;
        rc = LIBAD.ad_analog_in (adh, LIBAD.AD_CHA_TYPE_ANALOG_IN | chav[i], range, ref voltage);
        if (rc == 0)
          Console.WriteLine ("cha {0,2}: {1,7:##0.000} V", chav[i], voltage);
        else
          Console.WriteLine ("error: failed to read cha {0}: err = {1}", chav[i], rc);
      }
    // Close DAQ system again.
    LIBAD.ad_close (adh);
  }
  // Show usage.
  static void
  usage ()
  {
    Console.WriteLine ("usage: analog_in <driver> [ -r <range> ] <cha1> .. <chan>");
    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>       number of first analog input to read");
    Console.WriteLine ("  <chan>       number of last analog input to read");
  }
  // 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 sytem 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 numbers and add those to the channel array.
        int[] chav = new int[argv.Length - start];
        for (int i = start; i < argv.Length; i++)
          chav[i - start] = int.Parse (argv[i]);
        // Measure analog inputs and print results
        // to the console.
        read_analog_inputs (name, range, chav);
        if (argv[0]== "-")
          {
            Console.WriteLine ("press return to continue...");
            Console.ReadLine ();
          }
        return 0;
      }
    else
      {
        usage ();
        return 1;
      }
  }
}
' Libad Analog Input Example
'
' Example showing how to read the voltage at some analog inputs
' using bmcm's LIBAD4.
Imports System
Imports LIBAD4
Module Example
  ' Read analog input(s).
  Sub read_analog_inputs (driver As String, range As Integer, ByVal chav As Integer())
    ' 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
    ' Read voltage at analog inputs.
    For i = 0 To chav.Length-1
      Dim voltage As Single = 0.0
      Dim rc As Integer
      rc = LIBAD.ad_analog_in (adh, LIBAD.AD_CHA_TYPE_ANALOG_IN or chav(i), range, voltage)
      If rc = 0 Then
        Console.WriteLine ("cha {0,2}: {1,7:##0.000} V", chav(i), voltage)
      Else
        Console.WriteLine ("error: failed to read 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_in <driver> [ -r <range> ] <cha1> .. <chan>")
    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>       number of first analog input to read")
    Console.WriteLine ("  <chan>       number of last analog input to read")
    Environment.Exit (1)
  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 numbers and add those to the channel array.
      Dim chav(argv.Length-1 - start) As Integer
      For i = start To argv.Length-1
        chav(i - start) = Int32.Parse (argv(i))
      Next
      ' Measure analog inputs and print results
      ' to the console.
      read_analog_inputs (name, range, chav)
      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
'''
 Libad Analog Input Example
 
 Example showing how to read the voltage at some analog inputs
 using bmcm's LIBAD4.
'''

from ctypes import *
from ctypes import GetLastError
import ctypes
from operator import le
import os.path
import sys


# Load the .dll file
my_path = os.path.abspath(os.path.dirname(__file__))
path = os.path.join(my_path, "libad4.dll")

try:
    libad = CDLL(os.path.join(my_path, "libad4.dll"))
except Exception as e:
    print(e)

libad.ad_open.argtypes = [ctypes.c_char_p]
libad.ad_analog_in.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_int]


# Read analog inputs.
def read_analog_input(driver, rng, cha):

    # Open DAQ System.
    adh = libad.ad_open(driver.encode('utf-8'))

    if adh == -1:
        print("failed to open %s: err = %r\n" % (driver, ctypes.GetLastError()))
        return

    # Read voltage at analog inputs.
    for i in range(len(cha)):
        voltage = c_float()

        rc = libad.ad_analog_in(adh, int(cha[i]), int(rng), byref(voltage))

        if rc == 0:
            print("cha %2d: %7.3f V" % (int(cha[i]), voltage.value))
        else:
            print("error: failed to read cha %d: err = %d\n" % (int(cha[i]), rc))

    #Close DAQ System again.
    libad.ad_close(adh)

def usage():
    print("usage: <driver> [ -r <range> ] <cha1> .. <chan>\n"
          "  <driver>     string to pass to ad_open()\n"
          "               - will prompt for name\n"
          "  <range>      range number of analog input\n"
          "  <cha1>       number of first analog input to read\n"
          "  <chan>       number of last analog input to read\n")

def main():
    argv = sys.argv

    if len(argv) > 1:

        # First command line argument is the DAQ's name.
        name = argv[1]

        # Range defaults to 0 but may get overridden by
        # -r on the command line.        
        start = 2
        rng = 0

        if len(argv) > 3:
            if '-r' in argv:
                rng = argv[argv.index('-r')+1]
                start += 2

        # Convert remaining command line arguments
        # into numbers and add those to the channel array.
        cha = [argv[i] for i in range(start, len(argv))]

        read_analog_input(name, rng, cha)
    else:
        usage()
        return 1


if __name__ =='__main__':
    main()