Communication between arduino and linux (e.g. code blocks)

Discussion in 'General Programming Discussion' started by achsel, Mar 25, 2015.

  1. achsel

    achsel New Member

    Joined:
    Mar 25, 2015
    Messages:
    2
    Likes Received:
    0
    Hey there,

    we would like to communicate between the two processors by using the GPIO-ports (Arduino-side as an output and Linux as an input). we already did some little arduino sketches, so this part shouldn't be a problem. But our problem is the c code: how do we set up the ports in c, if we don't want to use the console or any consol command in the c code? Is there an easy way similar to the way of the arduino sketches, just by setting up the port ? After reading the state of the GPIO in c we would like to send automatically an email, probably by using mutt and here we might use the console commands in c. But if you have a better way: just tell us!

    Cheers!
     
  2. Andrea Rovai

    Andrea Rovai Well-Known Member

    Joined:
    Oct 27, 2014
    Messages:
    1,703
    Likes Received:
    240
    Re: Communication between arduino and linux (e.g. code block

    Hi achsel and welcome in the forum!
    Actually the best way to use the GPIOs in C is probably using the system command. I'm sorry but I don't know any driver that allows you to manage GPIOs without using the system command.
     
  3. fetcher

    fetcher Member

    Joined:
    Mar 9, 2014
    Messages:
    166
    Likes Received:
    20
    Re: Communication between arduino and linux (e.g. code block

    Here is a simple demo of reading a GPIO input in C from the i.MX6 side, using interrupts to avoid having to waste CPU cycles polling the pin over and over.

    It is based on "gpio-irq-demo.c" (Google for that to see the original), which I modified slightly to use pread() instead of read() to avoid a race condition where initial pin-state can be lost, to wait "forever" for IRQ rather than timing out, and to set up edge-detection and pin direction by itself.

    Run as, for example. "./gpio-demo 159" to watch gpio159 (third from the left on the front header, right next to the I2C pins, but you can pick any one). You could test by just wiring a button between this pin and ground, since there's an internal pullup to +3.3V enabled by default, but expect many interrupts per button-press in that case due to switch-bounce-- not an issue when reading signals sent by the SAM3X or other "clean" logic-level source...

    After running this, "cat /proc/interrupts | grep gpiolib" should show something like

    415: 8538 0 0 0 GPIO gpiolib

    With 8538 being the number of times it was triggered! I was testing by just shorting two wires together by hand, so there was quite a bit of bounce :)

    To disable that IRQ after you're done, do "echo none >/sys/class/gpio/gpio159/edge", substituting 159 for the chosen GPIO.

    See also https://www.kernel.org/doc/Documentation/gpio/sysfs.txt (present in kernel source tree if you have it installed) for a quick overview of how this user-mode IRQ mechanism works.

    Code:
    #include <stdio.h>
    #include <poll.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <string.h>
    
    #define GPIO_FN_MAXLEN  64
    #define POLL_TIMEOUT    -1
    #define RDBUF_LEN       16
    
    int main(int argc, char **argv) {
            char fn[GPIO_FN_MAXLEN];
            int fd,ret;
            struct pollfd pfd;
            char rdbuf[RDBUF_LEN];
    
            memset(rdbuf, 0x00, RDBUF_LEN);
            memset(fn, 0x00, GPIO_FN_MAXLEN);
    
            if(argc!=2) {
                    printf("Usage: %s <GPIO>\nGPIO must be exported to sysfs and have enabled edge detection\n", argv[0]);
                    return 1;
            }
    
            snprintf(fn, GPIO_FN_MAXLEN-1, "/sys/class/gpio/gpio%s/direction", argv[1]);
            fd=open(fn, O_WRONLY);
            if(fd<0) {
                    perror(fn);
                    return 2;
            }
            ret=write(fd,"in\n",3);
            if(ret <= 0) {
                    perror("input direction setup");
                    return 2;
            }
            close(fd);
    
            snprintf(fn, GPIO_FN_MAXLEN-1, "/sys/class/gpio/gpio%s/edge", argv[1]);
            fd=open(fn, O_WRONLY);
            if(fd<0) {
                    perror(fn);
                    return 2;
            }
            ret=write(fd,"falling\n",8);
            if(ret <= 0) {
                    perror("edge detect setup");
                    return 2;
            }
            close(fd);
    
            memset(rdbuf, 0x00, RDBUF_LEN);
    
            snprintf(fn, GPIO_FN_MAXLEN-1, "/sys/class/gpio/gpio%s/value", argv[1]);
            fd=open(fn, O_RDONLY);
            if(fd<0) {
                    perror(fn);
                    return 2;
            }
    
            pfd.fd=fd;
            pfd.events=POLLPRI;
            
            ret=pread(fd, rdbuf, RDBUF_LEN-1, 0);
            if(ret<0) {
                    perror("read()");
                    return 4;
            }
            printf("value is: %s\n", rdbuf);
            
            while(1) {
                    memset(rdbuf, 0x00, RDBUF_LEN);
                    lseek(fd, 0, SEEK_SET);
                    ret=poll(&pfd, 1, POLL_TIMEOUT);
                    if(ret<0) {
                            perror("poll()");
                            close(fd);
                            return 3;
                    }
                    if(ret==0) {
                            printf("timeout\n");
                            continue;
                    }
                    ret=read(fd, rdbuf, RDBUF_LEN-1);
                    if(ret<0) {
                            perror("read()");
                            return 4;
                    }
                    printf("interrupt, value is: %s\n", rdbuf);
            }
            close(fd);
            return 0;
    }
    
     
  4. achsel

    achsel New Member

    Joined:
    Mar 25, 2015
    Messages:
    2
    Likes Received:
    0
    Re: Communication between arduino and linux (e.g. code block

    Hey, we solved it now in a different way: by opening the files in which the value of each pin is deposited. then we read the value und write it into a variable. It is working!!! Even the connection with mutt is running!

    Thanks
     

Share This Page