01-22-2013 03:24 PM
Hello,
I am trying to write an aquisition program for digital input coming from a hall sensor. I will be passing a magnet over a hall sensor on a motor and want to record the number of rotations. I have pasted together a script based on various websites, but it isn't functioning the way I want. I would like to be able to collect data points indefinately, or fixed, and then print out the resulting count. I have attepted to use the ctypes wrapper in Python. The NI functions remain unchanged though, so if you don't know Python it shouldn't be a problem to read. I am using a NI PCI-6503.
The code:
# C:\Program Files\National Instruments\NI-DAQ\Examples\DAQmx ANSI C\Analog In\Measure Voltage\Acq-Int Clk\Acq-IntClk.c
import ctypes
import numpy
nidaq = ctypes.windll.nicaiu # load the DLL
##############################
# Setup some typedefs and constants
# to correspond with values in
# C:\Program Files\National Instruments\NI-DAQ\DAQmx ANSI C Dev\include\NIDAQmx.h
# the typedefs
int32 = ctypes.c_long
uInt32 = ctypes.c_ulong
uInt64 = ctypes.c_ulonglong
float64 = ctypes.c_double
TaskHandle = uInt32
# the constants
DAQmx_Val_ChanForAllLines = int32(0)
##############################
def CHK(err):
"""a simple error checking routine"""
if err < 0:
buf_size = 200
buf = ctypes.create_string_buffer('\000' * buf_size)
nidaq.DAQmxGetErrorString(err,ctypes.byref(buf),buf_size)
raise RuntimeError('nidaq call failed with error %d: %s'%(err,repr(buf.value)))
# initialize variables
taskHandle = TaskHandle(0)
max_num_samples = 1000
# array to gather points
data = numpy.zeros((max_num_samples,),dtype=numpy.float64)
# now, on with the program
CHK(nidaq.DAQmxCreateTask("",ctypes.byref(taskHandle)))
CHK(nidaq.DAQmxCreateDIChan(taskHandle,'Dev1/port1/line1',"", DAQmx_Val_ChanForAllLines))
CHK(nidaq.DAQmxStartTask(taskHandle))
read = int32()
CHK(nidaq.DAQmxReadDigitalU32(taskHandle,int32(-1),float64(1),DAQmx_Val_GroupByChannel,data.ctypes.data,max_num_samples,ctypes.byref(read),None))
print "Acquired %d points"%(read.value)
if taskHandle.value != 0:
nidaq.DAQmxStopTask(taskHandle)
nidaq.DAQmxClearTask(taskHandle)
print "End of program, press Enter key to quit"
raw_input()
This script returns "Acquired 1 points" immediately, regardless of how many times the hall sensor has been switched.
I apologize for the sloppy code, but I understand very little of the underlying principles of these DAQ functions, despite reading their documentation. Seeing as how the code does not return an error, I am hoping there is just a minor tweak or two that will be farily obvious to someone with more experience.
Thanks
01-23-2013 09:21 AM - edited 01-23-2013 09:22 AM
Hello
I don't understand much of Python, but the error might be on how you are updating your read array with values. What does the line read = int32()
do? Are you assigning it the value of a function, or is it a declaration?
Notice that on the DAQmx example ReadDigChan.c (Start » Programs » National Instruments » NI-DAQ » Text-Based Code Support Digital » Read Values) we acquire 100 values and write them to "data", our read array. In the example, we read the samples using the function
printf("Data acquired, channel %d: 0x%X\n",i,data[i]);
You are missing printing out the data that holds the actual read values, in the example’s case, data[i]. I hope this helps.
01-24-2013 10:28 AM
Hello and thanks for the reply.
So the read variable, from what I can tell, hold hows many points were returned by the function. That is why read.value always is returning 1. I think this is what is happening. Also, yes, printing data[0], displayed the value returned by the read function. Subsequent calls to the functions did not accumulate new points into the array though. For example, after three calls to the read function, the array 'data', looks like this: [1,,,,,,], instead of this [1,1,1,,,,].
My hardware doesn't do timing, so time functions are not accepted, and that is why I figured if I just ran the read function in a loop, the values would accumulate in the 'data' array, which they didn't. Do you know why this might be?
Thanks again,
Paul
01-31-2013 04:44 PM
/*********************************************/
// DAQmx Read Code
/*********************************************/
DAQmxErrChk (DAQmxReadDigitalLines(taskHandle,1,10.0,DAQmx_Val_GroupByChannel,data,100,&read,&bytesPerSamp,NULL));
// assuming 8 channels acquired
for(Samp2Read=0;Samp2Read<2;Samp2Read++){
for(i=0;i<8;++i)
printf("Data acquired, channel %d: 0x%X\n",i,data[i]);
printf("read= %d",read);
Sleep(1000);
}
On your code I see
CHK(nidaq.DAQmxReadDigitalU32(taskHandle,int32(-1),float64(1),DAQmx_Val_GroupByChannel,data.ctypes.data,max_num_samples,ctypes.byref(read),None))
Are you setting the parameter as a pointer?
02-01-2013 10:20 AM
Thank you for the reply. I decided just to run the function in a Python loop and collect the each value in a list. I worked out well. Thank you for your help though.
Paul
02-04-2013 11:35 AM
Hi Paul,
I'm glad it's working. In case anyone else has this problem in the future, could you post your working Python code here? Thanks for making our community grow.
02-04-2013 01:35 PM
Hey Daniel,
Most of this script is from http://www.scipy.org/Cookbook/Data_Acquisition_with_NIDAQmx.
I needed to run the ReadDigitalU32 function in Python loop because my DAQ device did not support timed aquistion and I don't have LabView.
import numpy
import time
import ctypes
nidaq = ctypes.windll.nicaiu # load the DLL
##############################
# Setup some typedefs and constants
# to correspond with values in
# C:\Program Files\National Instruments\NI-DAQ\DAQmx ANSI C Dev\include\NIDAQmx.h
# the typedefs
int32 = ctypes.c_long
uInt32 = ctypes.c_ulong
uInt64 = ctypes.c_ulonglong
float64 = ctypes.c_double
TaskHandle = uInt32
# the constants
DAQmx_Val_Cfg_Default = int32(-1)
DAQmx_Val_Volts = 10348
DAQmx_Val_Rising = 10280
DAQmx_Val_FiniteSamps = 10178
DAQmx_Val_GroupByChannel = 0
DAQmx_Val_ChanForAllLines = int32(0)
# initialize variables
taskHandle = TaskHandle(0)
max_num_samples = 10000
data = numpy.zeros((max_num_samples,),dtype=numpy.float64)
read = uInt32()
bufferSize = uInt32(10000)
def CHK(err):
"""a simple error checking routine"""
if err < 0:
buf_size = 200
buf = ctypes.create_string_buffer('\000' * buf_size)
nidaq.DAQmxGetErrorString(err,ctypes.byref(buf),buf_size)
raise RuntimeError('nidaq call failed with error %d: %s'%(err,repr(buf.value)))
# Start up DAQ
CHK(nidaq.DAQmxCreateTask("",ctypes.byref(taskHandle)))
CHK(nidaq.DAQmxCreateDIChan(taskHandle,"Dev?/port?/line?","", DAQmx_Val_ChanForAllLines))
CHK(nidaq.DAQmxStartTask(taskHandle))
#initialize lists and time 1
t1 = time.time()
times = []
points = []
while True:
try:
CHK(nidaq.DAQmxReadDigitalU32(taskHandle,int32(-1),float64(1),
DAQmx_Val_GroupByChannel,data.ctypes.data,uInt32(2*bufferSize.value)
,ctypes.byref(read), None))
t2 = time.time()
#data[0] is the position in the numpy array 'data' that holds the value aquired
#from your device
points.append(data[0])
times.append(t2 - t1)
t1 = time.time()
#Choose time interval between data aquisition
time.sleep(.02)
except KeyboardInterrupt:
break
#process the lists of points and time intervals as you so choose
Thanks for the help!
Paul