Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
25
Help us understand the problem. What is going on with this article?
@nanase

コインサイズ Arduino互換機 Seeeduino XIAO を使ってみた

title.jpg

Seeeduino XIAO の実機を入手したのでスペックや特徴を紹介していきます。

各店商品ページ: 秋月電子 / はんだ付け済みの完成品 / SwitchScience / Amazon (3個セット)

特徴

  • ARM Cortex M0+ CPU (SAMD21G18) 48MHz 搭載
  • 256 KB フラッシュ、32 KB SRAM
  • USB Type-C
  • SPI, I2C, UART, DMA が利用可
  • 20mm x 17.5mm とコインサイズ
  • ロジックレベルは 3.3V

基板背面には突起物がなく、さらにすべてのピンが 端面スルーホール加工 となっており別の基板上へのはんだ付けが容易になっています。

内容物: 太ピンヘッダとシールが付属 側面と背面

スペック

公式Wiki から抜粋・補足

諸元
CPU ARM Cortex-M0+ 32 bit (SAMD21G18)
動作周波数 最大 48 MHz (32.768 kHz から逓倍)
ストレージ Flash 256KB、SRAM 32 KB
ピン GPIO 14 ピン、デジタル入出力 11 ピン、アナログ入力 11 ピン、DAC出力 1 ピン
ピン機能 SPI、I2C、UART、PWM、外部割り込み、SWD(背面パッド)
ロジックレベル 3.3V
内蔵LED プログラム可能 1 個、電源 1 個、シリアルポート 2 個
電源 USB Type-C から 5V (スケッチ書き込みと端子共用)、背面 VIN パッド 5V
サイズ 長辺 20 mm、短辺 17.5 mm、高さ 3.5 mm

いわゆる SAMD系 Arduino です。

Arduino MKR シリーズと同じ系列となり、それら向けに書かれたライブラリであれば使用できます。一方 Arduino Uno のような ATmega系 Arduino とは別物で、ATmega の特定レジスタに依存しているライブラリは使用できません。

GPIO 14 ピンは側面の 11 ピンと、リセットピン、背面の SWD (SWCLK, SWDIO) の合計 14 ピンを指しています。
背面パッドの使用に関しては こちら をご参照ください。

ピン機能にある UART は USB 経由のシリアルとは別物で、Serial1 で操作が可能なものです。

スケッチ書き込みとリセット

こちら を参考に Arduino IDE へボードを追加してください。

Seeeduino XIAO はリセットボタンがありません。代わりに リセットパッド が存在します。
リセット時はこのリセットパッドを短絡させて GND を印加してください。

bootloaderモード

動作中にハングアップしたり、スケッチを書き込めなくなったときは素早く2回リセットをかけると bootloader モード に入ります。
このモードでは LED がゆっくりと点滅し、Seeeduino XIAO が USB メモリデバイスと認識され通常モードとはシリアルポートが別になり、ボードに書き込まれているプログラムを起動せずに常時スケッチの書き込みモードになります。

bootloader モードから通常のモードに復帰させるにはスケッチを書き込むか、再度素早く2回リセットをかけてください。

PC から Seeeduino XIAO が USB デバイスとして認識されていない状態で bootloader モードに入ると、LED が速く点滅します。

Lチカ

本家の Arduino と同じようにサンプルスケッチから Basics > Blink を選んで Upload してください。

blink.ino
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(1000);
  digitalWrite(LED_BUILTIN, LOW);
  delay(1000);
}

本家 Arduino とは逆に LOW で点灯、HIGH で消灯 になっています。

他にも2つ点滅可能な内蔵LEDがある

ところで、公式サイトにはその他 2 つの内蔵 LED について two LEDs for serial port downloading と記載しています。ところが回路図を見るとこれらの RX, TX の LED と繋がっている物理ピンがまったく存在しません。

ここで USBCore.cpp を見ると、SerialUSB の送受信が発生する度に digitalWrite で点灯させていることがわかります。つまりこの 2 つの LED は自由に操作できます。

USBCore.cpp(抜粋)
uint32_t USBDeviceClass::recv(uint32_t ep, void *_data, uint32_t len)
{
    if (!_usbConfiguration)
        return -1;

#ifdef PIN_LED_RXL
    if (rxLEDPulse == 0)
        digitalWrite(PIN_LED_RXL, LOW);

    rxLEDPulse = TX_RX_LED_PULSE_MS;
#endif

具体的なピン番号は SAMD 系 Arduino と同様に variant.h/variant.cpp に記述されており、Seeeduino XIAO の場合、以下のように 11, 12 に割り当てられています。

variant.h
#define PIN_LED_13  (13u)
#define PIN_LED     PIN_LED_13
#define LED_BUILTIN PIN_LED

#define PIN_LED_RXL          (12u)
#define PIN_LED_TXL          (11u)
#define PIN_LED2             PIN_LED_RXL
#define PIN_LED3             PIN_LED_TXL

以下に 3 つの LED を点滅させるスケッチを示します。RX, TX 用のLEDは青色のようです。

blink3.ino
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(PIN_LED2, OUTPUT);
  pinMode(PIN_LED3, OUTPUT);
}

void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  digitalWrite(PIN_LED2, HIGH);
  digitalWrite(PIN_LED3, HIGH);
  delay(1000);
  digitalWrite(LED_BUILTIN, LOW);
  digitalWrite(PIN_LED2, LOW);
  digitalWrite(PIN_LED3, LOW);
  delay(1000);
}

インタフェース

Serial over USB CDC

Arduino MKR シリーズでも同様ですが ATmega系Arduino とは違い、シリアル通信の実態は USB CDC です。つまり通常のシリアル通信よりも高速にシリアル通信ができます。

したがって Serial.begin(speed) によるボーレートの指定は意味をなしませんが、それ以外は従来通りの Serial として使えます。

速度の計測

Seeeduino XIAO to PC (Serial over USB CDC)

今回は こちら のスケッチを使って、Seeeduino XIAO から PC への転送速度を測定しました。片方向のみですが PC からの転送速度も同じになるはずです。

横軸はバッファサイズで Serial.write(buf, len) で一度に送るサイズです。
1 バイトずつ送った場合は 0.11 Mbps (14.53 KB/s) しか速度が出ませんが、64 バイトずつだと 6.30 Mbps (805.86 KB/s) とかなり速くなります。64 バイトの整数倍に速度の飛びがあるのがわかるように、内部バッファのサイズが 64 バイトであると推測できます。

前述の通りシリアル通信では LED の点滅が行われますが、これによる速度の低下はほとんどありませんでした。

SPI (microSDカード)

Seeeduino XIAO のロジックレベルは 3.3V です。つまりレベルシフタなしに SPI を介して microSD カードが扱えます。
SPI については ATmega系 Arduino とは一部異なる挙動がありますので、注意点などは こちら をご確認ください。

今回は秋月電子の マイクロSDカードスロットDIP化キット を使用して microSD カードを読みます。

スケッチは Arduino のサンプルコードそのままですが、SD.begin(cs_pin) の引数には SS を指定しておきます。variant.h によると SS = 4 となっており、これは D4/A4/SDA のピンと同じです。もちろんこれ以外のピンも指定できます。

microsd_photo.jpg microsd_schematic.jpg
配線例 回路図
microsd.ino
#include <SPI.h>
#include <SD.h>

File myFile;

void setup() {
  Serial.begin(9600);
  while (!Serial) ;

  Serial.print("Initializing SD card... ");

  if (!SD.begin(SS)) { // <-------------------------------- SS = D4/A4/SDA pin
    Serial.println("initialization failed!");
    while (1) ;
  }
  Serial.println("initialization done.");

  myFile = SD.open("test.txt", FILE_WRITE);

  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("testing 1, 2, 3.");

    myFile.close();
    Serial.println("done.");
  }
  else
    Serial.println("error opening test.txt");

  myFile = SD.open("test.txt");
  if (myFile) {
    Serial.println("test.txt:");

    while (myFile.available())
      Serial.write(myFile.read());

    myFile.close();
  }
  else
    Serial.println("error opening test.txt");
}

void loop() { }
microsd.inoの出力
Initializing SD card...initialization done.
Writing to test.txt...done.
test.txt:
testing 1, 2, 3.

I2C

I2C も使えます。3.3V 系デバイスはレベルシフタなしで直接接続できます。

今回は BME280 を使って温湿度と気圧を測定しました。BME280 は 3.3V で動作するため、レベルシフタなしで接続できます。Arduino と BME280 の接続については こちらの記事 にて詳しく解説します。

bme280_photo.jpg bme280_schematic.jpg
配線例 回路図
bme280.ino
#include <Wire.h>
#include "SparkFunBME280.h"

BME280 sensor;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  sensor.beginI2C(); // Wire を用いて I2C 接続開始
}

void loop() {
  Serial.print("Temp: ");
  Serial.print(sensor.readTempC(), 2);

  Serial.print(" °C, Humidity: ");
  Serial.print(sensor.readFloatHumidity(), 2);

  Serial.print(" %, Pressure: ");
  Serial.print(sensor.readFloatPressure() / 100.0, 1);
  Serial.println(" hPa");

  delay(5000);
}
bme280.inoの出力
Temp: 22.05 °C, Humidity: 44.99 %, Pressure: 1009.0 hPa
Temp: 22.05 °C, Humidity: 44.72 %, Pressure: 1008.9 hPa
Temp: 22.06 °C, Humidity: 44.81 %, Pressure: 1008.9 hPa

UART

前述したように、物理ピンで出ている UART ピンは USB CDC のものとは異なります。TX, RX ピンを使ったシリアル通信は Serial1 を使います。

今回は GPS受信機キット を接続して PC から NMEA 情報を取得します。Seeeduino XIAO で行うことは非常にシンプルで、GPS 受信機キットとシリアルの中継だけです。

gps_photo.jpg gps_schematic.jpg
配線例 回路図
gps.ino
void setup() {
  Serial.begin(9600);
  Serial1.begin(9600);
}

void loop() {
  if (Serial.available()) {
    char c = (char)Serial.read();
    Serial1.write(c);
  }

  if (Serial1.available()) {
    char c = (char)Serial1.read();
    Serial.write(c);
  }
}

今回は NMEA 情報の閲覧に GPSFox を使っています。画像の通り問題なく座標が測位できています。

発展

DMA

SAMD系 Arduino の特徴のひとつである DMA の使用が可能です。DMA についての詳細は こちらの記事 をご参照ください。

Single Cycle IOBUS

Cortex M0+ はクロックのワンサイクルで GPIO の出力を操作できる Single Cycle IOBUS という機能を持っています。特定のレジスタに書き込むと、論理の反転、ピンの無効化、ピンのドライブ電流を変更できます。

digitalWrite のとき

まずは愚直に digitalWrite を使ってパルスを作ります。どの Arduino でも使える方法です。loop 関数の呼び出しにかかるオーバヘッドをへらすため反復しています。

step1.ino
void setup() {
  pinMode(PIN_A7, OUTPUT);
}

#define P                     \
  digitalWrite(PIN_A7, HIGH); \
  digitalWrite(PIN_A7, LOW);

#define W P P P P P P P P P P P P P P P P
void loop() { W W W W W W W W W W W W W W W W }

レジスタを直接操作するとき

digitalWrite を使わずレジスタを直接操作してパルスを作ります。

step2.ino
void setup() {
  pinMode(PIN_A7, OUTPUT);
}

#define P                                                             \
  digitalPinToPort(PIN_A7)->OUTSET.reg = digitalPinToBitMask(PIN_A7); \
  digitalPinToPort(PIN_A7)->OUTCLR.reg = digitalPinToBitMask(PIN_A7);

#define W P P P P P P P P P P P P P P P P
void loop() { W W W W W W W W W W W W W W W W }

Single Cycle IOBUS を使うとき

本題の機能を使います。今回は ここ で紹介されている IOBUS.h を使います。ピン番号の指定が特殊です。

step3.ino
#include "IOBUS.h"

#define digitalPinToIOPin(P) ((g_APinDescription[P].ulPort << 5) + g_APinDescription[P].ulPin)
#define PIN_NUM digitalPinToIOPin(PIN_A7)

void setup() {
  IOBUS::pinMode(PIN_NUM, OUTPUT, true);
}

#define P IOBUS::toggleOutput(PIN_NUM);

#define W P P P P P P P P P P P P P P P P
void loop() { W W W W W W W W W W W W W W W W }

結果

digitalWrite レジスタ操作 Single Cycle IOBUS
波形 step1.png step2.png step3_2.png
周波数 333 kHz 6 MHz 24 MHz
1周期にかかるサイクル数 144 サイクル 8 サイクル 2 サイクル

サイクル数は LOW → HIGH → LOW の 1 周期で示したので、確かに 1 サイクル (48MHz) で論理が反転できています。

Tips

25
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
25
Help us understand the problem. What is going on with this article?