Moteino M0

The MoteinoM0 (release notes) is a SAMD21 Cortex M0+ based Moteino featuring these general specifications:

  • ATSAMD21G18A microcontroller (48pin LQFP) running at 48Mhz, 3.3V core
  • Input voltage: 3.6-6V
  • Digital pins: 23 (11 PWM)
  • Analog ADC pins: 6 (12bit)
  • Analog DAC pins: 1 (10bit)
  • Flash Program memory: 256KB (8KB used by bootloader)
  • SRAM: 32KB
  • Transceivers: RFM69HCW, RFM95, RFM96
  • Low power: ~8uA in standby mode (FLASH and transceiver in deep sleep)

Memory & Bootloader

The MoteinoM0 runs the standard Arduino Zero bootloader – enhanced to allow flashing the memory from the external FLASH-MEM memory. This is similar/compatible with Dualoptiboot for AVR Moteinos and OTA/Wireless programming. The booloader is located in the first 8KB of internal flash memory and is protected by the NVM user byte fuse.

There is no dedicated EEPROM on the SAMD21 microcontroller but EEPROM can be emulated up to 16kb and the Arduino EEPROM library can be used to access this emulated EEPROM.

The M0 bootloader is available here for download if you wish to reinstall in on a M0 board using a SWD programmer (ex. Atmel ICE).

Pin reference


Input voltage – VIN

Please note that on the first batch of PCBs, there is an error on the silkscreen next to the VIN pin, the input voltage when the MoteinoM0 is powered from the VIN pin, should be 3-6V (the limiting factor is the MCP73831 charger which can take no more than 6V). This error will be corrected in a future revision of the PCB, and current boards will ship with a small marking to cover the “1” in 3-16V:

Example reading the VIN

The sketch below illustrates how to read the input voltage (USB or battery). The MoteinoM0 has a simple voltage monitor connected to A5 throug a half (50%) voltage divider (see schematic). When the reading is around 1 schottky diode below 5V it means USB is connected. When the battery is connected in addition to USB, the reading is typically around 4.2V. When only the battery is connected, then A5 will read the actual battery voltage. Below is a sample of code to correctly read the voltage monitor through pin A5:

#if defined (MOTEINO_M0) && defined(SERIAL_PORT_USBVIRTUAL)
  #define Serial SERIAL_PORT_USBVIRTUAL // Required for Serial on Zero based boards

// the setup function runs once when you press reset or power the board
void setup() {
  pinMode(A5, INPUT);

// the loop function runs over and over again forever
void loop() {
  float vin = analogRead (A5) * 2 * 0.003226; // 0.003226 = 3.3 / 1023
  delay(1000);                       // wait for a second

Solder Jumpers

There are 4 solder jumpers on the bottom of MoteinoM0. You can see each one in the schematic. Here’s a short explanation of each jumper’s function and (default state):

  • LED_EN (shorted): cut this open and the onboard LED is disconnected – a measn to save a little extra power, or use pin D13 for other purposes
  • DIODE_BYPASS (open): solder this jumper and you will short the Schottky diode that blocks current to flow back into the USB connector. This is experimental and should be left open.
  • VMON_EN A & B (both shorted): these two jumpers allow you to disconnect the onboard battery monitoring voltage divider circuit. Both should be the same state – either open or shorted. If you open them, then pin A5 will be available for other purposes.

Hardware / Driver install

To use MoteinoM0 with ArduinoIDE you will need to install the latest Arduino SAMD Boards package and then also the Moteino SAMD Boards package by LowPowerLab.

First add the Moteino core json definition URL to your Board Manager.

Then in Board Manager you will see AVR and SAMD boards by LowPowerLab.

If you’re on MAC or Linux you should not need any drivers. Also Windows 10 will probably detect the board as a virtual serial port and assign it a COM port by default without the need of installing a driver. Older Windows versions are likely going to fail to install a driver when MoteinoM0 is first plugged in. Click below to get the USB driver and unzip it to your Desktop or another folder. The ZIP file contains a screenshot walkthrough of how to install the driver.

Using with the ArduinoIDE

It’s important to understand how the board operates and how to enter the bootloader to ensure you can program it regardless what state the board is in. The bootloader behaves identically to the Arduino Zero samba bootloader, so if you’re familiar with that board, you should be all set.

If you load a low power sketch, or turn off the USB-Device (serial port) in your sketch, or even using certain sketches will cause the board to appear unresponsive to an Upload command while it’s in sleep mode or if it’s caught up doing other things. In such cases an Upload will fail from the IDE, and it’s necessary to do a fast double-tap on the RST button to put the board in bootloader mode. In some even more precarious situations where the board does to sleep immediately after boot, you might need to first do a single tap, then shortly after do the double-tap. You know you have entered the bootloader when the onboard LED is in a breathing pattern and a new serial port appears. Once there, select the new serial port, and try an Upload. There will be a delay until the board receives the sketch, or if you’re in a hurry you can jump start the upload by doing another double-tap. It’s only confusing until you manage to do this a few times!

Example deep sleep sketch

The sketch below illustrates how to put the MoteinoM0 to standby sleep (lowest power sleep), and optionally wake it from an external interrupt (active low on digital pin 0). It also puts the FLASH-MEM and transceiver (if any) to sleep.

//Standby sleep example for MoteinoM0 with external interrupt wakeup
//expected current in standby sleep: 7.5uA
const int pin = 0; //pin to use as interrupt (can be any digital pin)

//#define WITHRFM69  //comment this out if you don't have a radio installed on your MoteinoM0

#ifdef WITHRFM69
  #include <RFM69.h>    //get it here:
  #define NODEID        2   //must be unique for each node on same network (range up to 254, 255 is used for broadcast)
  #define NETWORKID     100  //the same on all nodes that talk to each other (range up to 255)
  #define GATEWAYID     1
  #define FREQUENCY     RF69_915MHZ
  #define IS_RFM69HW    //uncomment only for RFM69HW! Leave out if you have RFM69W!
  RFM69 radio;

#include <SPIFlash.h> //get it here:
SPIFlash flash(SS_FLASHMEM, 0xEF30); //EF30 for 4mbit  Windbond chip (W25X40CL)

//replace Serial with SerialUSB
#if defined (MOTEINO_M0)
    #define Serial SERIAL_PORT_USBVIRTUAL // Required for Serial on Zero based boards

void setup()
  pinMode(0, INPUT_PULLUP); //using internal pullup, makes pin 0 active low

  //Uses internal pullup eliminates the need for external resistor and makes interupt pin active low
  //If you need active high, then attach to HIGH and declare pin as INPUT without PULLUP, then use external resistor from GND to pin to keep it from floating
  attachInterrupt(pin, wakeupISR, LOW); //note: RISING and FALLING do not seem to work, use LOW or HIGH instead

  if (flash.initialize())
    Serial.println("flash.init() OK, sleeping it...");
  else Serial.println("flash.init() FAIL");

#ifdef WITHRFM69
  if (!radio.initialize(FREQUENCY,NODEID,NETWORKID))
    Serial.println("radio.init() FAIL");
    Serial.println("radio.init() SUCCESS");
  #ifdef IS_RFM69HW
    radio.setHighPower(); //uncomment only for RFM69HW!

  for (byte count=0; count < 3; count++)
  Serial.println("Entering standby sleep mode...");

void loop() 

  //interrupt happened: WAKE UP and blink the LED!

void blink(int ms) {
  digitalWrite(LED_BUILTIN, HIGH);
  digitalWrite(LED_BUILTIN, LOW);

byte toggle=true;
void wakeupISR(void)
  //nothing here, just a placeholder

void standbySleep() {
  //Disable USB (optional)

  //Standby - lowest power sleep mode
  __WFI(); // Wait For Interrupt call

  //Sleep until woken by interrupt...

  //Enable USB

Example periodic sleep using RTCZero library

The sketch below illustrates how to put the MoteinoM0 to sleep and wake it up periodically using the RTC (Real Time Clock timer). On a bare MoteinoM0 this sketch should achieve ~8.7uA while sleeping.

#include <RTCZero.h>

RTCZero zerortc;

// Set how often alarm goes off here
const byte alarmSeconds = 3;
const byte alarmMinutes = 0;
const byte alarmHours = 0;

volatile bool alarmFlag = false; // Start awake

#if defined (MOTEINO_M0)
    #define Serial SERIAL_PORT_USBVIRTUAL // Required for Serial on Zero based boards

void setup()
  delay(1000); // Wait for console
  digitalWrite(LED_BUILTIN, LOW);

  zerortc.begin(); // Set up clocks and such
  resetAlarm();  // Set alarm
  zerortc.attachInterrupt(alarmMatch); // Set up a handler for the alarm

void loop()
  if (alarmFlag == true) {
    alarmFlag = false;  // Clear flag
    digitalWrite(LED_BUILTIN, HIGH);
    Serial.println("Alarm went off - I'm awake!");
  resetAlarm();  // Reset alarm before returning to sleep
  Serial.println("Alarm set, going to sleep now.");
  digitalWrite(LED_BUILTIN, LOW);
  zerortc.standbyMode();    // Sleep until next alarm match

void alarmMatch(void)
  alarmFlag = true; // Set flag

void resetAlarm(void) {
  byte seconds = 0;
  byte minutes = 0;
  byte hours = 0;
  byte day = 1;
  byte month = 1;
  byte year = 1;
  zerortc.setTime(hours, minutes, seconds);
  zerortc.setDate(day, month, year);

  zerortc.setAlarmTime(alarmHours, alarmMinutes, alarmSeconds);

USB Device

MoteinoM0 can act like any USB device. It can emulate a keyboard or a joystick, a mouse or even a USB stick. You could prank a friend and plug a MoteinoM0 into their PC that simulates a keyboard, and remotely have another MoteinoM0 that hosts a real keyboard on which you can type (in that case it would act as a USB-Device, see below) and remotely type keys on your friend’s computer through the radio link, that would make quite a prank!

Check out the standard Arduino examples which provide samples to make the MoteinoM0 be a keyboard, mouse, or a combination of these:

USB Host

MoteinoM0 can also act like any USB-Host. It can host another USB-device on its USB-micro connector, via a USB-OTG adapter. Since USB devices require 5V, powering both the M0 and the attached USB-device from a LiPo battery (4v) is not enough, hence it is required to provide a stable 5V on the VUSB pin. The photo below illustrates how this wiring is achieved. The Keyboard could be replaced with any other USB device:

Here is a sample sketch that reads the inputs from the attached keyboard, and outputs them to the Serial port (pins 30,31):

 Keyboard Controller Example

 Shows the output of a USB Keyboard connected to
 the USB-micro port (through USB-OTG adapter) on a MoteinoM0 board.
 See for wiring
 Output is provided on the SERIAL_PORT_MONITOR, ie Serial port on pins 30,31

 created 8 Oct 2012 by Cristian Maglie
 adapted for MoteinoM0 by Felix Rusu (

 This sample code is part of the public domain.

// Require keyboard control library
#include <KeyboardController.h>

// Initialize USB Controller
USBHost usb;

// Attach keyboard controller to USB
KeyboardController keyboard(usb);

void printKey();

// This function intercepts key press
void keyPressed() {
  SERIAL_PORT_MONITOR.print("Pressed:  ");

// This function intercepts key release
void keyReleased() {
  SERIAL_PORT_MONITOR.print("Released: ");

void printKey() {
  digitalWrite(LED, HIGH); delay(10);
  // getOemKey() returns the OEM-code associated with the key
  SERIAL_PORT_MONITOR.print(" key:");

  // getModifiers() returns a bits field with the modifiers-keys
  int mod = keyboard.getModifiers();
  SERIAL_PORT_MONITOR.print(" mod:");

  SERIAL_PORT_MONITOR.print(" => ");

  if (mod & LeftCtrl)
    SERIAL_PORT_MONITOR.print("L-Ctrl ");
  if (mod & LeftShift)
    SERIAL_PORT_MONITOR.print("L-Shift ");
  if (mod & Alt)
    SERIAL_PORT_MONITOR.print("Alt ");
  if (mod & LeftCmd)
    SERIAL_PORT_MONITOR.print("L-Cmd ");
  if (mod & RightCtrl)
    SERIAL_PORT_MONITOR.print("R-Ctrl ");
  if (mod & RightShift)
    SERIAL_PORT_MONITOR.print("R-Shift ");
  if (mod & AltGr)
    SERIAL_PORT_MONITOR.print("AltGr ");
  if (mod & RightCmd)
    SERIAL_PORT_MONITOR.print("R-Cmd ");

  // getKey() returns the ASCII translation of OEM key
  // combined with modifiers.
  digitalWrite(LED, LOW);

void setup()
  SERIAL_PORT_MONITOR.begin( 115200 );
  while (!SERIAL_PORT_MONITOR); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
  SERIAL_PORT_MONITOR.println("Keyboard Controller Program started");

  if (usb.Init() == -1)
	  SERIAL_PORT_MONITOR.println("OSC did not start.");
  delay( 20 );

void loop()
  // Process USB tasks

Eagle library components

You can now use the Moteino Eagle library (Moteino.lbr) and drop-in Moteino layouts including MoteinoM0, straight into your design. Import the Moteino.lbr library in Eagle and add the recommended routing to accomodate the radio module mounted on the MoteinoM0 bottom (if any). This way you can flush-mount MoteinoM0 directly on your PCB, here is an example: