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?

Parents
  • 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

Reply Children
  • 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