Circuitpython On Orangepi Linux
Circuitpython On Orangepi Linux
Orange Pi
Created by lady ada
https://learn.adafruit.com/circuitpython-on-orangepi-linux
Overview 5
• Why CircuitPython?
• CircuitPython on Microcontrollers
• CircuitPython Libraries on Desktop Linux
Orange Pi PC Setup 8
• Install ARMbian on your Orange Pi
• Logging in
• Install Python and set Python 3 to Default
• Install libgpiod
• Update Your Board and Python
• Enable UART, I2C and SPI
• Install Python libraries
Orange Pi R1 Setup 15
• Install ARMbian on your Orange Pi
• Connecting the GPIO/Debug Header
• Prepare the header strip:
• Place the header:
• And Solder!
• You're done!
• Logging in using Serial
• Connecting using DHCP and SSH
• MacOS/Linux
• Windows
• Set your Python install to Python 3 Default
• Install libgpiod
• Install Required pip3 Modules
• Update Your Board and Python
• Enable UART, I2C and SPI
• Install Python libraries
Digital I/O 26
• Parts Used
• Wiring
• Blinky Time!
• Button It Up
UART / Serial 43
• The Easy Way - An External USB-Serial Converter
• The Hard Way - Using Built-in UART
• Install the CircuitPython GPS Library
• Run that code!
More To Come! 50
Here at Adafruit we're always looking for ways to make making easier - whether that's
making breakout boards for hard-to-solder sensors or writing libraries to simplify
motor control. Our new favorite way to program is CircuitPython.
Why CircuitPython?
CircuitPython is a variant of MicroPython, a very small version of Python that can fit on
a microcontroller. Python is the fastest-growing programming language. It's taught in
schools, used in coding bootcamps, popular with scientists and of course
programmers at companies use it a lot!
CircuitPython adds the Circuit part to the Python part. It lets you program in Python
and talk to Circuitry like sensors, motors, and LEDs!
CircuitPython on Microcontrollers
CircuitPython runs on microcontroller boards, such as our Feather, Metro, QT Py, and
ItsyBitsy boards, using a variety of chips, such as the MicroChip SAMD21 SAMD51, the
All of these chips have something in common - they are microcontrollers with
hardware peripherals like SPI, I2C, ADCs etc. We squeeze Python into 'em and can
then make the project portable.
But...sometimes you want to do more than a microcontroller can do. Like HDMI video
output, or camera capture, or serving up a website, or just something that takes more
memory and computing than a microcontroller board can do...
By adding a software layer, you can use CircuitPython hardware control capabilities wi
th "regular Python", as found on your desktop or single-board Linux computer/ There
are tons of projects, libraries and example code for CircuitPython on microcontrollers,
and thanks to the flexibility and power of Python its' pretty easy to get that code
working on micro-computers like the Raspberry Pi or other single-board Linux
computers with GPIO pins available.
The upshot is that most code we write for CircuitPython will be instantly and easily
runnable on Linux computers like Raspberry Pi.
In particular, you'll be able to use all of our device drivers - the sensors, led
controllers, motor drivers, HATs, bonnets, etc. And nearly all of these use I2C or SPI!
The rest of this guide describes how to install and set up Blinka, and then how to use
it to run CircuitPython code to control hardware.
The next obvious step is to bring CircuitPython back to 'desktop Python'. We've got
tons of projects, libraries and example code for CircuitPython on microcontrollers, and
thanks to the flexibility and power of Python its pretty easy to get it working with
micro-computers like Orange Pi or other 'Linux with GPIO pins available' single board
computers.
We'll use a special library called adafruit_blinka () (named after Blinka, the
CircuitPython mascot ()) to provide the layer that translates the CircuitPython
hardware API to whatever library the Linux board provides. For example, on Orange Pi
we use the python libgpiod bindings. For any I2C interfacing we'll use ioctl messages
to the /dev/i2c device. For SPI we'll use the spidev python library, etc. These
details don't matter so much because they all happen underneath the adafruit_blinka
layer.
The upshot is that any code we have for CircuitPython will be instantly and easily
runnable on Linux computers like Orange Pi.
In particular, we'll be able to use all of our device drivers - the sensors, led controllers,
motor drivers, HATs, bonnets, etc. And nearly all of these use I2C or SPI!
WiringOP, a modification of WiringPi, is for GPIO usage only, it doesn't work well for
various I2C or SPI devices.
By letting you use CircuitPython on Raspberry Pi via adafruit_blinka, you can unlock
all of the drivers and example code we wrote! And you can keep using WiringOP for
pins, buttons and LEDs. We save time and effort so we can focus on getting code that
works in one place, and you get to reuse all the code we've written already.
Right now, Blinka only supports the Orange Pi PC (because that's the only board
we've got for testing).
Yep! Blinka can easily be updated to add other boards. We've started with the one
we've got, so we could test it thoroughly. If you have an OrangePi or other SBC board
you'd like to adapt check out the adafruit_blinka code on github (), pull requests are
welcome as there's a ton of different Linux boards out there!
Orange Pi PC Setup
This page is for the Orange Pi PC only!
Once armbian is installed, its easy to tell what board you have, simply cat /etc/
armbian-release and look for BOARD_NAME
Download and install the latest armbian, for example we're using https://
www.armbian.com/orange-pi-pc-plus/ ()
Blinka only supports ARMbian because that's the most stable OS we could find
and it's easy to detect which board you have
Logging in
USB to TTL Serial Cable - Debug /
Console Cable for Raspberry Pi
The cable is easiest way ever to connect
to your microcontroller/Raspberry Pi/WiFi
router serial console port. Inside the big
USB plug is a USB<->Serial conversion
chip and at...
https://www.adafruit.com/product/954
Once installed, you may want to enable mdns so you can ssh pi@orangepipc
instead of needing to know the IP address:
then reboot
Install libgpiod
libgpiod is what we use for gpio toggling. To install run this command:
After installation you should be able to import gpiod from within Python3
and
and
sudo bash
You only have to do this once per board but by default all three interfaces are
disabled!
overlay_prefix=sun8i-h3
overlays=uart3 i2c0 spi-spidev
param_spidev_spi_bus=0
Once you're done with both and have rebooted, verify you have the I2C and SPI
devices with the command ls /dev/i2c* /dev/spi*
You should see at least one i2c device and one spi device
You can also install WiringOP and then run gpio readall to see the MUX status. If
you see ALT3 next to a pin, its a plain GPIO. If you see ALT4 or ALT5, its an SPI/I2C/
UART peripheral
The computer will install a few different libraries such as adafruit-pureio (our
ioctl-only i2c library), spidev (for SPI interfacing), Adafruit-GPIO (for detecting
your board) and of course adafruit-blinka
Create a new file called blinkatest.py with nano or your favorite text editor and put the
following in:
print("Hello blinka!")
print("done!")
You should see the following, indicating digital i/o, I2C and SPI all worked
Orange Pi R1 Setup
This page is for the Orange Pi R1 only!
Once armbian is installed, its easy to tell what board you have, simply cat /etc/
armbian-release and look for BOARD_NAME
Download and install the latest armbian, for example we're using https://
www.armbian.com/orange-pi-r1/ ()
Blinka only supports ARMbian because that's the most stable OS we could find
and it's easy to detect which board you have
And Solder!
Be sure to solder all pins for reliable
electrical contact.
Once installed, you may want to enable mDNS so you can ssh [email protected]
instead of needing to know the IP address:
By default, most routers have DHCP enabled and some routers will display all of the
hosts connected to them through the web configuration panel. If you are able to
retrieve the IP address, then you can connect through SSH.
MacOS/Linux
Mac and Linux should have SSH installed by default and you can access it by going to
the command line and typing ssh [email protected] if the IP address of your
Orange Pi is 192.168.0.25.
Windows
The easiest way to connect with windows is to use a Terminal program called PuTTY
from https://www.putty.org ().
You can read more about connecting through SSH in our Adafruit's Raspberry Pi
Lesson 6. Using SSH () guide. Although this is written for Raspberry Pi, the steps
should be the same.
After installation you should be able to import gpiod from within Python3
and
sudo bash
You only have to do this once per board but by default all three interfaces are
disabled!
Once you're done with both and have rebooted, verify you have the I2C and SPI
devices with the command ls /dev/i2c* /dev/spi*
You should see at least one i2c device and one spi device
You can also install WiringOP-Zero and then run gpio readall to see the MUX
status. If you see ALT3 next to a pin, it's a plain GPIO. If you see ALT4 or ALT5, its an
SPI/I2C/UART peripheral
The computer will install a few different libraries such as adafruit-pureio (our
ioctl-only i2c library), spidev (for SPI interfacing), Adafruit-GPIO (for detecting
your board) and of course adafruit-blinka
Create a new file called blinkatest.py with nano or your favorite text editor and put the
following in:
print("Hello blinka!")
print("done!")
You should see the following, indicating digital i/o, I2C and SPI all worked
Digital I/O
The first step with any new hardware is the 'hello world' of electronics - blinking an
LED. This is very easy with CircuitPython and Orange Pi. We'll extend the example to
also show how to wire up a button/switch.
Orange Pi (Allwinner) boards don't have any way to set the pullup/pulldown
resistors, so you'll need to use external resistors instead of built-in pullups,
whenever it makes sense!
You can use a Cobbler to make this a little easier, the pins will be labeled according to
Raspberry Pi names so just check the Orange Pi name!
Wiring
Connect the Orange Pi Ground pin to the blue ground rail on the breadboard.
Double-check you have the right wires connected to the right location, it can be
tough to keep track of Pi pins as there are forty of them!
Blinky Time!
The finish line is right up ahead, lets start with an example that blinks the LED on and
off once a second (half a second on, half a second off):
import time
import board
import digitalio
print("hello blinky!")
led = digitalio.DigitalInOut(board.PD14)
led.direction = digitalio.Direction.OUTPUT
while True:
led.value = True
time.sleep(0.5)
Verify the LED is blinking. If not, check that it's wired to GPIO PD14, the resistor is
installed correctly, and you have a Ground wire to the Orange Pi.
Button It Up
Now that you have the LED working, lets add code so the LED turns on whenever the
button is pressed
import time
import board
import digitalio
led = digitalio.DigitalInOut(board.PD14)
led.direction = digitalio.Direction.OUTPUT
button = digitalio.DigitalInOut(board.PA6)
button.direction = digitalio.Direction.INPUT
# use an external pullup since we don't have internal PU's
#button.pull = digitalio.Pull.UP
while True:
led.value = not button.value # light when button is pressed!
Lets show how to wire up a popular BME280. This sensor provides temperature,
barometric pressure and humidity data over I2C
We're going to do this in a lot more depth than our guide pages for each sensor, but
the overall technique is basically identical for any and all I2C sensors.
Parts Used
Adafruit BME280 I2C or SPI Temperature
Humidity Pressure Sensor
Bosch has stepped up their game with
their new BME280 sensor, an
environmental sensor with temperature,
barometric pressure and humidity! This
sensor is great for all sorts...
https://www.adafruit.com/product/2652
You can use a Cobbler to make this a little easier, the pins are then labeled!
Wiring
• Connect the Orange Pi 3.3V power pin to Vin
• Connect the Orange Pi GND pin to GND
• Connect the Pi SDA pin to the BME280 SDI
• Connect the Pi SCL pin to to the BME280 SCK
As of this writing, not all libraries are up on PyPI so you may want to search before
trying to install. Look for circuitpython and then the driver you want.
As of this writing there's only one example. But that's cool, here it is:
import time
import board
from adafruit_bme280 import basic as adafruit_bme280
while True:
print("\nTemperature: %0.1f C" % bme280.temperature)
print("Humidity: %0.1f %%" % bme280.relative_humidity)
print("Pressure: %0.1f hPa" % bme280.pressure)
print("Altitude = %0.2f meters" % bme280.altitude)
time.sleep(2)
Save this code to your Pi by copying and pasting it into a text file, downloading it
directly from the Pi, etc.
python3 bme280_simpletest.py
The code will loop with the sensor data until you quit with a Control-C
https://circuitpython.readthedocs.io/projects/bme280/en/latest/ ()
The nice thing about SPI is you can have as many chips as you like, even the same
kind, all share the three SPI wires, as long as each one has a unique chip select pin.
Remember, connect all SCK, MOSI and MISO pins together (unless there's some
specific reason/instruction not to) and a unique CS pin for each device.
SPI on microcontrollers is fairly simple, you have an SPI peripheral and you can
transfer data on it with some low level command. Its 'your job' as a programmer to
control the CS lines with a GPIO. That's how CircuitPython is structured as well. busi
o does just the SPI transmit/receive part and busdevice handles the chip select pin
as well.
Linux, on the other hand, doesn't let you send data to SPI without a CS line, and the
CS lines are fixed in hardware as well. For example on the Orange Pi PC, there's only
one CS pins available for the hardware SPI pins - SPI_CS known as PC3 - and you hav
The upshot here is - to let you use more than 1 peripheral on SPI, we decided to let
you use any CS pins you like, CircuitPython will toggle it the way you expect. But
when we transfer SPI data we always tell the kernel to use SPI_CS. SPI_CS will toggle
like a CS pin, but if we leave it disconnected, its no big deal
The upshot here is basically never connect anything to SPI_CS. Use whatever chip
select pin you define in CircuitPython and just leave the CS pin alone, it will toggle as
if it is the chip select line, completely on its own, so you shouldn't try to use it as a
digital input/output/whatever.
Parts Used
OK now that we've gone thru the warning, lets wire up an SPI MAX31855
thermocouple sensor, this particular device doesn't have a MOSI pin so we'll not
connect it.
You can use a Cobbler to make this a little easier, the pins are then labeled!
Wiring
• Connect the Orange Pi 3.3V power pin to Vin
• Connect the Orange Pi GND pin to GND
• Connect the Pi SCLK pin to the MAX31855 CLK
• Connect the Pi MISO pin to to the MAX31855 DO
• Connect the Pi GPIO PA7 pin to to the MAX31855 CS
Double-check you have the right wires connected to the right location, it can be
tough to keep track of Pi pins as there are forty of them!
As of this writing, not all libraries are up on PyPI so you may want to search before
trying to install. Look for circuitpython and then the driver you want.
(If you don't see it you can open up a github issue on circuitpython to remind us ()!)
Check out the examples for your library by visiting the repository for the library and
looking in the example folder. In this case, it would be https://github.com/adafruit/
Adafruit_CircuitPython_MAX31855/tree/master/examples ()
As of this writing there's only one example. But that's cool, here it is:
import time
import board
import digitalio
import adafruit_max31855
spi = board.SPI()
cs = digitalio.DigitalInOut(board.D5)
Save this code to your Pi by copying and pasting it into a text file, downloading it
directly from the Pi, etc.
cs = digitalio.DigitalInOut(board.D5)
to
python3 max31855_simpletest.py
The code will loop with the sensor data until you quit with a Control-C
Make sure you have a K-type thermocouple installed into the sensor breakout or
you will get an error like the one below!
That's it! Now if you want to read the documentation on the library, what each function
does in depth, visit our readthedocs documentation at
https://circuitpython.readthedocs.io/projects/max31855/en/latest/ ()
UART / Serial
After I2C and SPI, the third most popular "bus" protocol used is serial (also sometimes
referred to as 'UART'). This is a non-shared two-wire protocol with an RX line, a TX
line and a fixed baudrate. The most common devices that use UART are GPS units,
MIDI interfaces, fingerprint sensors, thermal printers, and a scattering of sensors.
One thing you'll notice fast is that most linux computers have minimal UARTs, often
only 1 hardware port. And that hardware port may be shared with a console.
We'll demonstrate wiring up & using an Ultimate GPS with both methods
Here are some options, they have varying chipsets and physical designs but all will do
the job. We'll list them in order of recommendation.
The first cable is easy to use and even has little plugs that you can arrange however
you like, it contains a CP2102
Both the FTDI friend and cable use classic FTDI chips, these are more expensive than
the CP2104 or PL2303 but sometimes people like them!
Once the USB adapter is plugged in, you'll need to figure out what the serial port
name is. You can figure it out by unplugging-replugging in the USB and then typing
dmesg | tail -10 (or just dmesg ) and looking for text like this:
At the bottom, you'll see the 'name' of the attached device, in this case its ttyUSB0 ,
that means our serial port device is available at /dev/ttyUSB0
There's no Orange Pi Fritzing object, but the Raspberry Pi has the same pinout so
we're using that instead
As of this writing, not all libraries are up on PyPI so you may want to search before
trying to install. Look for circuitpython and then the driver you want.
(If you don't see it you can open up a github issue on circuitpython to remind us ()!)
You'll notice we also installed a dependancy called pyserial. This is a great thing
about pip, if you have other required libraries they'll get installed too!
Check out the examples for your library by visiting the repository for the library and
looking in the example folder. In this case, it would be https://github.com/adafruit/
Adafruit_CircuitPython_GPS/tree/master/examples ()
import adafruit_gps
# Create a serial connection for the GPS connection using default speed and
# a slightly higher timeout (GPS modules typically update once a second).
# These are the defaults you should use for the GPS FeatherWing.
# For other boards set RX = GPS module TX, and TX = GPS module RX pins.
uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=10)
# If using I2C, we'll create an I2C interface to talk to using default pins
# i2c = board.I2C() # uses board.SCL and board.SDA
# i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a
microcontroller
# Initialize the GPS module by changing what data it sends and at what rate.
# These are NMEA extensions for PMTK_314_SET_NMEA_OUTPUT and
# PMTK_220_SET_NMEA_UPDATERATE but you can send anything from here to adjust
# the GPS module behavior:
# https://cdn-shop.adafruit.com/datasheets/PMTK_A11.pdf
# Turn on the basic GGA and RMC info (what you typically want)
gps.send_command(b"PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0")
# Turn on just minimum info (RMC only, location):
# gps.send_command(b'PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
# Turn off everything:
# gps.send_command(b'PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
# Tuen on everything (not all of it is parsed!)
# gps.send_command(b'PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0')
We'll need to configure this code to work with our UART port name.
Comment out the lines that reference board.TX , board.RX and busio.uart and
uncomment the lines that import serial and define the serial device, like so:
# Define RX and TX pins for the board's serial port connected to the GPS.
# These are the defaults you should use for the GPS FeatherWing.
# For other boards set RX = GPS module TX, and TX = GPS module RX pins.
#RX = board.RX
#TX = board.TX
# Create a serial connection for the GPS connection using default speed and
# a slightly higher timeout (GPS modules typically update once a second).
#uart = busio.UART(TX, RX, baudrate=9600, timeout=3000)
And update the "/dev/ttyUSB0" device name if necessary to match your USB
interface
Whichever method you use, you should see output like this, with $GP "NMEA
sentences" - there probably wont be actual location data because you haven't gotten
More To Come!
That's just a taste of what we've got working so far
We're adding more support constantly, so please hold tight and visit the
adafruit_blinka github repo () to share your feedback and perhaps even submit some
improvements!
If you'd like to contribute, but aren't sure where to start, check out the following
guides:
This FAQ covers all the various platforms and hardware setups you can run Blinka on.
Therefore, some of the information may not apply to your specific setup.
Most issues can be solved by forcing Python to upgrade to the latest blinka /
platform-detect libraries. Try running
DO NOT try to fix this by manually installing a library named board . There is one
out there () and it has nothing to do with Blinka. You will break things if you install
that library!
95% of SPI devices are mode 0, check the driver to see mode or polarity settings.
For example:
$ python3
Python 3.6.8 (default, Oct 7 2019, 12:59:55)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more
information.
>>> import spidev
>>> spidev.__version__
If you see a version lower then 3.4 reported, then try a force upgrade of spidev
with (back at command line):
return self._hid.read(64)
File "hid.pyx", line 122, in hid.device.read
OSError: read error
Windows:
set BLINKA_MCP2221_RESET_DELAY=0.5
Linux:
export BLINKA_MCP2221_RESET_DELAY=0.5
This is a value in seconds to wait between resetting the MCP2221 and the attempt
to reopen it. The reset is seen by the operating system as a hardware disconnect/
reconnect. Different operating systems can need different amounts of time to wait
after the reconnect before the attempt to reopen. Setting the above environment
https://forums.adafruit.com/viewtopic.php?f=19&t=166999 ()
https://github.com/pyusb/pyusb/issues/120 ()
which describes copying the 32bit and 64bit DLLs into specific folders. (example
for Win7 ())
We aim to have, at a minimum, digitalio and busio (I2C/SPI). This lets you use
the vast number of driver libraries
For analog inputs, the MCP3xxx library () will give you AnalogIn objects. For PWM
outputs, try the PCA9685 (). For audio, use pygame or other Python3 libraries to
play audio.