Closed MarkRivers closed 2 years ago
The problem was that the DataRate was not being set on Linux. On Windows it is configured by InstaCal, typically to 60 Hz. That is store in non-volatile memory on the USB-2408. Even if cbIgnoreInstaCal() is called on Windows that value is still read from non-volatile memory.
Once I changed the code to add this call on Linux
status = ulAISetConfigDbl(daqDeviceHandle_, AI_CFG_CHAN_DATA_RATE, addr, value);
it worked OK.
The exception is that if the rate is set to 20 Hz or less then it occasionally gets a bad temperature reading. I have added some debugging to libuldaq-1.2.1 to do the following:
Here is the output for 3 good readings when running 2408_Tin.c. Note that the aIn readings are all close to -29600 and the CJC values are all 7840.
UsbDaqDevice::query status=4, buff[] = 84 140 255 0 (16747604)
AiUsb24xx::aIn i32RawVal=-29612
UsbDaqDevice::query status=4, buff[] = 160 30 96 30 (509615776)
AiUsb24xx::updateCjcValues data[0]=7840
Channel 0: 72.053
UsbDaqDevice::query status=4, buff[] = 100 140 255 0 (16747620)
AiUsb24xx::aIn i32RawVal=-29596
UsbDaqDevice::query status=4, buff[] = 160 30 255 30 (520036000)
AiUsb24xx::updateCjcValues data[0]=7840
Channel 0: 72.060
UsbDaqDevice::query status=4, buff[] = 104 140 255 0 (16747624)
AiUsb24xx::aIn i32RawVal=-29592
UsbDaqDevice::query status=4, buff[] = 160 30 96 30 (509615776)
AiUsb24xx::updateCjcValues data[0]=7840
Channel 0: 72.062
Here is the output for a reading that is very bad (16.5 rather than 72.0). Note that the aIn reading is still very close to -2960. However, first 2 bytes of the CJC reading from libusb_control_transfer are 255 when they should not be, and thus the CJC value is -1 rather than 7840.
UsbDaqDevice::query status=4, buff[] = 90 140 255 0 (16747610)
AiUsb24xx::aIn i32RawVal=-29606
UsbDaqDevice::query status=4, buff[] = 255 255 96 30 (509673471)
AiUsb24xx::updateCjcValues data[0]=-1
Channel 0: 16.523
Here is the output for a reading that is only slightly high (72.7 vs 72.0). Note that the aIn reading is still very close to -2960. However, first byte of the CJC reading is 255 when it should not be, and thus the CJC value is 7935 rather than 7840.
UsbDaqDevice::query status=4, buff[] = 87 140 255 0 (16747607)
AiUsb24xx::aIn i32RawVal=-29609
UsbDaqDevice::query status=4, buff[] = 255 30 96 30 (509615871)
AiUsb24xx::updateCjcValues data[0]=7935
Channel 0: 72.729
I always see this for the bad readings. If the first and second byte from libusb_control_transfer for the CJC reading are both 255 then the reading is very low. If only the first byte from libusb_control_transfer for the CJC reading is 255 then the reading is slightly high.
There is clearly something wrong so that the CJC value read from the device is occasionally corrupted.
I was able to fix the problem by adding a 100 microsecond sleep in AiUsb24xx::updateCjcValues() before the call to read the CJC values:
usleep(100); // Add this 100 usec sleep
daqDev().queryCmd(CMD_CJC, 0, 0, (unsigned char*) &data, dataCount * sizeof(short));
With this modification it never glitches. This proves pretty conclusively that it is a timing issue, and perhaps Measurement Computing is not seeing it on the Raspberry Pi because it is slower. I’m not sure why it works on Windows, except the timing of the USB driver may be different.
The USB-2408 temperature readings are much noisier on Linux than on Windows. Something must not be configured correctly. This issue is described here: https://github.com/mccdaq/uldaq/issues/37