Jump to content

JRys

MCC Staff
  • Posts

    1,496
  • Joined

  • Last visited

Everything posted by JRys

  1. Hello, Fixing the .XML error simple, just make sure DASYLab is configured to run as an administrator. This is because the default IOtech XML hardware file is kept in the DASYLab folder which under Program Files (x86) and that requires permission to read/write. After you correct the XML error, if the remaining errors are the Action modules check if you have DASYLab FULL or PrO. You need at least FULL to use Action modules. For this run the DASYLab Configurator utility. There should be listed a serial number which is a 26 character string. If you provide the last six digits, I can use it to investigate to see if it is FULL/PRO version. Best regards, John
  2. Hello, Access the Raspberry PI Preferences/Raspberry PI Configuration/Interfaces and make sure I2C and SPI are enabled. Regards, John
  3. DASYLab is used to make and run custom programs (worksheets), which are saved to a file with a .DSB extension. There are two ways to start the worksheet: you can start DASYLab and then access the DASYLab File menu to open it; or you can double click the file which launches DASYLab and loads the worksheet at the same time. Many customer put their worksheet on the desktop then double click it to begin. Perhaps the file is there? John
  4. Attached is a Python for Windows program to read the TC inputs using the daq_in_scan function. Best regards, John """ File: daq_in_scan_usb_1800.py Library Call Demonstrated: mcculw.ul.daq_in_scan() Purpose: Synchronously scans 8 thermocouple channels Demonstration: how to covert raw data to temperature Other Library Calls: mcculw.ul.daq_in_scan() mcculw.ul.get_tc_values() mcculw.ul.win_buf_free() mcculw.ul.release_daq_device() Special Requirements: This examples filters on the USB-1808 Series. """ from __future__ import absolute_import, division, print_function from builtins import * # @UnusedWildImport from time import sleep # 1616HS and 2500 series do not have ScaleData support # from ctypes import cast, POINTER, c_double from ctypes import cast, POINTER, c_ushort, c_float from mcculw import ul from mcculw.enums import ScanOptions, ChannelType, ULRange, TempScale, DigitalPortType from mcculw.device_info import DaqDeviceInfo from mcculw.ul import ULError from mcculw.enums import FunctionType, Status try: from console_examples_util import config_first_detected_device except ImportError: from .console_examples_util import config_first_detected_device def run_example(): use_device_detection = False board_num = 0 # Supported PIDs for the USB-1808 Series rate = 100 points_per_channel = 64 memhandle = None try: # use board zero from InstaCal daq_dev_info = DaqDeviceInfo(board_num) print('\nActive DAQ device: ', daq_dev_info.product_name, ' (', daq_dev_info.unique_id, ')\n', sep='') scan_options = ScanOptions.FOREGROUND # Create the daq_in_scan channel configuration lists chan_list = [] chan_type_list = [] gain_list = [] # Analog channels must be first in the list chan_list.append(0) chan_type_list.append(ChannelType.CJC) gain_list.append(ULRange.BIP10VOLTS) chan_list.append(0) chan_type_list.append(ChannelType.TC) gain_list.append(ULRange.BIP10VOLTS) chan_list.append(1) chan_type_list.append(ChannelType.CJC) gain_list.append(ULRange.BIP10VOLTS) chan_list.append(1) chan_type_list.append(ChannelType.TC) gain_list.append(ULRange.BIP10VOLTS) chan_list.append(1) chan_type_list.append(ChannelType.CJC) gain_list.append(ULRange.BIP10VOLTS) chan_list.append(2) chan_type_list.append(ChannelType.TC) gain_list.append(ULRange.BIP10VOLTS) chan_list.append(2) chan_type_list.append(ChannelType.CJC) gain_list.append(ULRange.BIP10VOLTS) chan_list.append(3) chan_type_list.append(ChannelType.TC) gain_list.append(ULRange.BIP10VOLTS) chan_list.append(3) chan_type_list.append(ChannelType.CJC) gain_list.append(ULRange.BIP10VOLTS) chan_list.append(4) chan_type_list.append(ChannelType.TC) gain_list.append(ULRange.BIP10VOLTS) chan_list.append(4) chan_type_list.append(ChannelType.CJC) gain_list.append(ULRange.BIP10VOLTS) chan_list.append(5) chan_type_list.append(ChannelType.TC) gain_list.append(ULRange.BIP10VOLTS) chan_list.append(4) chan_type_list.append(ChannelType.CJC) gain_list.append(ULRange.BIP10VOLTS) chan_list.append(6) chan_type_list.append(ChannelType.TC) gain_list.append(ULRange.BIP10VOLTS) chan_list.append(5) chan_type_list.append(ChannelType.CJC) gain_list.append(ULRange.BIP10VOLTS) chan_list.append(7) chan_type_list.append(ChannelType.TC) gain_list.append(ULRange.BIP10VOLTS) num_chans = len(chan_list) total_count = num_chans * points_per_channel half_count = total_count / 2 # Allocate memory for the scan and cast it to a ctypes array pointer memhandle = ul.scaled_win_buf_alloc(total_count) # 1616HS and 2500 series do not have ScaleData support # ctypes_array = cast(memhandle, POINTER(c_double)) ctypes_array = cast(memhandle, POINTER(c_ushort)) # Check if the buffer was successfully allocated if not memhandle: raise Exception('Error: Failed to allocate memory') scan_options = ScanOptions.CONTINUOUS | ScanOptions.BACKGROUND # Start the scan actRate, preCount, postCount = ul.daq_in_scan( board_num, chan_list, chan_type_list, gain_list, num_chans, rate, 0, total_count, memhandle, scan_options) status, curr_count, curr_index = ul.get_status( board_num, FunctionType.DAQIFUNCTION) # boolean flag used to toggle reading upper and lower buffer read_lower = True # acquire 640 samples acquire = points_per_channel * num_chans * 10 while status != Status.IDLE: status, curr_count, curr_index = ul.get_status( board_num, FunctionType.DAQIFUNCTION) if (curr_index > half_count) and (read_lower == True): # use if you also have voltage or digital inputs ul.win_buf_to_array(memhandle, ctypes_array, 0, int(half_count)) # Points per channel is 64 so there are 32 to convert which starts at the zero e, temps = ul.get_tc_values( board_num, chan_list, chan_type_list, num_chans, memhandle, 0, int(points_per_channel/2), TempScale.CELSIUS) for j in range(256): if j % 8 == 0: print() print('{:2.2f}\t'.format(temps[j]), end ='') read_lower = False elif (curr_index < half_count) and (read_lower == False): # use if you also have voltage or digital inputs ul.win_buf_to_array(memhandle, ctypes_array, int(half_count), int(half_count)) # Points per channel is 64 so there are 32 to convert which starts at the halfway point e, temps = ul.get_tc_values( board_num, chan_list, chan_type_list, num_chans, memhandle, int(points_per_channel/2), int(points_per_channel/2), TempScale.CELSIUS) for j in range(256): if j % 8 == 0: print() print('{:2.2f}\t'.format(temps[j]), end='') read_lower = False if curr_count > acquire: print('\nAcquired number of scans = {:d}'.format(int(curr_count / num_chans))) break ul.stop_background(board_num, FunctionType.DAQIFUNCTION) print("\nscan completed successfully.") except ULError as e: print('\n', e) finally: if memhandle: # Free the buffer in a finally block to prevent a memory leak. ul.win_buf_free(memhandle) if use_device_detection: ul.release_daq_device(board_num) if __name__ == '__main__': run_example() daq_in_scan_tc_get_values.py
  5. That would be best, but another option is to purchase DASYLab Lite ($499). It has the ability to convert the square wave flow sensor signal to a frequency measurement using the counter input. If you own LabVIEW you could use it too to make the measurement. best regards, John
  6. This sensor requires a device that can read the frequency of its square wave output. The USB-2416 does have a Counter input that could be used for this, but it would require the DASYLab software to measure frequency. Our basic software packages (DAQami & TracerDAQ) cannot.
  7. Hi @Gregoire It is best to stay with the Buster operating system because, although some initial checks indicate it works, MCC has not fully tested Bullseye. Best regards, John
  8. Hello, The initial high level reading could be a settling time issue caused by turning on IEPE current source. It's best to turn it on at the beginning of your program and leave it on. It's good to add a delay after turning it on so that the input & accelerometer can settle. This should be listed in the accelerometer specifications. Best regards, John
  9. Hello, Here's the gist. The paragraph in question has to do with customers that create products for resale. If your company has purchased one or more of our devices and are using the software in house, the paragraph doesn't apply to you. On the other hand, if you've created a product for resale and intend bundle our software with it then reach out to us for permission. Best regards, John
  10. Hey Martin, We ran some test here and the best we could achieve with a custom program was about 200 Hz. It just wasn't designed to deliver high speed digital data. We do have a few devices that can read the port faster (with a custom program), but even they won't hit 10,000 Hz. The best device to use to scan a digital port is the USB-DIO32HS. https://www.mccdaq.com/usb-data-acquisition/USB-DIO32HS-Series Adding a second USB-205 and a custom program is the way to go. With a custom program you could uses the Ext Clock pins on each device and run them synchronously. This way, each channel on both devices is sampled at the sample time. Best regards, John
  11. Hello Martin, The USB-205 has an oscillator circuit that provides an accurate clock to pace the acquisition, but it only applies to the analog inputs. Reading the digital port is done one update at a time using a software polling scheme, which is much slower operation. Best regards, John
  12. Thanks for letting us know best regards, John
  13. Hello @Gregoire For the record, are you running 32 or 64-bit Bullseye and do you have the RPI 4 with 2, 4 or 8Gb? John
  14. Hello @e_reed Hopefully you don't mind reviewing C#. I'm hoping to have a mcculw Python example next week. Attached is a C# example that uses the DaqInScan functionality to continuously collect TC data. First, it's important to associate the correct CJC channel with each TC channel. For instance, CJC3 is assigned to TC4 and CJC4 is assigned to both TC5 and TC6. Collecting the 16 channels (8x CJC and 8x TC) should be straightforward. The default oversample property is 256 which makes the device no faster than 1M Hz / 256 / number of channels or about 244 Hz. When in doubt check the return 'rate' variable from DaqInScan. The confusing part is the GetTCValues. I put a few notes in the section that continuously reads the data and gets the TC values. Below is the algorithm that spins while data is being collected waiting to process more data when another half buffer has filled. The WinBufToArray is not needed but is included if later you change a TC channel back to Analog voltage or digital. using System; using MccDaq; // also, add reference to MccDaq to the project //This program uses the DaqInScan function to read 8 thermocouple channels; the return data //in the form of raw counts from both the CJC and the thermocouple; in order to get //temperature data, as second function named GetTCValues is used namespace CSharp_USB_1616HS_DaqInScan { static class Constants { public const int ChanCount = 16; //number of channels ( 8x TC 8x CJC) public const int BUFFSIZE = 32 * ChanCount; public static int bufferSize = BUFFSIZE; public const int HALFBUFF = BUFFSIZE / 2; public static MccBoard daq; public static int rate = 100; public static int preTrigCount = 0; public const int TC_Count = 2; } class Program { static void Main(string[] args) { int BoardNum = 0; int Count = 0; int Index = 0; short daqStatus = 0; ushort[] ADData = new ushort[Constants.BUFFSIZE]; //raw data float[] tempVals = new float[Constants.BUFFSIZE]; //used for temperatures short[] ChanArray = new short[Constants.ChanCount]; // array to hold channel queue information ChannelType[] ChanTypeArray = new ChannelType[Constants.ChanCount]; // array to hold channel type information Range[] GainArray = new Range[Constants.ChanCount]; // array to hold gain queue information Console.WriteLine("Locating Device...Please wait\n"); BoardNum = GetBoardNum("1616"); if (BoardNum == -1) { Console.WriteLine("Device not detected!"); WaitForKey(); return; } else { Constants.daq = new MccDaq.MccBoard(BoardNum); Constants.daq.AInputMode(AInputMode.Differential); //Channel configuration array definitions int i = 0; //if mixing voltage an TC, make the TC channels first in the list for easier conversion using GetTCValues. //TC0 ChanArray[i] = 0; ChanTypeArray[i] = ChannelType.CJC; GainArray[i] = Range.NotUsed; i++; ChanArray[i] = 0; ChanTypeArray[i] = ChannelType.TC; GainArray[i] = Range.NotUsed; //TC1 i++; ChanArray[i] = 1; ChanTypeArray[i] = ChannelType.CJC; GainArray[i] = Range.NotUsed; i++; ChanArray[i] = 1; ChanTypeArray[i] = ChannelType.TC; GainArray[i] = Range.NotUsed; i++; //TC2 ChanArray[i] = 1; //TC2 uses CJC1 ChanTypeArray[i] = ChannelType.CJC; GainArray[i] = Range.NotUsed; i++; ChanArray[i] = 2; ChanTypeArray[i] = ChannelType.TC; GainArray[i] = Range.NotUsed; i++; //TC3 ChanArray[i] = 2; //TC3 uses CJC2 ChanTypeArray[i] = ChannelType.CJC; GainArray[i] = Range.NotUsed; i++; ChanArray[i] = 3; ChanTypeArray[i] = ChannelType.TC; GainArray[i] = Range.NotUsed; i++; //TC4 ChanArray[i] = 3; //TC4 uses CJC3 ChanTypeArray[i] = ChannelType.CJC; GainArray[i] = Range.NotUsed; i++; ChanArray[i] = 4; ChanTypeArray[i] = ChannelType.TC; GainArray[i] = Range.NotUsed; i++; //TC5 ChanArray[i] = 4; //TC5 uses CJC 4 ChanTypeArray[i] = ChannelType.CJC; GainArray[i] = Range.NotUsed; i++; ChanArray[i] = 5; ChanTypeArray[i] = ChannelType.TC; GainArray[i] = Range.NotUsed; i++; //TC6 ChanArray[i] = 4; //TC6 also uses CJC4 ChanTypeArray[i] = ChannelType.CJC; GainArray[i] = Range.NotUsed; i++; ChanArray[i] = 6; ChanTypeArray[i] = ChannelType.TC; GainArray[i] = Range.NotUsed; i++; //TC7 ChanArray[i] = 5; //TC7 uses CJC5 ChanTypeArray[i] = ChannelType.CJC; GainArray[i] = Range.NotUsed; i++; ChanArray[i] = 7; ChanTypeArray[i] = ChannelType.TC; GainArray[i] = Range.NotUsed; ScanOptions Options = ScanOptions.ConvertData | ScanOptions.Continuous | ScanOptions.Background; //allocate buffer int bufferSize = Constants.bufferSize; IntPtr buffer = MccService.WinBufAllocEx(Constants.bufferSize); Console.WriteLine("Actual Rate {0}\n", Constants.rate); WaitForKey(); IsError(Constants.daq.DaqInScan(ChanArray, ChanTypeArray, GainArray, Constants.ChanCount, ref Constants.rate, ref Constants.preTrigCount, ref Constants.bufferSize, buffer, Options)); System.ConsoleKeyInfo cki = new System.ConsoleKeyInfo(); bool readLow = true; do { System.Threading.Thread.Sleep(1); IsError(Constants.daq.GetStatus(out daqStatus, out Count, out Index, FunctionType.DaqiFunction)); if ((Index > Constants.HALFBUFF) && readLow) { MccService.WinBufToArray(buffer, ADData, 0, Constants.HALFBUFF); //the buffer contains 32 scans of the 16 channels. Because the TC are first in the list the TC conversion starts at 0 for the lower portion. //Keep in mind that GetTCValues uses scans whereas WinBufToArray uses Scans * Channel Count IsError(Constants.daq.GetTCValues(ChanArray, ChanTypeArray, Constants.ChanCount, buffer, 0, 16, TempScale.Celsius, tempVals)); readLow = false; i = 0; for (int idx = 0; idx < Constants.HALFBUFF; idx+=16) { Console.Write("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\r\n", tempVals[i++].ToString("00.00"), tempVals[i++].ToString("00.00"), tempVals[i++].ToString("00.00"), tempVals[i++].ToString("00.00"), tempVals[i++].ToString("00.00"), tempVals[i++].ToString("00.00"), tempVals[i++].ToString("00.00"), tempVals[i++].ToString("00.00")); idx += 8; } } else if ((Index < Constants.HALFBUFF) && !readLow) { MccService.WinBufToArray(buffer, ADData, Constants.HALFBUFF, Constants.HALFBUFF); //the buffer contains 32 scans of the 16 channels. Because the TC are first in the list the TC conversion starts at 16 for the upper portion. //Keep in mind that GetTCValues uses scans whereas WinBufToArray uses Scans * Channel Count IsError(Constants.daq.GetTCValues(ChanArray, ChanTypeArray, Constants.ChanCount, buffer, 16, 16, TempScale.Celsius, tempVals)); readLow = true; i = 0; for (int idx = 0; idx < Constants.HALFBUFF; idx+=16) { Console.Write("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\r\n", tempVals[i++].ToString("00.00"), tempVals[i++].ToString("00.00"), tempVals[i++].ToString("00.00"), tempVals[i++].ToString("00.00"), tempVals[i++].ToString("00.00"), tempVals[i++].ToString("00.00"), tempVals[i++].ToString("00.00"), tempVals[i++].ToString("00.00")); } } } while (!Console.KeyAvailable); cki = Console.ReadKey(); //stop background operation IsError(Constants.daq.StopBackground(FunctionType.DaqiFunction)); Constants.daq.TimerOutStop(0); //free up memory IsError(MccService.WinBufFreeEx(buffer)); WaitForKey(); } // end of program } /*////////////////////////////////////////////////////////////////////////////////////*/ public static int GetBoardNum(string dev) { MccDaq.DaqDeviceManager.IgnoreInstaCal(); MccDaq.DaqDeviceDescriptor[] inventory = MccDaq.DaqDeviceManager.GetDaqDeviceInventory(MccDaq.DaqDeviceInterface.Any); int DevicesFound = inventory.Length; if (DevicesFound > 0) { for (int boardNum = 0; boardNum < DevicesFound; boardNum++) { try { if (inventory[boardNum].ProductName.Contains(dev)) { MccDaq.MccBoard daqBoard = MccDaq.DaqDeviceManager.CreateDaqDevice(boardNum, inventory[boardNum]); Console.WriteLine("Product Name: {0}", inventory[boardNum].ProductName); Console.WriteLine("Device Type # : {0}", inventory[boardNum].ProductID); Console.WriteLine("Serial # : {0}", inventory[boardNum].UniqueID); return boardNum; } } catch (ULException ule) { Console.WriteLine("Error occured: " + ule.Message); } } } return -1; } /*////////////////////////////////////////////////////////////////////////////////////*/ public static void WaitForKey() { Console.WriteLine("\nPress any key to continue...\n"); do { //idle loop System.Threading.Thread.Sleep(10); } while (!Console.KeyAvailable); Console.ReadKey();//get rid of the key press } /*////////////////////////////////////////////////////////////////////////////////////*/ public static int IsError(ErrorInfo e) { if (e.Value != 0) { Console.WriteLine(e.Message); WaitForKey(); return 1; } return 0; } /*////////////////////////////////////////////////////////////////////////////////////*/ //function to convert to engineering units; if just volts set scale to 1.0 and offset to 0.0 public static double ScaleData(Range rng, ushort dataval, double scale, double offset) { float V2 = 0.0f; Constants.daq.ToEngUnits(rng, dataval, out V2); return V2 * scale + offset; } } } Best regards, John Program.cs
  15. Hello, I've reach out to our legal department for clarity on the Use of Site paragraph you've flagged. I'm thinking it was copied from our parent company website and either shouldn't be there or doesn't apply to programs like Personal DaqView. I'll update this post when I get more feedback. Best regards, John
  16. Hello @Gregoire I've check our support database and could not find similar cases to yours. So, no we have not experienced such a problem. The maximum update rating of the USB-3105 is 100 Hz / number of channels. You could try slowing down so that the updates less than 100 times per second. Does the device work for 30 minutes only if it has been unplugged for a while, or does restarting the program make it work for 30 more minutes? What are you controlling with 16 outputs? Is it near any equipment that emits electrical noise like RFI/EMI? If so, try using a USB cable the has built-in ferrite filters. Best regards, John
  17. Hello @e_reed t_in and t_in_scan are polling functions, in fact t_in_scan calls t_in for each in the list. However, the USB-1616HS series has another function called DaqInScan that can scan both thermocouple and voltage inputs. For an example of how it works, take a look at the C# example DaqInScan03. In this example, you can see how to setup the channel arrays and how to convert the data. There is a DaqInScan Python example but it doesn't include thermocouples so you would need to modify. Once you have it working you could make the whole operation run in the background with the BACKGROUND|CONTINUOUS option. Best regards, John
  18. Hello @Ariel Nothing for the USB-CTR04-OEM but it's the same size as our USB-1808-OEM and I do have a file for it - see attached zip file. Best regards, John 1808_OEM_Drawings.zip
  19. Hello @MaxCrowe Assuming you've installed the Omni CD and OpenLayers Dot Net support, and have tested your DT9857E with QuickDAQ to make sure all is well, the example to look at is "readbufferediepedataasraw". In plain english it's "read buffered data from IEPE device and return raw data" ( The DT9857E has built-in IEPE signal conditioning for dynamic sensors. ) If you're having trouble finding the examples, they should be in C:\Program Files (x86)\Data Translation\DotNet\OLClassLib\Examples\AnalogInput\. Because they are installed in Program Files (x86), you will need elevated permission to access them with Visual Studio IDE. I suggest to use "run as administrator" when starting the IDE. For more information about using the various objects and enumerations, the DT-Open Layers for .NET API Help is available via a shortcut from your start programs menu. Best regards, John
  20. Hey Lee, I've reached out to the design engineer regarding the use of external trigger and your original assumption is true. Although the two boards share the sample clock they need an external trigger to provide the initial synchronization. You need a trigger signal to synchronize the sampling start between the two 172s, but it can be done without an external source or wiring. Set both 172s up as trigger slaves, start a scan on both boards, then create a rising edge on the Pi GPIO pin that is used to share the trigger (GPIO 5). mcc172_a_in_clock_config_write using SOURCE_SLAVE mcc172_a_in_clock_config_write using SOURCE_MASTER mcc172_trigger_config using SOURCE_SLAVE mcc172_trigger_config using SOURCE_SLAVE Toggle GPIO5 to trigger both without adding any external wires. Best regards, John
  21. Hello, i'm sorry, but there is no 64-bit programming support for any of the IOtech products. Best regards, John
  22. Hello Christine, I'm sorry, but we do not offer repair services for the Daqhat boards including the MCC 118. Best regards, John
  23. I believe the issue is the low analysis frequency not being able to capture the sharp edge of the impact. 118 Hz is approximately 236 S/s or about a sample every 4mS. I originally used 399 Hz but when I dropped to 118Hz it wouldn't trigger. However, switching to Analog Threshold Neg Edge seemed to make a positive difference - I'm not sure why. Or increase the analysis frequency and FFT size appropriately. I'm sorry there not a more concrete solution. best regards, John
  24. Hello, It should be possible start an a_in_scan BACKGROUND|CONTINUOUS acquisition in function1 and then call ul.GetStatus(board_number, FunctionType.AIFUNCTION) in function2. Perhaps you could post or attach the class code if it's not too big. Best regards, John
  25. I should also add that if you have control over the block size, set it to at least 10% of the sample rate for acceptable results. A block size of one adds too much overhead and is usually is for sample rates under 100. John
×
×
  • Create New...