Post Go back to editing

Can't run cn0554_example.py

Category: Software
Product Number: CN0554

Hi Everyone,

I am directly interfacing the CN0554 to an RPI4 running ADI-Kuiper-Linux OS. I followed the instructions in https://wiki.analog.com/resources/tools-software/linux-software/pyadi-iio to install pyadi-iio. 

After that I downloaded the example https://github.com/analogdevicesinc/pyadi-iio/blob/master/examples/cn0554_example.py and tried to run it, but I get the error below

Traceback (most recent call last):
File "/home/analog/code/cn0554_example.py", line 17, in <module>
my_cn0554 = adi.cn0554(uri='local')
AttributeError: module 'adi' has no attribute 'cn0554'

Has anybody else run into this error?

Thanks,

Massimo

Parents Reply
  • Hi Dragos, I finally was able to install the updated pyadi-iio package and I was able to run the cn0554_example.py file, at least for the most part.  For instance, if I change the voltage values to make voltage01 negative, then the ADC gives 0 V (even though the default range is +/-13.75V).

    The example is quite basic, but I would definitely need additional documentation to be able to do things like settings the ADC sampling rate, configure the ADC as single ended (would that be an option?), define which ADC channels to read, calibrate the ADC, and so on. I am new to this adi/python environment, so I would need more information than I can find on the official CN0554 user guide page.

    Thank you,

    Massimo

Children
  • Hi Massimo,

     

    Below are responses to your previous inquiries.

     

    >>>"The example is quite basic, but I would definitely need additional documentation to be able to do things like settings the ADC sampling rate, configure the ADC as single ended (would that be an option?), define which ADC channels to read, calibrate the ADC, and so on. I am new to this adi/python environment, so I would need more information than I can find on the official CN0554 user guide page."

     

    = Inside the pyadi-iio repository, if you navigate to pyadi-iio > adi folder, you will be able to locate the cn0554.py python file.

     

    This is the class for the cn0554 device which contains all the functions, parameters, and properties that would control and set, as well as read from, the device based on your requirements.

     

    The functions that were used on the cn0554_example.py python file that you run were based on the cn0554.py class. This is where you can browse and explore the board's reading and writing capabilities.

     

    To give you an example, to set the ADC sampling rate, I would go and add the line below to my example script:

    my_cn0554.adc.sample_rate = 614400

     

    In addition to that, to choose which ADC channels to read from, (in the below example only channels 0,1, and 2 are enabled), I would add the following line as well:

    my_cn0554.adc.rx_enabled_channels = [0, 1, 2]

    This sample rate setter function can be found in lines 108 - 111 of the cn0554 pyadi-iio python class. While the adc channel setter function can be found in lines 75 - 78.

    pyadi-iio > adi > cn0554.py

    === The functions to use to calibrate the adc as well as the dac can be found in the cn0554 pyadi-iio class.

    >>>"For instance, if I change the voltage values to make voltage01 negative, then the ADC gives 0 V (even though the default range is +/-13.75V)."

    = For the ADC to be able to recognize both positive and negative analog input voltages, the CN0554 device tree overlay must be edited. To enable the bipolar coding mode, the following line must be added to the 8 ADC channels found in the .dts file:

    bipolar;

    The CN0554 device tree overlay can be found in this link: linux/arch/arm/boot/dts/overlays/rpi-cn0554-overlay.dts at rpi-5.10.y · analogdevicesinc/linux (github.com)

    AD7124 fragment in .dts file:

    adc7214: ad7124@0 {

    compatible = "adi,ad7124-8";

    reg = <0>;

    spi-max-frequency = <5000000>;

     

    #address-cells = <1>;

    #size-cells = <0>;

     

    clocks = <&ad7124_mclk>;

    clock-names = "mclk";

     

    interrupts = <25 2>;

    interrupt-parent = <&gpio>;

     

    refin1-supply = <&vref>;

     

    channel@0 {

    reg = <0>;

    bipolar;

    diff-channels = <0 1>;

    };

     

    channel@1 {

    reg = <1>;

    bipolar;

    diff-channels = <2 3>;

    };

     

    channel@2 {

    reg = <2>;

    bipolar;

    diff-channels = <4 5>;

    };

     

    channel@3 {

    reg = <3>;

    bipolar;

    diff-channels = <6 7>;

    };

     

    channel@4 {

    reg = <4>;

    bipolar;

    diff-channels = <8 9>;

    };

     

    channel@5 {

    reg = <5>;

    bipolar;

    diff-channels = <10 11>;

    };

     

    channel@6 {

    reg = <6>;

    bipolar;

    diff-channels = <12 13>;

    };

     

    channel@7 {

    reg = <7>;

    bipolar;

    diff-channels = <14 15>;

    };

    };

    Here is an edited cn0554 .dts file where the bipolar mode is enabled.

    rpi-cn0554-bipolar.zip

     

    After editing the .dts file, the compiled and built new .dtbo file must be added to the /boot/overlays folder of the raspberry pi. And then reference the overlay in config.txt found in the boot folder.

    For your reference, I have attached a .dtbo file below where the bipolar mode is enabled. Let me know if this works for you.

    rpi-cn0554-bipolar-dtbo.zip

    You would need to copy the .dtbo file inside the /boot/overlays folder of the raspberry pi and then change the current dtoverlay line to:

    dtoverlay=rpi-cn0554-bipolar

    Then reboot the system.

     

    Note: When the bipolar mode is enabled, you must definitely set the adc rx output type to "raw". The .rx data capturing function for bipolar values in SI unit is natively not supported.

     

    To get the actual bipolar voltage input values to the ADC, refer to the formula below:

     

    read_adc_voltage _input = [(raw value + offset value) * scale value] / 1000] * scale_resistor divider

     

    When in bipolar mode, coding is offset binary which means that the offset value is -(2^(n-1)) = -8388608

     

     

    >>> Additionally, yes, it is possible to configure the ADC as single-ended. To do this, you would have to edit the device tree overlay.

    You may refer to the thread below on how to change the 8 differential channels of the ADC to 16 single-ended channels.

    (+) ad7124-8 device tree(How to pseudo differential channels) - Q&A - Linux Software Drivers - EngineerZone (analog.com)

    Please don't hesitate to reach out with any questions or clarifications.

    Regards,

    Andy

  • Hi Andy,

    Thanks a lot for your detailed answers. 

    I can see that the Python interface page for CN0554 has been revved up and now it is more complete. 

    Since I had posted my questions a while ago, I have been making some progress using the python interface to the ad7124 device. However, the information you included about the bipolar and single ended modes is new (and very useful) to me. I am not quite sure how to process the .dts file though. I checked on my system and I have not found one. Is there an example/tutorial that explains how to process this file?

    Another question I have about the adc conversion is about the scale. For my board the default value  (0.000149011) is too small (it should be something close to 0.00015362). I tried to change the attribute in several ways (using the libiio ii0_attr app, the IIO Oscilloscope app, overwriting the related file, etc.), but it seems that it is changed right back by some background process. Is there a way to change the scale values?

    I have also been trying to use the libiio directly. The issue I am facing with the related applications (e.g. iio-readdev) is that I can only run them as root (otherwise it will say that I don't have the permission to create the buffer). Is there an easy solution to this problem?

    Thanks,

    Massimo

  • Hi Massimo,

     

    In your Linux PC, to open and edit a .dts file, you may open it using Visual Studio code and still make sure that the file is still has the ".dts" extension when re-saving.

    The next step would be to compile the .dts (device tree source) file into a .dtbo (device tree blob overlay) file in binary form, which would be the one that will be added to the original device tree.

    This is necessary because by converting the DTS file into a DTBO, you can overlay a central Device Tree Blob (DTB) onto the device tree.

    In your Linux PC, using the command line terminal, two commands would be helpful to generate the dtbo file from your dts file:

    Notes:

    *** Let's use the rpi-cn0554-bipolar.dts file for this example

    2185.rpi-cn0554-bipolar.zip

    *** Let's say that the .dts file is located in the directory: /linux/arch/arm/boot/dts/overlays

    *** Let's that you are currently in the "linux" folder directory (take note that the directory you are currently in in the command line terminal will be the destination of the preprocessed dts file and the dtbo file you will generate)

    *** The RPi + CN0554 is connected thru LAN connection

     

    1. The first command will pre-process the the dts file with the C preprocessor in order to convert the file into a format that will be accepted by the Device Tree compiler.
      cpp -nostdinc -I include -I arch  -undef -x assembler-with-cpp ../linux/arch/arm/boot/dts/overlays/rpi-cn0554-bipolar.dts ../rpi-cn054-bipolar.dts.preprocessed
    2. The second command will compile the file and generate the .dtbo file
      dtc -@ -I dts -O dtb -o ../rpi-cn0554-bipolar.dtbo ../rpi-cn0554-bipolar.dts.preprocessed

    Once you have generated the .dtbo file, this can now be added into your Raspberry Pi to apply the configuration changes you've made to the actual device based on your desired requirements.

    If you wish to try and edit the .dts file of the CN0554 found in this link: https://github.com/analogdevicesinc/linux/blob/rpi-5.10.y/arch/arm/boot/dts/overlays/rpi-cn0554-overlay.dts, you may download, open, and edit it using Visual studio code or any code editor available to you.

     

     ============================

    There are two ways to incorporate the edited dtbo to your Raspberry Pi. The first way is by changing the boot and hardware configuration of the RPi by editing its existing config.txt file and the second way is to build a new kernel image containing the edited device tree overlay.

     

    First WayAdd the dtbo file to the boot/overlays folder of your RPi flashed with the ADI Kuiper Linux Image and edit .config.txt

    To perform an initial testing of the CN0554 wherein the bipolar mode is enabled, you may use the .dtbo file that I have attached before. The steps to change the current overlay of your board are as follows:

    5810.rpi-cn0554-bipolar-dtbo.zip

    1. Download and extract the .dtbo file from the attached zip file.
    2. Boot the raspberry pi with the flashed ADI-Kuiper-Linux image.
    3. Transfer the .dtbo file from your Host PC to your Raspberry Pi.
      1. In our setup, I transferred the .dbto file to the rpi using Filezilla, available for download from the internet. But you may try any way that may work for you, as long as the file will not be encryrpted in any way during the transfer of the DTBO file into your Raspberry Pi flashed with the ADI Kuiper Linux image.
      2. The credentials to connect to the rpi server is as follows:
        1. Host: analog.local
        2. Username: analog
        3. Password: analog
        4. Port: 22 (Port 22 is used for SSH/SFTP protocol)
      3. Transfer the .dtbo file to the RPi Desktop
      4. Proceed to your RPi device. Copy the rpi-cn0554-bipolar.dtbo file to /boot/overlays folder of the Raspberry pi.
        1. In this example, the .dtbo file is located in the Desktop of the RPi. 
        2. The command to copy the file into the boot/overlays folder is as follows:
          The syntax to copy and paste a file in RPi is: cp source-directory/file-to-copy. txt destination-directory/.

          sudo cp rpi--cn0554-bipolar.dtbo /boot/overlays
          The command must be run as root user. Enter "analog" when prompted for a password.

          *** Sometimes the command line terminal will present an error after attempting to copy the file even though the file was actually copied. Please double check if the file was copied before proceeding and re-checking your command.

    4. After successfully copying the .dtbo file to the boot/overlays folder, navigate to the boot/ folder to edit the config.txt file and change the dtoverlay line.
      1. Change directory to navigate to the 'boot' folder
      2. After navigating to the boot folder, open and edit the config.txt file by entering the following command:
        sudo mousepad config.txt
        *** The command must be run as root user. Enter "analog" when prompted for a password.

      3. This brings up the config.txt file in a text editor window. Scroll down until the line that begins with “dtoverlay” is found; then, whatever it currently is, change it to: 
        dtoverlay=rpi-cn0554-bipolar
      4. Save the file. Reboot the system by typing on the command prompt:
        sudo reboot

        Second Way: Build a new kernel image

        If you wish to try and re-build a new kernel image containing the device tree overlay you have edited, you may refer to the link below:

         

        Building for Raspberry PI [Analog Devices Wiki]

         

        You may also refer to this thread below for compiling a new kernel image for RPis:

        (+) Compiling a linux kernel for AD5360 - Q&A - Linux Software Drivers - EngineerZone (analog.com)

        https://linux.ime.usp.br/~marcelosc/2019/09/RaspberryPi-kernel-compilation

         

         

        >>> "Another question I have about the adc conversion is about the scale. For my board the default value  (0.000149011) is too small (it should be something close to 0.00015362). I tried to change the attribute in several ways (using the libiio ii0_attr app, the IIO Oscilloscope app, overwriting the related file, etc.), but it seems that it is changed right back by some background process. Is there a way to change the scale values?"

         

        It's not possible to overwrite the scale value of the ADC but may I ask where the value 0.00015362 was computed from and more details on why you would need to change it?

        The default scale value 0.000149011 is correct given by the equation:

        2.5 / (2^24) = 0.0 0.000149011 x 10^(-3) volts

        ***Where 2.5 is the voltage reference of the 24-bit ADC.

         

        >>> "I have also been trying to use the libiio directly. The issue I am facing with the related applications (e.g. iio-readdev) is that I can only run them as root (otherwise it will say that I don't have the permission to create the buffer). Is there an easy solution to this problem?"

         

        Running the script thru "ip:localhost", will enable it to use the network backend via iiod.

         

         

        Please don't hesitate to reach out with any questions or clarifications.

         

        Regards

        Andy

      1. Hi Andy,

        Thanks again for the very detailed answers. Your instructions are very clear and on point.

        Thanks to your suggestions, I am finally able to run the libiio apps without elevating my permissions. 

        I think last big question I have regarding the CN0554 is if the ad7124 can be used for continuous acquisition, i.e. streaming. Do you know if there are any examples showing how the continuous acquisition can be implemented? 

        Regarding your question about the scale factor, the reason that I would like to adjust it is that voltage values returned by the script cn554_example.py are not correct. Below is the output from this script

        #####################################################################################
        #####################################################################################
        Scale factor from onboard resistors: 11
        -------Vset values: 1500mV 1200mV -------

        Capturing data....


        Expected difference measurements: 0.3
        Average Values of voltage01: 0.2908132800101074
        #####################################################################################

        Scale factor from onboard resistors: 11
        -------Vset values: 4500mV 1200mV -------

        Capturing data....


        Expected difference measurements: 3.3
        Average Values of voltage01: 3.2008079310833937
        #####################################################################################


        Scale factor from onboard resistors: 11
        -------Vset values: 7500mV 1200mV -------

        Capturing data....


        Expected difference measurements: 6.3
        Average Values of voltage01: 6.11092098143696
        #####################################################################################
        #####################################################################################

        Using the corrected scale would make the average measurement much closer to the expected value. 

        On the other hand, it could well be that the scale factor related to the onboard resistor is off on my board. I guess I should use the jumpers to change the resistors and verify.

        Thanks,

        Massimo

      2. Hi Massimo,

        The live data capture feature from the ADC was not utilized during the development of the example for the CN0554. But I came across these links discussing about the data capturing feature of the AD7124, for your reference:

        1. Precision ADC Tutorial [Analog Devices Wiki]
          1. This page presents complete and detailed examples on how to capture, plot, analyze data from the ADC using python
          2. There is also a downloadable zip file containing example python scripts on how to get data from the AD7124

        2. (+) ad7124_simple_capture.py does not find ad7124 device - Q&A - Software Interface Tools - EngineerZone (analog.com)
          1. Within this thread in EngineerZone discussing about an AD7124 issue, an example code located in github was posted by the user for plotting the values from the ADC, in real-time. You may check this out for your reference in creating your own example code.

         

        Hope this helps. Please don't hesitate to reach out with any questions.

         

        Regards,
        Andy

      3. Hi Andy,

        Thanks again for your feedback.

        The examples you mentioned are very useful (I had learned a lot from them about the AD7124 class), however I am not sure they show how to setup the AD7124 for continuous streaming. For instance, the second link you sent includes the script called ADC1.py where the acquisition is run on a separate thread. Basically, it is an infinite loop where the method rx() is called, the returned data are put in a queue and then a signal is sent to the main thread. This would be an implementation of continuous acquisition if no data is lost between two consecutive calls of the rx() method.  This implies that the AD7124 starts the conversion before the rx() method is called, otherwise loss of data between two consecutive calls of rx() would be inevitable. 

        I guess the question I have here is: when does the conversion start, after enabling the channel(s), or when the rx() method is called?

        Thanks,

        Massimo

      4. Hi  , I'm not the Linux driver expert but I do have some experience working with the AD7124 and its pyadi-iio class. Fundamentally, it may not be possible to achieve continuous streaming data with the Raspberry Pi, limited by the SPI peripheral and how quickly it can respond to interrupts. We do have designs that capture high sample rates over a serial SPI interface, but they typically use the SPI engine (see https://wiki.analog.com/resources/fpga/peripherals/spi_engine) which requires an FPGA.

        Note that the AD7124 is not specified for measuring AC signals (where you'd quantify THD, SNR, etc. with a sinewave applied.) And it's not possible to truly synchronize the sampling with an external event, at least not with the present incarnation of the driver. There is a SYNC pin, but I'm not sure if that will confuse the driver, nor how it would affect operation when multiple channels are involved. That would be a question for  Linux Software Drivers .  

        As another tangible experiment, in this article: https://www.analog.com/en/technical-articles/use-python-for-analysis-of-noise.html we had to throttle the sample rate to 64 sps to guarantee no missing samples in the data records used to plot the filter response.

        Another point - While the AD7124 is capable of running at a base sample rate of 19.2 ksps, whenever you enable multiple channels, this is not only split across the channels, but an additional number of samples are required to flush the digital filter - for example if the SINC4 filter is selected and two channels are enabled, the effective sample rate per channel is the base sample rate divided by 8.

        To summarize - the AD7124 is mainly suitable for DC measurements, or signals that move slowly such that a one-sample delay in reading data (caused by a missed data point) won't affect overall operation.

           is working on another pyadi-iio class for a power supply board that uses the CN0554 as a controller / monitor, and I've recommended to NOT use rx(), rather use raw * scale + offset (with some additional scaling that applies to the board it's attached to.) The original intent was to use rx() to capture a buffer of samples, then average them. But the AD7124 already does this - setting the sample rate to a lower value inherently averages more, has a narrower filter bandwidth, and correspondingly lower noise.

        If you do need to characterize quickly moving signals, the AD7768 family (single, quad, and octal) of sigma-delta ADCs is an option - but requires an FPGA to receive the data. Depending on how fast the signals are moving, a SAR (sampling) ADC may be more appropriate.

        -Mark

      5.  Hi Mark,

        Thanks for providing additional information on  the AD7124. 

        I may have overlooked it, but I have not found a method for selecting the filter in the ad7124 class. 

        Using the iio_attr app from the libiio, I can see that the "filter_low_pass_3dB_frequency" value changes as the sampling frequency is changed, but I have not seen how to select SYNC3 (assuming that SYNC4 is the default one).

        I ran a simple test based on some suggestion I found online (see the command reported below), and I found that, with the sampling rate set a 19200 Sa/s, the throughput is about 15.6 kB/s, when retrieving data from 4 channels. Here is the command I used:

        iio_readdev -u ip:localhost ad7124-8 voltage0-voltage1 voltage2-voltage3 voltage4-voltage5 voltage6-voltage7| dd of=/dev/null status=progress
        4715008 bytes (4.7 MB, 4.5 MiB) copied, 303 s, 15.6 kB/s

        Since these are 4-byte words, the effective sampling rate is not quite 1 kSa/s. 

        Yes, not the fastest. Also, with this settings I measured about 1.1 mV RMS noise.

        Well, not very exciting, but it may be good enough for my application.

        Thanks,

        Massimo