Jump to content

JRys

MCC Staff
  • Posts

    1,460
  • Joined

  • Last visited

Everything posted by JRys

  1. Thanks for letting us know best regards, John
  2. 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
  3. 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
  4. 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
  5. 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
  6. 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
  7. 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
  8. 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
  9. 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
  10. Hello, i'm sorry, but there is no 64-bit programming support for any of the IOtech products. Best regards, John
  11. Hello Christine, I'm sorry, but we do not offer repair services for the Daqhat boards including the MCC 118. Best regards, John
  12. 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
  13. 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
  14. 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
  15. Hello, Close DASYLab and open NI's Measurement & Automation Explorer (MAX). Modify the analog input task to run continuous and change the sample rate to 10,000 S/s. Run the task to make sure it meets your requirements. Save the task, close MAX start DASYLab. Place a DAQmx Analog Input on the DASYLab worksheet and link to the task. Connect it to a y/t chart for display and run. This should provide much better performance. If you need to modify the sample rate, there's no need to run MAX again because this is one of the few items DASYLab can control with NI hardware. You may need to set the sample rate higher if you wish to reproduce waveforms above 100 Hz. A good looking sine wave consists of 100 data points. So 10,000 S/s divided by 100 Hz is 100. If you can set the sample rate to 100k Hz, then sine waves up to 1000 Hz should look good. Best regards, John
  16. Hey Lee, I've order a second MCC 172 but it won't arrive until next week - I'm hoping Monday. In the meantime, I modified the code - attached. MASTER is defined as zero, so I added a SLAVE defined as 1 and changed the clock config write and ain scan start sequence to reflect SLAVE first. // Configure the slave clock first result = mcc172_a_in_clock_config_write(address[SLAVE],SOURCE_SLAVE, sample_rate); // Configure the master clock last so the clocks are synchronized result = mcc172_a_in_clock_config_write(address[MASTER],SOURCE_MASTER, sample_rate); STOP_ON_ERROR(result); ..... // Start the scans //for (device = 0; device < DEVICE_COUNT; device++) //{ result = mcc172_a_in_scan_start(address[SLAVE], chan_mask[SLAVE],samples_per_channel, options); result = mcc172_a_in_scan_start(address[MASTER], chan_mask[MASTER],samples_per_channel, options); STOP_ON_ERROR(result); //} I couldn't run it but it did compile. Let me know if you see improvement otherwise I'll plan on testing early next week. Best regards, John 1a_multi_hat_synchronous_scan.c
  17. Hello, Could you attach (or include link to) the data sheet for the sensor at the end of your hammer? I have a 50g 100mV/g accelerometer on the end of my hammer and am not experiencing the same trouble. My QuickDAQ version is 3.7.0.49. I've configured the FFT Analyzer for an Analysis Frequency of 399Hz and the FFT size is 1024. Each trigger will take a little over 2 seconds to acquire. The trigger is Ain 0 Analog Threshold Pos Edge set to 1g which is approximately 0.1 volts from the accelerometer. A lite tap is all that is needed. Below are my results halfway through a 10 trigger sequence. On Ain 1, I've connected a signal generator set to sine wave 158 Hz 1.0v peak (IEPE current off), hence the hump in the blue trace. Best regards, John
  18. Hello, I found this statement in the programming guide for the clock config write: If you change the clock configuration on one device after configuring the master, then the data will no longer be in sync. The devices cannot detect this and will still report that they are synchronized. Try reversing the order for the clock config write functions and configure the slave is first. Let me know if it solves the issue, but if does not attach your script and I'll investigate. Best regards, John
  19. Hello, The IOtech DaqIO LabVIEW Support is based on 32-bit DLL's and as such, you must use a 32-bit version of LabVIEW. I believe if you were to install the LabVIEW Community Edition you have more success. https://www.ni.com/en-us/support/downloads/software-products/download.labview-community.html#460309 Best regards, John
  20. Hello, It works the way you've described, but not with a_in_scan, but with daq_in_scan function. The state of the digital port must be read along with the analog data for the trigger mechanism to work. The same hold true for analog triggering, if you want channel 1 to be the trigger channel it must be in the scan list. With daq_in_scan, a loop-back wire from a DIO to the external trigger pin is unnecessary. When the output from d_out_scan reaches the target value, daq_in_scan function will begin to dump data to the acquisition buffer. If for some reason you need to stick with a_in_scan, then the workaround is a wire from a DIO to the external trigger must be used with an explicit write to set the DIO. Best regards, John
  21. The IOtech PersonalDaq/55 used a better name for the same type of setting, it used Measurement Duration. So Data Rate is really the time the analog-to-digital converter measures the input value and it's not the sample rate, which is sample to sample time. Although choosing a low setting will limit the maximum sample rate. Page 16 in the following user manual has the formula that explains the relationship. https://www.mccdaq.com/pdfs/manuals/USB-2416.pdf The analog-to-digital converter is a sigma-delta converter. These can run very fast but when doing so they produce inaccurate data. So the technique is to slow them down to achieve higher accuracy. A side effect of this technique is it creates a low pass filter capable of reducing signal noise too. For thermocouple measurements, I found the 60 Hz setting works well. Long story short, when you see the term data rate, think measurement duration. Best regards, John
  22. Hello, For the digital pattern trigger to work, the program must be actively scanning the digital port. To read both analog and digital at the same time use the daq_in_scan function. When properly configured, it can simultaneously read analog + digital + counter. Take a look a the example daq_in_usb_1800.py. To use pattern triggering add EXTTRIGGER to the daq_in_scan options (for example CONTINUOUS|BACKGROUND|EXTTRIGGER) and use set_trigger function to configure the pattern. The low threshold parameter is the digital pattern and the high threshold is the mask. For example set_trigger(board_num, TRIG_PATTERN_ABOVE, 3, 15) Best regards, John
  23. Hello and good catch, I apologize for the misinformation. The MCC 172 is a little different, when compared to our other products, in that it has the function a_in_clock_config_write that sets the clock direction. Because of this, you don't use the OptionsFlags.EXTCLOCK and instead use just DEFAULT or CONTINUOUS with a_in_scan_start. Start the slave board first then the master and it should all fall into to place. Best regards, John
  24. Hello again, I was able to locate your board (s/n 1FAC0F0) in our system but have some bad news. It was delivered to Logicbus in June of 2021 which puts it outside of the 1-year warranty period. Best regards, John
  25. Hello, Are you looking for a system integrator that could build you a custom device with BNC connectors and/or create a custom program to suit your application? Best regards, John
×
×
  • Create New...