Raspberry Pi GPIO library for go-lang

go-rpio

Native GPIO-Gophers for your Pi!

Documentation: GoDoc

go-rpio is a Go library for accessing GPIO-pins on the Raspberry Pi.

It requires no external c libraries such as WiringPI or bcm2835.

There's a tiny bit of additional information over at my blog.

raspberrypi-blink

Releases

  • 1.0.0 - Supports original rpi A/B/B+
  • 2.0.0 - Adds support for rpi 2, by @akramer
  • 3.0.0 - Adds support for /dev/gpiomem, by @dotdoom
  • 4.0.0 - Adds support for PWM and Clock modes, by @drahoslove
  • 4.1.0 - Adds support for edge detection, by @drahoslove
  • 4.2.0 - Faster write and toggle of output pins, by @drahoslove
  • 4.3.0 - Adds support for SPI, by @drahoslove
  • 4.4.0 - Support for disabling interrupts (workaround for #35), by @drahoslove
  • 4.5.0 - Improve rpi 4 support, by @wfd3
  • 4.6.0 - Adds Balanced PWM mode, by @youngkin

Usage

import "github.com/stianeikeland/go-rpio/v4"

If you're using an older go.mod incompatible you should instead use:

import "github.com/stianeikeland/go-rpio"

Open memory range for GPIO access in /dev/mem

err := rpio.Open()

Initialize a pin, run basic operations. Pin refers to the bcm2835 pin, not the physical pin on the raspberry pi header. Pin 10 here is exposed on the pin header as physical pin 19.

pin := rpio.Pin(10)

pin.Output()       // Output mode
pin.High()         // Set pin High
pin.Low()          // Set pin Low
pin.Toggle()       // Toggle pin (Low -> High -> Low)

pin.Input()        // Input mode
res := pin.Read()  // Read state from pin (High / Low)

pin.Mode(rpio.Output)   // Alternative syntax
pin.Write(rpio.High)    // Alternative syntax

Pull up/down/off can be set using:

pin.PullUp()
pin.PullDown()
pin.PullOff()

pin.Pull(rpio.PullUp)

Unmap memory when done

rpio.Close()

Also see example examples/blinker/blinker.go

SPI

setup/teardown

  • rpio.SpiBegin(rpio.Spi0) has to be called first before using any Spi func. It will change pin modes to Spi and initialize default setting.
  • rpio.SpiEnd(rpio.Spi0) should be called at the end, it will switch pin modes to Input.

transferring data

  • rpio.SpiTransmit(byte) or rpio.SpiTransmit(bytes...) will transmit byte or bytes to slave.
  • rpio.SpiReceive(n) will return n bytes received from slave.
  • rpio.SpiExchange(buffer) will simultaneously transmit data from the buffer to slave and data from slave to the same buffer in full duplex way.

settings

  • rpio.SpiSpeed(hz) will set transmit speed of SPI
  • rpio.SpiChipSelect(n) will select chip/slave (ce0, ce1, or ce2) to which transferring will be done
  • rpio.SpiChipSelectPolarity(n, pol) set chip select polarity (low enabled is used by default which usually works most of the time)
  • rpio.SpiMode(cpol, cpha) set clock/communication mode (=combination of clock polarity and clock phase; cpol=0, cpha=0 is used by default which usually works most of the time)

Other

Currently, it supports basic functionality such as:

  • Pin Direction (Input / Output)
  • Write (High / Low)
  • Read (High / Low)
  • Pull (Up / Down / Off)
  • PWM (hardware, on supported pins)
  • Clock
  • Edge detection

It works by memory-mapping the bcm2835 gpio range, and therefore require root/administrative-rights to run.

Using without root

This library can utilize the new /dev/gpiomem memory range if available.

You will probably need to upgrade to the latest kernel (or wait for the next raspbian release) if you're missing /dev/gpiomem. You will also need to add a gpio group, add your user to the group, and then set up udev rules. I would recommend using create_gpio_user_permissions.py if you're unsure how to do this.

PWM modes will still require root.

Owner
Stian Eikeland
☕️☔️💻🍺
Stian Eikeland
Comments
  • EdgeDetection crashes Raspberry Pi 3

    EdgeDetection crashes Raspberry Pi 3

    Using Detect and running a very basic program on the Raspberry Pi 3, will result in the whole Raspberry Pi locking up (and needing a forced restart). This only happens on a pin with very many rises/falls, currently I am using this for a RF receiver, so there are quite a lot of rises/falls.

    The code I am using is this ...

    package main
    
    import (
    	"fmt"
    	"time"
    
    	rpio "github.com/stianeikeland/go-rpio"
    )
    
    // This program is just going to be
    // a POC of the sender working.
    // This should and WILL be cleaned up
    // I do not care, I will not fucking
    // write the report without having
    // the time to do this properly
    
    // Raspberry Pi 3 GPIO
    // https://i.imgur.com/PPFf2ul.png
    const rx_pin_nr = 2
    
    var preamble = [8]int{1, 0, 1, 0, 1, 0, 1, 0}
    var sfd = [8]int{1, 0, 1, 0, 1, 0, 1, 1}
    var rx_pin rpio.Pin
    
    func main() {
    	// initialize go-rpio
    	err := rpio.Open()
    
    	if err != nil {
    		fmt.Println(err)
    	}
    
    	// set our pin as a output
    	rx_pin = rpio.Pin(rx_pin_nr)
    	rx_pin.Input()
    	rx_pin.Detect(rpio.RiseEdge)
    
    	for {
    		// sendData(test)
    		fmt.Println("Running stuff")
    		time.Sleep(100 * time.Millisecond)
    	}
    }
    
    func check_sync() {
    
    }
    

    Not even doing anything with it. I don't know what the solution would be, but I think that we could get the interrupt etc. if we used such a system as epoll (http://man7.org/linux/man-pages/man7/epoll.7.html), I know it is uses for another Go system for GPIO interaction here - https://godoc.org/github.com/kidoman/embd

  • Updated to support Raspberry Pi 4 GPIO Base Address

    Updated to support Raspberry Pi 4 GPIO Base Address

    As requested, a pull request for my changes to support Pi4. Note that this is a bit different than the patch I attached to be bug in that it encapsulates error checking in the readBase() helper function.

  • Raspberry Pi Zero W compatibility issue

    Raspberry Pi Zero W compatibility issue

    Tested on Raspberry Pi Zero W OS Version: RASPBIAN STRETCH LITE (Release Date: 2018-06-27) Kernel Version: Linux raspberrypi 4.14.52+ #1123 Wed Jun 27 17:05:32 BST 2018 armv6l GNU/Linux Go Version: go1.10.3 linux/arm Problems: I connect to pi via ssh, system freeze after initialize GPIO, but the same code works well on Raspberry Pi 3 which has the same OS Version, Kernel Version and Go Version. sample code:

    const (
    	io1    = uint8(5)
    	rst    = uint8(13)
    	intIn  = uint(26)
    	intOut = uint(21)
    )
    var outPin rpio.Pin
    var inPin rpio.Pin
    func startGPIO() {
    	err := rpio.Open()
    	if err != nil {
    		log.Fatal(err)
    	}
    	log.Info("open rpio successfully")
    	io1Pin := rpio.Pin(io1)
    	io1Pin.Output()
    	io1Pin.Low()
    
    	rstPin := rpio.Pin(rst)
    	rstPin.Output()
    	rstPin.High()
    
    	outPin = rpio.Pin(intOut)
    	outPin.Input()
    	outPin.Detect(rpio.FallEdge)
    
    	inPin = rpio.Pin(intIn)
    	inPin.Output()
    	inPin.High()
    }
    
  • Add support for PWM

    Add support for PWM "Balanced" algorithm (default BCM mode)

    Looking at SetDutyCycle() the use of mark/space is hard-coded. Is there a reason the default algorithm is being overridden? Would it be possible to add support for explicitly setting which algorithm should be used?

  • RPI 4 B PWM not working

    RPI 4 B PWM not working

    I know this has been mentioned in several other issues but I am putting it here for a specific issue.

    I'm running on a RPI 4 Model B. Running output on Pin 18 and setting the pin to High works. Setting the same Pin 18 to PWM and setting it to a 100% duty cycle does not work.

    I'm running the program as root.

    There has been suggestions made that the PWM functionality was fixed for the RPI 4. This does not appear to be the case.

  • strangely, does *not* work with sudo

    strangely, does *not* work with sudo

    I'm having a very strange issue here, hopefully someone can shed some light on the subject.

    go 1.14, raspberry pi 4 B+

    using the blinker.go example:

    ./blinker works just fine sudo ./blinker makes nothing happen.

    Why is this? Normally that would be fine, except that I'm trying to use rpio along with a dht11 library that requires root access to run. I find it perplexing that running rpio with heightened privileges causes it to not work.

  • Device is stuck on EdgeDetected

    Device is stuck on EdgeDetected

    I'm running this code (just experimenting for now) and after some time (about 1 minute) device is going to be stuck. (I did the same actions with another languages: python, nodejs, but nothing, everything works stable and great, but when running this go application - I have a stuck and need just manually disconnect device from power supply and enable again).

    I have Raspberry Pi 3 Model B. Hardware : BCM2835 Revision : a22082

    Kernel: 4.19.58-v7+

    Distributor ID: Raspbian Description: Raspbian GNU/Linux 10 (buster) Release: 10 Codename: buster

    package main
    
    import (
    	"fmt"
    	"github.com/stianeikeland/go-rpio"
    	"log"
    	"time"
    )
    
    func main() {
    	err := rpio.Open()
    	if err != nil {
    		log.Fatal(err)
    	}
    
    	ch := make(chan struct{})
    
    	pin := rpio.Pin(10)
    	pin.Input()
    	pin.PullUp()
    	pin.Detect(rpio.FallEdge)
    
    	lastTime := time.Now().UnixNano() / 1000000
    
    	go func() {
    		for {
    			if pin.EdgeDetected() {
    				now := time.Now().UnixNano() / 1000000
    				diff := now - lastTime
    				lastTime = now
    				fmt.Println("Heyhey!", diff)
    			}
    			time.Sleep(time.Millisecond * 10)
    		}
    	}()
    	fmt.Println("init")
    
    	<-ch
    }
    
  • add GPIO frequency detection

    add GPIO frequency detection

    Hi,

    I think it would be very useful if you can add a function which measure the frequency a GPIO pin change status. This will allow to interface with a multitude of sensors. Some examples of implementation in C are here: http://abyz.me.uk/rpi/pigpio/examples.html#C_code Arduino core library has a conceptually similar functio called pulseIn: https://www.arduino.cc/reference/en/language/functions/advanced-io/pulsein/

    I tried to use a loop with pin.EdgeDetected() and a microsecond sleep but my RPI freezes all the time.

    Thanks

  • Implement clock and pwm modes

    Implement clock and pwm modes

    Hi there. I managed to add third pin mode - clock.

    It is just clock (using CM_GPnDIV and CM_GPnCTL registers) - no pwm (yet).

    Suggestions about better method/function naming are welcomed. I tried to be consistent with current ideology, but not sure if it makes sense.

    So this: PinMode(pin, rpio.Clock) <=> pin.Mode(rpio.Clock) <=> pin.Clock() is analogical to: PinMode(pin, rpio.Output) <=> pin.Mode(rpio.Output) <=> pin.Output()

    and this: SetFreq(pin, 10000) <=> pin.Freq(10000) <=> ??? is analogical to: WritePin(pin, rpio.High) <=> pin.Write(rpio.High) <=> pin.High()

    Also not sure if it might make sense to add more public methods eg. for stopping/resetting clocks.

    Please merge this if you like it.

  • Input interrupts

    Input interrupts

    Hi,

    Have you considered adding input interrupts? You can get them from the files exposed by sysfs in /sys/class/gpio. I've made a library which does this at https://github.com/brian-armstrong/gpio

    sysfs can also expose i2c and spi if you uncomment the modules in /boot/config.txt and then reboot. This might be an easy way for you to add i2c and spi functionality as well.

  • pullup does not work on RPI 4 B

    pullup does not work on RPI 4 B

    I tried to build and run the pullup example https://github.com/stianeikeland/go-rpio/blob/master/examples/pullup/pullup.go. But it does not build, see error message:

    pi@raspberrypi ~/g/e/pullup> go build
    # github.com/stianeikeland/go-rpio/v4/examples/pullup
    ./pullup.go:26:48: pin.ReadPull undefined (type rpio.Pin has no field or method ReadPull)
    ./pullup.go:30:50: pin.ReadPull undefined (type rpio.Pin has no field or method ReadPull)
    note: module requires Go 1.13~
    

    After I removed the ReadPull() call, I got the following output:

    pi@raspberrypi ~/g/e/pullup> ./pullup
    PullUp: 0, 0
    PullDown: 0, 0
    

    That means PullUp does not work.

  • Fix spi speed

    Fix spi speed

    Round down cdiv result make real CLK faster than caller expect.

    for example:

    1. when call SpiSpeed(6000000) // caller want set CLK to 6MHz
    cdiv = uint32(250000000 / 6000000) = 41
    with setSpiDiv will ignore LSB of cdiv, real cdiv will be 40, which result CLK = 6.25MHz
    
    new implement:
    cdiv = uint32((250000000 + 12000000 - 1) / 6000000) = 43
    with setSpiDiv will ignore LSB of cdiv, real cdiv will be 42, which result CLK = 5.95MHz
    
    1. when call SpiSpeed(11000000) // caller want set CLK to 11MHz
    cdiv = uint32(250000000 / 11000000) = 22
    with setSpiDiv will ignore LSB of cdiv, real cdiv will be 22, which result CLK = 11.36MHz
    
    new implement:
    cdiv = uint32((250000000 + 22000000 - 1) / 11000000) = 24
    with setSpiDiv will ignore LSB of cdiv, real cdiv will be 24, which result CLK = 10.4MHz
    
    1. when call SpiSpeed(500000) // caller want set CLK to 5MHz
    cdiv = uint32(250000000 / 5000000) = 50
    with setSpiDiv will ignore LSB of cdiv, real cdiv will be 50, which result CLK = 5MHz
    
    new implement:
    cdiv = uint32((250000000 + 10000000 - 1) / 5000000) = 51
    with setSpiDiv will ignore LSB of cdiv, real cdiv will be 50, which result CLK = 5MHz
    
    1. when call SpiSpeed(1000000) // caller want set CLK to 10MHz
    cdiv = uint32(250000000 / 10000000) = 25
    with setSpiDiv will ignore LSB of cdiv, real cdiv will be 24, which result CLK = 10.4MHz
    
    new implement:
    cdiv = uint32((250000000 + 20000000 - 1) / 10000000) = 26
    with setSpiDiv will ignore LSB of cdiv, real cdiv will be 26, which result CLK = 9.6MHz
    
  • Fix spelling mistakes

    Fix spelling mistakes

    First of all, I really enjoy this library. However, there were some spelling mistakes in the comments which i corrected. Because I have not changed any real code, this PR should be ready to be merged.

  • Try gpiomem when /dev/mem is not found

    Try gpiomem when /dev/mem is not found

    When running go-rpio inside a docker container with only /dev/gpiomem mounted, the library fails (docker run --device /dev/gpiomem). Currently, it only checks whether there is a permission problem with /dev/mem. In this case, however, /dev/mem is not found inside the container leading to a file not found error. In this case, it should also be tried if /dev/gpiomem is available.

  • Hardlock when EdgeDetect is used

    Hardlock when EdgeDetect is used

    I found a small issue with the library. For some reason when rpio is close and EdgeDetect is still enable it will hard lock the rpi. i tested it on both a pi3 and pi4. if i call pin.Detect(rpio.NoEdge) before close nothing locks up and everything is fine. I don't have any logs unfortunately dmsg and the kernel log give no insight.

    go version: go1.17 linux/arm64 kernel version (uname-a): Linux XXXX 5.13.0-1013-raspi #15-Ubuntu SMP PREEMPT Fri Jan 7 23:16:57 UTC 2022 aarch64 aarch64 aarch64 GNU/Linux go-rpio version: 4.5.1

  • DHT22/AM2302 example

    DHT22/AM2302 example

    I just wrote this function for my printer enclosure, which has 2 DHT22s installed. Works almost every time, sometimes it runs into a timeout, but that's likely due to long wires and the very strict timing requirements of those sensors. Communication protocol from the sensor datasheet, algorithm entirely written by me. Tested on a Raspberry Pi 3 Model B, should work on all variants. Don't forget the resistor (4.7k to 10k) between Data and VCC if your sensor hasn't one built in!

Related tags
Govalid is a data validation library that can validate most data types supported by golang

Govalid is a data validation library that can validate most data types supported by golang. Custom validators can be used where the supplied ones are not enough.

Apr 22, 2022
Maintain a lower-bitrate copy of a music library in sync with the main copy.

msync Maintain a lower-bitrate copy of your music library, in sync with the main copy.

Mar 6, 2022
Golang library to act on structure fields at runtime. Similar to Python getattr(), setattr(), hasattr() APIs.

go-attr Golang library to act on structure fields at runtime. Similar to Python getattr(), setattr(), hasattr() APIs. This package provides user frien

Dec 16, 2022
Go library for HTTP content type negotiation

Content-Type support library for Go This library can be used to parse the value Content-Type header (if one is present) and select an acceptable media

Jul 10, 2022
A tool and library for using structural regular expressions.

Structural Regular Expressions sregx is a package and tool for using structural regular expressions as described by Rob Pike (link).

Dec 7, 2022
A super simple Lodash like utility library with essential functions that empowers the development in Go
A super simple Lodash like utility library with essential functions that empowers the development in Go

A simple Utility library for Go Go does not provide many essential built in functions when it comes to the data structure such as slice and map. This

Jan 4, 2023
go-sysinfo is a library for collecting system information.

go-sysinfo go-sysinfo is a library for collecting system information. This includes information about the host machine and processes running on the ho

Dec 26, 2022
Molecule is a Go library for parsing protobufs in an efficient and zero-allocation manner

Molecule Molecule is a Go library for parsing protobufs in an efficient and zero-allocation manner. The API is loosely based on this excellent Go JSON

Jan 5, 2023
A Go (golang) library for parsing and verifying versions and version constraints.

go-version is a library for parsing versions and version constraints, and verifying versions against a set of constraints. go-version can sort a collection of versions properly, handles prerelease/beta versions, can increment versions, etc.

Jan 9, 2023
A library for parsing ANSI encoded strings
 A library for parsing ANSI encoded strings

Go ANSI Parser converts strings with ANSI escape codes into a slice of structs that represent styled text

Sep 20, 2022
go generate based graphql server library
go generate based graphql server library

gqlgen What is gqlgen? gqlgen is a Go library for building GraphQL servers without any fuss. gqlgen is based on a Schema first approach — You get to D

Dec 29, 2022
This is Go library for building GraphQL client with gqlgen

gqlgenc What is gqlgenc ? This is Go library for building GraphQL client with gqlgen Motivation Now, if you build GraphQL api client for Go, have choi

Jan 7, 2023
A library for diffing golang structures

Diff A library for diffing golang structures and values. Utilizing field tags and reflection, it is able to compare two structures of the same type an

Dec 29, 2022
Go library for decoding generic map values into native Go structures and vice versa.

mapstructure mapstructure is a Go library for decoding generic map values to structures and vice versa, while providing helpful error handling. This l

Dec 28, 2022
🍀 Go basic library. || Go语言基础库
🍀 Go basic library. || Go语言基础库

Go语言基础库 工程目录说明 pkg/ ...... 源码包 |-- bininfo/ ...... 将编译时源码的git版本信息(当前commit log的sha值和commit message),编译时间,Go版本,平台打入程序中

Dec 28, 2022
A well tested and comprehensive Golang statistics library package with no dependencies.

Stats - Golang Statistics Package A well tested and comprehensive Golang statistics library / package / module with no dependencies. If you have any s

Dec 30, 2022
go-sundheit:A library built to provide support for defining service health for golang services
go-sundheit:A library built to provide support for defining service health for golang services

A library built to provide support for defining service health for golang services. It allows you to register async health checks for your dependencies and the service itself, and provides a health endpoint that exposes their status.

Dec 27, 2022
Go library that provides fuzzy string matching optimized for filenames and code symbols in the style of Sublime Text, VSCode, IntelliJ IDEA et al.
Go library that provides fuzzy string matching optimized for filenames and code symbols in the style of Sublime Text, VSCode, IntelliJ IDEA et al.

Go library that provides fuzzy string matching optimized for filenames and code symbols in the style of Sublime Text, VSCode, IntelliJ IDEA et al. This library is external dependency-free. It only depends on the Go standard library.

Dec 27, 2022
Helper library for full uint64 randomness, pool backed for efficient concurrency

fastrand64-go Helper library for full uint64 randomness, pool backed for efficient concurrency Inspired by https://github.com/valyala/fastrand which i

Dec 5, 2021