Arduino環境でXIAO RP2040を使う

it

SeeedStudioのXIAO RP2040を使います。
Arduino環境で開発できるRP2040搭載基板では最小クラスのサイズです。
基本的な入出力と、通信を試してみます。

XIAO RP2040

主なスペック

Arduino環境で使用できるXIAO SAMD21と同規格の基板。

CPURP2040 ARM Cortex M0+ 133MHz
接続Micro B
USB1.1 ホスト/デバイス両対応
MemorySRAM 264KB
フラッシュメモリ 2MB
ロジックレベル3.3V
GPIO11
PWM11 (8bit 0 ~ 255)
ADC4 (10bit 0 ~ 1023)
UART1
I2C2
SPI2
その他リセットボタン
LED 青(GPIO25) Lowで点灯
LED 赤(GPIO17) Lowで点灯
LED 緑(GPIO16) Lowで点灯
WS2812 (GPIO12, 使用するための電源 GPIO11)

ピン配置

外観

400穴ブレッドボードでは左右3列と2列ずつ使用することができます。

WS2812を使ってみました。
簡単な命令でカラフルに発色させることができます。
画像は黄色の最大輝度発光でかなりの明るいです。

下の画像はRGB LED(緑)を点灯させた状態です。(赤は電源LED)
論理が逆(LOWで点灯)ですが、GPIOの操作だけで手軽に使用できます。
WS2812と比べると優しい発色です。

使ってみて

Good

小さいのに必要なピン機能は十分搭載されている。
Groveを扱うための拡張基板とモジュールが豊富

Bad

ピン番号がシルク印刷されていないので、ピン配置が手元に必要。
使用するボードライブラリによりI2Cの実体が異なりややこしい。

そのほか

このボードの躓きポイントにボードライブラリの選択するボードの種類によってI2Cの振る舞いが変わるややこしさが悩ましい。

発売からメーカーからのライブラリの修正や名称そのものの変更も多く、落ち着かない印象のあるマイコン基板ですが、使い慣れてしまうとちょっとした実験はコレで済ませてしまうことが多くなります。

こちらのサイトではXIAO RP2040の詳しい説明がされているので参考にしてください。


RP2040搭載基板では最小クラスなので、ブレッドボードへの挿抜が楽です。
通信線はUART, I2C, SPIも使用でき、いくつかのI/Oも使用できるので、ちょっとした実験や治具に使用したり、簡単なガジェットやゲームでも十分開発できるます。

準備

基板の初期化とシリアル認識

基板の初期化とシリアル認識は以下の記事を参考にしてください。

ライブラリ

ボードライブラリ

Arduino IDEのボードマネージャからXIAO RP2040用のライブラリのインストールとボードの選択をします。
ボードライブラリには「Raspberry Pi Pico/RP2040 by Earle F. Philhower, III」を使用します。
選択する当サイトではGeneric RP2040を使用します。

追加のボードマネージャのURLhttps://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
検索RP2040
ボードライブラリRaspberry Pi RP2040 Boards(x.x.x)※
選択するボードRaspberry Pi RP2040 Boards(x.x.x) > Generic RP2040
※動作確認はバージョン 3.8.0です

モジュールライブラリ

この記事では小型OLED SSD1306の使用サンプルを掲載します。
モジュールを使用しない場合インストールの必要はありません。

機能/モジュールライブラリ名検索確認時のバージョン
SSD1306Adafruit SSD1306 by AdafruitSSD13062.5.1
SSD1306Adafruit GFX Library by AdafruitGFX1.11.3
WS2812Adafruit NeoPixel by Adafruitneopixel1.11.0

トラブル

シリアル認識しなくなった

スケッチ書き込み後に動作しない。
シリアル認識しなくなった。

UART、I2C、SPIのピン設定を指定できる場所以外のピンに設定すると現象が発生します。

XIAO RP2040 ではボードライブラリで選択したボードによりWireオブジェクトのI2C系統が変わります。
(SAMD21 XIAOと共通スケッチを使用できるようにするためだと思います。)

選択したボードが「RaspberryPi Pico」や「Generic RP2040」の場合、I2C0ではWire、I2C1ではWire1オブジェクトを使用します。
下図左のようにXIAO SAMD21のI2C位置にはI2C1(下図右側)が充てられているため、このピンをI2Cに使用する場合Wire1オブジェクトを使用します。

しかし選択したボードが「Seeed XIAO RP2040」の場合WireにはI2C0が使われます。

その状態でのSDAにGPIO6、SCLにGPIO7を指定して実行すると、I2C0にI2C1のピンを設定したことになり本現象が発生します。

選択したボードが「Generic RP2040」だった場合はI2C1のWire1オブジェクトをライブラリにあたえる記述に変更することで対応できます。
オブジェクトの変更方法はライブラリの設計によりそれぞれですが、代表してSSD1306 OLEDをAdafruit製ライブラリを使った制御での変更方法を掲載します。

//SSD1306の制御にWire1(I2C1)を使用するコンストラクタ
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire1, OLED_RESET);

//Wire1(I2C1)のSDAにGPIO6, SCLにGPIO7を指定する
Wire1.setSDA(6);
Wire1.setSCL(7);

Adafruit SSD1306 by Adafruitでは、コンストラクタでI2Cに使用するオブジェクトを指定します。
そのほかのライブラリでもI2Cオブジェクトを変更するための方法はあると思うので、各ライブラリのドキュメントを参照してください。

WS2812LEDが点灯しない

WS2812の点灯スケッチを書きこんでも点灯しない理由としてLEDの電源がOFFのままが考えられます。

「スケッチ」でも紹介していますが、下のサンプルのようにGPIO11をHighに設定することで使用することができます。

//電源用ピンをHighに設定
pinMode(11, OUTPUT);
digitalWrite(11, HIGH);

RGB LEDが消えない

XIAO RP2040にはチップRGB LEDが実装されています。
電源を投入するだけで、勝手に点灯してしまいます。(下図赤○)

LED用のGPIOピンにHIGHを設定することでLEDは消灯します。

pinMode(16, OUTPUT);
pinMode(17, OUTPUT);
pinMode(25, OUTPUT);

//GPIO 16, 17, 25 を HIGHにすることで消灯する
digitalWrite(16, HIGH);
digitalWrite(17, HIGH);
digitalWrite(25, HIGH);

スケッチ

基本的なI/Oの使い方や通信については、こちらの記事に記載します。
またボードライブラリは「Raspberry Pi Pico/RP2040 by Earle F. Philhower, III」、ボードは「Generic RP2040」を選択します。

RGB LED

説明

青->赤->緑の順に点灯と消灯を繰り返します。

配線

基板実装RGB LEDを使用するので配線不要。

スケッチ


//青 = 25
//赤 = 17
//緑 = 16
char ary[] = {25, 17, 16};

void setup() {

  for (int i = 0; i < sizeof(ary); i ++){
    pinMode(ary[i], OUTPUT);
  }

}

void loop() {

  //LOW = 点灯, HIGH = 消灯
  for (int i = 0; i< sizeof(ary); i ++)
  {
    delay(1000);
    digitalWrite(ary[i], LOW);
    delay(1000);
    digitalWrite(ary[i], HIGH);
  }
}

結果

RGB LEDが点灯、消灯しました。
WS2812の明るさと比べると優しい発色です。

I2C(SSD1306)

説明

本サンプルは、「Generic RP2040」でSAMD21 XIAOと同じI2C位置に配線したI2Cを使用するためのサンプルです。

I2Cを使ってSSD1306(OLED 0.96inch)モニタのサンプルを動作させます。

掲載以外の図形表示などのサンプルは以下のサンプルを参照してください。
ファイル(F) > スケッチ例 > Adafruit SSD1306 > ssd1306_128x64_i2c

配線

本サンプルはI2C1を使用します。
配線は以下の表のとおりです。

スケッチ

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>


#define I2C0_SDA (0)
#define I2C0_SCL (1)
#define I2C1_SDA (6)
#define I2C1_SCL (7)

#define SCREEN_WIDTH (128)                //解像度 128 x 64 で使用します。
#define SCREEN_HEIGHT (64)                //SCREEN_HEIGHTは 32 に設定することができます。

#define OLED_RESET     (-1)               //使用しないので -1を設定する。
#define SCREEN_ADDRESS (0x3C)             //I2Cアドレスは 0x3C

//Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);     //I2C0の場合
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire1, OLED_RESET);     //I2C1の場合

void setup()
{
  
  // //I2C0の場合
  // Wire.setSDA(I2C0_SDA);            //Wire1 -> Wire
  // Wire.setSCL(I2C0_SCL);

  //I2C1の場合
  Wire1.setSDA(I2C1_SDA);
  Wire1.setSCL(I2C1_SCL);


  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    for(;;);
  }

  display.clearDisplay();               //何か表示されている場合に備えて表示クリア

  display.setTextSize(2);               //フォントサイズは2(番目に小さい)
  display.setTextColor(SSD1306_WHITE);  //色指定はできないが必要
  display.setCursor(20, 0);            //テキストの表示開始位置
  display.print(F("TAMANEGI"));         //表示文字列
  display.setCursor(15, 25);
  display.print(F("OLED 0.96"));
  display.setCursor(25, 45);
  display.print(F("SSD1306"));

  display.display();                    //バッファ転送(表示)
}

void loop()
{
}

結果

SSD1306のサンプルスケッチが動作しました。

Neopixel(WS2812)

説明

1秒ごとに、LEDの色を変化させます。
赤->緑->黄->青->紫->水->白

XIAO RP2040では、WS2812を使用するためにWS2812に電源を供給する必要があります。
GPIO11をOUTPUT設定にして出力をHIGHにします。

配線

基板実装WS2812を使用するので配線不要。

スケッチ

#include <Adafruit_NeoPixel.h>

#define POWER_PIN 11          //NeoPixelの電源
#define DIN_PIN 12            // NeoPixel の出力ピン番号
#define LED_COUNT 1           // LEDの連結数
#define WAIT_MS 1000          // 次の点灯までのウエイト
#define BRIGHTNESS 128        // 輝度
Adafruit_NeoPixel pixels(LED_COUNT, DIN_PIN, NEO_GRB + NEO_KHZ800);

void setup()
{
  //Neopixelの電源供給開始
  pinMode(POWER_PIN, OUTPUT);
  digitalWrite(POWER_PIN, HIGH);

  pixels.begin();             //NeoPixel制御開始
}

void loop()
{
  pixels.clear();
  
  //pixels.Color(Red, Green, Blue)で、パレット情報を作成する。
  //赤点灯
  pixels.setPixelColor(0, pixels.Color(BRIGHTNESS, 0, 0));
  pixels.show();
  delay(WAIT_MS);

  //緑点灯
  pixels.setPixelColor(0, pixels.Color(0, BRIGHTNESS, 0));
  pixels.show();
  delay(WAIT_MS);

  //赤 + 緑 で 黄点灯
  pixels.setPixelColor(0, pixels.Color(BRIGHTNESS, BRIGHTNESS, 0));
  pixels.show();
  delay(WAIT_MS);

  //青点灯
  pixels.setPixelColor(0, pixels.Color(0, 0, BRIGHTNESS));
  pixels.show();
  delay(WAIT_MS);

  //赤 + 青 で 紫点灯
  pixels.setPixelColor(0, pixels.Color(BRIGHTNESS, 0, BRIGHTNESS));
  pixels.show();
  delay(WAIT_MS);

  //緑 + 青 で 水点灯
  pixels.setPixelColor(0, pixels.Color(0, BRIGHTNESS, BRIGHTNESS));
  pixels.show();
  delay(WAIT_MS);

  //赤 + 緑 + 青 で 白点灯
  pixels.setPixelColor(0, pixels.Color(BRIGHTNESS, BRIGHTNESS, BRIGHTNESS));
  pixels.show();
  delay(WAIT_MS);
}
結果

Nexpixelが1秒毎に色の変化をしました。

コメント

タイトルとURLをコピーしました