safe to read/write gpios value

Discussion in 'General Discussion' started by maldives, Mar 19, 2015.

  1. maldives

    maldives New Member

    Joined:
    Mar 19, 2015
    Messages:
    8
    Likes Received:
    0
    can i read/write to /sys/class/gpio/gpio21/value using python with a delay. or its better to listen to serial port ttymxc3?
    for eg:

    while true:
    open file to read
    read file
    close file
    if value is 1:
    do something
    delay
     
  2. fetcher

    fetcher Member

    Joined:
    Mar 9, 2014
    Messages:
    166
    Likes Received:
    20
    If you're asking whether it's safe to write to GPIO outputs directly from the i.MX6 processor (Linux side) rather than the SAM3X (Arduino), that's perfectly fine so long as both chips aren't trying to write conflicting signals to the same pin, one pulling it high and the other low. All pins on the SAM3X side default to high-impedance inputs, so if you aren't using the Arduino section at all, or are running a sketch that doesn't do anything with the pins in question there should be no trouble. The only exception I've found has been a single pin, "CANTX" aka D69 -- that one defaults to an Arduino output, so if you want to use Linux gpio8 on the i.MX6, or the i.MX6 CAN bus you'd need to first do pinMode(69, INPUT); in setup() on the Arduino... or just pick a different pin and avoid that single one. Or hold the SAM3X in RESET, if it's not being used ( echo 0 >/gpio/gpio0/value ). Again, only an issue for D69.

    Using a given pin as an input to both CPUs simultaneously, or as an output on one and an input to the other is also OK, in case that's ever useful.

    Check these documentation files for help in matching up Linux gpio's with the corresponding Arduino pins:

    http://udoo.org/download/files/pinout/U ... iagram.pdf

    http://udoo.org/download/files/pinout/U ... _table.pdf
     
  3. maldives

    maldives New Member

    Joined:
    Mar 19, 2015
    Messages:
    8
    Likes Received:
    0
    thank you, very helpful one more question which is better
    1. open /sys/class/gpio/gpio21/value from python and write to file
    or
    2 pass shell command in python for eg: echo 1 > /sys/class/gpio/gpio21/value
    or
    any other way?

    I am trying to build a internet radio using mpd, mpc and to have next,pre(maybe Rotary Encoders) ,Play/Pause and Two line 16 character LCD. There are many tutorial how to do this in Raspberry PI but i couldn't find any for udoo.



    Thank you
     
  4. fetcher

    fetcher Member

    Joined:
    Mar 9, 2014
    Messages:
    166
    Likes Received:
    20
    It's more efficient to open the /dev/gpio/* files and write to them directly from your code, especially since you can hold the file descriptors open for multiple write cycles, like sending a stream of characters to an HD44780-type LCD (with each nibble in that stream requiring 5-6 separate GPIOs to be toggled) . Spawning a shell command for each operation has significant overhead, and also would repeat the open() and close() calls (the shell doing that on your behalf) for every update to every signal.

    For GPIO input from buttons and such, you'd ideally want to have those pins generate interrrupts so they don't have to be constantly polled. I think this is possible, since the /dev/gpio/gpioXX/ pseudo-directories contain an "edge" file, but haven't tried it myself. It may be easier to have the SAM3X chip monitor your buttons, handle any debouncing, etc. and relay them across via ttymxc3.
     
  5. maldives

    maldives New Member

    Joined:
    Mar 19, 2015
    Messages:
    8
    Likes Received:
    0
    thank you, VERY HELPFUL
     
  6. fetcher

    fetcher Member

    Joined:
    Mar 9, 2014
    Messages:
    166
    Likes Received:
    20
    Here is some C code I wrote for sending text to an HD44780 on the Udoo, which might be useful as a template for yours. Note the particular pins I used, which you'll probably want to change... I picked GPIO's all on a single row of the double-wide header (with GND and +5V at either end) while trying to avoid the ones also usable for SPI buses, UARTs etc. so that those remained free for future expansion.

    These displays seem happy to accept 3.3V signals (they do need +5V for power and contrast bias), just be sure R/W is pulled low, tied to ground, so that the LCD never tries to send any data back at 5V levels.

    Code:
    // jnh - based on Adafruit Adafruit_CharLCD_IPclock_example.py
    // 2014-07-07
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <error.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    
    // commands
    #define LCD_CLEARDISPLAY             0x01
    #define LCD_RETURNHOME               0x02
    #define LCD_ENTRYMODESET             0x04
    #define LCD_DISPLAYCONTROL           0x08
    #define LCD_CURSORSHIFT              0x10
    #define LCD_FUNCTIONSET              0x20
    #define LCD_SETCGRAMADDR             0x40
    #define LCD_SETDDRAMADDR             0x80
    
    // flags for display entry mode ( | LCD_ENTRYMODESET = 0x04 );
    #define LCD_ENTRYRIGHT               0x00
    #define LCD_ENTRYLEFT                0x02
    #define LCD_ENTRYSHIFTINCREMENT      0x01
    #define LCD_ENTRYSHIFTDECREMENT      0x00
    
    // flags for display on/off control ( | DISPLAYCONTROL = 0x08 )
    #define LCD_DISPLAYON                0x04
    #define LCD_DISPLAYOFF               0x00
    #define LCD_CURSORON                 0x02
    #define LCD_CURSOROFF                0x00
    #define LCD_BLINKON                  0x01
    #define LCD_BLINKOFF                 0x00
    
    // flags for display/cursor shift  ( | LCD_CURSORSHIFT = 0x10 )
    #define LCD_DISPLAYMOVE              0x08
    #define LCD_CURSORMOVE               0x00
    #define LCD_MOVERIGHT                0x04
    #define LCD_MOVELEFT                 0x00
    
    // flags for function set    ( | LCD_FUNCTIONSET = 0x20 )
    #define LCD_8BITMODE                 0x10
    #define LCD_4BITMODE                 0x00
    #define LCD_2LINE                    0x08
    #define LCD_1LINE                    0x00
    #define LCD_5x10DOTS                 0x04
    #define LCD_5x8DOTS                  0x00
    
    int RS, EN, D[8];
    unsigned char displaycontrol=0, displayfunction=0, displaymode=0;
    
    pulse_en () {
            write(EN, "1",1);
            usleep(2);
            write(EN, "0",1);
            usleep(1);
            write(EN, "1",1);
            usleep(2);
    }
    
    write1nibble(unsigned char nib) {
            write(RS, "0", 1);
    
            write(D[7], (nib & 0x8) ? "1" : "0", 1);
            write(D[6], (nib & 0x4) ? "1" : "0", 1);
            write(D[5], (nib & 0x2) ? "1" : "0", 1);
            write(D[4], (nib & 0x1) ? "1" : "0", 1);
            usleep(20);
    
            pulse_en();
    
            usleep(40);
    }
    
    writenibbles(unsigned char value, char mode) {
            unsigned char nib;
    
            //fprintf(stderr,"sending %X / %d]\n",value, mode);
    
            write(RS, mode ? "1" : "0", 1);
    
            /* high nibble first */
            nib = (value >> 4);
    
            write(D[7], (nib & 0x8) ? "1" : "0", 1);
            write(D[6], (nib & 0x4) ? "1" : "0", 1);
            write(D[5], (nib & 0x2) ? "1" : "0", 1);
            write(D[4], (nib & 0x1) ? "1" : "0", 1);
            usleep(20);
    
            pulse_en();
    
            usleep(20);
    
            nib = (value & 0x0f);
    
            write(D[7], (nib & 0x8) ? "1" : "0", 1);
            write(D[6], (nib & 0x4) ? "1" : "0", 1);
            write(D[5], (nib & 0x2) ? "1" : "0", 1);
            write(D[4], (nib & 0x1) ? "1" : "0", 1);
            usleep(20);
    
            pulse_en();
    
            usleep(100);
    }
    
    message (char *msg) {
     int j;
    
     for (j=0; (msg[j]!=0); j++) {
      if ((msg[j] == '\n' || msg[j] == '\r'))
            writenibbles(0xC0,0);  /* next line */
       else writenibbles(msg[j],1);
     }
     
    }
    
    main(int argc, char **argv) {
    
     int DIR;
    
     int i,s,gpio[] = { 33, 35, 205, 141, 139, 135 };
     unsigned char tmp[256];
    
    /*
      D7: 29 / gpio135
      D6: 33 / gpio139 (ECSPI2_MISO, mirrored on 50)
      D5: 35 / gpio141 (ECSPI2_SCLK, mirroed on 52)
      D4: 39 / gpio205
      EN: 41 / gpio35
      RS: 43 / gpio33
    */
    
     for (i=0; i<6; i++) {
      sprintf(tmp, "/sys/class/gpio/gpio%d/direction",gpio[i]);
      if  ( ( DIR=open(tmp,O_WRONLY|O_SYNC) ) <= 0 ) { fprintf(stderr,"%s\n",tmp); perror("gpio_dir_setup"); exit(1); }
      write(DIR,"out\n",4);
      close(DIR);
     }
     sprintf(tmp, "/sys/class/gpio/gpio%d/value",gpio[0]);
     if  ( ( RS=open(tmp,O_WRONLY|O_SYNC) ) <= 0 ) { perror("gpio0_val"); exit(1); }
     write(RS, "0",1);
     sprintf(tmp, "/sys/class/gpio/gpio%d/value",gpio[1]);
     if  ( ( EN=open(tmp,O_WRONLY|O_SYNC) ) <= 0 ) { perror("gpio1_val"); exit(1); }
     write(EN, "1",1);
     sprintf(tmp, "/sys/class/gpio/gpio%d/value",gpio[2]);
     if  ( ( D[4]=open(tmp,O_WRONLY|O_SYNC) ) <= 0 ) { perror("gpio2_val"); exit(1); }
     write(D[4], "0",1);
     sprintf(tmp, "/sys/class/gpio/gpio%d/value",gpio[3]);
     if  ( ( D[5]=open(tmp,O_WRONLY|O_SYNC) ) <= 0 ) { perror("gpio3_val"); exit(1); }
     write(D[5], "0",1);
     sprintf(tmp, "/sys/class/gpio/gpio%d/value",gpio[4]);
     if  ( ( D[6]=open(tmp,O_WRONLY|O_SYNC) ) <= 0 ) { perror("gpio4_val"); exit(1); }
     write(D[6], "0",1);
     sprintf(tmp, "/sys/class/gpio/gpio%d/value",gpio[5]);
     if  ( ( D[7]=open(tmp,O_WRONLY|O_SYNC) ) <= 0 ) { perror("gpio5_val"); exit(1); }
     write(D[7], "0",1);
    
     /* init: enter & exit 8-bit mode to reset possible nibble misalignment... */
     write1nibble(0x3);
     usleep(5000);
     write1nibble(0x3);
     usleep(5000);
     write1nibble(0x3);
     usleep(1000);
     write1nibble(0x2);
     usleep(1000);
    
     writenibbles(LCD_FUNCTIONSET | LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS,0);
     usleep(50);
     writenibbles(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF,0);  // 0x0C
     usleep(50);
     writenibbles(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT,0);         // 0x06
     usleep(50);
    
     writenibbles(LCD_CLEARDISPLAY,0);
     usleep(3200);
    
     if (argc > 2) {
       s=atoi(argv[1]);
       for (i=s;i<(s+16);i++) writenibbles(i,1);
       writenibbles(0xC0,0);
       for (i=(s+16);i<(s+32);i++) writenibbles(i,1);
     }
     else if (argc != 1 )
      message (argv[1]);
     
     for (i=4; i<8; i++) {
      close(D[i]);
     }
     close(EN); close(RS);
    }
    
     
  7. maldives

    maldives New Member

    Joined:
    Mar 19, 2015
    Messages:
    8
    Likes Received:
    0
    Thank you fetcher your C code really help me to change Adafruit_CharLCD.py for Raspberry pi to UDOO in python.
    Code:
    #!/usr/bin/python
    
    # for UDOO change by manikm - maldives
    # based on code from lrvick and LiquidCrystal
    # lrvic - https://github.com/lrvick/raspi-hd44780/blob/master/hd44780.py
    # LiquidCrystal - https://github.com/arduino/Arduino/blob/master/libraries/LiquidCrystal/LiquidCrystal.cpp
    #
    
    from time import sleep
    
    
    class Adafruit_CharLCD(object):
    
        # commands
        LCD_CLEARDISPLAY        = 0x01
        LCD_RETURNHOME          = 0x02
        LCD_ENTRYMODESET        = 0x04
        LCD_DISPLAYCONTROL      = 0x08
        LCD_CURSORSHIFT         = 0x10
        LCD_FUNCTIONSET         = 0x20
        LCD_SETCGRAMADDR        = 0x40
        LCD_SETDDRAMADDR        = 0x80
    
        # flags for display entry mode
        LCD_ENTRYRIGHT          = 0x00
        LCD_ENTRYLEFT           = 0x02
        LCD_ENTRYSHIFTINCREMENT = 0x01
        LCD_ENTRYSHIFTDECREMENT = 0x00
    
        # flags for display on/off control
        LCD_DISPLAYON           = 0x04
        LCD_DISPLAYOFF          = 0x00
        LCD_CURSORON            = 0x02
        LCD_CURSOROFF           = 0x00
        LCD_BLINKON             = 0x01
        LCD_BLINKOFF            = 0x00
    
        # flags for display/cursor shift
        LCD_DISPLAYMOVE         = 0x08
        LCD_CURSORMOVE          = 0x00
    
        # flags for display/cursor shift
        LCD_DISPLAYMOVE         = 0x08
        LCD_CURSORMOVE          = 0x00
        LCD_MOVERIGHT           = 0x04
        LCD_MOVELEFT            = 0x00
    
        # flags for function set
        LCD_8BITMODE            = 0x10
        LCD_4BITMODE            = 0x00
        LCD_2LINE               = 0x08
        LCD_1LINE               = 0x00
        LCD_5x10DOTS            = 0x04
        LCD_5x8DOTS             = 0x00
    
    
    #  D7: 2 / gpio20
    #  D6: 3 / gpio16
    #  D5: 4 / gpio17
    #  D4: 5 / gpio18
    #  EN: 11 / gpio9
    #  RS: 12 / gpio3
    
    
        def __init__(self, pin_rs=3, pin_e=9, pins_db=[18, 17, 16, 20], GPIO=None):
            # Emulate the old behavior of using RPi.GPIO if we haven't been given
            # an explicit GPIO interface to use
     #       if not GPIO:
      #          import RPi.GPIO as GPIO
     #           GPIO.setwarnings(False)
     #       self.GPIO = GPIO
            self.pin_rs = pin_rs
            self.pin_e = pin_e
            self.pins_db = pins_db
    
    #        self.GPIO.setmode(GPIO.BCM)
     
     #       self.GPIO.setup(self.pin_e, GPIO.OUT)
            self.setupdirection(self.pin_e, "out")
    
    #        self.GPIO.setup(self.pin_rs, GPIO.OUT)
            self.setupdirection(self.pin_rs, "out")
    
            for pin in self.pins_db:
                #self.GPIO.setup(pin, GPIO.OUT)
                self.setupdirection(pin, "out")
    
            self.write4bits(0x33)  # initialization
            self.write4bits(0x32)  # initialization
            self.write4bits(0x28)  # 2 line 5x7 matrix
            self.write4bits(0x0C)  # turn cursor off 0x0E to enable cursor
            self.write4bits(0x06)  # shift cursor right
    
            self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF
    
            self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS
            self.displayfunction |= self.LCD_2LINE
    
            # Initialize to default text direction (for romance languages)
            self.displaymode = self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT
            self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)  # set the entry mode
    
            self.clear()
    
        def setupdirection(self, pin, value):
            fs =  open("/sys/class/gpio/gpio%d/direction" % pin, "w")
            fs.write("%s" % value)
            fs.close() 
    
        def outputvalue(self, pin, value):
            fo =  open("/sys/class/gpio/gpio%d/value" % pin, "w")
            if value:
                fo.write("1")
            else:
                fo.write("0")
            fo.close()  
    
        def begin(self, cols, lines):
            if (lines > 1):
                self.numlines = lines
                self.displayfunction |= self.LCD_2LINE
    
        def home(self):
            self.write4bits(self.LCD_RETURNHOME)  # set cursor position to zero
            self.delayMicroseconds(3000)  # this command takes a long time!
    
        def clear(self):
            self.write4bits(self.LCD_CLEARDISPLAY)  # command to clear display
            self.delayMicroseconds(3000)  # 3000 microsecond sleep, clearing the display takes a long time
    
        def setCursor(self, col, row):
            self.row_offsets = [0x00, 0x40, 0x14, 0x54]
            if row > self.numlines:
                row = self.numlines - 1  # we count rows starting w/0
            self.write4bits(self.LCD_SETDDRAMADDR | (col + self.row_offsets[row]))
    
        def noDisplay(self):
            """ Turn the display off (quickly) """
            self.displaycontrol &= ~self.LCD_DISPLAYON
            self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)
    
        def display(self):
            """ Turn the display on (quickly) """
            self.displaycontrol |= self.LCD_DISPLAYON
            self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)
    
        def noCursor(self):
            """ Turns the underline cursor off """
            self.displaycontrol &= ~self.LCD_CURSORON
            self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)
    
        def cursor(self):
            """ Turns the underline cursor on """
            self.displaycontrol |= self.LCD_CURSORON
            self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)
    
        def noBlink(self):
            """ Turn the blinking cursor off """
            self.displaycontrol &= ~self.LCD_BLINKON
            self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)
    
        def blink(self):
            """ Turn the blinking cursor on """
            self.displaycontrol |= self.LCD_BLINKON
            self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol)
    
        def DisplayLeft(self):
            """ These commands scroll the display without changing the RAM """
            self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT)
    
        def scrollDisplayRight(self):
            """ These commands scroll the display without changing the RAM """
            self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVERIGHT)
    
        def leftToRight(self):
            """ This is for text that flows Left to Right """
            self.displaymode |= self.LCD_ENTRYLEFT
            self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)
    
        def rightToLeft(self):
            """ This is for text that flows Right to Left """
            self.displaymode &= ~self.LCD_ENTRYLEFT
            self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)
    
        def autoscroll(self):
            """ This will 'right justify' text from the cursor """
            self.displaymode |= self.LCD_ENTRYSHIFTINCREMENT
            self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)
    
        def noAutoscroll(self):
            """ This will 'left justify' text from the cursor """
            self.displaymode &= ~self.LCD_ENTRYSHIFTINCREMENT
            self.write4bits(self.LCD_ENTRYMODESET | self.displaymode)
    
        def write4bits(self, bits, char_mode=False):
            """ Send command to LCD """
            self.delayMicroseconds(1000)  # 1000 microsecond sleep
            bits = bin(bits)[2:].zfill(8)
            #self.GPIO.output(self.pin_rs, char_mode)
            self.outputvalue(self.pin_rs, char_mode)
            for pin in self.pins_db:
                #self.GPIO.output(pin, False)
                self.outputvalue(pin, False)
    
            for i in range(4):
                if bits[i] == "1":
                    #self.GPIO.output(self.pins_db[::-1][i], True)
                    self.outputvalue(self.pins_db[::-1][i], True)
    
            self.pulseEnable()
            for pin in self.pins_db:
                #self.GPIO.output(pin, False)
                self.outputvalue(pin, False)
            for i in range(4, 8):
                if bits[i] == "1":
                    #self.GPIO.output(self.pins_db[::-1][i-4], True)
                    self.outputvalue(self.pins_db[::-1][i-4], True)
            self.pulseEnable()
    
        def delayMicroseconds(self, microseconds):
            seconds = microseconds / float(1000000)  # divide microseconds by 1 million for seconds
            sleep(seconds)
    
        def pulseEnable(self):
            #self.GPIO.output(self.pin_e, False)
            self.outputvalue(self.pin_e, False)
            self.delayMicroseconds(1)       # 1 microsecond pause - enable pulse must be > 450ns
            #self.GPIO.output(self.pin_e, True)
            self.outputvalue(self.pin_e, True)        
            self.delayMicroseconds(1)       # 1 microsecond pause - enable pulse must be > 450ns
            #self.GPIO.output(self.pin_e, False)
            self.outputvalue(self.pin_e, False)        
            self.delayMicroseconds(1)       # commands need > 37us to settle
    
        def message(self, text):
            """ Send string to LCD. Newline wraps to second line"""
            for char in text:
                if char == '\n':
                    self.write4bits(0xC0)  # next line
                else:
                    self.write4bits(ord(char), True)
    
    
    if __name__ == '__main__':
        lcd = Adafruit_CharLCD()
        lcd.clear()
        lcd.message("  Adafruit 16x2\n  Standard LCD")
    
     
  8. maldives

    maldives New Member

    Joined:
    Mar 19, 2015
    Messages:
    8
    Likes Received:
    0
    Internet Radio Rotary Encoders

    I am trying to build internet radio from Udoo board currently can sent text from linux to 1602 lcd
    now i want to connect Rotary Encoder to use as a channel changer or tuner what is the most effective way to go ahead? any project/code i can study
     

Share This Page