Jump to content

sgjava

Members
  • Posts

    411
  • Joined

  • Last visited

Everything posted by sgjava

  1. @Igor the Ubuntu releases (4.14 kernel currently) have been very solid on the Duo. I have one on my network running 24/7 without any issues for months. This was the nightly Debian release with the 4.16 kernel. The interface comes up for less then a minute then dies. I logged into the serial console and it shows wlan0 unavailable (haven't had time to dig in more). I'll wait for the Ubuntu with 4.16 and test again. I'm just happy I can access all the user space stuff without sudo now that PWM works.
  2. I just tested this with Linux NanoPi-Duo 4.16.0-rc6 #239 SMP Wed Apr 11 14:03:49 CST 2018 armv7l armv7l armv7l GNU/Linux using official FriendlyArm image. Just add gpio group, add your non-root user to group and add udev rules /etc/udev/rules.d/99-com.rules I posted above. I tried the Armbian nightly image with 4.16 kernel, but wifi kept dying.
  3. SUBSYSTEM=="pwm*", PROGRAM="/bin/sh -c '\ chown -R root:gpio /sys/class/pwm && chmod -R 770 /sys/class/pwm;\ chown -R root:gpio /sys/devices/platform/soc/*.pwm/pwm/pwmchip* && chmod -R 770 /sys/devices/platform/soc/*.pwm/pwm/pwmchip*\ '" This seems to set the permissions correctly, but nothing happened (at least no errors) while sudo works fine. I'm using kernel 4.14.18 and it looks like it was merged into the RPi kernel http://lists.infradead.org/pipermail/linux-rpi-kernel/2017-December/007193.html
  4. Nice, I did that before I asked. See https://github.com/raspberrypi/linux/issues/1983
  5. I've been able to use all the other user space I/O without being root. PWM on the other hand seems to create files only after opening device. Is there a udev rule that will work with 4.14 kernel? For all other devices I use a simple rc.local script: chown -R root:gpio /dev/gpiochip0 chmod -R ug+rw /dev/gpiochip0 chown -R root:gpio /dev/gpiochip1 chmod -R ug+rw /dev/gpiochip1 chown -R root:i2c /dev/i2c-0 chmod -R ug+rw /dev/i2c-0 chown -R root:spi /dev/spidev1.0 chmod -R ug+rw /dev/spidev1.0
  6. @chwe I just did a quick test using User Space IO which uses liggpiod 1.1. On a NanoPi Duo I was able to toggle a pin at 25 KHz (on/off cycle) with Python. If you need speed or precision I'd go with hardware PWM which User Space IO supports.
  7. If you want to get ahead of the curve a little I've been testing libgpiod master with User Space IO. This version includes Python bindings, so I'm no longer generating CFFI bindings for this library. I've converted all the example code to use the new bindings. User Space IO is Python 3 and Java 8 bindings for Linux user space GPIO, SPI, I2C, PWM and Serial interfaces. User Space IO is a consistent API for C, Python 3 and most JVM languages. No more hacked up RPi.GPIO and WiringPi for each SBC model.
  8. @chwe actually 0 for on and 1 for off is correct. I'm wiring my LED like https://www.sunfounder.com/learn/Super_Kit_V3_0_for_Raspberry_Pi/lesson-1-blinking-led-super-kit-v3-0-for-raspberry-pi.html. This works the same on my NodeMCU as well (ESP8266).
  9. @chwe I don't remember why I removed this. I just added it back. Try again and it should register with Python now.
  10. As a dev I vote to keep the dev packages in. Sure is nice to have the build tools (even git client) installed even if things like libtool and pkg-config are missing from the base. If you are going for a minimal install I understand stripping all this stuff out, but I'm not sure how important it is to have a 700K vs 1.6 G image in today's terms. As @tkaiser points out most people have moved on beyond 4G SD cards. I've been using 32G for years and the price/performance is good for what I need it for. I've have some home made security cameras that write/read/delete 100s of movies and images a day 24/7 for years without failure. I realize there may be more intensive usages scenarios (more write intensive), but at the current pricing levels I'll toss the SD out every few years if I have to. As with all things the lowest common denominator or race to the bottom isn't always the best strategy. Stability and standardization are more important to me then a little extra RAM, a little more SD life, etc. Not that these are not important, but the bigger picture I think is more important to focus on.
  11. I agree, and maybe just use a sizeof since the arrays are static. Then there's no need for an array of number of pins.
  12. Edit: User Space IO depracated. Use Java Periphery instead https://github.com/sgjava/java-periphery https://github.com/sgjava/userspaceio After a lot of work and testing I have produced the User Space IO project! It provides Python 3 and Java 8 bindings for Linux user space GPIO, SPI, I2C, PWM and Serial interfaces. This allows cross SBC and cross language development using a common API. I took two best of breed C APIs for Linux user space libgpiod and c-periphery and produced CFFI bindings for Python and JNA bindings for Java. Since all the bindings closely match the C API it's easy to move from language to language. The side effect of using the Java library is that it should work with many different JVM based languages. How about creating your programs in Kotlin or Scala for instance? GPIO access uses the new gpiod interface and not the deprecated sysfs interface using libgpiod v1.1 (head from git repo). GPIO, SPI, I2C and serial interfaces expose all the low level functionality. I have added some helper methods for handling repetitive functions like building I2C messages, reading words from two registers, etc. You can of course go as low level as you need to. Please use Github to post any issues, pull requests, etc. I have tested Nano Pi Duo for 32 bit and NanoPi Neo +2 for 64 bit compatibility. I'll test more SBCs as I have time. Also, I have deleted https://github.com/sgjava/libgpiod-extra since User Space IO supersedes it. Based of some of the questions I had in the past please note the following: gpiod_ctxless_event_loop_multiple can handle GPIO interrupts Miscellaneous GPIO request flags GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN, GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE, GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW Non-root access using rc.local. Demo program using hardware PWM to flash LED:
  13. Did you look at the C header? /** * @brief Miscellaneous GPIO request flags. */ enum { GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN = GPIOD_BIT(0), /**< The line is an open-drain port. */ GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE = GPIOD_BIT(1), /**< The line is an open-source port. */ GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW = GPIOD_BIT(2), /**< The active state of the line is low (high is the default). */ }; Common GPIO Properties ====================== These properties are met through all the other documents of the GPIO interface and it is useful to understand them, especially if you need to define GPIO mappings. Active-High and Active-Low -------------------------- It is natural to assume that a GPIO is "active" when its output signal is 1 ("high"), and inactive when it is 0 ("low"). However in practice the signal of a GPIO may be inverted before is reaches its destination, or a device could decide to have different conventions about what "active" means. Such decisions should be transparent to device drivers, therefore it is possible to define a GPIO as being either active-high ("1" means "active", the default) or active-low ("0" means "active") so that drivers only need to worry about the logical signal and not about what happens at the line level. Open Drain and Open Source -------------------------- Sometimes shared signals need to use "open drain" (where only the low signal level is actually driven), or "open source" (where only the high signal level is driven) signaling. That term applies to CMOS transistors; "open collector" is used for TTL. A pullup or pulldown resistor causes the high or low signal level. This is sometimes called a "wire-AND"; or more practically, from the negative logic (low=true) perspective this is a "wire-OR". One common example of an open drain signal is a shared active-low IRQ line. Also, bidirectional data bus signals sometimes use open drain signals. Some GPIO controllers directly support open drain and open source outputs; many don't. When you need open drain signaling but your hardware doesn't directly support it, there's a common idiom you can use to emulate it with any GPIO pin that can be used as either an input or an output: LOW: gpiod_direction_output(gpio, 0) ... this drives the signal and overrides the pullup. HIGH: gpiod_direction_input(gpio) ... this turns off the output, so the pullup (or some other device) controls the signal. The same logic can be applied to emulate open source signaling, by driving the high signal and configuring the GPIO as input for low. This open drain/open source emulation can be handled transparently by the GPIO framework. If you are "driving" the signal high but gpiod_get_value(gpio) reports a low value (after the appropriate rise time passes), you know some other component is driving the shared signal low. That's not necessarily an error. As one common example, that's how I2C clocks are stretched: a slave that needs a slower clock delays the rising edge of SCK, and the I2C master adjusts its signaling rate accordingly.
  14. There's a lot different in the DTS. I really do not have time to see if it's just certain sections, but I'd just go with the FriendlyElec DTB. The DTS is attached. sun8i-h2-plus-nanopi-duo-friendlyelec.dts
  15. I tried modifying the existing DTS as described, but it didn't work. I'll do a diff when I have some time.
  16. I do exactly this with my ARM server rack to backup each server. My crontab (runs on machine to back up) looks something like: # Backup root file system 00 01 * * 0 tar -cvpzf /backuppath/servname.backup.`date +\%Y\%m\%d_\%H\%M\%S`.tar.gz --one-file-system /. > /backuppath/servname.backup.log 2>&1
  17. On my journey to finding the best solution for cross SBC/cross language GPIO support I went through the same issues as Python by the C side author did it seems and landed on CFFI. This is faster than ctypes and seem more natural to program with. ctypesgen (the code generator) doen't really support Python 3, so I've hit a dead end there. It seems like JNA is still the best choice for Java bindings, so I'm sticking with that for now. In any event I threw together a button press app that uses CFFI and libgrpiod. I'll be updating my bindings project to support this soon. libgpiod version 1.1.devel Name: gpiochip1, label: 1f02c00.pinctrl, lines: 32 Press button within 5 seconds Falling edge timestamp 02/10/2018 19:49:05 """ Test blocking event using built in button ------------- Should work on any board with a button built in. Just change chip and line value as needed. """ import sys, time from argparse import * from cffi import FFI parser = ArgumentParser() parser.add_argument("--chip", help="GPIO chip number (default 1 '/dev/gpiochip1')", type=int, default=1) parser.add_argument("--line", help="GPIO line number (default 3 button on NanoPi Duo)", type=int, default=3) args = parser.parse_args() ffi = FFI() # Specify each C function, struct and constant you want a Python binding for # Copy-n-paste with minor edits ffi.cdef(""" enum { GPIOD_LINE_EVENT_RISING_EDGE, GPIOD_LINE_EVENT_FALLING_EDGE, }; struct timespec { long tv_sec; long tv_nsec; }; struct gpiod_line { unsigned int offset; int direction; int active_state; bool used; bool open_source; bool open_drain; int state; bool up_to_date; struct gpiod_chip *chip; int fd; char name[32]; char consumer[32]; }; struct gpiod_chip { struct gpiod_line **lines; unsigned int num_lines; int fd; char name[32]; char label[32]; }; struct gpiod_line_event { struct timespec ts; int event_type; }; const char *gpiod_version_string(void); struct gpiod_chip *gpiod_chip_open_by_number(unsigned int num); struct gpiod_line *gpiod_chip_get_line(struct gpiod_chip *chip, unsigned int offset); int gpiod_line_request_falling_edge_events(struct gpiod_line *line, const char *consumer); int gpiod_line_event_wait(struct gpiod_line *line, const struct timespec *timeout); int gpiod_line_event_read(struct gpiod_line *line, struct gpiod_line_event *event); void gpiod_line_release(struct gpiod_line *line); void gpiod_chip_close(struct gpiod_chip *chip); """) lib = ffi.dlopen("libgpiod.so") print "libgpiod version %s" % ffi.string(lib.gpiod_version_string()) gpiod_chip = lib.gpiod_chip_open_by_number(args.chip) # Make sure GPIO chip opened if gpiod_chip != ffi.NULL: print("Name: %s, label: %s, lines: %d" % (ffi.string(gpiod_chip.name), ffi.string(gpiod_chip.label), gpiod_chip.num_lines)) gpiod_line = lib.gpiod_chip_get_line(gpiod_chip, args.line) # Verify we have line if gpiod_line != ffi.NULL: consumer = sys.argv[0][:-3] if lib.gpiod_line_request_falling_edge_events(gpiod_line, consumer) == 0: timespec = ffi.new("struct timespec*") timespec.tv_sec = 5 print("Press button within 5 seconds") rc = lib.gpiod_line_event_wait(gpiod_line, timespec) if rc == 0: print("Timed out") elif rc == 1: event = ffi.new("struct gpiod_line_event*") # Read event off queue lib.gpiod_line_event_read(gpiod_line, event) if event.event_type == lib.GPIOD_LINE_EVENT_RISING_EDGE: print("Rising edge timestamp %s" % time.strftime('%m/%d/%Y %H:%M:%S', time.localtime(event.ts.tv_sec))) else: print("Falling edge timestamp %s" % time.strftime('%m/%d/%Y %H:%M:%S', time.localtime(event.ts.tv_sec))) else: print("Unable request falling edge for line %d" % args.line) lib.gpiod_line_release(gpiod_line) else: print("Unable to get line %d" % args.line) lib.gpiod_chip_close(gpiod_chip) else: print("Unable to open chip %d" % args.chip)
  18. sysfs is not a good solution with all the context switching, losing events, etc. I've already switched to libgpiod (see https://github.com/sgjava/libgpiod-extra). It wouldn't be difficult to add Larry's concept of a common pin mapping since that's just done with pin arrays (at the C level, so the wrappers just need to be generated for Python and Java). I just added I2C support and SPI support is coming. This will be the user space way to do things on Linux, so it will not be just for Armbian. There are other things missing like PWM, but the big three (GPIO, I2C and SPI) will be implemented. Any ways, this is all scripted already, so I'm not sure I'd include it in Armbian. Plus I'm moving at a rapid pace, so it's best to pull from master to get the latest changes/fixes.
  19. And the Java thread example https://github.com/sgjava/libgpiod-extra/blob/master/java/src/com/codeferm/demo/ButtonThread.java
  20. Just finished up the JNA Java bindings. LedTest for Java now works!
  21. OK, I whipped up a simple Python program using a thread to wait for an edge event while the main program is doing something else. https://github.com/sgjava/libgpiod-extra/blob/master/python/buttonthread.py You can pass --chip with GPIO chip number and --line for the line (pin) where your built in button is located. Really no need for IRQs since the events are queued and the thread is waiting on the edge to happen. You can use the thread to do a callback using OOP and an Observer pattern. This is more elegant than having C callback to Python, Java, etc.
  22. If it runs on mainline and you see something listed using ls /dev/gpiochip* then there's a good chance it will work, so you'll have to test it yourself. libgpiod is written in C, but the author said he's working on C++ 11 bindings. Right now I have one C example and a few Python ones in my project https://github.com/sgjava/libgpiod-extra. For now you'll need to do blocking callbacks (built in) or just stick a wait for edge in a thread. gpiod queues events, so you will not miss any like sysfs. I'll have a Python threaded callback example soon.
  23. I noticed the Neo+ 2 has a blue LED: line 10: unnamed "nanopi:green:pwr" output active-high [used] line 20: unnamed "nanopi:blue:status" output active-high [used] It's not doing the heartbeat flash like the NanoPi Duo. uname -a Linux nanopineoplus2 4.14.15-sunxi64 #95 SMP Wed Jan 24 10:55:45 CET 2018 aarch64 GNU/Linux
×
×
  • Create New...

Important Information

Terms of Use - Privacy Policy - Guidelines