Seeed Studio XIAO RA4M1でのピン多重化
デジタル
XIAO RA4M1は最大11個の通常のGPIOピン、6個のアナログピン、そして8個の再利用可能なIOポートを備えています。この例では、XIAO RA4M1、XIAO拡張ボード、およびリレーを使用して、異なるデジタルピンを読み書きに使用する方法を実演します。
ハードウェアの準備
Seeed Studio XIAO R4M1 | Seeed Studio Expansion Base for XIAO with Grove OLED | Grove - Relay |
---|---|---|
![]() | ![]() | ![]() |
XIAO RA4M1またはSenseを拡張ボードに取り付け、Groveケーブルを使用してリレーを拡張ボードのA0/D0インターフェースに接続してください。最後に、USB-CケーブルでXIAOをコンピューターに接続します。
ソフトウェア実装
この例では、XIAO拡張ボードに接続されたボタンを使用してリレーのオン/オフ状態を制御する実装を行います。ボタンが押されるとリレーがオンになり、ボタンが離されるとリレーがオフになります。
const int buttonPin = D1; // the number of the pushbutton pin
int buttonState = 0; // variable for reading the pushbutton status
const int relayPin = D0;
void setup() {
// initialize the Relay pin as an output:
pinMode(relayPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT_PULLUP);
}
void loop() {
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);
// check if the pushbutton is pressed. If it is, the buttonState is HIGH:
if (buttonState == HIGH) {
// turn Relay on:
digitalWrite(relayPin, HIGH);
} else {
// turn Relay off:
digitalWrite(relayPin, LOW);
}
}
すべてが順調に進めば、プログラムをアップロードした後、以下の効果が確認できるはずです。

デジタルをPWMとして使用
XIAO RA4M1のすべてのGPIOピンはPWM出力をサポートしています。そのため、任意のピンを使用してPWMを出力し、ライトの明るさを調整したり、サーボを制御したり、その他の機能を実現できます。
ハードウェアの準備
Seeed Studio XIAO RA4M1 | Seeed Studio Expansion Base for XIAO with Grove OLED | Grove - Variable Color LED |
---|---|---|
![]() | ![]() | ![]() |
XIAO RA4M1またはSenseを拡張ボードに取り付け、Groveケーブルを使用してVariable Color LEDを拡張ボードのA0/D0インターフェースに接続してください。最後に、USB-CケーブルでXIAOをコンピューターに接続します。
ソフトウェア実装
この例では、PWM出力を使用してライトの明るさを制御する方法を実演します。
int LED_pin = D0; // LED connected to digital pin 10
void setup() {
// declaring LED pin as output
pinMode(LED_pin, OUTPUT);
}
void loop() {
// fade in from min to max in increments of 5 points:
for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 3) {
// sets the value (range from 0 to 255):
analogWrite(LED_pin, fadeValue);
// wait for 30 milliseconds to see the dimming effect
delay(30);
}
// fade out from max to min in increments of 5 points:
for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 3) {
// sets the value (range from 0 to 255):
analogWrite(LED_pin, fadeValue);
// wait for 30 milliseconds to see the dimming effect
delay(30);
}
}
プログラムが正常に実行されると、以下の実行効果が表示されます。

アナログ
XIAO RA4M1開発ボードは、アナログセンサー値の高解像度読み取りのために最大14ビットADCを搭載しており、より正確な値を読み取ることができます。XIAO RA4M1開発ボードのアナログ-デジタル変換器(ADC)。デフォルトでは、解像度は10ビットに設定されており、アナログ読み取りの精度向上のために12ビットと14ビット解像度の両方に設定できます。
ADC精度による詳細データ
- 10ビット:0~1024
- 12ビット:0~4096
- 14ビット:0~16383
次に、ADCの特性を反映するために2つのセンサーを選択します。
ハードウェア準備
Seeed Studio XIAO RA4M1 | Grove-Variable Color LED | Grove-Rotary Angle Sensor | Seeed Studio Grove Base for XIAO |
---|---|---|---|
![]() | ![]() | ![]() | ![]() |
ソフトウェア実装
#define ADC_Bit_Fourteen 14
#define ADC_Bit_Twelve 12
#define ADC_Bit_Ten 10
const int analogInPin = A1; // Analog input pin that the potentiometer is attached to
const int analogOutPin = 9; // Analog output pin that the LED is attached to
int sensorValue = 0; // value read from the pot
int outputValue = 0; // value output to the PWM (analog out)
void setup() {
Serial.begin(115200);
// Ten_Bite_ADC_Config(); // 10bit
// Twelve_Bite_ADC_Config(); // 12bit
Fourteen_Bite_ADC_Config(); // 14bit
}
void loop() {
sensorValue = analogRead(analogInPin);
outputValue = map(sensorValue, 0, 4095, 0, 255);
analogWrite(analogOutPin, outputValue);
Serial.print("sensor = ");
Serial.print(sensorValue);
Serial.print("\t output = ");
Serial.println(outputValue);
delay(100);
}
void Ten_Bite_ADC_Config() {
analogReadResolution(ADC_Bit_Ten);
}
void Twelve_Bite_ADC_Config() {
analogReadResolution(ADC_Bit_Twelve);
}
void Fourteen_Bite_ADC_Config() {
analogReadResolution(ADC_Bit_Fourteen);
}
すべてが順調に進めば、プログラムをアップロードした後、以下のような効果が確認できるはずです。

Serial
Arduino IDEで作業する際、シリアル通信は多くのプロジェクトにおいて重要な部分です。Arduino IDEでSerialを使用するには、まずSerial Monitorウィンドウを開く必要があります。これは、ツールバーのSerial Monitorアイコンをクリックするか、Ctrl+Shift+Mのショートカットキーを押すことで実行できます。
一般的な使用方法
よく使用されるSerial関数には以下があります:
Serial.begin()
-- 指定されたボーレートで通信を初期化しますSerial.print()
-- 読み取り可能な形式でSerialポートにデータを送信しますSerial.write()
-- Serialポートにバイナリデータを送信しますSerial.available()
-- Serialポートから読み取り可能なデータがあるかどうかを確認しますSerial.read()
-- Serialポートから1バイトのデータを読み取りますSerial.flush()
-- 送信中のシリアルデータの送信完了を待ちます
これらのSerial関数を使用することで、Arduinoボードとコンピュータ間でデータの送受信が可能になり、インタラクティブなプロジェクトを作成する多くの可能性が開かれます。
以下はサンプルプログラムです:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}
void loop() {
// send data to the serial port
Serial.println("Hello World!");
// read data from the serial port
if (Serial.available() > 0) {
// read the incoming byte:
char incomingByte = Serial.read();
// print the incoming byte to the serial monitor:
Serial.print("I received: ");
Serial.println(incomingByte);
}
// wait for a second before repeating the loop
delay(1000);
}
Serial1の使用方法
上記のXIAO RA4M1の具体的なパラメータのピン図によると、TXピンとRXピンがあることが確認できます。 これはシリアル通信とは異なりますが、使用方法も非常に似ており、いくつかのパラメータを追加する必要があるだけです。 そこで次に、チップから引き出されたピンをシリアル通信に使用します。
#define BAUD 115200
void setup() {
Serial1.begin(BAUD);
}
void loop() {
if(Serial1.available() > 0)
{
char incominByte = Serial1.read();
Serial1.print("I received : ");
Serial1.println(incominByte);
}
delay(1000);
}
Usage of Software Serial
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // RX, TX
void setup() {
// initialize serial communication
Serial.begin(9600);
while (!Serial);
// initialize software serial
mySerial.begin(9600);
}
void loop() {
// read data from software serial
if (mySerial.available()) {
char data = mySerial.read();
Serial.print("Received data: ");
Serial.println(data);
}
// write data to software serial
mySerial.print("Hello World!");
// wait for a second before repeating the loop
delay(1000);
}
このプログラムでは、まずSoftwareSerial.h
ライブラリをインクルードしてソフトウェアシリアルを使用します。次に、ピン2と3をそれぞれRXとTXとして使用して、mySerialという新しいSoftwareSerialオブジェクトを作成します。
setup()
関数では、ハードウェアシリアル(Serial.begin()
)とソフトウェアシリアル(mySerial.begin()
)の両方を初期化します。
loop()
関数では、mySerial.available()
関数を使用してソフトウェアシリアルから読み取り可能なデータがあるかどうかを確認します。データがある場合は、mySerial.read()
関数を使用して受信バイトを読み取り、dataという変数に格納します。次に、Serial.print()
とSerial.println()
関数を使用して、「Received data: 」に続いてdataの値をハードウェアシリアルに出力します。
また、mySerial.print()
関数を使用してソフトウェアシリアルに「Hello World!」を書き込みます。これにより、XIAOからソフトウェアシリアルポートに接続されたデバイスにデータが送信されます。
最後に、delay()
関数を追加してループを繰り返す前に1秒間待機します。
IIC
XIAO RA4M1には、多くのセンサーのデータ送信と解析、およびOLEDスクリーンの使用に利用できるI2Cインターフェースがあります。
ハードウェア準備
Seeed Studio XIAO RA4M1 | Seeed Studio Expansion Base for XIAO with Grove OLED |
---|---|
![]() | ![]() |
XIAO拡張ボード上のOLEDディスプレイはI2Cプロトコルを使用し、ボード上のI2C回路を通じてXIAOのI2Cインターフェースに接続されています。そのため、XIAOを拡張ボードに直接接続し、プログラムを作成して画面にコンテンツを表示することができます。
ソフトウェア実装
この例では、Seeed Studio Expansion Base for XIAO RA4M1のOLEDディスプレイの使用方法を紹介します。
ステップ1. Seeed Studio XIAO RA4M1を拡張ボードに取り付け、Type-Cケーブルを接続します。
ステップ2. u8g2ライブラリをインストールします。
ステップ3. コードをコピーしてArduino IDEに貼り付け、アップロードします。
#include <Arduino.h>
#include <U8x8lib.h>
#include <Wire.h>
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE); // OLEDs without Reset of the Display
void setup(void) {
u8x8.begin();
u8x8.setFlipMode(1); // set number from 1 to 3, the screen word will rotary 180
}
void loop(void) {
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8.setCursor(0, 0);
u8x8.print("i'm XIAO RA4M1");
}
コードの最初の数行では、Arduino.h、U8x8lib.h、Wire.hなどの必要なライブラリをインクルードしています。U8x8lib.hライブラリはOLEDディスプレイを制御する関数を提供し、Wire.hライブラリはI2C通信用の関数を提供します。
setup()
関数では、u8x8.begin()
関数を使用してOLEDディスプレイを初期化します。また、u8x8.setFlipMode()
関数を使用してディスプレイのフリップモードを設定し、画面を180度回転させます。
loop()
関数では、u8x8.setFont()
関数を使用してフォントを設定し、u8x8.setCursor()
関数を使用してディスプレイ上のカーソルの位置を指定します。最後に、u8x8.print()
関数を使用してOLEDディスプレイに「Hello World!」という文字列を表示します。
XIAO RA4M1にプログラムをアップロードすると、拡張ボード上のOLEDディスプレイ画面にコンテンツが表示されます。

SPI
RA4M1チップは複数の周辺機器を統合しており、フラッシュメモリ、ディスプレイ、センサーなどの外部SPIデバイスを接続するために使用できるSPIインターフェースを含んでいます。XIAO RA4M1は高速SPI転送モードもサポートしており、最大80MHzのSPI転送レートを実現でき、ほとんどのSPIデバイスのデータ転送ニーズを満たします。
ハードウェア準備
Seeed Studio XIAO RA4M1 | Grove - OLED Display 1.12 (SH1107) V3.0 - SPI/IIC |
---|---|
![]() | ![]() |
上記のハードウェアを準備した後、ジャンパーワイヤーを使用してXIAOとOLEDのSPIインターフェースを接続します。配線方法については以下の図を参照してください。
ソフトウェア実装
次に、以下のプログラムを例として、SPIインターフェースを使用してOLED画面表示を制御する方法を紹介します。
u8g2ライブラリをインストールします。
#include <Arduino.h>
#include <U8g2lib.h>
#include <SPI.h>
#include <Wire.h>
U8G2_SH1107_128X128_1_4W_HW_SPI u8g2(U8G2_R3, /* cs=*/ D7, /* dc=*/ D4, /* reset=*/ D5);
void setup(void) {
u8g2.begin();
}
void loop(void) {
u8g2.firstPage();
do {
u8g2.setFont(u8g2_font_luBIS08_tf);
u8g2.drawStr(0,24,"Hello Seeed!");
} while ( u8g2.nextPage() );
}
setup()
関数では、U8G2_SH1107_128X128_1_4W_HW_SPI
クラスが、チップセレクト(cs)、データ/コマンド(dc)、リセットに使用されるピンを指定する適切なコンストラクタ引数でインスタンス化されます。その後、u8g2.begin()
関数が呼び出されてディスプレイを初期化します。
loop()
関数では、u8g2.firstPage()
、u8g2.setFont()
、u8g2.drawStr()
関数を使用してディスプレイが新しいコンテンツで更新されます。u8g2.firstPage()
関数は書き込み用のディスプレイバッファを設定し、u8g2.nextPage()
は更新されたコンテンツを表示します。do-while ループは、プログラムが停止されるまでコンテンツが継続的に表示されることを保証します。
全体的に、このコードは U8g2 ライブラリを使用して OLED ディスプレイを制御し、テキストを表示する方法を示しています。

CAN(XIAO CAN Bus Expansion Board)
Hadware Preparation
Seeed Studio XIAO RA4M1 | XIAO CAN Bus Expansion Board |
---|---|
![]() | ![]() |
ステップ1. 2つのCAN BusブレークアウトボードとXIAO RA4M1を準備する
ステップ2. これら2つのXIAO RA4M1をそれぞれCAN Busブレークアウトボードに挿入する
ステップ3. デュポンライン接続を準備する

ソフトウェアの準備
MCP2515ボード用のArduinoライブラリを提供しています。
このライブラリには以下を含む複数のサンプルが含まれています:
- OBDII-PIDs - OBD-IIインターフェースからデータを取得
- send - CANバスにフレームを送信
- recv - CANバスからフレームを受信
- set_mask_filter_recv - マスクとフィルタ設定でCANバスからフレームを受信
ソフトウェア実装
2つのXIAO RA4M1を同時に電源投入してプログラムをダウンロードすることは許可されていません。これによりシリアルポートのダウンロード時にエラーが発生します。1つをダウンロードした後、それを抜いてから、もう一方のXIAO RA4M1に電源を入れてプログラムをダウンロードし、最後に同時に電源を入れてシリアルポートメッセージを確認してください
CAN書き込みコード
/* send a frame from can bus
CAN Baudrate,
#define CAN_5KBPS 1
#define CAN_10KBPS 2
#define CAN_20KBPS 3
#define CAN_25KBPS 4
#define CAN_31K25BPS 5
#define CAN_33KBPS 6
#define CAN_40KBPS 7
#define CAN_50KBPS 8
#define CAN_80KBPS 9
#define CAN_83K3BPS 10
#define CAN_95KBPS 11
#define CAN_100KBPS 12
#define CAN_125KBPS 13
#define CAN_200KBPS 14
#define CAN_250KBPS 15
#define CAN_500KBPS 16
#define CAN_666KBPS 17
#define CAN_1000KBPS 18
*/
#include <mcp_can.h>
#include <SPI.h>
/* Please modify SPI_CS_PIN to adapt to your board.
CANBed V1 - 17
CANBed M0 - 3
CAN Bus Shield - 9
CANBed 2040 - 9
CANBed Dual - 9
OBD-2G Dev Kit - 9
OBD-II GPS Kit - 9
Hud Dev Kit - 9
Seeed Studio CAN-Bus Breakout Board for XIAO and QT Py - D7
*/
#define SPI_CS_PIN D7
MCP_CAN CAN(SPI_CS_PIN); // Set CS pin
void setup()
{
Serial.begin(115200);
while(!Serial);
// below code need for OBD-II GPS Dev Kit Atemga32U4 version
// pinMode(A3, OUTPUT);
// digitalWrite(A3, HIGH);
// below code need for OBD-II GPS Dev Kit RP2040 version
// pinMode(12, OUTPUT);
// digitalWrite(12, HIGH);
while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println("CAN BUS FAIL!");
delay(100);
}
Serial.println("CAN BUS OK!");
}
unsigned char stmp[8] = {0, 1, 2, 3, 4, 5, 6, 7};
void loop()
{
CAN.sendMsgBuf(0x00, 0, 8, stmp);
delay(100); // send data per 100ms
}
// END FILE
CAN読み取りコード
/* receive a frame from can bus
CAN Baudrate,
#define CAN_5KBPS 1
#define CAN_10KBPS 2
#define CAN_20KBPS 3
#define CAN_25KBPS 4
#define CAN_31K25BPS 5
#define CAN_33KBPS 6
#define CAN_40KBPS 7
#define CAN_50KBPS 8
#define CAN_80KBPS 9
#define CAN_83K3BPS 10
#define CAN_95KBPS 11
#define CAN_100KBPS 12
#define CAN_125KBPS 13
#define CAN_200KBPS 14
#define CAN_250KBPS 15
#define CAN_500KBPS 16
#define CAN_666KBPS 17
#define CAN_1000KBPS 18
CANBed V1: https://www.longan-labs.cc/1030008.html
CANBed M0: https://www.longan-labs.cc/1030014.html
CAN Bus Shield: https://www.longan-labs.cc/1030016.html
OBD-II CAN Bus GPS Dev Kit: https://www.longan-labs.cc/1030003.html
*/
#include <SPI.h>
#include "mcp_can.h"
/* Please modify SPI_CS_PIN to adapt to your board.
CANBed V1 - 17
CANBed M0 - 3
CAN Bus Shield - 9
CANBed 2040 - 9
CANBed Dual - 9
OBD-2G Dev Kit - 9
OBD-II GPS Kit - 9
Hud Dev Kit - 9
Seeed Studio CAN-Bus Breakout Board for XIAO and QT Py - D7
*/
#define SPI_CS_PIN D7
MCP_CAN CAN(SPI_CS_PIN); // Set CS pin
void setup()
{
Serial.begin(115200);
while(!Serial);
// below code need for OBD-II GPS Dev Kit Atemga32U4 version
// pinMode(A3, OUTPUT);
// digitalWrite(A3, HIGH);
// below code need for OBD-II GPS Dev Kit RP2040 version
// pinMode(12, OUTPUT);
// digitalWrite(12, HIGH);
while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println("CAN BUS FAIL!");
delay(100);
}
Serial.println("CAN BUS OK!");
}
void loop()
{
unsigned char len = 0;
unsigned char buf[8];
if(CAN_MSGAVAIL == CAN.checkReceive()) // check if data coming
{
CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf
unsigned long canId = CAN.getCanId();
Serial.println("-----------------------------");
Serial.print("Get data from ID: ");
Serial.println(canId, HEX);
for(int i = 0; i<len; i++) // print the data
{
Serial.print(buf[i], HEX);
Serial.print("\t");
}
Serial.println();
}
}
// END FILE
この例では、CAN Bus Breakout Board の端子ピン P1 の一つをはんだ付けする必要があります。そうすることで任意の速度を使用できるようになります。そうしないと 125 CAN ボーレート以下でしか使用できません。

CAN(その他のトランシーバー)
チュートリアルとコードを提供してくれた Arduino に感謝いたします。
ハードウェアの準備
CAN プロトコルでは、送信側が送信したメッセージを受信する必要があります。単純に TX と RX を接続するだけでは通信を完了することはできません。通信にはトランシーバーを接続する必要があります。ここでは、Arduino 公式の SN65HVD230 スプリッターモジュール を使用します。
3.3 V | GND | D9(CANRX0) | D10 (CANTX0) |
---|---|---|---|
VCC | GND | CANRX | CANTX |
ソフトウェアの準備
CAN Write コード
/*
CANWrite
Write and send CAN Bus messages
See the full documentation here:
https://docs.arduino.cc/tutorials/uno-r4-wifi/can
*/
/**************************************************************************************
* INCLUDE
**************************************************************************************/
#include <Arduino_CAN.h>
/**************************************************************************************
* CONSTANTS
**************************************************************************************/
static uint32_t const CAN_ID = 0x20;
/**************************************************************************************
* SETUP/LOOP
**************************************************************************************/
void setup()
{
Serial.begin(115200);
while (!Serial) { }
if (!CAN.begin(CanBitRate::BR_250k))
{
Serial.println("CAN.begin(...) failed.");
for (;;) {}
}
}
static uint32_t msg_cnt = 0;
void loop()
{
/* Assemble a CAN message with the format of
* 0xCA 0xFE 0x00 0x00 [4 byte message counter]
*/
uint8_t const msg_data[] = {0xCA,0xFE,0,0,0,0,0,0};
memcpy((void *)(msg_data + 4), &msg_cnt, sizeof(msg_cnt));
CanMsg const msg(CanStandardId(CAN_ID), sizeof(msg_data), msg_data);
/* Transmit the CAN message, capture and display an
* error core in case of failure.
*/
if (int const rc = CAN.write(msg); rc < 0)
{
Serial.print ("CAN.write(...) failed with error code ");
Serial.println(rc);
for (;;) { }
}
/* Increase the message counter. */
msg_cnt++;
/* Only send one message per second. */
delay(1000);
}
CAN読み取りコード
/*
CANRead
Receive and read CAN Bus messages
See the full documentation here:
https://docs.arduino.cc/tutorials/uno-r4-wifi/can
*/
/**************************************************************************************
* INCLUDE
**************************************************************************************/
#include <Arduino_CAN.h>
/**************************************************************************************
* SETUP/LOOP
**************************************************************************************/
void setup()
{
Serial.begin(115200);
while (!Serial) { }
if (!CAN.begin(CanBitRate::BR_250k))
{
Serial.println("CAN.begin(...) failed.");
for (;;) {}
}
}
void loop()
{
if (CAN.available())
{
CanMsg const msg = CAN.read();
Serial.println(msg);
}
}
ターミナル抵抗器をいつ接続する必要がありますか?
-
- 長距離通信:CANバスが長い場合(例:1メートル以上)、信号反射による通信問題を避けるため、バスの両端にターミナル抵抗器を接続する必要があります。
-
- マルチノード通信:複数のノードが同じCANバスに接続されている場合、ターミナル抵抗器も不可欠です。これらはバスのインピーダンス安定性を確保し、信号歪みを防ぎます。
ターミナル抵抗器をいつ切断できますか?
-
- 短距離通信:一部の短距離アプリケーション(通常1メートル未満)では、信号反射が通信に与える影響が比較的小さいため、ターミナル抵抗器を省略できます。
-
- 単一ノード通信:バス上にノードが1つしかない場合(デバッグ環境など)で、距離が短い場合、ターミナル抵抗器を一時的に切断できます。
送信側コード結果 | 受信側コード結果 |
---|---|
![]() | ![]() |
技術サポート & 製品ディスカッション
弊社製品をお選びいただき、ありがとうございます!お客様の製品体験を可能な限りスムーズにするため、さまざまなサポートを提供いたします。異なる好みやニーズに対応するため、複数のコミュニケーションチャネルをご用意しています。