Jump to content

JRys

MCC Staff
  • Posts

    1,451
  • Joined

  • Last visited

Everything posted by JRys

  1. None of our current products offer gated control. However, they do have external ADC clock support, and if you could control the external ADC clock, you would be able to control the ADC. A device like the USB-1608GX and USB-1808X have a timer output that can be used as a clock, which is half the battle. The other half is developing a gate circuit to function as a control.
  2. The USB-1208FS-PLUS is on the list of devices they support. https://www.mathworks.com/hardware-support/measurement-computing.html
  3. Please watch the following video about installing DASYLab and the Measurement Computing support. It will show how to install the Measurement Computing driver and access the input and output modules. When the driver installation gets to the destination folder panel, edit the path (press Change) so that it is \Program Files (x86)\DASYLab 2022.1_en\. Otherwise, you will get a path not found error.
  4. The manual says to connect a 50-ohm resistor to the ground on the detector output. The output is current, and the resistor generates the output voltage. Connect the MCC 128 input across the resistor. I recommend placing the inputs in differential mode for the measurement. If the signal is too low with the 50 ohm resistor, use a 1000-ohm load resistor.
  5. Could you send me the optical detector datasheet and model number, and let me know the voltage measured from the input ground to the output ground of the 12V to 5V Transformer?
  6. The message pops up because 1.) you do not have a sound card installed, and 2.) you have the sound card support enabled in the Configurator. It is enabled by default, and you can either check the box on the message not to display it again or disable the sound card support in the Configurator. I recommended checking the message box so it doesn't bug you anymore.
  7. Restart DASYLab with administrator privileges. Go to c:\Program Files (x86)\DASYLab 2022.1_en\ and get the properties for DASYLab.exe. Select the Compatibility tab and enable Run this program as an administrator.
  8. Neither DAQami nor DASYLab can display 64 channels on a single graph or chart. Instead, 64 channels should be distributed to several DAQami strip charts. You can create additional tab pages to make it easier to navigate multiple charts. When using various devices, DAQami writes the data for each one into a separate file.
  9. You can add more USB-TEMPs and use DAQami. But if you want one file with 64 channels, use DASYLab BASIC. You have too many channels for DASYLab LITE. DASYLab modules are limited to 16 channels, which limits the number you can write to file. To get around the limitation, the Multiplexer module can take up to 16 inputs and output them as a single stream. Connect this output to a Data Write module, and, in the setting, configure the number of channels coming in on that input. When properly configured, the Data Write unpacks channels to be written to a file.
  10. The following program generates a ~10 Hz sine wave on analog output 0 with an update rate of 1000 S/s. It also captures data on the analog input channel 0 at 500 S/s. I have also tested it at 1100, which is the max. You should be able to use two channels at 550 S/s. The config(board_num, num_chans) function performs the setting normally done by InstaCal. Attached below is the file. from __future__ import absolute_import, division, print_function import time from builtins import * # @UnusedWildImport from ctypes import addressof, sizeof, cast, POINTER, c_double, c_ushort from math import pi, sin from time import sleep from mcculw import ul from mcculw.enums import (AiChanType, BoardInfo, Status, InterfaceType, FunctionType, InfoType, ScanOptions, ULRange, AnalogInputMode) use_device_detection = True packet_size = 32 def config(board_num: int, n_channels: int): for ch in range(n_channels): ul.set_config( InfoType.BOARDINFO, board_num, ch, BoardInfo.ADCHANTYPE, AiChanType.VOLTAGE ) # ul.set_config( # InfoType.BOARDINFO, board_num, ch, # BoardInfo.CHANTCTYPE, TcType.K # ) ul.set_config( InfoType.BOARDINFO, board_num, ch, BoardInfo.ADDATARATE, 3750 ) def run_example(): dev_id_list = [] board_num = 0 desired_rate = 512 actual_rate = 0 desired_out_rate = 1000 actual_out_rate = 0 file_name = 'scan_data.csv' memhandle = None # The size of the UL buffer to create, in seconds buffer_size_seconds = 2 # The number of buffers to write. After this number of UL buffers are # written to file, the example will be stopped. num_buffers_to_write = 5 board_num = 0 board_index = 0 find_device = "USB-2416-4AO" if use_device_detection: board_num = -1 ul.ignore_instacal() dev_list = ul.get_daq_device_inventory(InterfaceType.USB) if len(dev_list) > 0: for device in dev_list: if str(device) == find_device: print(f"Found {find_device} board number = {board_index}") print(f"Serial number: {device.unique_id}") print(f"Product type: {hex(device.product_id)}") board_num = board_index ul.create_daq_device(board_num, device) board_index = board_index + 1 if board_num == -1: print(f"Device {find_device} not found") return else: print("No devices detected") return # **********End of Discovery************ try: chan = 0 num_chans = 1 config(board_num, num_chans) ul.a_chan_input_mode(board_num, chan, AnalogInputMode.SINGLE_ENDED) # Create a circular buffer that can hold buffer_size_seconds worth of # data, or at least 10 points (this may need to be adjusted to prevent # a buffer overrun) points_per_channel = max(desired_rate * buffer_size_seconds, 10) ul_buffer_count = points_per_channel * num_chans # Write the UL buffer to the file num_buffers_to_write times. points_to_write = ul_buffer_count * num_buffers_to_write # When handling the buffer, we will read 1/10 of the buffer at a time write_chunk_size = int(ul_buffer_count / 10) scan_options = (ScanOptions.BACKGROUND | ScanOptions.CONTINUOUS | ScanOptions.SCALEDATA) memhandle = ul.scaled_win_buf_alloc(ul_buffer_count) # Allocate an array of doubles temporary storage of the data write_chunk_array = (c_double * write_chunk_size)() # Check if the buffer was successfully allocated if not memhandle: raise Exception('Failed to allocate memory') # set output to zero zero_volts = 0.0 ul.v_out(board_num, 0, ULRange.BIP10VOLTS, zero_volts, 0) # Allocate a buffer for the scan count = 1024 memhandle2 = ul.win_buf_alloc(count) # Convert the memhandle to a ctypes array # Note: the ctypes array will no longer be valid after win_buf_free # is called. # A copy of the buffer can be created using win_buf_to_array # before the memory is freed. The copy can be used at any time. ctypes_array = cast(memhandle2, POINTER(c_ushort)) # Check if the buffer was successfully allocated if not memhandle2: raise Exception('Error: Failed to allocate memory') frequencies = add_example_data(board_num, ctypes_array, ULRange.BIP10VOLTS, num_chans, desired_out_rate, count) print("Channel", chan, 'Output Signal Frequency:', frequencies[chan]) # Start single channel output scan actual_out_rate = ul.a_out_scan(board_num, chan, chan, count, desired_out_rate, ULRange.BIP10VOLTS, memhandle2, ScanOptions.BACKGROUND | ScanOptions.CONTINUOUS) print('desired output rate =: ' + str(desired_out_rate)) print('actual output rate =: ' + str(actual_out_rate)) # Start the scan actual_rate = ul.a_in_scan( board_num, chan, chan, ul_buffer_count, desired_rate, ULRange.BIP10VOLTS, memhandle, scan_options) print('desired input rate =: ' + str(desired_rate)) print('actual input rate =: ' + str(actual_rate)) status = Status.IDLE # Wait for the scan to start fully while status == Status.IDLE: status, _, _ = ul.get_status(board_num, FunctionType.AIFUNCTION) # Create a file for storing the data with open(file_name, 'w') as f: print('Writing data to ' + file_name, end='') # Write a header to the file for chan_num in range(chan, chan + 1): f.write('Channel ' + str(chan_num) + ',') f.write(u'\n') prev_count = 0 prev_index = 0 write_ch_num = chan while status != Status.IDLE: # Get the latest counts status, curr_count, _ = ul.get_status(board_num, FunctionType.AIFUNCTION) new_data_count = curr_count - prev_count # Check for a buffer overrun before copying the data, so # that no attempts are made to copy more than a full buffer # of data if new_data_count > ul_buffer_count: # Print an error and stop writing ul.stop_background(board_num, FunctionType.AIFUNCTION) print('A buffer overrun occurred') break # Check if a chunk is available if new_data_count > write_chunk_size: wrote_chunk = True # Copy the current data to a new array # Check if the data wraps around the end of the UL # buffer. Multiple copy operations will be required. if prev_index + write_chunk_size > ul_buffer_count - 1: first_chunk_size = ul_buffer_count - prev_index second_chunk_size = ( write_chunk_size - first_chunk_size) # Copy the first chunk of data to the # write_chunk_array ul.scaled_win_buf_to_array( memhandle, write_chunk_array, prev_index, first_chunk_size) # Create a pointer to the location in # write_chunk_array where we want to copy the # remaining data second_chunk_pointer = cast(addressof(write_chunk_array) + first_chunk_size * sizeof(c_double), POINTER(c_double)) # Copy the second chunk of data to the # write_chunk_array ul.scaled_win_buf_to_array( memhandle, second_chunk_pointer, 0, second_chunk_size) else: # Copy the data to the write_chunk_array ul.scaled_win_buf_to_array( memhandle, write_chunk_array, prev_index, write_chunk_size) # Check for a buffer overrun just after copying the data # from the UL buffer. This will ensure that the data was # not overwritten in the UL buffer before the copy was # completed. This should be done before writing to the # file, so that corrupt data does not end up in it. status, curr_count, _ = ul.get_status( board_num, FunctionType.AIFUNCTION) if curr_count - prev_count > ul_buffer_count: # Print an error and stop writing ul.stop_background(board_num, FunctionType.AIFUNCTION) print('A buffer overrun occurred') break for i in range(write_chunk_size): f.write(str(write_chunk_array[i]) + ',') write_ch_num += 1 if write_ch_num == chan + 1: write_ch_num = chan f.write(u'\n') else: wrote_chunk = False if wrote_chunk: # Increment prev_count by the chunk size prev_count += write_chunk_size # Increment prev_index by the chunk size prev_index += write_chunk_size # Wrap prev_index to the size of the UL buffer prev_index %= ul_buffer_count if prev_count >= points_to_write: break print('.', end='') else: # Wait a short amount of time for more data to be # acquired. sleep(0.1) ul.stop_background(board_num, FunctionType.AOFUNCTION) ul.v_out(board_num, 0, ULRange.BIP10VOLTS, zero_volts, 0) ul.stop_background(board_num, FunctionType.AIFUNCTION) except Exception as e: print('\n', e) finally: print('Done') if memhandle: # Free the buffer in a final block to prevent a memory leak. ul.win_buf_free(memhandle) if use_device_detection: ul.release_daq_device(board_num) def add_example_data(board_num, data_array, ao_range, num_chans, rate, points_per_channel): # Calculate frequencies that will work well with the size of the array frequencies = [] for channel_num in range(num_chans): frequencies.append( (channel_num + 1) / (points_per_channel / rate) * 10) # Calculate an amplitude and y-offset for the signal # to fill the analog output range amplitude = (ao_range.range_max - ao_range.range_min) / 2 y_offset = (amplitude + ao_range.range_min) / 2 # Fill the array with sine wave data at the calculated frequencies. # Note that since we are using the SCALEDATA option, the values # added to data_array are the actual voltage values that the device # will output data_index = 0 for point_num in range(points_per_channel): for channel_num in range(num_chans): freq = frequencies[channel_num] value = amplitude * sin(2 * pi * freq * point_num / rate) + y_offset raw_value = ul.from_eng_units(board_num, ao_range, value) data_array[data_index] = raw_value data_index += 1 return frequencies if __name__ == '__main__': run_example() a_in_scan_file_2416_py.txt
  11. The DAQ Adaptor for MATLAB does not have a channel Sensitivity function, hence the error message. Instead, you could do your own scaling with some simple math. Let's say you have an array of voltage measurements. Divide the values in the array by 0.00922 to get g's.
  12. Use the QuickDAQ export feature to generate a text version of the data. See page 37 in the following PDF: https://files.digilent.com/downloads/DTSoftware/QuickDAQ/QuickDAQ.pdf Use File->Open Hpf Data File to reopen and convert previously recorded files.
  13. Could you jump into InstaCal and check how channel 0 is configured and how the Data Rate filter property is set? It must be set to 3750 to sample at 550 samples per second. Page 16 in the user manual discusses throughput rates. Another thing to keep in mind is that the USB-2416-4AO is a device that remembers how it is set even after power is removed. Not all MCC devices do this. So, if a colleague sets it for temperature and you try to use it for voltage, it will generate an error until it is reconfigured with InstaCal.
  14. You can synchronize two or more devices using the Sync IO output clock. It is turned off by default, but you can enable it with InstaCal or the programming interface. Connect the Sync terminal to both devices, but allow Sync output only on one. Program the device that outputs the Sync last. Sharing the Sync signal will allow both devices to record data simultaneously.
  15. Below is my get-board number function. It takes a device name string, such as '1208FS', to search for the device. Once it finds a device name that contains '1208FS', it determines if 'Plus' is in the name and, if so, sets the global variable PACKETSIZE to 32. Otherwise, it's 31. It is crucial to size the buffer as a multiple of PACKETSIZE times channel count. I have also attached my test program below that uses this function. 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]); if (daqBoard.BoardName.Contains("Plus")) PACKETSIZE = 32; else PACKETSIZE = 31; return boardNum; } } catch (ULException ule) { Console.WriteLine("Error occurred: " + ule.Message); } } } return -1; } USB_1208FS_CONT_EXAMPLE.cs
  16. The MCC 172 is not designed to use an external clock because the clock runs 512x the sample rate, and a sync pulse is used to synchronize the ADCs. GPIO 19 is used to clock other MCC 172 boards on the RPI stack, and a sync pulse on GPIO 6 synchronizes all the ADCs. None of the other MCC daqhat boards can use its clock. After the sync pulse is set low, it takes 128 conversions before data is ready. You can make the clock appear on GPIO 19 using the SOURCE_MASTER clock mode with the mcc172_a_in_clock_config_write function.
  17. Use the beta version, which is at https://github.com/mccdaq/daqhats/tree/pi5 Follow the instructions below to install. 1. $ cd daqhats 2. $ sudo ./uninstall.sh 3. $ git pull 4. $ git checkout pi5 5. $ sudo ./install.sh 6. $ pip install daqhats (manually add Python support) You can switch back to the released library by uninstalling the library, running “git checkout master”, and then installing the library. Use the installed MCC DAQ HAT Manager utility application to verify communication with the MCC 118/MCC 128 or use terminal commands. $ sudo daqhats_read_eeproms $ daqhats_list_boards
  18. Ping-ponging between the two buffer halves is an easy and efficient way to manage a circular buffer. To perform a single acquisition of a fixed number of points, you could use the current count parameter from GetStatus to determine when to end the acquisition. You could also change the scan options to just ScaledData. This will tell the AInScan function to wait until the acquisition is complete before returning control to the program. Once it returns, use ScaleWinBufToArray to copy the driver data into an array.
  19. We have yet to release a LabVIEW 2024 installer, so use LabVIEW 2023 (32 or 64-bit) for now.
  20. Before starting, configure your device using the InstaCal utility. Make sure it's closed before starting DASYLab. Next, run the DASYLab Configurator utility, select the Packages tab, and open Data Acquisition. Find the Measurement Computing driver and enable it. Closing the Configurator will start an installation program. When it gets to the Destination panel, press the Change button and change the path to reflect DASYLab 2022.1_en instead of DASYLab. When the installation is finished, start DASYLab and review this video. It will demonstrate the fundamentals. To add calculations, use the Formula module. There is also a Scale module for simple mx+b linear conversion. I've also attached a DDE example that demonstrates how to use it to transfer data to Excel. Load the example spreadsheet using Excel before starting DASYLab, then run the example DASYLab worksheet. If all goes well, you should see live data entered into Excel. DDE-Example.xls DDE-EXCEL_V14.DSB
  21. Please use the forum's private message feature to send me the worksheet (.dsb) file and your DASYLab serial number.
  22. The worksheet (.dsb) file is the program. Open it with DASYLab, and it will display the block diagram, which consists of modules (blocks) wired together. OBDC modules are not wired to other modules; they sit separately. Double-click the module to find the ODBC source name listed in the Data Source section. This is the name you look for in the ODBC Data Source Administrator (32-bit) to locate the file. Move the file to your new computer and register it with the ODBC Data Source Administrator (32-bit). Hopefully, there's only one. Also, check your Write Data modules to ensure it's using a valid path. Write Data is used to save acquired measurement data to a file.
  23. An easy way to check the voltage output is to connect it to an analog input. For the measurement, set the input to single-ended mode. On my unit, I've connected VDAC0 to CH0H. When I set the output to zero, the measurement is approximately 1.2 mV. If your offset is much larger, the input can be checked by connecting it to GND instead of the voltage output. To verify thermocouple performance, a thermocouple calibrator is required to apply a known temperature. Configure the channel for Temperature with the Data Rate set to 60 Hz. Connect the thermocouple and let it and the unit warm up for 30 minutes. If you fail to let it warm up, or the Data Rate is set higher than 60 Hz, you can see errors of several degrees. If you want us to do the testing, private message me with your contact information, order information, and device serial number, and someone will get back to you with the details.
  24. The data source name is listed in the DASYLab ODBC module. Once you have the name, start the ODBC Data Source Administrator, select the ODBC name, and press the Configure button to display the setup panel with the filename and path.
  25. The error indicates that your ODBC database is missing. Get the database from the computer that ran DASYLab 13. Once you have it, use the ODBC Data Sources (32-bit) tool (in the Windows Control Panel Administrative Tools) to make it visible to the DASYLab ODBC module. If it's an Excel worksheet, select Excel Files and press Add.
×
×
  • Create New...