This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM4378: ADC sample in continuous mode

Part Number: AM4378

Processor: AM4378

Kernel: 4.1.6

Background:

When I use generic_buffer tool to sample the data from a pwm
channel(50%duty), I find data are not in uniform distribution,
even it has big difference between high level and low level
voltage. I know it is impossible to make the data in uniform
distribution, but the big difference makes me in bad situation.

Params:

1. generic_buffer: lenght=20, 5ms sample once.

2. Below "ADC value" is raw data from "read"

3. "ADC AVG" is the highest (array[16]+array[17]+array[18])/3

Devicetree:

this channel is configured as "adc" instead of "tsc"

opendelay=0x00

sampledelay=0xff

I only use channel6, and in dts, i open channel 5/6/7 three
channels.

Thanks for any suggestion.

iio device number being used is 0
scan_size:2
read_size:40
ADC value:1821 1820 1819 1820 1820 864 8 0 0 0 0 1823 0 0 0 1835 
1816 1818 1825 1817 
ADC AVG Value: 1823
read_size:40
ADC value:1817 24 0 2 0 0 1841 1818 1820 1818 1818 1820 0 0 0 0 
1823 1819 1819 1818 
ADC AVG Value: 1821
read_size:40
ADC value:1818 1821 0 0 0 0 0 1824 1830 1819 1820 1818 1820 1817 
1819 1821 1816 97 5 0 
ADC AVG Value: 1822
read_size:40
ADC value:10 0 1855 1824 1820 1817 1822 1820 233 0 0 0 1819 2 0 0 
0 0 1830 1820 
ADC AVG Value: 1825
read_size:40
ADC value:1817 1832 1817 1819 6 0 0 0 0 1844 1821 1820 0 0 1821 
1820 1818 1822 1819 619 
ADC AVG Value: 1825
read_size:40
ADC value:0 0 0 0 0 1823 1820 1818 1818 1824 1822 0 1819 1818 
1816 16 0 2 0 0 
ADC AVG Value: 1821
read_size:40
ADC value:1838 1819 1818 1827 1821 1818 47 0 0 8 0 1846 0 4 0 0 
1824 1819 1819 1820 
ADC AVG Value: 1829
read_size:40
ADC value:1818 1817 7 0 1 0 0 1825 1821 1818 1818 1821 1820 1818 
1820 29 0 0 0 0 
ADC AVG Value: 1820
read_size:40
ADC value:1839 1821 1820 1821 1831 1820 45 0 0 0 0 1841 0 0 0 0 
1824 1820 1828 1819 
ADC AVG Value: 1832
read_size:40
ADC value:1822 1818 3 0 0 4 0 1825 1820 1818 1818 1820 1821 1836 
1820 1819 1819 103 0 6 
ADC AVG Value: 1822

  • Please see processors.wiki.ti.com/.../Linux_Core_ADC_Users_Guide I don't understand why you must read in 3 channels if you only need one. I also don't understand your logic for the averaging calculation.
  • Hi Biser, thanks for your reply.
    1. why 3 channels, I just keep these channels, and i only use one channel in generic_buffer. But 3 channels should be ok.
    2. Average, because i just need high level, so i will keep 3 highest value(except array[19]), this is just my logic, it has no association with this topic.
    3. I have read wiki before, but generic_buffer printing as above, it is not uniform distribution, even worse.

  • Hi Biser,

    can you give some guide, I have read your guide many times. Also it tells me to use generic_buffer to test adc continuous mode. But it is not uniformat distribution, even worse. Thanks.
  • Aaron,

    Can you post a few things here:
    * device tree file section that sets up the ADC
    * any sysfs commands you are using on the /sys/bus/iio/devices/iio\:device0/ interface
    * any C code that you've written for this

    Also, what is the voltage of the PWM signal that you are trying to read? Keep in mind that the built-in ADC can only read values up to 1.8v and nothing higher than that should be connected.

    I know the duty cycle is 50% but what is the frequency of your PWM that you are trying to capture?

    Jason Reeder
  • Hi Jason,

    Thanks for your reply and sorry for my later reply.

    • devicetree
    adc {
        ti,adc-channels = <5 6 7>;
        ti,chan-step-opendelay = <0x0 0x0 0x0>;
        ti,chan-step-sampledelay = <0xff 0xff 0xff>;
        ti,chan-step-avg = <1 1 1>;
    }
    • sysfs command

    I am using generic_buffer, so all sysfs command keeps corresponding with it except for below:

    1. SAMPLE_NUM=20

    2. adc_channel=6

    • C code

    c code keeps corresponding with generic_buffer.

    Another question:

    Can I calculate sample frequency based on opendelay time and sample delay. Because one sample FSM includes Open, SOC, Wait for EOC according to Datasheet, and <Wait for EOC> is not fixed.

  • Aaron,

    According to the AM437x TRM (http://www.ti.com/lit/pdf/spruhl7) the minimum number of ADC cycles between samples is 15. This is explained underneath Figure 11-4 in section 11.4.1. To achieve this minimum number of samples the open delay should be set to 0, the sample delay should be set to 1 and the average should be set to 0. 

    After reading into the Linux ADC driver I found that the ADC clock is being run at 3MHz (24 MHz divided by 8 (adc_clkdiv = 7)) in order to achieve a sampling rate of 200ksps across all the channels (200ksps for 1 channel, 100ksps each for 2 channels, etc). This comes from:

    1 / 3MHz = 333.33ns ADC clock period --> 333.33ns * 15 ADC clocks = 5us sample period --> 1 / 5us = 200ksps sampling rate

    I was able to verify all of this was working correctly by enabling a single ADC channel (channel 5), providing a 50% duty cycle signal (using a PRU pin and a voltage divider), and then see that half the samples were low and half the samples were high.

    Here is what I changed my device tree to:

    &tscadc {
            status = "okay";
    
            adc {
                    ti,adc-channels = <5>;
                    ti,chan-step-opendelay = <0x0>;
                    ti,chan-step-sampledelay = <0x1>;
                    ti,chan-step-avg = <0>;
            };
    };

    I then provided a signal with a 100us period (50% low and 50% high) and I ran the unmodified iio_generic_buffer application with the following command line arguments:

    ./iio_generic_buffer -N 0 -g -a

    My output shows ~50% samples are close to 0 and ~50% of the samples are close to the high value:

    3557.000000
    3352.000000
    3346.000000
    3141.000000
    3352.000000
    3358.000000
    3549.000000
    3352.000000
    3328.000000
    0.000000
    8.000000
    15.000000
    5.000000
    0.000000
    0.000000
    1.000000
    2.000000
    31.000000
    3349.000000
    3346.000000
    3142.000000
    3349.000000
    3359.000000
    3562.000000
    3349.000000
    3347.000000
    3350.000000
    3319.000000
    6.000000
    6.000000
    0.000000
    0.000000
    0.000000
    1.000000
    7.000000
    14.000000
    7.000000
    3328.000000
    3356.000000
    3357.000000
    3455.000000
    3349.000000
    3345.000000
    3146.000000
    3351.000000
    3353.000000

    If you are only reading from a single channel then you should disabled the other 2 by removing them from your device tree. If they remain enabled then they will reduce your sample rate by a factor of 3 since the ADC peripheral cycles through enabled channels sequentially.

    I'm not sure why you want a sample delay of 0xFF (255) but this is going to greatly reduce your sampling rate. Instead of 15 ADC cycles per sample you are probably somewhere around 270 ADC cycles per samples. Assuming a single channel this will reduce your sampling rate to ~11ksps. If 3 channels are enabled each with sample delays of 0xFF then your sample rate will fall further to ~3.7ksps.

    Depending on your PWM frequency, this could explain the uneven readings that you are receiving. I also don't understand the sample 16, 17, 18 average strategy either.

    Please try only enabling a single channel and reducing the sample delay to a value of 1 and let me know if your problems persist.

    Jason Reeder

  • Thanks a lot, Jason, I will verify.
  • Jason, It works perfectly. My main problem is "chan-step-avg" setting. I regard that <1> is no average. But after your description, <0> should be no average.
    After your prompt, I know how to calculate the sample time.
    I'd really appreciate it.