Visual Basic USB-1616HS DaqInScan with Asynchronous Digital Input & Output

The following example demonstrates how to continuously read data using DaqInScan and at the same time asynchronously controlling digital lines on FirstPortC. Helper functions are used but not shown as they typically are do not demonstrate MccDaq functionality. To view these function load the project attached to this article.

To access the API, add a reference to the MccDaq object. Adding the reference is usually accomplished by right clicking the Project [under the Project Explorer] and selecting Add Reference.

The functionality is fairly simple, the program puts data into the buffer and the program retrieves it one half buffer at a time. To command the API to sample continuously, the Scan Options enumeration Background and Continuous is used. How it collects data is it ping-pongs between reading the lower half then the upper in attempt to keep up with the incoming data. Care should be taken that data doesn't come so fast that the program fails to keep up. When this happens a buffer overrun occurs which is condition where unread data get overwritten.

For digital output, program uses use keyboard keys 0-3 as a signal to change the state of an I/O line on FirstPortC. In the digital update routine the program reads the digital output port and use an exclusive OR function (XOR) to flip the state. To continuously monitor the key input the program uses a loop and to read the input data it uses timer interrupt routine that fires off every 50mS.

Disclaimer: The attached Code or Example is provided As Is. It has not been tested or validated as a product, for use in a deployed application or system, or for use in hazardous environments. You assume all risks for use of the Code for Example.

import statements help reduce line length and typing
Imports MccDaq
Imports MccDaq.ChannelType
Imports MccDaq.Range
Imports MccDaq.ScanOptions
Imports MccDaq.DigitalPortType
Imports MccDaq.FunctionType
Imports MccDaq.ErrorInfo.ErrorCode
Imports MccDaq.MccService
Imports System.Convert
Imports System.Threading.Thread
Imports System.Timers
Imports System.IO

Module Module1

    Const BLOCKSIZE As Integer = 100 'samples per channel
    Const CHANNELCOUNT As Integer = 4
    Const SAMPLERATE As Integer = 100 'desired sample rate
    Const BUFFERSIZE As Integer = CHANNELCOUNT * BLOCKSIZE ' size of the buffer
    Const HALFBUFFER As Integer = BUFFERSIZE / 2 'size of half buffer
    Const TOTAL As Integer = SAMPLERATE * CHANNELCOUNT * 60 * 2 '2 minutes

    'AInScan running options
    Dim theOptions As MccDaq.ScanOptions = Continuous + Background + ConvertData


    Dim CurrentCount As Integer = 0 'indicates total samples taken
    Dim CurrentIndex As Integer = 0 'points to the last scan read

    Dim Status As Short = 0

    Dim theDevice As MccBoard 'device object
    Dim buffer As IntPtr
    Dim ret As ErrorInfo
    Dim ReadLower As Boolean = True 'semaphore flag that prevents duplicate buffer reads

    'text file name and path. Use ASC extension if using DASYLab software to read the file.
    Dim Path As String = "C:\Users\Public\Documents\theDataFile.asc"

    Dim fStream As StreamWriter

    Dim ChanArray(CHANNELCOUNT) As Short                    ' array to hold channel queue information
    Dim ChanTypeArray(CHANNELCOUNT) As MccDaq.ChannelType   ' array to hold channel type information
    Dim GainArray(CHANNELCOUNT) As MccDaq.Range             ' array to hold gain queue information
    Dim ChanText(CHANNELCOUNT) As String
    Dim ChanScale(CHANNELCOUNT) As Single



    Sub Main()

        Dim atimer As Timer
        Dim ret As MccDaq.ErrorInfo
        Dim bNum As Integer
        Dim str As String = "USB-1616HS"

        bNum = GetBoardNum(str)

        If bNum = -1 Then
            Console.WriteLine("No {0} detected!", str)
            WaitForKey()
            End
        End If

 

        'load the arrays with values
        ChanArray(0) = 0
        ChanTypeArray(0) = Analog
        GainArray(0) = Bip10Volts
        ChanText(0) = "In0 [V]" + vbTab
        ChanScale(0) = Convert.ToSingle(10.0 / 32768) 'volts per bit for the +/- 10 volt range

        ChanArray(1) = 1
        ChanTypeArray(1) = Analog
        GainArray(1) = Bip10Volts
        ChanText(1) = "In1 [V]" + vbTab
        ChanScale(1) = Convert.ToSingle(10.0 / 32768) 'volts per bit for the +/- 10 volt range

        ChanArray(2) = 3
        ChanTypeArray(2) = Analog
        GainArray(2) = Bip10Volts
        ChanText(2) = "In1 [V]" + vbTab
        ChanScale(2) = Convert.ToSingle(10.0 / 32768) 'volts per bit for the +/- 10 volt range

        ChanArray(3) = FirstPortA
        ChanTypeArray(3) = Digital16
        GainArray(3) = NotUsed
        ChanText(3) = "FirstPortA [dec]"
        ChanScale(3) = 1


        theDevice = New MccBoard(bNum) 'get the devices' programming object

        'set digital port C for output
        ret = theDevice.DConfigPort(FirstPortC, MccDaq.DigitalPortDirection.DigitalOut)
        If ret.Value <> MccDaq.ErrorInfo.ErrorCode.NoErrors Then
            Stop
        End If

        'let's start with all 8 bits low
        Dim PortVal As UShort = 0
        ret = theDevice.DOut(FirstPortC, PortVal)
        If ret.Value <> MccDaq.ErrorInfo.ErrorCode.NoErrors Then
            Stop
        End If

        buffer = MccService.WinBufAllocEx(BUFFERSIZE)
        atimer = New Timer
        atimer.AutoReset = True
        atimer.Interval = 50
        AddHandler atimer.Elapsed, AddressOf TimerEvent

        Console.WriteLine("This program reads channel 1,2,3 & FirstPortA as a 16 bit word." + vbCrLf)
        Console.WriteLine("The program will stream the data continously to:")
        Console.WriteLine("{0}{1}", Path, vbCrLf)
        Console.WriteLine("While doing this the digital output lines on Port C can be changed as follows:" + vbCrLf)

        Console.WriteLine("Keys 0 - 3 toggles the state of D0-D3 on FirstPortC." + vbCrLf)
        Console.WriteLine("Press <SPACE> to clear all...<ESC> exit program" + vbCrLf)
        WaitForKey()


        ret = theDevice.DaqInScan(ChanArray, ChanTypeArray, GainArray, CHANNELCOUNT, SAMPLERATE, 0, BUFFERSIZE, buffer, theOptions)
        If ret.Value <> MccDaq.ErrorInfo.ErrorCode.NoErrors Then Stop

        'create a text file to hold the data
        fStream = New StreamWriter(Path)
        CreateFileHeader()

        'Timer routines checks/reads data every 50mS
        atimer.Start()

        '''''''''''''''''''' MAIN LOOP ''''''''''''''''''''''''''
        Dim cki As ConsoleKeyInfo = New ConsoleKeyInfo
        Do

            If Console.KeyAvailable = True Then
                cki = Console.ReadKey()
                'call function to update digital outputs
                UpdateFirstPortC(cki)
            End If

        Loop Until ((cki.Key = ConsoleKey.Escape) Or (CurrentCount > TOTAL))
        ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        atimer.Stop()
        WaitForKey()
        theDevice.StopBackground(AiFunction)
        fStream.Close()
    End Sub

    Sub TimerEvent(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)


        ret = theDevice.GetStatus(Status, CurrentCount, CurrentIndex, MccDaq.FunctionType.DaqiFunction)
        If ret.Value <> MccDaq.ErrorInfo.ErrorCode.NoErrors Then Stop

        'ping pong between low half and upper half
        If ((CurrentIndex >= HALFBUFFER) And (ReadLower = True)) Then

            'read the lower half and set Upper flag to zero so that next read is upper half
            Dim theArray(BUFFERSIZE) As UShort
            ret = MccDaq.MccService.WinBufToArray(buffer, theArray, 0, HALFBUFFER)
            If ret.Value <> MccDaq.ErrorInfo.ErrorCode.NoErrors Then Stop

            ReadLower = False
            DisplayData(theArray, HALFBUFFER \ CHANNELCOUNT)

        ElseIf ((CurrentIndex < HALFBUFFER) And (ReadLower = False)) Then

            'read the upper half and set Upper flag to one so that next read is lower half
            Dim theArray(BUFFERSIZE) As UShort
            ret = MccDaq.MccService.WinBufToArray(buffer, theArray, HALFBUFFER, HALFBUFFER)
            If ret.Value <> MccDaq.ErrorInfo.ErrorCode.NoErrors Then Stop

            ReadLower = True
            DisplayData(theArray, HALFBUFFER \ CHANNELCOUNT)

        End If

    End Sub

    Sub UpdateFirstPortC(ByVal cki As ConsoleKeyInfo)
        'Function used to change level on individual FirstPortC lines

        Dim PortVal As UShort
        Dim ret As ErrorInfo = New ErrorInfo

        Select Case cki.Key

            Case ConsoleKey.D0

                ret = theDevice.DIn(FirstPortC, PortVal)
                PortVal = PortVal Xor 1
                ret = theDevice.DOut(DigitalPortType.FirstPortC, PortVal)

            Case ConsoleKey.D1

                ret = theDevice.DIn(FirstPortC, PortVal)
                PortVal = PortVal Xor 2
                ret = theDevice.DOut(DigitalPortType.FirstPortC, PortVal)

            Case ConsoleKey.D2

                ret = theDevice.DIn(FirstPortC, PortVal)
                PortVal = PortVal Xor 4
                ret = theDevice.DOut(DigitalPortType.FirstPortC, PortVal)

            Case ConsoleKey.D3

                ret = theDevice.DIn(FirstPortC, PortVal)
                PortVal = PortVal Xor 8
                ret = theDevice.DOut(DigitalPortType.FirstPortC, PortVal)

            Case ConsoleKey.Spacebar
                ret = theDevice.DOut(DigitalPortType.FirstPortC, 0)

        End Select
        If ret.Value <> MccDaq.ErrorInfo.ErrorCode.NoErrors Then Stop

    End Sub

Attachments
VBNET2008_USB-1616HS_CONT_READ_WITH_ASYNC_DIGITAL.zip