rpio

package module
v5.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 1, 2021 License: MIT Imports: 9 Imported by: 0

README

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 @Drahoslav7
  • 4.1.0 - Adds support for edge detection, by @Drahoslav7
  • 4.2.0 - Faster write and toggle of output pins, by @Drahoslav7
  • 4.3.0 - Adds support for SPI, by @Drahoslav7
  • 4.4.0 - Support for disabling interrupts (workaround for #35), by @Drahoslav7

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.

Documentation

Overview

Package rpio provides GPIO access on the Raspberry PI without any need for external c libraries (eg. WiringPi or BCM2835).

Supports simple operations such as:

  • Pin mode/direction (input/output/clock/pwm,alt0,alt1,alt2,alt3,alt4,alt5)
  • Pin write (high/low)
  • Pin read (high/low)
  • Pin edge detection (no/rise/fall/any)
  • Pull up/down/off

Also clock/pwm related oparations:

  • Set Clock frequency
  • Set Duty cycle

And SPI oparations:

  • SPI transmit/recieve/exchange bytes
  • Chip select
  • Set speed

Example of use:

rpio.Open()
defer rpio.Close()

pin := rpio.Pin(4)
pin.Output()

for {
	pin.Toggle()
	time.Sleep(time.Second)
}

The library use the raw BCM2835 pinouts, not the ports as they are mapped on the output pins for the raspberry pi, and not the wiringPi convention.

          Rev 2 and 3 Raspberry Pi                        Rev 1 Raspberry Pi (legacy)
+-----+---------+----------+---------+-----+      +-----+--------+----------+--------+-----+
| BCM |   Name  | Physical | Name    | BCM |      | BCM | Name   | Physical | Name   | BCM |
+-----+---------+----++----+---------+-----+      +-----+--------+----++----+--------+-----+
|     |    3.3v |  1 || 2  | 5v      |     |      |     | 3.3v   |  1 ||  2 | 5v     |     |
|   2 |   SDA 1 |  3 || 4  | 5v      |     |      |   0 | SDA    |  3 ||  4 | 5v     |     |
|   3 |   SCL 1 |  5 || 6  | 0v      |     |      |   1 | SCL    |  5 ||  6 | 0v     |     |
|   4 | GPIO  7 |  7 || 8  | TxD     | 14  |      |   4 | GPIO 7 |  7 ||  8 | TxD    |  14 |
|     |      0v |  9 || 10 | RxD     | 15  |      |     | 0v     |  9 || 10 | RxD    |  15 |
|  17 | GPIO  0 | 11 || 12 | GPIO  1 | 18  |      |  17 | GPIO 0 | 11 || 12 | GPIO 1 |  18 |
|  27 | GPIO  2 | 13 || 14 | 0v      |     |      |  21 | GPIO 2 | 13 || 14 | 0v     |     |
|  22 | GPIO  3 | 15 || 16 | GPIO  4 | 23  |      |  22 | GPIO 3 | 15 || 16 | GPIO 4 |  23 |
|     |    3.3v | 17 || 18 | GPIO  5 | 24  |      |     | 3.3v   | 17 || 18 | GPIO 5 |  24 |
|  10 |    MOSI | 19 || 20 | 0v      |     |      |  10 | MOSI   | 19 || 20 | 0v     |     |
|   9 |    MISO | 21 || 22 | GPIO  6 | 25  |      |   9 | MISO   | 21 || 22 | GPIO 6 |  25 |
|  11 |    SCLK | 23 || 24 | CE0     | 8   |      |  11 | SCLK   | 23 || 24 | CE0    |   8 |
|     |      0v | 25 || 26 | CE1     | 7   |      |     | 0v     | 25 || 26 | CE1    |   7 |
|   0 |   SDA 0 | 27 || 28 | SCL 0   | 1   |      +-----+--------+----++----+--------+-----+
|   5 | GPIO 21 | 29 || 30 | 0v      |     |
|   6 | GPIO 22 | 31 || 32 | GPIO 26 | 12  |
|  13 | GPIO 23 | 33 || 34 | 0v      |     |
|  19 | GPIO 24 | 35 || 36 | GPIO 27 | 16  |
|  26 | GPIO 25 | 37 || 38 | GPIO 28 | 20  |
|     |      0v | 39 || 40 | GPIO 29 | 21  |
+-----+---------+----++----+---------+-----+

See the spec for full details of the BCM2835 controller:

https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2835/BCM2835-ARM-Peripherals.pdf and https://elinux.org/BCM2835_datasheet_errata - for errors in that spec

Changes to support the BCM2711, used on the Raspberry Pi 4, were cribbed from https://github.com/RPi-Distro/raspi-gpio/

Index

Examples

Constants

View Source
const (
	GPPUPPDN0 = 57 // Pin pull-up/down for pins 15:0
	GPPUPPDN1 = 58 // Pin pull-up/down for pins 31:16
	GPPUPPDN2 = 59 // Pin pull-up/down for pins 47:32
	GPPUPPDN3 = 60 // Pin pull-up/down for pins 57:48
)

BCM 2711 has a different mechanism for pull-up/pull-down/enable

Variables

View Source
var (
	SpiMapError = errors.New("SPI registers not mapped correctly - are you root?")
)

Functions

func Close

func Close() error

Close unmaps GPIO memory

func DetectEdge

func DetectEdge(pin Pin, edge Edge)

DetectEdge: Enable edge event detection on pin.

Combine with pin.EdgeDetected() to check whether event occured.

Note that using this function might conflict with the same functionality of other gpio library.

It also clears previously detected event of this pin if there was any.

Note that call with RiseEdge will disable previously set FallEdge detection and vice versa. You have to call with AnyEdge, to enable detection for both edges. To disable previously enabled detection call it with NoEdge.

WARNING: this might make your Pi unresponsive, if this happens, you should either run the code as root, or add `dtoverlay=gpio-no-irq` to `/boot/config.txt` and restart your pi,

func DisableIRQs

func DisableIRQs(irqs uint64)

DisableIRQs: Disables given IRQs (by setting bit to 1 at intended position). See 'ARM peripherals interrupts table' in pheripherals datasheet. WARNING: you can corrupt your system, only use this if you know what you are doing.

func EdgeDetected

func EdgeDetected(pin Pin) bool

EdgeDetected checks whether edge event occured since last call or since detection was enabled

There is no way (yet) to handle interruption caused by edge event, you have to use polling.

Event detection has to be enabled first, by pin.Detect(edge)

func EnableIRQs

func EnableIRQs(irqs uint64)

EnableIRQs: Enables given IRQs (by setting bit to 1 at intended position). See 'ARM peripherals interrupts table' in pheripherals datasheet. WARNING: you can corrupt your system, only use this if you know what you are doing.

func Open

func Open() (err error)

Open and memory map GPIO memory range from /dev/mem . Some reflection magic is used to convert it to a unsafe []uint32 pointer

func PinMode

func PinMode(pin Pin, mode Mode)

PinMode sets the mode of a given pin (Input, Output, Clock, Pwm or Spi)

Clock is possible only for pins 4, 5, 6, 20, 21. Pwm is possible only for pins 12, 13, 18, 19.

Spi mode should not be set by this directly, use SpiBegin instead.

func PullMode

func PullMode(pin Pin, pull Pull)

func SetDutyCycle

func SetDutyCycle(pin Pin, dutyLen, cycleLen uint32)

SetDutyCycle: Set cycle length (range) and duty length (data) for Pwm pin in M/S mode

 |<- duty ->|
  __________
_/          \_____________/
 |<------- cycle -------->|

Output frequency is computed as pwm clock frequency divided by cycle length. So, to set Pwm pin to freqency 38kHz with duty cycle 1/4, use this combination:

pin.Pwm()
pin.DutyCycle(1, 4)
pin.Freq(38000*4)

Note that some pins share common pwm channel, so calling this function will set same duty cycle for all pins belonging to channel. The channels are:

channel 1 (pwm0) for pins 12, 18, 40
channel 2 (pwm1) for pins 13, 19, 41, 45.

func SetFreq

func SetFreq(pin Pin, freq int)

SetFreq: Set clock speed for given pin in Clock or Pwm mode

Param freq should be in range 4688Hz - 19.2MHz to prevent unexpected behavior, however output frequency of Pwm pins can be further adjusted with SetDutyCycle. So for smaller frequencies use Pwm pin with large cycle range. (Or implement custom software clock using output pin and sleep.)

Note that some pins share the same clock source, it means that changing frequency for one pin will change it also for all pins within a group. The groups are:

gp_clk0: pins 4, 20, 32, 34
gp_clk1: pins 5, 21, 42, 44
gp_clk2: pins 6 and 43
pwm_clk: pins 12, 13, 18, 19, 40, 41, 45

func SpiBegin

func SpiBegin(dev SpiDev) error

SpiBegin: Sets all pins of given SPI device to SPI mode

dev\pin | CE0 | CE1 | CE2 | SCLK | MOSI | MISO |
Spi0    |   7 |   8 |   - |    9 |   10 |   11 |
Spi1    |  16 |  17 |  18 |   19 |   20 |   21 |
Spi2    |  40 |  41 |  42 |   43 |   44 |   45 |

It also resets SPI control register.

Note that you should disable SPI interface in raspi-config first!

Example
err := SpiBegin(Spi0) // pins 7 to 11
if err != nil {
	panic(err)
}

// any Spi functions must go there...
SpiTransmit(42)

SpiEnd(Spi0)
Output:

func SpiChipSelect

func SpiChipSelect(chip uint8)

SpiChipSelect: Select chip, one of 0, 1, 2 for selecting slave on CE0, CE1, or CE2 pin

func SpiChipSelectPolarity

func SpiChipSelectPolarity(chip uint8, polarity uint8)

SpiChipSelectPolarity: Sets polarity (0/1) of active chip select default active=0

func SpiEnd

func SpiEnd(dev SpiDev)

SpiEnd: Sets SPI pins of given device to default (Input) mode. See SpiBegin.

func SpiExchange

func SpiExchange(data []byte)

SpiExchange: Transmit all bytes in data to slave and simultaneously receives bytes from slave to data.

If you want to only send or only receive, use SpiTransmit/SpiReceive

func SpiMode

func SpiMode(polarity uint8, phase uint8)

SpiMode: Set polarity (0/1) and phase (0/1) of spi clock default polarity=0; phase=0

func SpiReceive

func SpiReceive(n int) []byte

SpiReceive receives n bytes from slave.

Note that n zeroed bytes are send to slave as side effect.

func SpiSpeed

func SpiSpeed(speed int)

SpiSpeed: Set (maximal) speed [Hz] of SPI clock. Param speed may be as big as 125MHz in theory, but only values up to 31.25MHz are considered relayable.

func SpiTransmit

func SpiTransmit(data ...byte)

SpiTransmit takes one or more bytes and send them to slave.

Data received from slave are ignored. Use spread operator to send slice of bytes.

Example
SpiTransmit(0xFF)             // send single byte
SpiTransmit(0xDE, 0xAD, 0xBE) // send several bytes

data := []byte{'H', 'e', 'l', 'l', 'o', 0}
SpiTransmit(data...) // send slice of bytes
Output:

func StartPwm

func StartPwm()

StartPwm starts pwm for both channels

func StopPwm

func StopPwm()

StopPwm: Stop pwm for both channels

func TogglePin

func TogglePin(pin Pin)

TogglePin: Toggle a pin state (high -> low -> high)

func WritePin

func WritePin(pin Pin, state State)

WritePin sets a given pin High or Low by setting the clear or set registers respectively

Types

type Edge

type Edge uint8
const (
	NoEdge Edge = iota
	RiseEdge
	FallEdge
	AnyEdge = RiseEdge | FallEdge
)

Edge events

type Mode

type Mode uint8
const (
	Input Mode = iota
	Output
	Clock
	Pwm
	Spi
	Alt0
	Alt1
	Alt2
	Alt3
	Alt4
	Alt5
)

Pin mode, a pin can be set in Input or Output, Clock or Pwm mode

type Pin

type Pin uint8

func (Pin) Clock

func (pin Pin) Clock()

Clock: Set pin as Clock

func (Pin) Detect

func (pin Pin) Detect(edge Edge)

Detect: Enable edge event detection on pin

func (Pin) DutyCycle

func (pin Pin) DutyCycle(dutyLen, cycleLen uint32)

DutyCycle: Set duty cycle for Pwm pin (see doc of SetDutyCycle)

func (Pin) EdgeDetected

func (pin Pin) EdgeDetected() bool

EdgeDetected checks edge event on pin

func (Pin) Freq

func (pin Pin) Freq(freq int)

Freq: Set frequency of Clock or Pwm pin (see doc of SetFreq)

func (Pin) High

func (pin Pin) High()

High: Set pin High

func (Pin) Input

func (pin Pin) Input()

Input: Set pin as Input

func (Pin) Low

func (pin Pin) Low()

Low: Set pin Low

func (Pin) Mode

func (pin Pin) Mode(mode Mode)

Mode: Set pin Mode

func (Pin) Output

func (pin Pin) Output()

Output: Set pin as Output

func (Pin) Pull

func (pin Pin) Pull(pull Pull)

Pull: Set a given pull up/down mode

func (Pin) PullDown

func (pin Pin) PullDown()

PullDown: Pull down pin

func (Pin) PullOff

func (pin Pin) PullOff()

PullOff: Disable pullup/down on pin

func (Pin) PullUp

func (pin Pin) PullUp()

PullUp: Pull up pin

func (Pin) Pwm

func (pin Pin) Pwm()

Pwm: Set pin as Pwm

func (Pin) Read

func (pin Pin) Read() State

Read pin state (high/low)

func (Pin) ReadPull

func (pin Pin) ReadPull() Pull

func (Pin) Toggle

func (pin Pin) Toggle()

Toggle pin state

func (Pin) Write

func (pin Pin) Write(state State)

Write: Set pin state (high/low)

type Pull

type Pull uint8
const (
	PullOff Pull = iota
	PullDown
	PullUp
	PullNone
)

Pull Up / Down / Off

type SpiDev

type SpiDev int
const (
	Spi0 SpiDev = iota
	Spi1        // aux
	Spi2        // aux
)

SPI devices. Only SPI0 supported for now.

type State

type State uint8
const (
	Low State = iota
	High
)

State of pin, High / Low

func ReadPin

func ReadPin(pin Pin) State

ReadPin reads the state of a pin

Directories

Path Synopsis
examples
pwm
spi

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL