Giter Site home page Giter Site logo

nidaq.jl's Introduction

National Instruments Data Acquisition Interface

This package provides an interface to NI-DAQmx--- National Instruments' driver for their data acquisition boards. Their entire C header file was ported using Clang.jl, and a rudimentary higher-level API is provided for ease of use.

Similar functionality for the Python language is provided by PyDAQmx.

System Requirements

General

  • Supports Windows and Linux
  • NI-DAQmx Base is not supported

Linux specific

  • Requires the latest DAQmx (currently 20.1)
  • DAQmx on linux does not support USB DAQ devices

Installation

Windows
First download and install NI-DAQmx version 20.1 (or 19.6, 18.6; or for Julia 0.6, 17.1.0; or for Julia 0.5, 16.0.0; or for Julia 0.4, 15.1.1; or for Julia 0.3, 14.1.0, 14.0.0, or 9.6.0) from National Instruments.

Linux
The package only supports DAQmx 20.1 on linux. Follow the instructions from this support doc.

Adding NIDAQ.jl
Then on the Julia command line:

]add NIDAQ

Basic Usage

With no input arguments, the high-level getproperties function can be used to query the system:

julia> using NIDAQ

julia> getproperties()
Dict{String,Tuple{Any,Bool}} with 7 entries:
  "DevNames"           => (SubString{String}["Dev1"],false)
  "GlobalChans"        => (SubString{String}[""],false)
  "NIDAQMajorVersion"  => (0x00000010,false)
  "NIDAQMinorVersion"  => (0x00000000,false)
  "NIDAQUpdateVersion" => (0x00000000,false)
  "Scales"             => (SubString{String}[""],false)
  "Tasks"              => (SubString{String}[""],false)

Returned is a dictionary of tuples, the first member indicating the property value and the second a boolean indicating whether the former is mutable.

getproperties can also input a string containing the name of a data acquisition device:

julia> getproperties("Dev1")
Dict{String,Tuple{Any,Bool}} with 61 entries:
  "AIBridgeRngs"                           => (Float64[],false)
  "AICouplings"                            => (:Val_Transferred_From_Buffer,false)
  "AICurrentIntExcitDiscreteVals"          => (Float64[],false)
  "AICurrentRngs"                          => (Float64[],false)
  "AIDigFltrLowpassCutoffFreqDiscreteVals" => (Float64[],false)
  "AIDigFltrLowpassCutoffFreqRangeVals"    => (Float64[],false)
  "AIFreqRngs"                             => (Float64[],false)
  "AIGains"                                => (Float64[],false)
  "AILowpassCutoffFreqDiscreteVals"        => (Float64[],false)
  "AILowpassCutoffFreqRangeVals"           => (Float64[],false)
  "AIMaxMultiChanRate"                     => (2.0e6,false)
  "AIMaxSingleChanRate"                    => (2.0e6,false)
  "AIMinRate"                              => (0.0232831,false)
  "AIPhysicalChans"                        => (SubString{String}["Dev1/ai0","Dev1/ai1","Dev1/ai2",".
  "AIResistanceRngs"                       => (Float64[],false)
  "AISampModes"                            => (Symbol[:Val_FiniteSamps,:Val_ContSamps],false)
  "AISupportedMeasTypes"                   => (Symbol[:Val_Current,:Val_Resistance,:Val_Strain_Gage.
  "AITrigUsage"                            => (14,false)
  "AIVoltageIntExcitDiscreteVals"          => (Float64[],false)
  "AIVoltageIntExcitRangeVals"             => (Float64[],false)
  "AIVoltageRngs"                          => ([-1.0,1.0,-2.0,2.0,-5.0,5.0,-10.0,10.0],false)
  "AOCurrentRngs"                          => (Float64[],false)
  "AOGains"                                => (Float64[],false)
  "AOMaxRate"                              => (3.33333e6,false)
  "AOMinRate"                              => (0.0232831,false)
  "AOPhysicalChans"                        => (SubString{String}["Dev1/ao0","Dev1/ao1"],false)
  "AOSampModes"                            => (Symbol[:Val_FiniteSamps,:Val_ContSamps],false)
  "AOSupportedOutputTypes"                 => (Symbol[:Val_Voltage],false)
  "AOTrigUsage"                            => (10,false)
  "AOVoltageRngs"                          => ([-5.0,5.0,-10.0,10.0],false)
  "AccessoryProductNums"                   => (UInt32[0x00000000],false)
  "AccessoryProductTypes"                  => (SubString{String}[""],false)
  "AccessorySerialNums"                    => (UInt32[0x00000000],false)
  "BusType"                                => (:Val_USB,false)
  "CIMaxSize"                              => (0x00000020,false)
  "CIMaxTimebase"                          => (1.0e8,false)
  "CIPhysicalChans"                        => (SubString{String}["Dev1/ctr0","Dev1/ctr1","Dev1/ctr2.
  "CISampModes"                            => (Symbol[:Val_FiniteSamps,:Val_ContSamps],false)
  "CISupportedMeasTypes"                   => (Symbol[:Val_CountEdges,:Val_Freq,:Val_Period,:Val_Tw.
  "CITrigUsage"                            => (42,false)
  "COMaxSize"                              => (0x00000020,false)
  "COMaxTimebase"                          => (1.0e8,false)
  "COPhysicalChans"                        => (SubString{String}["Dev1/ctr0","Dev1/ctr1","Dev1/ctr2.
  "COSampModes"                            => (Symbol[:Val_FiniteSamps,:Val_ContSamps],false)
  "COSupportedOutputTypes"                 => (Symbol[:Val_Pulse_Freq,:Val_Pulse_Ticks,:Val_Pulse_T.
  "COTrigUsage"                            => (42,false)
  "ChassisModuleDevNames"                  => (SubString{String}[""],false)
  "DILines"                                => (SubString{String}["Dev1/port0/line0","Dev1/port0/lin.
  "DIMaxRate"                              => (1.0e7,false)
  "DIPorts"                                => (SubString{String}["Dev1/port0","Dev1/port1","Dev1/po.
  "DITrigUsage"                            => (14,false)
  "DOLines"                                => (SubString{String}["Dev1/port0/line0","Dev1/port0/lin.
  "DOMaxRate"                              => (1.0e7,false)
  "DOPorts"                                => (SubString{String}["Dev1/port0","Dev1/port1","Dev1/po.
  "DOTrigUsage"                            => (10,false)
  "NumDMAChans"                            => (0x00000000,false)
  "ProductCategory"                        => (:Val_XSeriesDAQ,false)
  "ProductNum"                             => (0x000075a1,false)
  "ProductType"                            => (SubString{String}["USB-6366 (64 MS) (Mass Terminatio.
  "SerialNum"                              => (0x01719e54,false)
  "Terminals"                              => (SubString{String}["/Dev1/PFI0","/Dev1/PFI1","/Dev1/P.

One can index into the dictionary to get a list of channels:

julia> getproperties("Dev1")["AIPhysicalChans"]
(SubString{ASCIIString}["Dev1/ai0","Dev1/ai1","Dev1/ai2","Dev1/ai3","Dev1/ai4","Dev1/ai5","Dev1/ai6","Dev1/ai7"],false)

A bit simpler in this case though is to use another high-level function which returns just the string Array:

julia> analog_input_channels("Dev1")
8-element Array{String,1}:
 "Dev1/ai0"
 "Dev1/ai1"
 "Dev1/ai2"
 "Dev1/ai3"
 "Dev1/ai4"
 "Dev1/ai5"
 "Dev1/ai6"
 "Dev1/ai7"

To add, for example, analog input channels, use the high-level analog_input function:

julia> t = analog_input("Dev1/ai0:1")
NIDAQ.AITask(Ptr{Nothing} @0x0000000025d18600)

julia> typeof(t)
NIDAQ.AITask (constructor with 3 methods)

julia> supertype(NIDAQ.AITask)
NIDAQ.Task

Two channels were added above using the : notation. Additional channels can be added later by inputing the returned Task:

julia> analog_input(t, "Dev1/ai2")

getproperties can also input a Task:

julia> getproperties(t)
Dict{String,Tuple{Any,Bool}} with 5 entries:
  "Devices"    => (SubString{String}["Dev1"],false)
  "Channels"   => (SubString{String}["Dev1/ai0","Dev1/ai1","Dev1/ai2"],false)
  "Name"       => (SubString{String}["_unnamedTask<0>"],false)
  "NumChans"   => (0x00000003,false)
  "NumDevices" => (0x00000001,false)

as well as a string containing the name of the channel:

julia> getproperties(t, "Dev1/ai0")
Dict{String,Tuple{Any,Bool}} with 52 entries:
  "AccelUnits"                        => (:Val_g,false)
  "AutoZeroMode"                      => (:Val_None,false)
  "BridgeUnits"                       => (:Val_VoltsPerVolt,false)
  "ChanCalDesc"                       => (SubString{String}[""],false)
  "ChanCalOperatorName"               => (SubString{String}[""],false)
  "ChanCalPolyForwardCoeff"           => (Float64[],false)
  "ChanCalPolyReverseCoeff"           => (Float64[],false)
  "ChanCalScaleType"                  => (:Val_Table,false)
  "ChanCalTablePreScaledVals"         => (Float64[],false)
  "ChanCalTableScaledVals"            => (Float64[],false)
  "ChanCalVerifAcqVals"               => (Float64[],false)
  "ChanCalVerifRefVals"               => (Float64[],false)
  "Coupling"                          => (:Val_DC,false)
  "CurrentACRMSUnits"                 => (:Val_Amps,false)
  "CurrentUnits"                      => (:Val_Amps,false)
  "CustomScaleName"                   => (SubString{String}[""],false)
  "DataXferMech"                      => (:Val_ProgrammedIO,false)
  "DataXferReqCond"                   => (:Val_OnBrdMemNotEmpty,false)
  "DevScalingCoeff"                   => ([0.000102924,0.000312673,5.87393e-14,-3.31855e-19],false)
  "EddyCurrentProxProbeUnits"         => (:Val_Meters,false)
  "ForceUnits"                        => (:Val_Newtons,false)
  "FreqUnits"                         => (:Val_Hz,false)
  "Gain"                              => (1.0,false)
  "InputSrc"                          => (SubString{String}["_external_channel"],false)
  "LVDTUnits"                         => (:Val_Meters,false)
  "LossyLSBRemovalCompressedSampSize" => (0x00000010,false)
  "Max"                               => (10.0,false)
  "MeasType"                          => (:Val_Voltage,false)
  "Min"                               => (-10.0,false)
  "PressureUnits"                     => (:Val_PoundsPerSquareInch,false)
  "RVDTUnits"                         => (:Val_Degrees,false)
  "RawDataCompressionType"            => (:Val_None,false)
  "RawSampJustification"              => (:Val_RightJustified,false)
  "RawSampSize"                       => (0x00000010,false)
  "ResistanceUnits"                   => (:Val_Ohms,false)
  "Resolution"                        => (16.0,false)
  "ResolutionUnits"                   => (:Val_Bits,false)
  "RngHigh"                           => (10.0,false)
  "RngLow"                            => (-10.0,false)
  "SoundPressureUnits"                => (:Val_Pascals,false)
  "StrainGageCfg"                     => (:Val_FullBridgeI,false)
  "StrainUnits"                       => (:Val_Strain,false)
  "TempUnits"                         => (:Val_DegC,false)
  "TermCfg"                           => (:Val_Diff,false)
  "ThrmcplCJCVal"                     => (25.0,false)
  "TorqueUnits"                       => (:Val_NewtonMeters,false)
  "UsbXferReqCount"                   => (0x00000004,false)
  "UsbXferReqSize"                    => (0x00008000,false)
  "VelocityUnits"                     => (:Val_MetersPerSecond,false)
  "VoltageACRMSUnits"                 => (:Val_Volts,false)
  "VoltageUnits"                      => (:Val_Volts,false)
  "VoltagedBRef"                      => (1.0,false)

Use setproperty! to change a mutable property:

julia> setproperty!(t, "Dev1/ai0", "Max", 5.0)

Once everything is configured, get some data using the read function:

julia> start(t)

julia> read(t, 10)
10x3 Array{Float64,2}:
 1.52407   -0.448835   0.381075
 1.37546   -0.213537   0.305847
 1.2363    -0.0268698  0.262826
 1.109      0.118619   0.243117
 0.995797   0.2311     0.240073
 0.896695   0.315782   0.248004
 0.811452   0.378752   0.262746
 0.739429   0.424257   0.281893
 0.679263   0.456223   0.302402
 0.629672   0.477774   0.323473

julia> stop(t)

julia> clear(t)

read can also return Int16, Int32, UInt16, and UInt32 by specifying those types as an additional argument:

julia> read(t, 10, Int16)
10ร—3 Array{Int16,2}:
 -12619  -5351  -13973
 -12618  -5350  -13973
 -12620  -5350  -13973
 -12619  -5350  -13974
 -12618  -5351  -13972
 -12618  -5348  -13974
 -12619  -5350  -13973
 -12619  -5350  -13973
 -12619  -5350  -13972
 -12620  -5350  -13973

Similar work flows exist for analog_output, digital_input, and digital_output. The high-level API also supports many counter functions too, including count_edges and generate_pulses. For a full list of convenience functions use the names function in Julia Base:

julia> names(NIDAQ)
25-element Array{Symbol,1}:
  :analog_output_channels 
  :digital_input_channels 
  :setproperty!           
  :line_to_line           
  :counter_input_channels 
  :counter_output_channels
  :NIDAQ                  
  :analog_voltage_input_ranges    
  :analog_current_input_ranges    
  :digital_input          
  :stop                   
  :generate_pulses        
  :count_edges            
  :digital_output_channels
  :analog_input           
  :channel_type           
  :analog_voltage_output_ranges   
  :analog_current_output_ranges   
  :devices                
  :digital_output         
  :getproperties          
  :quadrature_input       
  :analog_input_channels  
  :analog_output          
  :Bool32                 
  :clear                  

NIDAQmx is a powerful interface, and while NIDAQ.jl provides wrappers for all of it's functions, it only abstracts a few of them. If these don't suit your needs you'll have to dive deep into src/functions_V*.jl and src/constants_V*.jl. Complete documentation of this low-level API is here and here.

One situation where the low-level API is needed is to specify continous output of pulses using a counter:

julia> t = generate_pulses("Dev1/ctr0")
NIDAQ.COTask(Ptr{Nothing} @0x00000000059d8790)

julia> fieldnames(typeof(t))
(:th,)

julia> NIDAQ.CfgImplicitTiming(t.th, NIDAQ.Val_ContSamps, UInt64(1))
0

Note that tasks consist of just a single field th, and that this "task handle" is what must be passed into many low-level routines.

Also, for brevity NIDAQ.jl strips the "DAQmx" prefix to all functions and constants in NI-DAQmx, and converts the latter to 32 bits. One must still take care to caste the other inputs appropriately though.

Adding Support for a Version of NI-DAQmx

Install Clang.jl. If there are build problems, make sure that llvm-config is on your PATH, and that libclang can be found, as described in the Clang.jl README. Clang defaults to using a system installed version of LLVM. An alternative is to set BUILD_LLVM_CLANG=1 in Make.user, and compile Julia from source.

Find NIDAQmx.h, which usually lives in C:\Program Files (x86)\National Instruments\NI-DAQ\DAQmx ANSI C Dev\include.

Edit this header file as follows:

  • For NI-DAQmx v19.6 in NIDAQmx.h change __int64 int64 to long long int int64 and unsigned __int64 uInt64 to unsigned long long uInt64.
  • For NI-DAQmx v9.6.0 in NIDAQmx.h change defined(__linux__) to defined(__linux__) || defined(__APPLE__).

Then run Clang to produce the corresponding Julia files:

julia> using Clang
julia> wc = init(; headers = ["NIDAQmx.h"],
                   output_file = "NIDAQmx.jl",
                   common_file = "common.jl",
                   clang_includes = vcat(CLANG_INCLUDE),
                   clang_args = map(x->"-I"*x, find_std_headers()),
                   header_wrapped = (root, current)->root == current,
                   header_library = x->"NIDAQmx",
                   clang_diagnostics = true)
julia> run(wc)
$ mv NIDAQmx.jl src/functions_V<version>.jl
$ mv common.jl src/constants_V<version>.jl
$ rm LibTemplate.jl ctypes.jl

Finally, the following manual edits are necessary:

  • In constants_V<version>.jl
    • delete const CVICALLBACK = CVICDECL,
    • in NI-DAQmx v19.6 add struct CVITime; lsb::uInt64; msb::int64; end
    • in NI-DAQmx v17.1.0 comment out const CVIAbsoluteTime = VOID
    • change const bool32 = uInt32 to const bool32 = Bool32.
    • in NI-DAQmx v15 to v18 comment out using Compat
  • In functions_V<version>.jl
    • in NI-DAQmx v18 and earlier, globally search for Ptr and replace with Ref, then globally search for CallbackRef and replace with CallbackPtr.
    • globally search for Cstring and replace with SafeCstring
    • for Julia 0.7 support, replace type with _type

Author

Ben Arthur, [email protected]
Scientific Computing
Janelia Research Campus
Howard Hughes Medical Institute

Picture

nidaq.jl's People

Contributors

bjarthur avatar cody-g avatar halars avatar juliatagbot avatar petr-hlavenka avatar rubensrossi avatar urlicht avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

nidaq.jl's Issues

getproperties() takes excessive amount of time

When running the getproperties function. The call takes an excessive amount of time. This isn't a problem when just using the REPL and exploring, but any type of data acquisition script will likely suffer catastrophic timing results due to the use of getproperties in every read and write call.

Recommend either a struct for a task (allows people to break things by using native calls on a task instead of high level calls) or just multiple dispatch to have a more focused ccall specifically for reads and writes.

julia> @time getproperties()
  2.729390 seconds (859.03 k allocations: 53.213 MiB, 0.43% gc time)
Dict{String,Tuple{Any,Bool}} with 7 entries:
  "Tasks"              => (SubString{String}["CS", "MOSI", "MyAccelerationTask", "MyVoltageTask", "SCK", "SPI", "testVoltageTask"], false)
  "NIDAQUpdateVersion" => (0x00000000, false)
  "NIDAQMinorVersion"  => (0x00000006, false)
  "Scales"             => (SubString{String}[""], false)
  "DevNames"           => (SubString{String}["Dev1"], false)
  "GlobalChans"        => (SubString{String}[""], false)
  "NIDAQMajorVersion"  => (0x00000012, false)

julia> @time t = analog_input("Dev1/ai0")
  0.378259 seconds (509.50 k allocations: 25.669 MiB, 1.47% gc time)
NIDAQ.AITask(Ptr{Nothing} @0x0000000030c0f900)

julia> @time start(t)
  0.007996 seconds (2.82 k allocations: 158.683 KiB)

julia> @time read(t, Float64, 1)
  2.931029 seconds (1.33 M allocations: 76.679 MiB, 0.49% gc time)
1-element Array{Float64,1}:
 -0.0006444593315980392

julia> using Profile

julia> @profile read(t, Float64, 1)
1-element Array{Float64,1}:
 1.5828057680061097e-8

julia> Profile.print()
1    .\client.jl:436; _start()
 1 .\client.jl:284; exec_options(::Base.JLOptions)
  1 .\client.jl:346; run_main_repl(::Bool, ::Bool, ::Bool, ::Bool, ::Bool)
   1 .\essentials.jl:741; invokelatest
    1 .\essentials.jl:742; #invokelatest#1
     1 .\client.jl:362; (::getfield(Base, Symbol("##734#736")){Bool,Bool,Bool,Bool})(::Module)
      1 ...bot\worker\package_win64\build\usr\share\julia\stdlib\v1.1\REPL\src\REPL.jl:192; run_repl(::REPL.AbstractREPL, ::Any)
       1 ...bot\worker\package_win64\build\usr\share\julia\stdlib\v1.1\REPL\src\REPL.jl:1035; run_frontend(::REPL.LineEditREPL, ::REPL.REPLBackendRef)
        1 ...orker\package_win64\build\usr\share\julia\stdlib\v1.1\REPL\src\LineEdit.jl:2273; run_interface(::REPL.Terminals.TextTerminal, ::REPL.LineEdit.ModalInterface, ::REPL.LineEdit.MIState)
         1 .\essentials.jl:741; invokelatest
          1 .\essentials.jl:742; #invokelatest#1
           1 ...t\worker\package_win64\build\usr\share\julia\stdlib\v1.1\REPL\src\REPL.jl:714; (::getfield(REPL, Symbol("#do_respond#38")){Bool,getfield(REPL, Symbol("##48#57")){REPL.LineEditREPL,REPL.REPLHi...
            1 ...t\worker\package_win64\build\usr\share\julia\stdlib\v1.1\REPL\src\REPL.jl:140; print_response(::REPL.AbstractREPL, ::Any, ::Any, ::Bool, ::Bool)
             1 ...t\worker\package_win64\build\usr\share\julia\stdlib\v1.1\REPL\src\REPL.jl:155; print_response(::IO, ::Any, ::Any, ::Bool, ::Bool, ::Any)
              1 .\essentials.jl:741; invokelatest
               1 .\essentials.jl:742; #invokelatest#1
                1 .\multimedia.jl:287; display(::Any)
                 1 ...worker\package_win64\build\usr\share\julia\stdlib\v1.1\REPL\src\REPL.jl:135; display(::REPL.REPLDisplay, ::Any)
                  1 ...worker\package_win64\build\usr\share\julia\stdlib\v1.1\REPL\src\REPL.jl:131; display(::REPL.REPLDisplay, ::MIME{Symbol("text/plain")}, ::Any)
                   1 .\arrayshow.jl:316; show(::IOContext{REPL.Terminals.TTYTerminal}, ::MIME{Symbol("text/plain")}, ::Array{Float64,1})
                    1 .\show.jl:1837; summary
                     1 .\show.jl:1840; summary(::IOContext{REPL.Terminals.TTYTerminal}, ::Array{Float64,1}, ::Tuple{Base.OneTo{Int64}})
                      1 .\show.jl:1893; showarg
                       1 .\strings\io.jl:31; print(::IOContext{REPL.Terminals.TTYTerminal}, ::Type)
                        1 .\show.jl:436; show(::IOContext{REPL.Terminals.TTYTerminal}, ::DataType)
                         1 .\show.jl:526; show_datatype(::IOContext{REPL.Terminals.TTYTerminal}, ::DataType)
                          1 .\show.jl:436; show(::IOContext{REPL.Terminals.TTYTerminal}, ::DataType)
                           1 .\show.jl:532; show_datatype(::IOContext{REPL.Terminals.TTYTerminal}, ::DataType)
                            1 .\show.jl:458; show_type_name(::IOContext{REPL.Terminals.TTYTerminal}, ::Core.TypeName)
                             1 .\strings\io.jl:156; string
                              1 .\strings\io.jl:121; print_to_string(::Symbol)
                               1 .\none:0; Type
                                1 .\iobuffer.jl:114; #IOBuffer#316(::Bool, ::Bool, ::Nothing, ::Bool, ::Int64, ::Int64, ::Type)
                                 1 .\strings\string.jl:71; StringVector
1421 .\task.jl:259; (::getfield(REPL, Symbol("##26#27")){REPL.REPLBackend})()
 1421 ...dbot\worker\package_win64\build\usr\share\julia\stdlib\v1.1\REPL\src\REPL.jl:117; macro expansion
  1421 ...dbot\worker\package_win64\build\usr\share\julia\stdlib\v1.1\REPL\src\REPL.jl:85; eval_user_input(::Any, ::REPL.REPLBackend)
   1421 .\boot.jl:328; eval(::Module, ::Any)
    1420 C:\Users\aporter\.julia\packages\NIDAQ\BztQ2\src\analog.jl:71; read(::NIDAQ.AITask, ::DataType, ::Int64)
     1420 C:\Users\aporter\.julia\packages\NIDAQ\BztQ2\src\properties.jl:185; getproperties
      1420 C:\Users\aporter\.julia\packages\NIDAQ\BztQ2\src\properties.jl:185; #getproperties#35
       3    C:\Users\aporter\.julia\packages\NIDAQ\BztQ2\src\properties.jl:101; _getproperties(::Tuple{Ptr{Nothing}}, ::String, ::Bool)
        3 .\none:0; #names
         3 .\reflection.jl:98; #names#7
          3 .\sort.jl:682; sort!
           3 .\sort.jl:694; #sort!#7
            3 .\sort.jl:634; sort!
             3 .\sort.jl:539; sort!
              2 .\sort.jl:545; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array{Sym...
               1 .\sort.jl:545; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array{Sy...
                1 .\sort.jl:545; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array{Sy...
                 1 .\sort.jl:546; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array{S...
                  1 .\sort.jl:546; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array{S...
                   1 .\sort.jl:546; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array{...
                    1 .\sort.jl:545; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array...
                     1 .\sort.jl:545; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array...
                      1 .\sort.jl:557; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Arra...
                       1 .\ordering.jl:49; lt
                        1 .\strings\basic.jl:319; isless
                         1 .\strings\basic.jl:317; cmp
                          1 .\c.jl:234; unsafe_convert
                           1 .\pointer.jl:58; unsafe_convert
               1 .\sort.jl:546; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array{Sy...
                1 .\sort.jl:546; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array{Sy...
                 1 .\sort.jl:546; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array{S...
                  1 .\sort.jl:545; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array{S...
                   1 .\sort.jl:546; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array{...
                    1 .\sort.jl:545; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array...
                     1 .\sort.jl:545; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array...
                      1 .\sort.jl:557; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Arra...
                       1 .\ordering.jl:49; lt
                        1 .\strings\basic.jl:319; isless
                         1 .\strings\basic.jl:317; cmp
              1 .\sort.jl:546; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array{Sym...
               1 .\sort.jl:546; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array{Sy...
                1 .\sort.jl:545; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array{Sy...
                 1 .\sort.jl:546; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array{S...
                  1 .\sort.jl:545; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array{S...
                   1 .\sort.jl:545; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array{...
                    1 .\sort.jl:546; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array...
                     1 .\sort.jl:545; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Array...
                      1 .\sort.jl:546; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Arra...
                       1 .\sort.jl:546; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Arra...
                        1 .\sort.jl:540; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.MergeSortAlg, ::Base.Order.ForwardOrdering, ::Arr...
                         1 .\sort.jl:455; sort!(::Array{Symbol,1}, ::Int64, ::Int64, ::Base.Sort.InsertionSortAlg, ::Base.Order.ForwardOrdering)
                          1 .\ordering.jl:49; lt
                           1 .\strings\basic.jl:319; isless
                            1 .\strings\basic.jl:317; cmp
       1409 C:\Users\aporter\.julia\packages\NIDAQ\BztQ2\src\properties.jl:102; _getproperties(::Tuple{Ptr{Nothing}}, ::String, ::Bool)
        1403 C:\Users\aporter\.julia\packages\NIDAQ\BztQ2\src\NIDAQ.jl:21; eval
         1403 .\boot.jl:328; eval
       5    C:\Users\aporter\.julia\packages\NIDAQ\BztQ2\src\properties.jl:103; _getproperties(::Tuple{Ptr{Nothing}}, ::String, ::Bool)
        2 .\strings\basic.jl:229; *
         1 .\strings\substring.jl:180; string(::String, ::String)
          1 .\strings\string.jl:60; _string_n
           1 .\essentials.jl:355; cconvert
            1 .\number.jl:7; convert
             1 .\boot.jl:738; Type
              1 .\boot.jl:708; toUInt64
               1 .\boot.jl:597; check_top_bit
         1 C:\Users\aporter\AppData\Local\Julia-1.1.0\lib\julia\sys.dll:?; #s5#3(::Any, ::Any, ::Any, ::Any)
        1 .\strings\io.jl:156; string
         1 .\strings\io.jl:123; print_to_string(::Symbol)
          1 .\show.jl:158; print
           1 .\io.jl:509; write
            1 .\iobuffer.jl:414; unsafe_write(::Base.GenericIOBuffer{Array{UInt8,1}}, ::Ptr{UInt8}, ::UInt64)
        1 .\strings\string.jl:247; getindex
       1    C:\Users\aporter\.julia\packages\NIDAQ\BztQ2\src\properties.jl:109; _getproperties(::Tuple{Ptr{Nothing}}, ::String, ::Bool)
        1 .\refpointer.jl:84; Ref{Bool32}(::Int64)
         1 .\refvalue.jl:8; Base.RefValue{Bool32}(::Int64)
          1 .\number.jl:7; convert(::Type{Bool32}, ::Int64)
       2    C:\Users\aporter\.julia\packages\NIDAQ\BztQ2\src\properties.jl:155; _getproperties(::Tuple{Ptr{Nothing}}, ::String, ::Bool)
        2 .\array.jl:705; iterate
         1 .\array.jl:729; getindex
         1 .\array.jl:199; length

Cannot get Available Samples Per Channel

I'm trying to read from my NI 6363 X Series card in continuous mode. I keep running into issues where the buffer overflows after some time even though I am reading faster than the low sample rate I set using CfgSampClkTiming.

I would like to use DAQmxGetReadAvailSampPerChan to get the number of samples in the buffer. However, it only returns 0 when the task is running and -200983 when it is stopped. In particular, I'm not sure what I should pass in as the data parameter. I'm currently passing in an empty Int32 array. Any help is appreciated.

NIDAQmx version 16.1.0 is not supported

julia> using NIDAQ
INFO: Precompiling module NIDAQ.
ERROR: LoadError: NIDAQmx version 16.1.0 is not supported.

Also there was a recent bugfix that advanced version 16.0.0 to 16.0.1.

Runtime error on Julia 0.4-rel

The Pkg.test("NIDAQ") is failing on the first lines of test code.
On the 4th line of runtest.jl the call to

    d = devices()[1]

the error is

ERROR: LoadError: MethodError: `convert` has no method matching convert(::Type{P
tr{UInt8}}, ::Array{UInt8,1})                                                   
This may have arisen from a call to the constructor Ptr{UInt8}(...),            
since type constructors fall back to convert methods.                           
Closest candidates are:                                                         
  call{T}(::Type{T}, ::Any)                                                     
  convert{T<:Union{Int8,UInt8}}(::Type{Ptr{T<:Union{Int8,UInt8}}}, ::Cstring)   
  convert{T}(::Type{Ptr{T}}, ::UInt64)                                          
  ...                                                                           
 in devices at c:\Users\phlavenk\JuliaData\v0.4\NIDAQ\src\properties.jl:5       
 in include at boot.jl:261                                                      
 in include_from_node1 at loading.jl:304                                        
 in process_options at client.jl:308                                            
 in _start at client.jl:411                                                     
while loading c:\Users\phlavenk\JuliaData\v0.4\NIDAQ\test\runtests.jl, in expres
sion starting on line 4                                                         
================================[ ERROR: NIDAQ ]================================

The devices() function is defined in properties.jl code as:

    function devices()
        println("Here devices")
        sz = GetSysDevNames(convert(Ptr{UInt8},C_NULL), UInt32(0))
        data=zeros(UInt8,sz)
        catch_error(GetSysDevNames(convert(Ptr{UInt8}, data), UInt32(sz)))
        map((x)->convert(ASCIIString,x), split(chop(string(char(data)...)),", "))
    end

The problem is in the convert(Ptr{UInt8}, data) part to obtain the UInt8 pointer to array to pass to a function GetSysDevNames generated by Clang.jl
interestingly, if I execute this function line-by-line on the REPL the conversion runs just fine.

Could you please help me to fix this pointer conversion on 0.4.0?
Thanks a lot.

Petr

Test errors due to unsupported features of USB 6002 device

I just discovered that digital input, output, and counter tests fail for my USB 6002 device. The digital io failures seem to happen because this device doesn't support buffered digital io. The counter test fails because the device doesn't have any counter channels, and the check for that in the tests doesn't quite work as intended. I have fixes that I can submit as a PR after #6 merges.

Linux support update after NI's new driver support

This support article from August says that now you can install NI-DAQmx or NI-DAQmx Base on Ubuntu. Does this mean that this package can be modified to work with a linux system?

https://knowledge.ni.com/KnowledgeArticleDetails?id=kA00Z00000159XISAY&l=en-US

"Q: I am running a computer with an Ubuntu operating system. Is NI-DAQmx or NI-DAQmx Base supported on Ubuntu?

A: As of the NI Linux Device Drivers 2020, NI-DAQmx is supported on Unbuntu 18.04. Prior to this version, NI-DAQmx was not supported on Unbuntu. Please see the NI-DAQmx for Linux 20.1 readme for a list of devices supported by the NI-DAQmx for Linux driver."

cannot add aichannels past ai7

When trying to add channels past ai7, i get this error:

julia> t = analog_input("Dev1/ai10")
ERROR: NIDAQmx: Requested value is not a supported value for this property. The property value may be invalid because it conflicts with another property.

I believe this is caused by:

Ref(codeunits(channel),1)

I have tested changing this to simply pointer(channel) and pointer(""). Will do a pull request once I'm finished breaking, then fixing.

Bool32 sometimes very difficult to use

Bool32 is defined as a 32 bit primitive but no methods of any kind are available so some functions that use this argument are difficult to use. Is there a specific reason for this? Couldn't Bool32 be defined as a Int32?

Replace the line in NIDAQ.jl
primitive type Bool32<:Integer 32 end

with
const Bool32 = Int32

Paulo

Sync modules

Hi everyone,

currently I use LabVIEW to acquire the data from a cDAQ 9185 or 9189 and send it then to Julia for calculations.
I managed to read the cDAQ directly with this nice package, however there is one DAQmx function that gives me troubles.

I need to sync the acquisition with all the modules present in the cDAQ (1x NI9215 and 3x NI9229) and so far as I understood, I have to use the DAQmxGetSampClkTimebaseSrc -> DAQmxSetSampClkTimebaseSrc and DAQmxGetSampClkTimebaseRate -> DAQmxSetSampClkTimebaseRate.

Under LabVIEW everything works, but the code is hidden and I cannot find out which functions exactly are used or how they are called.

When I use Julia (Windows, Julia 1.6.1), I get always a -200077 error (Requested value is not a supported value for this property.).

This is what I tried:

task1 = analog_input(dev_name*"Mod4"*"/ai0", range = [-20,20]) # works
task2 = analog_input(dev_name*"Mod3"*"/ai0", range = [-20,20]) # works

# set the fs and continuous sampling
mod_fs = 1e5
NIDAQ.CfgSampClkTiming(task1.th,convert(Ref{UInt8},b""),mod_fs,NIDAQ.Val_Rising,NIDAQ.Val_ContSamps,mod_fs*2) # works
NIDAQ.CfgSampClkTiming(task2.th,convert(Ref{UInt8},b""),mod_fs,NIDAQ.Val_Rising,NIDAQ.Val_ContSamps,mod_fs*2) # works

data = 0.
NIDAQ.DAQmxGetSampClkTimebaseRate(task1.th,Ref(data)) # -> error -200077
data_rate = Ref{Float64}(0)
NIDAQ.DAQmxGetSampClkTimebaseRate(task1.th,data_rate) # -> error -200077
data_div = convert(Ref{UInt32},C_NULL)
NIDAQ.DAQmxGetSampClkTimebaseDiv(task1.th,data_div) # -> error -200077

Any idea would be welcome,

Thanks in advance
Rubens

getproperties() returns truncated property names

Hello,
getproperties() function return truncated key/property names.
Please see below for an example:

Example (Windows 10, Julia 1.2, DAQmx 18.6):

julia> getproperties()                                                                                                  

Dict{String,Tuple{Any,Bool}} with 6 entries:
"Chans"        => (SubString{String}[""], false)                                                                        "ajorVersion"  => (0x00000012, false)                                                                                   "inorVersion"  => (0x00000006, false)
"es"           => (SubString{String}["Dev1"], false)
""             => (SubString{String}["MyVoltageOutTask"], false)                                                        "pdateVersion" => (0x00000000, false)   

TagBot trigger issue

This issue is used to trigger TagBot; feel free to unsubscribe.

If you haven't already, you should update your TagBot.yml to include issue comment triggers.
Please see this post on Discourse for instructions and more details.

If you'd like for me to do this for you, comment TagBot fix on this issue.
I'll open a PR within a few hours, please be patient!

Error when adding a analogue channel from a cDAQ module

I'm having trouble adding analogue channels of a NI module. I have one device (Dev1) and one chassis (Dev2) with a module (Dev2Mod1)., connected. Output from getproperties:

julia> getproperties()["DevNames"][1]
3-element Array{SubString{String},1}:
 "Dev1"
 "Dev2"
 "Dev2Mod1"

Here are the outputs from analog_input_channels for each element:

julia> analog_input_channels("Dev1")
8-element Array{String,1}:
 "Dev1/ai0"
 "Dev1/ai1"
 "Dev1/ai2"
 "Dev1/ai3"
 "Dev1/ai4"
 "Dev1/ai5"
 "Dev1/ai6"
 "Dev1/ai7"

julia> analog_input_channels("Dev2")
1-element Array{String,1}:
 ""

julia> analog_input_channels("Dev2Mod1")
4-element Array{String,1}:
 "Dev2Mod1/ai0"
 "Dev2Mod1/ai1"
 "Dev2Mod1/ai2"
 "Dev2Mod1/ai3"

Trying to add channel 1 from Dev1 is successful:

julia> t = analog_input("Dev1/ai0")
NIDAQ.AITask(Ptr{Void} @0x000000000370a8a0)

But trying to add channel 1 for Dev2Mod1 is unsuccessful.

julia> t2 = analog_input("Dev2Mod1/ai0")
ERROR: NIDAQmx: Requested value is not a supported value for this property. The property value may be invalid because it conflicts with another property.
Stacktrace:
 [1] #catch_error#1(::Base.#error, ::Function, ::Int32, ::String) at C:\Users\lars\.julia\v0.6\NIDAQ\src\NIDAQ.jl:96
 [2] catch_error(::Int32) at C:\Users\lars\.julia\v0.6\NIDAQ\src\NIDAQ.jl:89
 [3] #analog_input#3(::String, ::Void, ::Function, ::NIDAQ.AITask, ::String) at C:\Users\lars\.julia\v0.6\NIDAQ\src\analog.jl:25
 [4] (::NIDAQ.#kw##analog_input)(::Array{Any,1}, ::NIDAQ.#analog_input, ::NIDAQ.AITask, ::String) at .\<missing>:0
 [5] #analog_input#2 at C:\Users\lars\.julia\v0.6\NIDAQ\src\analog.jl:15 [inlined]
 [6] analog_input(::String) at C:\Users\lars\.julia\v0.6\NIDAQ\src\analog.jl:14

I suspect no device/driver issues as there is no issue when using Matlab and its DAQ interface.

How should one add such a channel?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.