Post Go back to editing

Trouble calibrating CN0540 using pyadi-iio

Category: Software
Product Number: CN0540
Software Version: 0.0.16

I am trying to calibrate the CN0540 using pyadi-iio like IIO oscilloscope does.

I've found this commit in the pyadi-iio repo that removes the calibrate function from cn0540.py, why was this done?

Furthermore, I've tried to copy the settings used by IIO osc (see image) using pyadi-iio with the calibrate function copied from cn0532.py (this seems to be a newer impl, then the one removed from cn0540.py) and reworked.

    adc = cn0540.cn0540(uri='ip:localhost')

    adc.sw_cc = 1
    adc.fda_disable_status = 1
    adc.fda_mode = 'full-power'
    adc.monitor_powerup = 0


    adc_chan = adc._rxadc
    dac_chan = adc._ltc2606
    adc_scale = float(adc._get_iio_attr("voltage0", "scale", False, adc_chan))
    dac_scale = float(adc._get_iio_attr("voltage0", "scale", True, dac_chan))
    for _ in range(20):
        raw = adc._get_iio_attr("voltage0", "raw", False, adc_chan)
        adc_voltage = raw * adc_scale
        raw = adc._get_iio_attr("voltage0", "raw", True, dac_chan)
        dac_voltage = (raw * dac_scale - adc_voltage) / dac_scale

        e = int(dac_voltage * dac_scale)

        if int(dac_voltage) > 2 ** 16 - 1:
            print(
                "Warning: DAC voltage at upper limit, "
                + f"calibration may not converge (Error: {e-(2**16-1)} codes).\n"
                + "Make sure sensor is connected."
            )
            dac_voltage = 2 ** 16 - 1
        elif int(dac_voltage) < 0:
            print(
                "Warning: DAC voltage at lower limit, "
                + f"calibration may not converge (Error: {e} codes).\n"
                + "Make sure sensor is connected.")
            dac_voltage = 0

        print(f"dac_voltage= {dac_voltage}")
        adc._set_iio_attr_float("voltage0", "raw", True, int(dac_voltage), dac_chan)

    print(f"adc.input_voltage= {adc.input_voltage}")
    print(f"adc.shift_voltage= {adc.shift_voltage}")
    print(f"adc.sensor_voltage= {adc.sensor_voltage}")
    print(f"adc.rx()= {adc.rx()}")

The output of the above code is:

Warning: DAC voltage at lower limit, calibration may not converge (Error: -271 codes).
Make sure sensor is connected.
dac_voltage= 0
Warning: DAC voltage at lower limit, calibration may not converge (Error: -2089 codes).
Make sure sensor is connected.
dac_voltage= 0
Warning: DAC voltage at lower limit, calibration may not converge (Error: -1934 codes).
Make sure sensor is connected.
dac_voltage= 0
Warning: DAC voltage at lower limit, calibration may not converge (Error: -1815 codes).
Make sure sensor is connected.
dac_voltage= 0
Warning: DAC voltage at lower limit, calibration may not converge (Error: -1730 codes).
Make sure sensor is connected.
dac_voltage= 0
Warning: DAC voltage at lower limit, calibration may not converge (Error: -1662 codes).
Make sure sensor is connected.
dac_voltage= 0
Warning: DAC voltage at lower limit, calibration may not converge (Error: -1610 codes).
Make sure sensor is connected.
dac_voltage= 0
Warning: DAC voltage at lower limit, calibration may not converge (Error: -1571 codes).
Make sure sensor is connected.
dac_voltage= 0
Warning: DAC voltage at lower limit, calibration may not converge (Error: -1539 codes).
Make sure sensor is connected.
dac_voltage= 0
Warning: DAC voltage at lower limit, calibration may not converge (Error: -1515 codes).
Make sure sensor is connected.
dac_voltage= 0
Warning: DAC voltage at lower limit, calibration may not converge (Error: -1496 codes).
Make sure sensor is connected.
dac_voltage= 0
Warning: DAC voltage at lower limit, calibration may not converge (Error: -1481 codes).
Make sure sensor is connected.
dac_voltage= 0
Warning: DAC voltage at lower limit, calibration may not converge (Error: -1469 codes).
Make sure sensor is connected.
dac_voltage= 0
Warning: DAC voltage at lower limit, calibration may not converge (Error: -1459 codes).
Make sure sensor is connected.
dac_voltage= 0
Warning: DAC voltage at lower limit, calibration may not converge (Error: -1452 codes).
Make sure sensor is connected.
dac_voltage= 0
Warning: DAC voltage at lower limit, calibration may not converge (Error: -1446 codes).
Make sure sensor is connected.
dac_voltage= 0
Warning: DAC voltage at lower limit, calibration may not converge (Error: -1441 codes).
Make sure sensor is connected.
dac_voltage= 0
Warning: DAC voltage at lower limit, calibration may not converge (Error: -1437 codes).
Make sure sensor is connected.
dac_voltage= 0
Warning: DAC voltage at lower limit, calibration may not converge (Error: -1434 codes).
Make sure sensor is connected.
dac_voltage= 0
Warning: DAC voltage at lower limit, calibration may not converge (Error: -1431 codes).
Make sure sensor is connected.
dac_voltage= 0
adc.input_voltage= 1743.8377985608402
adc.shift_voltage= 0.0
adc.sensor_voltage= -7975.565681703683
adc.rx()= [2883584   11402   11402 ...   11394   11394   11394]

A sensor is connected to the CN0540.

What have I missed to get good data out of the CN0540 using pyadi-iio?

  • Hi Wyatt,

    What sensor are you using (CN0532, or other IEPE sensor?), and what is the output with a zero input? IEPE sensors typically have a 10V offset. You could measure this with a multimeter.

    Also see this issue:  CN0540/DE10-nano signal wrong 

    -Mark

      can you take a look at this as well?

  • Hi Mark,

    For testing, I'm using a skf cmss 2200 accelerometer.

    By zero input, do you mean without a sensor attached? If, so here is that output:

    Warning: DAC voltage at lower limit, calibration may not converge (Error: -299 codes).
    Make sure sensor is connected.
    dac_voltage= 0
    Warning: DAC voltage at lower limit, calibration may not converge (Error: -2111 codes).
    Make sure sensor is connected.
    dac_voltage= 0
    Warning: DAC voltage at lower limit, calibration may not converge (Error: -1950 codes).
    Make sure sensor is connected.
    dac_voltage= 0
    Warning: DAC voltage at lower limit, calibration may not converge (Error: -1821 codes).
    Make sure sensor is connected.
    dac_voltage= 0
    Warning: DAC voltage at lower limit, calibration may not converge (Error: -1728 codes).
    Make sure sensor is connected.
    dac_voltage= 0
    Warning: DAC voltage at lower limit, calibration may not converge (Error: -1655 codes).
    Make sure sensor is connected.
    dac_voltage= 0
    Warning: DAC voltage at lower limit, calibration may not converge (Error: -1598 codes).
    Make sure sensor is connected.
    dac_voltage= 0
    Warning: DAC voltage at lower limit, calibration may not converge (Error: -1553 codes).
    Make sure sensor is connected.
    dac_voltage= 0
    Warning: DAC voltage at lower limit, calibration may not converge (Error: -1517 codes).
    Make sure sensor is connected.
    dac_voltage= 0
    Warning: DAC voltage at lower limit, calibration may not converge (Error: -1489 codes).
    Make sure sensor is connected.
    dac_voltage= 0
    Warning: DAC voltage at lower limit, calibration may not converge (Error: -1467 codes).
    Make sure sensor is connected.
    dac_voltage= 0
    Warning: DAC voltage at lower limit, calibration may not converge (Error: -1449 codes).
    Make sure sensor is connected.
    dac_voltage= 0
    Warning: DAC voltage at lower limit, calibration may not converge (Error: -1435 codes).
    Make sure sensor is connected.
    dac_voltage= 0
    Warning: DAC voltage at lower limit, calibration may not converge (Error: -1423 codes).
    Make sure sensor is connected.
    dac_voltage= 0
    Warning: DAC voltage at lower limit, calibration may not converge (Error: -1414 codes).
    Make sure sensor is connected.
    dac_voltage= 0
    Warning: DAC voltage at lower limit, calibration may not converge (Error: -1406 codes).
    Make sure sensor is connected.
    dac_voltage= 0
    Warning: DAC voltage at lower limit, calibration may not converge (Error: -1400 codes).
    Make sure sensor is connected.
    dac_voltage= 0
    Warning: DAC voltage at lower limit, calibration may not converge (Error: -1395 codes).
    Make sure sensor is connected.
    dac_voltage= 0
    Warning: DAC voltage at lower limit, calibration may not converge (Error: -1391 codes).
    Make sure sensor is connected.
    dac_voltage= 0
    Warning: DAC voltage at lower limit, calibration may not converge (Error: -1388 codes).
    Make sure sensor is connected.
    dac_voltage= 0
    adc.input_voltage= 1689.82184965452
    adc.shift_voltage= 0.0
    adc.sensor_voltage= -7986.440015390977
    adc.rx()= [2752512   11037   11037 ...   11027   11027   11027]
    

    Probing VIN with a multimeter without a sensor attached reads 25.07, and 12.81 with the skf cmss 2200 connected.

    I'm pretty confident the issue is with how I'm using the device, because if I use IIO Oscilloscope (with a Kuiper image see this question) everything seems to work as expected.

    P.S How do link to an EZ question like in your reply?

  • Hi Wyatt,

    25.07 when disconnected, and 12.81 with the skf cmss 2200 connected sounds reasonable - and the CN0540 should be able to handle that offset.

    I've asked  to take a look at this he's more familiar with this board. In the meantime - can you try disable /commenting out the calibration routine, and manually write to the dac_chan, interpolating until you get an ADC output near zero? That should at least get everything else up and running.

    -Mark

  • Hello ,

    Have you had a chance to take a look at this thread? And if so, do you have any updates?

    Thank you.

  • After some experimentation,

    We've found that setting fda_disable_status to 0, and setting the cycles of the calibration loop to one, gets us this result:

    adc raw= -2114104
    adc_voltage= -1032.276815224
    dac raw= 32768
    dac_voltage= 49284.429043584
    dac_voltage= 49284.429043584
    adc.input_voltage= -1259.2794236079799
    adc.shift_voltage= 3757.9049999999997
    adc.sensor_voltage= 7692.945250348018
    adc.rx()= [-2228224    57278    57278 ...    57278    57278    57277]

    Which is much closer to what IIO Oscocope gives, but is still a bit off, calibration probably needs to be run more times, but that can't be done right now because dac_voltage hits a voltage limit.

    Any further help would be much appreciated.

    Thank you.

  • Hi  ,

    I been looking on this issue you've been encountering, and it looks like this is related to the FDA enable logic. I will try your setup on my side, and I will update you on this.

    Regards,

    Ivan

  • Hi Ivan,

    I appreciate your help with this issue, my colleague and I have, I'm pretty sure, made some head-way on a solution.

    After reading the datasheet some more, we wrote this script for testing:


    import time
    from adi import cn0540
    
    adc = cn0540.cn0540(uri='ip:localhost')
    
    adc.sw_cc = 1
    adc.fda_disable_status = 1
    adc.fda_mode = 'full-power'
    adc.monitor_powerup = 0
    
    
    adc_chan = adc._rxadc
    dac_chan = adc._ltc2606
    adc_scale = float(adc._get_iio_attr("voltage0", "scale", False, adc_chan))
    dac_scale = float(adc._get_iio_attr("voltage0", "scale", True, dac_chan))
    
    for i in range(16):
        print(f"Iteration #: {i}")
        raw_adc = adc._get_iio_attr("voltage0", "raw", False, adc_chan)
        adc_voltage = raw_adc * adc_scale
        sensor_voltage = adc.sensor_voltage
        raw_dac = adc._get_iio_attr("voltage0", "raw", True, dac_chan)
        dac_voltage = raw_dac * dac_scale
        # error = dac_voltage - adc_voltage
        # new_dac_voltage = dac_voltage + error
        if sensor_voltage > 0:
           new_dac_setting = raw_dac - (2 ** (16 - (i + 1)))
        else:
           new_dac_setting = raw_dac + (2 ** (16 - (i + 1)))
        print(f"sensor_voltage= {sensor_voltage}")
        print(f"new_dac_setting= {new_dac_setting}")
    
        e = int(dac_voltage * dac_scale)
    
        if int(new_dac_setting) > 2 ** 16 - 1:
            print(
                "Warning: DAC voltage at upper limit, "
                + f"calibration may not converge (Error: {e-(2**16-1)} codes).\n"
                + "Make sure sensor is connected."
            )
            new_dac_setting = 2 ** 16 - 1
        elif int(new_dac_setting) < 0:
            print(
                "Warning: DAC voltage at lower limit, "
                + f"calibration may not converge (Error: {e} codes).\n"
                + "Make sure sensor is connected.")
            new_dac_setting = 0
    
        print(f"adc_voltage= {adc_voltage}")
        print(f"dac_voltage= {dac_voltage}")
        print(f"new_dac_voltage= {dac_voltage}")
        print(f"new_dac_setting= {new_dac_setting}")
        adc._set_iio_attr_float("voltage0", "raw", True, int(new_dac_setting), dac_chan)
    
    print(f"adc.input_voltage= {adc.input_voltage}")
    print(f"adc.shift_voltage= {adc.shift_voltage}")
    print(f"adc.sensor_voltage= {adc.sensor_voltage}")
    #print(f"adc chan= {adc.rx_channel_names}")
    #print(f"adc.rx()= {adc.rx()}")
    
    adc.rx_output_type = 'SI'
    adc.sample_rate = 256000
    adc.rx_buffer_size = 256000
    
    data = adc.rx()
    print(data)
    data.tofile('/data/cal_test_file', ',\n')
    

    The output of this script is:

    Iteration #: 0
    sensor_voltage= 2843.3564057962435
    new_dac_setting= 0
    adc_voltage= 1399.236099997
    dac_voltage= 2048.0
    new_dac_voltage= 2048.0
    new_dac_setting= 0
    Iteration #: 1
    sensor_voltage= -7983.718207291492
    new_dac_setting= 16384
    adc_voltage= 1399.518326415
    dac_voltage= 0.0
    new_dac_voltage= 0.0
    new_dac_setting= 16384
    Iteration #: 2
    sensor_voltage= -2569.979393660044
    new_dac_setting= 24576
    adc_voltage= 1399.7487950470002
    dac_voltage= 1024.0
    new_dac_voltage= 1024.0
    new_dac_setting= 24576
    Iteration #: 3
    sensor_voltage= 136.8908081303632
    new_dac_setting= 20480
    adc_voltage= 1399.414322562
    dac_voltage= 1536.0
    new_dac_voltage= 1536.0
    new_dac_setting= 20480
    Iteration #: 4
    sensor_voltage= -1216.8760943204268
    new_dac_setting= 22528
    adc_voltage= 1398.991471216
    dac_voltage= 1280.0
    new_dac_voltage= 1280.0
    new_dac_setting= 22528
    Iteration #: 5
    sensor_voltage= -540.0654567404638
    new_dac_setting= 23552
    adc_voltage= 1399.1999672030001
    dac_voltage= 1408.0
    new_dac_voltage= 1408.0
    new_dac_setting= 23552
    Iteration #: 6
    sensor_voltage= -201.8093465179295
    new_dac_setting= 24064
    adc_voltage= 1399.106217251
    dac_voltage= 1472.0
    new_dac_voltage= 1472.0
    new_dac_setting= 24064
    Iteration #: 7
    sensor_voltage= -32.68313031770299
    new_dac_setting= 24320
    adc_voltage= 1399.086686011
    dac_voltage= 1504.0
    new_dac_voltage= 1504.0
    new_dac_setting= 24320
    Iteration #: 8
    sensor_voltage= 51.97701058653206
    new_dac_setting= 24192
    adc_voltage= 1399.094498507
    dac_voltage= 1520.0
    new_dac_voltage= 1520.0
    new_dac_setting= 24192
    Iteration #: 9
    sensor_voltage= 9.665365647716953
    new_dac_setting= 24128
    adc_voltage= 1399.107682094
    dac_voltage= 1512.0
    new_dac_voltage= 1512.0
    new_dac_setting= 24128
    Iteration #: 10
    sensor_voltage= -11.469100401835249
    new_dac_setting= 24160
    adc_voltage= 1399.158463318
    dac_voltage= 1508.0
    new_dac_voltage= 1508.0
    new_dac_setting= 24160
    Iteration #: 11
    sensor_voltage= -0.8939356333298747
    new_dac_setting= 24176
    adc_voltage= 1399.1809242440002
    dac_voltage= 1510.0
    new_dac_voltage= 1510.0
    new_dac_setting= 24176
    Iteration #: 12
    sensor_voltage= 4.425928954000028
    new_dac_setting= 24168
    adc_voltage= 1399.2160804760001
    dac_voltage= 1511.0
    new_dac_voltage= 1511.0
    new_dac_setting= 24168
    Iteration #: 13
    sensor_voltage= 1.7883326935623245
    new_dac_setting= 24164
    adc_voltage= 1399.208756261
    dac_voltage= 1510.5
    new_dac_voltage= 1510.5
    new_dac_setting= 24164
    Iteration #: 14
    sensor_voltage= 0.4543363976549699
    new_dac_setting= 24162
    adc_voltage= 1399.19361955
    dac_voltage= 1510.25
    new_dac_voltage= 1510.25
    new_dac_setting= 24162
    Iteration #: 15
    sensor_voltage= -0.18184133884642506
    new_dac_setting= 24163
    adc_voltage= 1399.1779945580001
    dac_voltage= 1510.125
    new_dac_voltage= 1510.125
    new_dac_setting= 24163
    adc.input_voltage= 1707.01442874254
    adc.shift_voltage= 1842.42875
    adc.sensor_voltage= 0.13893109151126737
    [1343.99931187    5.46532923    5.46532923 ...    5.46532923    5.46532923
        5.46532923]
    

    The problem with this is that the sampled voltage does not change beyond noise

    when tested with a sensor on a motor, while a reading from IIO Oscilloscope will.

    Is sensor_voltage the correct value to calibrate to zero-mean? Is there maybe a value that needs to be set to connect the ADC to the sensor, that we're missing?

    Thank you

    Wyatt

  • Hi Mark,

    I tried to do what you suggested, and manually set the value with this script:

    from adi import cn0540
    
    adc = cn0540.cn0540(uri='ip:localhost')
    
    adc.sw_cc = 1
    adc.fda_disable_status = 0
    adc.fda_mode = 'full-power'
    adc.monitor_powerup = 1
    
    adc.shift_voltage = 4057
    
    print(f'fault flag = {adc.sw_ff_status}')
    print(f'adc.input_voltage = {adc.input_voltage}')
    print(f'adc.shift_voltage = {adc.shift_voltage}')
    print(f'adc.sensor_voltage = {adc.sensor_voltage}')
    print(adc.rx())
    

    and the output was:

    fault flag = 0
    adc.input_voltage = -1001.87802219444
    adc.shift_voltage = 4056.9575
    adc.sensor_voltage = 9041.698873213465
    [-1703936    58965    58965 ...    58965    58965    58965]
    

    however, when I have the sensor on a spinning motor, rather than sitting on my desk, I get:

    fault flag = 0
    adc.input_voltage = -993.70200098994
    adc.shift_voltage = 4056.9575
    adc.sensor_voltage = 9032.38787706089
    [-1703936    58898    58899 ...    59053    59054    59055]
    

    Which leads me to think that the sensor is somehow disconnected from the ADC, even though sw_cc, and monitor_powerup are both set to 1, and the fault flag is 0, the fault LED on the board is on as well.

    Is there something I'm missing that could disconnect the sensor from the ADC?

    Thank you,

    --- Wyatt

  • Hi  , sorry for the late reply, I've been out of the office. I don't have immediate access to a CN0540 nor the exact sensor you're using, but there's a couple of simple measurements you can do to start building confidence that the setup is working properly. You've already confirmed that the excitation current source is working, and that the sensor is at least biasing up properly. One other simple test would be to put a milliammeter in series with the sensor and measure the actual excitation current, which I believe should be 4.5 mA.

    Next, take a multimeter and start "walking" down the signal chain - does 12.81V show up at R11? If not - that would indicate that U1, S2-D2 path is open, and to check the state of SW_IN.

    But the fact that you have to bring ADC.shift_voltage all the way to near full-scale is an indication that the signal is getting through the switch. Next - check the voltages at the centre conductor of J2 and J3 - both should be around 2.5V (assuming ADC.shift_voltage is set properly). If you wiggle the sensor, J3 should wiggle.

    Next, look at the output of U4, probing at either side of R64/R65. The average of these two voltages should be 2.5V, and if you wiggle the sensor, you should see complementary waveforms.

    I WAS going to say that your adc.input_voltage of around 1000 was fine, but it looks like that's in millivolts:

    https://github.com/analogdevicesinc/pyadi-iio/blob/master/adi/cn0540.py#L65

    If that's the case, it looks like something may indeed be going on, and you'd expect to see about a volt between R64 and R65.

    Let's start with this and see if it leads to any clues. (Or ideally, the root cause.)

    -Mark

  • HI ,

    I've tested the voltages you suggested, and I seem to be getting different results than you expected.

    With the sensor sitting idle, and adc.shift_voltage set to 4057, I read:

    R11: 12.8

    J2: 2.49

    J3: 1.41

    R65: 1.57

    R64: 2.39

    None of the points wiggle with the sensor on a spinning motor.

    I don't have a setup for measuring mAh from the sensor, but since I can get good data when using the Kuiper image, and IIO Oscilloscope (IIO Oscilloscope won't work on my image), I'm sure it's got to be a config issue.

    Do these readings provide any insight for you?

    Thanks,

    --- Wyatt