Embedded Programming Framework in Go
Go Shell
Latest commit adc3d47 Sep 25, 2016 @tve tve committed on GitHub Merge pull request #69 from kidoman/update
Add support for CHIP; merge piled-up PRs
Failed to load latest commit information.
controller Initial support for rfm69 radio Sep 6, 2016
convertors Fix typo Dec 22, 2015
embd cli: print the rev number in hex Jan 15, 2015
host make fork ready for merge-back Sep 7, 2016
interface interface: add an abstraction layer for character displays Feb 25, 2015
motion/servo unified servo and analog output support for pwms Apr 2, 2014
samples Println doesn't accept formatting. Dec 22, 2015
sensor gpio: provide an api to allow performance timing of pulses Apr 4, 2014
util add test for Map Mar 2, 2014
.gitignore bring in the idea of a hardware abstraction layer Feb 26, 2014
.travis.yml fix travis Sep 9, 2016
AUTHORS added support for us020 ultra sonic range finder Dec 13, 2013
CONTRIBUTING.md doc: how to contribute Apr 11, 2014
CONTRIBUTORS update contributors Sep 9, 2016
LICENSE initial commit Dec 8, 2013
README.md README update Sep 9, 2016
ROADMAP.md doc: add roadmap Apr 6, 2014
descriptor.go spi: added spi feature for all bbb and rpi Apr 27, 2014
detect.go add minimal support for NextThing CHIP Aug 27, 2016
detect_test.go simplify package structure Mar 2, 2014
doc.go revert some gratuitous whitespace changes Sep 9, 2016
gpio.go minor documentation addition Sep 9, 2016
gpiodriver.go gpio: added pinmap accessor for introspection usage Jan 15, 2015
gpiodriver_test.go gpio: added missing function in fakeDigitalPin Sep 3, 2014
i2c.go removing failed Stat use Oct 11, 2015
i2cdriver.go host specific drivers can now be loaded separately Apr 6, 2014
led.go allow lazy initialisation of the drivers Apr 11, 2014
leddriver.go host specific drivers can now be loaded separately Apr 6, 2014
pin.go gpio: CapNormal -> CapAnalog Mar 23, 2014
pin_test.go gpio: CapNormal -> CapAnalog Mar 23, 2014
spi.go Fix typo Dec 22, 2015
spidriver.go Support SPI minor devices >255 (PR #33) Sep 6, 2016
update_contributors.sh rename update_contibutors.sh Sep 9, 2016
utils.go host specific drivers can now be loaded separately Apr 6, 2014


embd Build Status GoDoc

embd is a hardware abstraction layer (HAL) for embedded systems.

It allows you to start your hardware hack on easily available hobby boards (like the Raspberry Pi, BeagleBone Black, C.H.I.P., etc.) by giving you straight-forward access to the board's capabilities as well as a plethora of sensors (like accelerometers, gyroscopes, thermometers, etc.) and controllers (PWM generators, digital-to-analog convertors) for which it includes drivers. If you move to custom designed boards you have to throw away your code: you carry forward the effort where the HAL abstraction of EMBD will save you precious time.

The overall strategy used in embd is to use Linux device drivers to access gpio pins, SPI and I2C buses, as well as interrupts. This makes it easy to port from one platform to another and it enables kernel code to handle the devices as efficiently as possible. What embd then adds is first a Golang library interface on top of the various Linux devices and then another layer of user-level drivers for specific sensors and controllers that are connected to gpio pins or one of the buses.

Development supported and sponsored by SoStronk and ThoughtWorks.

Also, you might be interested in: Why Golang?

Blog post introducing EMBD

Getting Started

Install Go version 1.6 or later to make compiling for ARM easy. The set up your GOPATH, and create your first .go file. We'll call it simpleblinker.go.

package main

import (

	_ "github.com/kidoman/embd/host/rpi" // This loads the RPi driver

func main() {
	for {
		time.Sleep(250 * time.Millisecond)

Then install the EMBD package:

$ go get github.com/kidoman/embd

Build the binary for linux/ARM:

$ export GOOS=linux
$ export GOARCH=arm
$ go build simpleblinker.go

Copy the cross-compiled binary to your RaspberryPi*:

$ scp simpleblinker pi@

Then on the rPi run the program with sudo*:

$ sudo ./simpleblinker

You will now see the green LED (next to the always on power LED) blink every 1/4 sec.

* Notes

  • Assuming your RaspberryPi has an IP address of Substitute as necessary
  • sudo (root) permission is required as we are controlling the hardware by writing to special files
  • This sample program is optimized for brevity and does not clean up after itself. Click here to see the full version

Getting Help

Join the slack channel

Platforms Supported

The command line tool

go get github.com/kidoman/embd/embd

will install a command line utility embd which will allow you to quickly get started with prototyping. The binary should be available in your $GOPATH/bin. However, to be able to run this on a ARM based device, you will need to build it with GOOS=linux and GOARCH=arm environment variables set.

For example, if you run embd detect on a BeagleBone Black:

root@beaglebone:~# embd detect

detected host BeagleBone Black (rev 0)

Run embd without any arguments to discover the various commands supported by the utility.

How to use the framework

Package embd provides a hardware abstraction layer for doing embedded programming on supported platforms like the Raspberry Pi and BeagleBone Black. Most of the examples below will work without change (i.e. the same binary) on all supported platforms. How cool is that?

Although samples are all present in the samples folder, we will show a few choice examples here.

Use the LED driver to toggle LEDs on the BBB:

import "github.com/kidoman/embd"
import _ "github.com/kidoman/embd/host/all"
defer embd.CloseLED()
led, err := embd.NewLED(3)

Even shorter when quickly trying things out:

import "github.com/kidoman/embd"
import _ "github.com/kidoman/embd/host/all"
defer embd.CloseLED()

3 is the same as USR3 for all intents and purposes. The driver is smart enough to figure all this out.


import "github.com/kidoman/embd"
import _ "github.com/kidoman/embd/host/all"
defer embd.CloseGPIO()
pwm, _ := embd.NewPWMPin("P9_14")
defer pwm.Close()

Control GPIO pins on the RaspberryPi / BeagleBone Black:

import "github.com/kidoman/embd"
import _ "github.com/kidoman/embd/host/all"
defer embd.CloseGPIO()
embd.SetDirection(10, embd.Out)
embd.DigitalWrite(10, embd.High)

Could also do:

import "github.com/kidoman/embd"
import _ "github.com/kidoman/embd/host/all"
defer embd.CloseGPIO()
pin, err := embd.NewDigitalPin(10)

Or read data from the Bosch BMP085 barometric sensor:

import "github.com/kidoman/embd"
import "github.com/kidoman/embd/sensor/bmp085"
import _ "github.com/kidoman/embd/host/all"
bus := embd.NewI2CBus(1)
baro := bmp085.New(bus)
temp, err := baro.Temperature()
altitude, err := baro.Altitude()

Even find out the heading from the LSM303 magnetometer:

import "github.com/kidoman/embd"
import "github.com/kidoman/embd/sensor/lsm303"
import _ "github.com/kidoman/embd/host/all"
bus := embd.NewI2CBus(1)
mag := lsm303.New(bus)
heading, err := mag.Heading()

The above two examples depend on I2C and therefore will work without change on almost all platforms.

Protocols Supported

Sensors Supported




  • MCP3008 8-channel, 10-bit ADC with SPI protocol, Datasheet


Pull requests that follow the guidelines are very appreciated. If you find a problem but are not up to coding a fix please file an issue. Thank you!


EMBD is affectionately designed/developed by Karan Misra (kidoman), Kunal Powar (kunalpowar) and FRIENDS. We also have a list of CONTRIBUTORS.