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.

AM3358: ADC issue in C program

Part Number: AM3358

Beaglebone Black Rev C , Linux ARM 4.14.108-ti-r104  April 9, 2019.

After reboot, command line cat  /sys/bus/iio/devices/iio:device0/in_voltage0_raw works fine returning 0 with AIN0 grounded to ADC_GND, 4095 when connected to VDD_ADC (1.8vdc), and around 3967 if left floating.  

But trying to read that pin from a compiled C program always returns Resource temporarily unavailable.  After giving up on open() and fopen() I've resorted to :

int value;
value= system( "cat /sys/bus/iio/devices/iio:device0/in_voltage_raw");


//OR:

value= system( "cat /sys/bus/iio/devices/iio\\:device0/in_voltage_raw");

This not only returns the Resource ...unavailable error message but also errors out later manual  attempts from Linux command line to use the 

cat  /sys/bus/iio/devices/iio:device0/in_voltage0_raw   command, returning the Resource unavailable error there as well.  After reboot the manual command line method works fine again. 

This all I'm doing.  No other ADC channels, no bluetooth.  HDMI out to my monitor, USB to a hub for keyboard, mouse, and wifi adapter.  

  • Hello Alan,

    This sounds like a generic Linux question rather than a TI-specific question. (How do I take something I type into the terminal, and put it in a script instead?). We only support TI-specific questions on the forum (e.g., how do I use the ADC driver? did I connect up my ADC wrong? etc). I suggest searching around on Google to find your answer.

    Feel free to reply if you disagree and we can continue the discussion.

    Regards,

    Nick

  • Nick, thanks for your reply.  Point well taken, but I've been googling for many days and of the half dozen or so applicable hits only the few on your TI forum seem to come close.  I was hoping someone might aim me at a kernel patch or something simple like that.  

    Experts on the TI forum have also referred to an esoteric [to me, that is] ADC timeout variable in your driver[s] that may have helped alleviate this resource unavailable error that does seem to originate from your TI driver.  My hope is that someone could help me adjust the driver settings to allow me to periodically, like once per minute, read the 3358 ADC without this problem.  

    So, I respectfully disagree even though having so little understanding of WTH is going on.

  • Hello Alan,

    I am taking a look at this now. Seeing if I can reference the code at tools/iio/iio_generic_buffer.c to do something useful.

    Regards,

    Nick

  • Awesome.  Thanks, Nick.  Still stumped.

    Alan

  • Hello Alan,

    Here is the C code I tested. I used open, read, close commands. There are probably some unneeded includes, I just threw the example together. It works as expected on AM65x ADC, but AM335x has the same ADC so it should work just fine on BeagleBone Black.

    Regards,

    Nick

    /*
     * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
     *
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     *      * Redistributions of source code must retain the above copyright
     *        notice, this list of conditions and the following disclaimer.
     *
     *      * Redistributions in binary form must reproduce the above copyright
     *        notice, this list of conditions and the following disclaimer in the
     *        documentation and/or other materials provided with the
     *        distribution.
     *
     *      * Neither the name of Texas Instruments Incorporated nor the names of
     *        its contributors may be used to endorse or promote products derived
     *        from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdint.h>
    #include <stdbool.h>
    #include <sys/time.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <stdbool.h>
    #include <poll.h>
    #include <inttypes.h>
    #include <unistd.h>
    #include <errno.h>
    
    /* 4 digits are sufficient to read ADC raw values */
    /* chose a bigger number just in case */
    #define BUF_SIZE 10
    char payload[BUF_SIZE];
    
    int main(int argc, char *argv[])
    {
            /* create output file descriptor */
            int output_fd;
            char adcName[] = "/sys/bus/iio/devices/iio\:device0/in_voltage0_raw";
            output_fd = open(adcName, O_RDWR);
            if (output_fd < 0) {
                    printf("failed to open ADC");
                    exit(EXIT_FAILURE);
            }
    
            /* read ADC voltage */
            int readResult = read(output_fd, payload, BUF_SIZE);
            printf("ADC output is %s \n",payload);
    
            close(output_fd);
    
            return EXIT_SUCCESS;
    }

  • My gcc compiler objected to the "\" backslash escape character in the file name:

    char adcName[] = "/sys/bus/iio/devices/iio\:device0/in_voltage0_raw";
    
    so, changed to:
    
    char adcName[] = "/sys/bus/iio/devices/iio:device0/in_voltage0_raw";
    

    And gcc found the variable  int readResult on line 66 not otherwise used in the program.  After correcting those bugs your code and mine compiled and ran fine if compiled in isolation, even after removing several of your  #includes.

    But when I compiled and linked several modules of code including my header file the ADC channel again could not be read, "resource temporarily unavailable" .

    The conflict turned out to be my using <iobb.h> and linking to that iobb library.  I'd been using that successfully to configure and manipulate four GPIO output pins not realizing it also includes code to handle ADC, apparently excluding the Robert C. Nelson device tree BB-ADC-00A0.dts.  

    By abandoning iobb and using the universal i/o config-pin utility to handle GPIO pins:

    system("config-pin P9.15 lo");
    

    github.com/.../beaglebone-universal-io

    then forcing my old eMMC bootloader to stop blocking u-boot overlays:

    sudo dd if=/dev/zero of=/dev/mmcblk1 bs=1M count=10
    

    It now all works well, GPIO manipulation and ADC reads via the simple open() and read()  C commands you demonstrated.  

    Hope my code and html Syntax Highlighter pastes are not confusing.  I see no way to preview , so will just post and then try to edit, and , yes, later feed back resolution of my issue.