This guide is no longer up to date - please check out https://learn.adafruit.com/welcome-to-circuitpython for the introduction guide to CircuitPython on ATSAMD21 boards (and more!)
Be aware as of 11/2016 the master branch of Adafruit's MicroPython GitHub repository has a new API which is not directly compatible with other MicroPython libraries. The following info is just for reference of the older 1.8.5 release of Adafruit SAMD21 MicroPython firmware. See the new API docs here: https://circuitpython.readthedocs.io/en/latest/

This quick start guide acts as both examples and a reference for what modules are currently implemented in the SAMD21 MicroPython port.  You can also find in-progress reference documentation for the SAMD21 MicroPython port here.

As of the time of this guide writing the current version of the SAMD21 MicroPython port is: v1.8.4-20161014

Contents:

Machine Module

The SAMD21 MicroPython port currently supports the following machine module features described below.  

Note there are some small differences in how the machine module support is implemented compared to other boards.  As the SAMD21 MicroPython firmware stabilizes and the machine module specification evolves these differences will hopefully grow smaller, but be aware you might need to slightly modify MicroPython code from other boards to run on the SAMD21 MicroPython port.

Digital I/O

You can use the machine.Pin class to perform digital I/O like reading buttons and blinking LEDs. See the MicroPython Digital I/O guide for more details on usage.

For the SAMD21 MicroPython port pins are identified by a string, like 'D6' for digital pin 6 on the board.  

For a Feather M0 the full list of pin names are:

  • A0 - analog input 0
  • A1 - analog input 1
  • A2 - analog input 2
  • A3 - analog input 3
  • A4 - analog input 4
  • A5 - analog input 5
  • SCK - SPI serial clock
  • MOSI - SPI serial main output, secondary input
  • MISO - SPI serial main input, secondary output
  • 0RX - digital pin 0 / UART receive (note UART isn't supported yet)
  • 1TX - digital pin 1 / UART transmit (note UART isn't supported yet)
  • SDA - I2C data line
  • SCL - I2C clock line
  • D5 - digital pin 5
  • D6 - digital pin 6
  • D9 - digital pin 9
  • D10 - digital pin 10
  • D11 - digital pin 11
  • D12 - digital pin 12
  • D13 - digital pin 13

For an Arduino Zero the full list of pin names are:

  • A0 - analog input 0
  • A1 - analog input 1
  • A2 - analog input 2
  • A3 - analog input 3
  • A4 - analog input 4
  • A5 - analog input 5
  • 0RX - digital pin 0 / UART receive (note UART isn't supported yet)
  • 1TX - digital pin 1 / UART transmit (note UART isn't supported yet)
  • D2 - digital pin 2 (note on the Arduino M0 Pro this is swapped with digital pin 4!)
  • D3 - digital pin 3
  • D4 - digital pin 4 (note on the Arduino M0 Pro this is swapped with digital pin 2!)
  • D5 - digital pin 5
  • D6 - digital pin 6
  • D7 - digital pin 7
  • D8 - digital pin 8
  • D9 - digital pin 9
  • D10 - digital pin 10
  • D11 - digital pin 11
  • D12 - digital pin 12
  • D13 - digital pin 13
  • SDA - I2C data line
  • SCL - I2C clock line

For example to blink a LED on pin #13 (the built-in LED for most boards) you could run the following code:

import machine
import time

led = machine.Pin('D13', machine.Pin.OUT)
while True:
    led.high()
    time.sleep(0.5)
    led.low()
    time.sleep(0.5)

Or to read a momentary push button connected to pin #6 and ground (using an internal pull-up resistor) you could run the following code:

import machine

button = machine.Pin('D6', machine.Pin.IN, machine.Pin.PULL_UP)
while True:
    if not button:
        print('Button pressed!')

Analog I/O

You can use analog inputs, PWM, and even a DAC output just like with using analog I/O on other MicroPython boards!  Remember the pin names are strings for the SAMD21 MicroPython port--see the digital I/O section above for all the pin names.

Analog to Digital Converter (ADC)

The SAMD21 includes a 12-bit ADC which can read up to 6 channels (labeled as A0-A5 on boards).  For example to read analog input 0 you could run the following code:

import machine

a0 = machine.ADC(machine.Pin('A0'))
value = a0.read()
print('Analog input 0 reads a value of: {0}'.format(value))

Note that the ADC class needs to take in a machine.Pin instance and not just a string pin name!

Since the ADC has a 12-bit resolution you'll see values between 0 and 4095.  A value of 0 means there's 0 volts on the analog input, and a value of 4095 means there's 3.3v or more on the input (be careful not to exceed 3.3v!).  An inbetween value like 2047 means there's about half of 3.3v, or 1.6v, on the analog input.

Pulse-Width Modulation (PWM)

To use a PWM output to fade up pin #13 (most board's built in LED) you could run the following code:

import machine
import time

led_pwm = machine.PWM(machine.Pin('D13'))
while True:
    for i in range(256):
        led_pwm.duty(i)
        time.sleep(0.01)

Note that PWM outputs currently have a fixed frequency of around 730 hz.  In the future configurable frequencies will be allowed (check this bug) but for now the frequency is fixed.

Duty cycle can be configured to any 8-bit value from 0 (completely off) to 255 (completely on).  A value of 127 for example would be a 50% duty cycle, or half lit LED if controlling the brightness of a LED.

Digital to Analog Converter

The SAMD21 includes a single channel 10-bit DAC (digital to analog converter) that can be used to produce a voltage between 0-3.3v (depending on the board's analog reference, most are 3.3V).  An example of the DAC usage to alternate between 0v, 1.6v (half of 3.3v), and 3.3v is:

import machine
import time

dac = machine.DAC()
while True:
    dac.write(0)    # 0 volts output on A0
    time.sleep(1.0)
    dac.write(512)  # 1.6 volts output on A0
    time.sleep(1.0)
    dac.write(1023) # 3.3 volts output on A0
    time.sleep(1.0)

For the SAMD21's DAC it can only output voltage on the A0 pin.  No other pin can be used to receive the DAC output.

The DAC write function takes a 10-bit value, i.e. one between 0 and 1023.  A value of 0 means 0v is output on the A0 pin, and 1023 means the maximum analog reference voltage (3.3v) is output on A0.  A value inbetween produce a proportional voltage, like 512 will output about half of 3.3v (1.6v).

There's also a handy write_mv function on the DAC object which allows you to specify a voltage in millivolts between 0 and 3300 (3.3v).  For example to set the DAC output to 2.5 volts you could run:

import machine

dac = machine.DAC()
dac.write_mv(2500)

I2C Devices

Communication with I2C devices is supported using a similar interface as I2C on other MicroPython boards. However one important difference is that you must either call an init function before using I2C and a deinit function after using it, or use a context manager.

First an example of reading the MAX9808 I2C temperature sensor with init & deinit:

import machine

# Function to convert temperature register to degrees celsius.
def temp_c(data):
    value = data[0] << 8 | data[1]
    temp = (value & 0xFFF) / 16.0
    if value & 0x1000:
        temp -= 256.0
    return temp

i2c = machine.I2C(machine.Pin('SCL'), machine.Pin('SDA'))
i2c.init()  # Initialize I2C interface.

print('Found I2C devices: {0}'.format(i2c.scan()))

address = 24
temp_reg = 5
data = i2c.readfrom_mem(address, temp_reg, 2)
print('Temperature: {0}C'.format(temp_c(data)))

i2c.deinit()  # Be sure to call deinit when done.

And the same example using the with statement and a context manager which guarantees the init & deinit functions are called appropriately:

import machine

# Function to convert temperature register to degress celsius.
def temp_c(data):
    value = data[0] << 8 | data[1]
    temp = (value & 0xFFF) / 16.0
    if value & 0x1000:
        temp -= 256.0
    return temp

# With statement uses I2C interface as context manager for automatic init/deinit.
with machine.I2C(machine.Pin('SCL'), machine.Pin('SDA')) as i2c:
    print('Found I2C devices: {0}'.format(i2c.scan()))
    
    address = 24
    temp_reg = 5
    data = i2c.readfrom_mem(address, temp_reg, 2)
    print('Temperature: {0}C'.format(temp_c(data)))

The choice of init/deinit vs. context manager comes down to how you'd like to structure your code.  For simplicity init & deinit are a good first choice, but if you need to guarantee the I2C interface is cleanly deinitialized (like on board soft reset) use a context manager.

Also note only the SCL and SDA pins as shown above can be used for the clock and data lines respectively.  The SAMD21 MicroPython port uses a hardware I2C interface which is fixed to those pins.  Also be aware you cannot take low level control of the I2C bus and send explicit start/stop bits or create custom transactions.  This means some libraries like the SSD1306 OLED display won't work until they are updated to work with hardware I2C interfaces.

Other I2C interface functions are supported too as shown in the MicroPython I2C guide:

  • readfrom_mem(address, register, number of bytes)
  • readfrom_mem_into(address, register, buffer)
  • writeto_mem(address, register, byte string)
  • readfrom(address, number of bytes)
  • readfrom_into(address, buffer)
  • writeto(address, byte string)

SPI Devices

SPI support is currently in-progress.  Check back with future releases to see when SPI is available!

NeoPixel Module

Basic RGB NeoPixel support is available in the neopixel module, just like with the ESP8266 MicroPython port.  For example to use a string of 4 NeoPixels connected to pin D6 of a Feather M0:

import machine
import neopixel

# Create NeoPixel signal pin (connected to D6).
pixel_pin = machine.Pin('D6', machine.Pin.OUT)

# Create a strip of 4 pixels.
pixels = neopixel.NeoPixel(pixel_pin, 4)

# Clear all the pixels to black/off.
pixels.fill((0,0,0))

# Use write to light up the pixels with the previously set colors.
pixels.write()

# Set the first four pixels to red, green, blue, white:
pixels[0] = (255, 0, 0)
pixels[1] = (0, 255, 0)
pixels[2] = (0, 0, 255)
pixels[3] = (255, 255, 255)

# Again call write to light up the pixels.
pixels.write()

OS Module

The OS module provides core 'operating system' style functions for MicroPython, particularly to access the file system on the board.  The SAMD21 MicroPython port currently implements the following OS module functions:

  • uname
  • chdir
  • getcwd
  • listdir
  • mkdir
  • remove
  • rename
  • rmdir
  • stat
  • statvfs
  • unlink
  • sync
  • sep
  • mount
  • umount
  • mkfs

See the pyboard OS module documentation for details on the OS module function usage as the functions are the same across boards.  

Note that the random number generation function urandom is not currently supported.

Time Module

The SAMD21 MicroPython port time module currently implements the following basic sleep/delay and millisecond tick functions:

  • sleep
  • sleep_ms
  • sleep_us
  • ticks_ms
  • ticks_diff

See the pyboard time module documentation for details on the time module function usage.

This guide was first published on Oct 17, 2016. It was last updated on Sep 23, 2016.

This page (Quick Start Guide) was last updated on Oct 13, 2016.

Text editor powered by tinymce.