'''
This example illustrates how pyrwi simplifies a lot of data acqusition
tasks.
'''
import sys
#Include the parent directory in the search path so that Python can
#find pyrwi
sys.path.append("..")
#Load the nidaqmx library and name it DAQmx so that all functions
#are available as DAQmx.function_name
import nidaqmx as DAQmx
import pyrwi #Load the PyRWI module so we can use its helpers
#pyFLTK is used to build the actual GUI
#See http://pyfltk.sourceforge.net/docs/CH0_Preface.html for more info
import fltk
#Load the math library to give us arrays and math functions
import scipy as sp
class LabWindow (pyrwi.RWI_Window):
'''
We make own window class so we can customize the window how we want.
Note that this window inherits from pyrwi.RWI_Window.
pyrwi.RWI_Window creates a lot of things for you. It automatically
includes a menu and a log. It also does some background work to
allow DAQmx to raise callbacks.
'''
def __init__(self, w, h, label):
'''
Create the window and place puttons on it.
'''
#Call the parent constructor
pyrwi.RWI_Window.__init__(self, w, h, label)
#Note there is no menu or log declarations here. Inheriting from
#pyrwi.RWI_Window does that for us.
#Create teh same button stack as was in gui_basic.py, just
#in a different order and they are in a row instead of column.
stack = pyrwi.Fl_Button_Stack(5,50,90,25,pdx=0.25)
self.run_btn = stack.addBtn("Run",self.btn_run_cb,"light")
stack.addBtn("Clear",self.btn_clear_cb)
stack.addBtn("Add",self.btn_addData_cb)
#Create a plot so I can show the data I read
self.myPlot = pyrwi.Fl_Plot(110,90, 400,200, "DAQ Reading")
#
# Logic Code
#
def configureTask(self) :
'''
This creates a new DAQmx task and configures that task.
The task is stored in the class as self.task.
'''
self.Fs = 1000.0 # Samples / second
self.nSamples = 100 #Number of samples to read into DAQ buffer
# before calling Python to empty the buffer
self.task = DAQmx.CreateTask("ContAcq") #Create a new task
DAQmx.CreateAIVoltageChan(self.task,"Dev1/ai0","",\
DAQmx.Val_Cfg_Default,-10.0,10.0,\
DAQmx.Val_Volts,None) #Configure to read a voltage
#Configure a continuous clock
DAQmx.CfgSampClkTiming(self.task,"",self.Fs,\
DAQmx.Val_Rising,DAQmx.Val_ContSamps,\
self.nSamples)
#The pyrwi.ReadChannelHelper handles the DAQ reads for you.
#With every read it updates the plot and also takes care of
#saving data to a file for you.
self.readHelper = pyrwi.ReadChannelHelper(self.task, self.myPlot, 'test.csv', buf_time=1.0)
#buf_time limits the plot to the last second of data. All data
#will be written to the file though.
#Tell DAQmx who to call every time the buffer fills.
DAQmx.RegisterEveryNSamplesEvent(self.task, DAQmx.Val_Acquired_Into_Buffer,\
self.nSamples,0,DAQmx.ReadAnalogF64_cb, self.readHelper.cb_AnalogRead)
#The 5th & 6th arguments work together. The 6th is a Python function
#that handles reading from the buffer. The 5th is a C function
#in the nidaqmx library that determines how the Python function
#will be called
#
#For the 5th argument you must supply one of three functions:
#1) DAQmx.EveryNCallPython_cb - This is the generic call back
# the Python function will have to empty the buffer on its
# own. This can be slow.
#2) DAQmx.ReadAnalogF64_cb - This is optimized for analog reads
# it will read analog data from the buffer for you
# and pass the data as a list to the Python function
#3) DAQmx.ReadDigitalU32_cb - This is like ReadAnalogF64_cb
# but reads 32bit digital data instead
#
#Typically you have to write your own Python function for the 6th
#argument, but the pyrwi.ReadChannelHelper provides a pre-written
#function for you and that is what is used here.
#
# Event Call Backs
#
def btn_run_cb(self, event) :
'''
This function is called when the Run button is pressed.
'''
self.log.note("Pushed! Value is %d" % self.run_btn.value())
if self.run_btn.value() == 1 :
#The button just turned on
self.log.note("Starting task")
self.configureTask() #Setup the task
DAQmx.StartTask(self.task) #start reading data
else :
#The button was just turned off
#Data be read continuously until we stop the task
DAQmx.StopTask(self.task)
#Delete the task
DAQmx.ClearTask(self.task)
def btn_clear_cb(self, event):
'''
This function is called when the Clear button is pressed.
'''
self.log.note("clear something!")
self.myPlot.clear()
def btn_addData_cb(self, event):
'''
This function is called when the Add button is pressed.
In this function will will make a single analog measurement.
'''
Fs = 10000.0
nSamples = 1000
#Create a configure a new task for this measurement.
taskHandle = DAQmx.CreateTask("AnalogAcq")
DAQmx.CreateAIVoltageChan(taskHandle,"Dev1/ai0","",DAQmx.Val_Cfg_Default,-10.0,10.0,DAQmx.Val_Volts,None)
DAQmx.CfgSampClkTiming(taskHandle,"",Fs,DAQmx.Val_Rising,DAQmx.Val_FiniteSamps,nSamples)
#Read the data right now
DAQmx.StartTask(taskHandle)
#Get the data from the DAQ buffer
data = DAQmx.ReadAnalogF64(taskHandle,nSamples,10.0,DAQmx.Val_GroupByChannel,nSamples,None)
DAQmx.StopTask(taskHandle)
DAQmx.ClearTask(taskHandle)
#Make a nice time vector for plotting the data
x = sp.arange(0,nSamples/Fs, 1.0/Fs)
#Plot the data
self.myPlot.plot(x,data)
if __name__ == "__main__" :
win = LabWindow(600, 500, "MyWindow")
win.show(1, sys.argv)
fltk.Fl.run()