10-13-2011 02:19 PM - edited 10-13-2011 02:23 PM
Hi guys, need a little help on this one. I have a cDAQ-9178 chassis with Analog In modules for reading voltage, current, and temp. 24 channels all together in my task. Using VB6 for programming. I would like to read 50 (or more, but for this example lets just say 50) samples per second per channel, and then average those 50 samples to get an average reading per second. I'm hoping this will eliminate the fluctuations/noise in my readings. Code as follows:
Form_Load()
numSampsPerChannel = 50
DAQmxErrChk DAQmxCreateTask("", myAITask)
DAQmxErrChk DAQmxCreateAIVoltageChan(myAITask, "cDAQ1Mod1/ai0:7", "", DAQmx_Val_Cfg_Default, 0, 10, DAQmx_Val_VoltageUnits2_Volts, "")
DAQmxErrChk DAQmxCreateAICurrentChan(myAITask, "cDAQ1Mod2/ai0:7", "", DAQmx_Val_Cfg_Default, 0#, 0.02, DAQmx_Val_CurrentUnits2_Amps,_ DAQmx_Val_CurrentShuntResistorLocation1_Internal, 100, "")
DAQmxErrChk DAQmxCreateAIThrmcplChan(myAITask, "cDAQ1Mod3/ai0:3", "", 0, 400, DAQmx_Val_DegF, DAQmx_Val_ThermocoupleType1_J_Type_TC, DAQmx_Val_CJCSource1_BuiltIn, 0#, "")
DAQmxErrChk DAQmxCreateAIThrmcplChan(myAITask, "cDAQ1Mod4/ai0:3", "", 0, 400, DAQmx_Val_DegF, DAQmx_Val_ThermocoupleType1_J_Type_TC, DAQmx_Val_CJCSource1_BuiltIn, 0#, "")
DAQmxErrChk DAQmxCfgSampClkTiming(myAITask, "OnboardClock", 1, DAQmx_Val_Rising, DAQmx_Val_AcquisitionType_FiniteSamps, 50)
DAQmxErrChk DAQmxGetTaskNumChans(myAITask, numChannels)
arraySizeInSamps = numSampsPerChannel * numChannels
ReDim data(arraySizeInSamps)
End Sub
'Now once per second (using timer on main form) I will read the data returned from the buffer
Public Function GetcDAQAnalogData()
Dim i As Long, j As Long
Dim data2$
sampsPerChanRead = 50
DAQmxErrChk DAQmxReadAnalogF64(myAITask, 1, 10#, DAQmx_Val_GroupByScanNumber, data(0), arraySizeInSamps, sampsPerChanRead, ByVal 0&)
For j = 1 To numChannels
data2$ = Left$(data(i), 7)
data2$ = Strings.FormatNumber(data(i), 7)
i = i + 1
Next
End Sub
Can anyone tell me how to change the above code in my GetcDAQAnalogData routine that will read the 50 samples per channel and average them together for each channel, and then output the result in my data2$ variable?
10-14-2011 04:11 PM
Nothing at all??? I just need a loop that will read 50 samples from each of my 24 channels, average those samples all together, and ouput the result for each channel. Any help would be greatly appreciated. I welcome any input whatsoever...Thanks
10-14-2011 05:28 PM
Hi Chris,
From looking at your code, you're currently performing a Finite Acquisiton, but I would think you would want to be acquiring data continuously for your specific application, so I would change your call when you configure your sample clock to DAQmx_Val_AcquisitionType_ContSamps. Also, the third argument in your DAQmxCfgSampClkTiming function is the sampling rate for your task, which you currently have set to 1 Hz. You should set this to whatever rate you want to acquire samples at per second per channel, so in your case you would want to set it to 50 Hz. I would also increase your buffer size, which is the final argument of this function, to at least 10x the number of samples you want to read from each channel, to avoid buffer overflow issues.
Additionally, you seem to be passing a 1 to your DAQmxReadAnalogF64 function as the number of samples to read every time that the loop iterates, but if you want to pull 50 samples upon each iteration, then you should change that argument to 50. From there, you should just need to average the data you pull out of the buffer with each iteration, and place it into a separate array.
I would recommend looking at the DAQmx in C reference help (I realize you are programming in VB6, but the VB6 help doesn't seem to have information about the arguments for specific function calls); it's helpful for verifying the correct arguments for function calls.
Best,
Dan N
Applications Engineer
10-17-2011 04:01 PM
Thanks for your response Dan. When I first started I was doing continuous sampling but kept getting buffer errors. I have now changed everything to your recommendations and it seems to work beautifully. Still having issues with creating and averaging for that second array you mention though. Could you possibly give me some additional help for pulling the data from the buffer and creating the average reads for each channel? If you aren't familiar with VB6 I understand...if anyone else could help with this I would be very grateful...Thanks
10-18-2011 10:06 AM
Worked out a solution and thought I would post for anyone interested. I decided to average 100 samples per channel which seems to filter out the noise very well. Steady readings to the 3rd and 4th digit.
Modified the following on Form_Load:
numSampsPerChannel = 100
DAQmxErrChk DAQmxCfgSampClkTiming(myAITask, "OnboardClock", 100, DAQmx_Val_Rising, DAQmx_Val_AcquisitionType_ContSamps, 1000)
Public Function GetcDAQAnalogDataDB(inRecordset As Recordset)
Dim count As Long, i As Long, j As Long, temp_i As Long
Dim ArrayAverage As Double
Dim sum As Variant
sampsPerChanRead = 100
DAQmxErrChk DAQmxReadAnalogF64(myAITask, 100, 10#, DAQmx_Val_GroupByChannel, data(0), arraySizeInSamps, 100, ByVal 0&)
ArrayAverage = 0
sum = 0
count = 0
i = 0
temp_i = 0
j = 1
inRecordset.MoveFirst
i = temp_i
For count = 0 To sampsPerChanRead - 1 'subtract 1 from total number of samples per channel
sum = sum + data(i)
i = i + 1
Next count
inRecordset.Edit
ArrayAverage = sum / sampsPerChanRead 'divide by number of samples per channel
ArrayAverage = Strings.FormatNumber(ArrayAverage, 7) '1st channel only
inRecordset.Fields!Egudata = ArrayAverage
inRecordset.Update
inRecordset.MoveNext
count = 0
sum = 0
ArrayAverage = 0
For j = 2 To numChannels - 1 'will cycle thru channel 2 and up
For count = 0 To sampsPerChanRead - 1
sum = sum + data(i)
i = i + 1
Next count
inRecordset.Edit
ArrayAverage = sum / sampsPerChanRead
ArrayAverage = Strings.FormatNumber(ArrayAverage, 7)
inRecordset.Fields!Egudata = ArrayAverage
If j >= 9 And j <= 16 Then 'this will format the decimal current readings from NI 9208 module into whole numbers for 4-20ma transducer channels
inRecordset.Fields!Egudata = inRecordset.Fields!Egudata * 1000
End If
inRecordset.Update
inRecordset.MoveNext
count = 0
sum = 0
ArrayAverage = 0
Next j
temp_i = temp_i + 1
End Function
10-18-2011 01:44 PM
Well of course I spoke too soon. You had recommended I set the buffer to 10 times the number of samples I want to acquire so I set it at 1000. After 5 minutes or so I will get a buffer error. So I doubled it to 2000 and still get the error. Is there something wrong with the last code I posted? Like I stated earlier I only need 50 samples per channel once every second. I guess i'm not reading in the data buffer fast enough. How can I fix this? Can I change to FiniteSamps and achieve the same thing? I never seemed to get buffer errors when using this method. Also notice the active light on the 9178 stays on while in contiuous sample mode, and with finite sample mode it only comes on about once per second, which makes more sense to me. Please advise...Thanks
10-21-2011 10:38 AM
Ended up changing code from conintuous samples to finite samples. Program has been running for 2 days with no errors.
DAQmxErrChk DAQmxCfgSampClkTiming(myAITask, "OnboardClock", 100, DAQmx_Val_Rising, DAQmx_Val_AcquisitionType_FiniteSamps, 1000)