こんにちは、ENGかぴです。
Seeeduino XIAOの標準ライブラリであるSerial1を使用すると外部機器とシリアル通信ができます。Serialはシリアルモニタ専用であるためArduino UNOできなかったシリアルモニタと外部機器へのシリアル通信を区別できます。外部機器にはトワイライト(TWELITE)を使用します。
トワイライトとシリアル通信をしていますが、受信データを受け入れてチェックする方法などは他のマイコンが対象でも応用できます。
Seeeduino XIAOで動作確認したことについてリンクをまとめています。
Seeeduino XIAOで学べるソフト開発と標準ライブラリの使い方
Seeeduino XIAOでシリアル通信する方法
Seeeduino XIAOではシリアルモニタ用と外部機器に出力する用途のシリアル通信が別々に実装されています。そのためArduino UNOできなかったシリアルモニタと外部機器へのシリアル通信を区別できます。
シリアル | 用途 |
---|---|
Serial(SerialUSB) | シリアルモニタ専用:ピンから出力しない |
Serial1 | 外部機器へのシリアル通信 6ピン:TX 7ピン:RX |
SerialはSerialUSBと表記してもSerialと同じ動作になるためどちらの表記でも問題ありません。Serialと表記した方が他のArduino環境でも使用できるためSerialUSBは使わない方が良いと思います。
標準ライブラリを使用する方法
Seeeduino XIAOでシリアル通信を使用する際はSerial.begin()を発行する必要があります。
void setup() {
Serial.begin(115200); //シリアルモニタ用
Serial1.begin(115200); //外部機器との通信用
//while(!Serial ){ } //ポートを開くまでの待ち
}
引数にシリアル通信のボーレートを入力します。ボーレートは任意でも良いのですが、マイコンのクロック周波数によって誤差が出るので注意が必要です。
Arduino IDEやVsCodeで選択できるボーレートから選択すると多くの場合問題になりませんが、ボーレートを早くしすぎると配線の長さや周辺回路の部品などの影響で通信できなくなることがあるので外部機器のクロックを含めて検討する必要があります。
Serial1.begin()を発行した後ポートが開く(初期設定待ち)までループさせて確実に設定が完了するまで待機させることもありますが、初期化時に他で遅延させている場合やbegin()の発行から直ちにシリアル通信をしない場合は実装する必要はありません。
PR:スキマ時間で自己啓発!スマホで学べる人気のオンライン資格講座【スタディング】まずは気になる講座を無料で体験しよう!
SerialとSerial1の使い分け
Serialはシリアルモニタに表示したい場合に使用します。Serial1で受信したデータをシリアルモニタに表示したい場合など使い分けることで効率よくデバッグできるようになります。
void loop() {
//受信データをモニタする例
while( Serial1.available()){ //Serial1に受信データがあるか
data = Serial1.read(); //Serial1データを読み出し
Serial.write(data); //シリアルモニタにSerial1から読み出したデータをモニタ表示
}
}
外部機器からシリアル通信のデータを受信するとSerial1.available()の条件を満たすためSerial1.read()によってSerial1のデータを読み出します。受信したデータをSerial.write()によってシリアルモニタに表示しています。
Serialでよく使うAPI
Serialでよく使うAPIをまとめました。Serialで表記していますがSerial1でも同様に使用できます。
API | 説明 | 使用例 |
---|---|---|
Serial.write() | バイナリデータを送信する | Serial.write(0x30) |
Serial.write(引数1,引数2) | 引数1に対象バッファのアドレス 引数2に送信するバイト数 | Serial.write(&buf,10) |
Serial.read() | 受信データを1バイトずつ取り出す | available()とセットで使う buf = Serial.read() |
Serial.availale() | 受信したデータ数を確認し、データがある場合 は0よりも大きな値となる。 | if(Serial.available() ){ } |
Serial.print() | 文字として送信する | Serial.print(0x10) |
Serial.println() | 改行コードをつけて文字として送信する | Serial.println(0x10) |
Serial.print(0x10)はバイナリデータでは16であるためモニタ上では16が表示されます。Serial.write(0x30)の場合は0x30がアスキーコード(テキストデータ)では0にあたるためモニタには0が表示されます。
Seeeduino XIAOとトワイライトの通信

Seeeduino XIAOとトワイライトをシリアル通信で接続してSeeeduino XIAOの電文でトワイライトの動作を切り替えます。トワイライトは電文を受け取るとCMDに応じた処理を行いOKを返信します。Seeeduino XIAOはOKの返信でCMDのカウントを更新します。
- 初期値は0でLEDを消灯する(CMD0)
- ブザーを鳴らす。(CMD1)
- ブザーを止める。(CMD2)
- LEDを消灯する。(CMD3)
1から4を繰り返してトワイライトの動作を切り替えます。ブザーは鳴り続けると耳障りに感じるため100ms間鳴らした後900msは鳴らないようにします。
トワイライトのシリアル通信はSerialParserのバイナリ形式を使います。
トワイライト(TWELITE)とArduino間でシリアル通信する
トワイライトのSerialParserの電文構成に従ってSeeeduino XIAOで電文を生成して送出することで双方のシリアル通信によるデータの送受信が可能となります。詳細は参考記事にまとめていますが、ポイントを整理すると電文の構成は次の通りになります。

この電文構成に従ってSeeeduino XIAOの電文を以下の例のように生成します。
struct COM_TYP{
uint8_t header[3];
uint8_t sz;
uint8_t buf[BUF_SZ];
uint8_t sum;
};
uint8_t buf[]={'C','M','D', 0x00};
COM_TYP txdata;
void SerialTxSet(uint8_t cmd){
uint8_t *adrs;
uint8_t allsz = 0;
txdata.header[0] = HEADER1; //0xA5
txdata.header[1] = HEADER2; //0x5A
txdata.header[2] = HEADER3; //0x80
txdata.sz = sizeof(buf);
for(uint8_t i=0; i < txdata.sz; i++){
txdata.buf[i] = buf[i]; //buf[0]分をオフセット
}
txdata.buf[3] = cmd;
txdata.sum = CalcSum(&txdata.buf[0],txdata.sz); //データ部のSUM値を計算
allsz = sizeof(txdata.header) + sizeof(txdata.sz) + txdata.sz; //すべてのデータ数
Serial1.write(&txdata.header[0],allsz); //下記のコメントアウト部分の書き方でもよい
Serial1.write(txdata.sum); //SUM値を最後に送出
//adrs =&txdata.header[0];
//for(uint8_t i = 0; i < allsz; i++ ){
// Serial1.write(*adrs);
// adrs++;
//}
//Serial1.write(txdata.sum);
}
トワイライトは電文を受信するとCMD番号に対する動作を実行しSeeeduino XIAOにOKを返信します。トワイライトの処理はソースコード全体を確認してください。トワイライトからの返信データに問題がなければCMDのカウントを進めてボタンが押されるのを待ちます。
void RxDataChk(){
int rxsz;
uint8_t sz;
uint8_t allsz;
uint8_t *adrs;
uint8_t rp = rxarduino.rp;
uint8_t chkdat[RXCHK_SZ];
rxsz = rxarduino.wp - rxarduino.rp; //受信データ数の算出
if( rxsz < 0 ){
rxsz = rxsz + RING_SZ;
}
if(rxsz >= RXCHK_SZ){
//サイズ部分まで一旦受信してチェックする
if( chkdat[0]== HEADER1 && chkdat[1]== HEADER2 && chkdat[2]== HEADER3 ){
//ヘッダー部分を確認
sz = chkdat[3] & 0x3F;//szが63を超えないようにする(データ長がおかしい場合の対策)
allsz = RXCHK_SZ + sz + 1; //+1はSUMで受信データすべての長さを算出
if( rxsz >= allsz ){ //確定したデータ数を受信したかを確認
//rxdata.bufに受信データを格納する
rxdata.sum = CalcSum(&rxdata.buf[0],sz); //SUMを計算
if( rxdata.sum == rxdata.buf[sz]){//SUMのチェック
if( rxdata.buf[0] == 'O'&& rxdata.buf[1] == 'K' ){
//トワイライトからのOKを確認
if(++reqcmd >= MODE_MAX ){ //コマンド番号を更新
reqcmd = 0;
}
}
}
else{
//SUMチェックが不一致なのでデータを破棄する
}
}
}
else{
//ヘッダーが不一致なのでデータを破棄する
}
}
}
トワイライトからの返信電文のチェックを行っています。ヘッダー部分(固定している箇所)で全体のデータ数が分かるため一旦ヘッダー部分を受信して全体のデータ数を確認しています。
電文を受け付けた後はSUMチェックを行い正常であれば正式な電文として処理します。電文を受け付けてもSUMチェックが一致しない場合はエラーとして電文を破棄します。
動作確認

Seeeduino XIAOのDIにはスイッチを実装しています。スイッチを押すとSeeeduino XIAOからトワイライトに電文を送出します。トワイライトは受信した電文に応じてLED1を点灯消灯したりブザーを鳴らしたりします。
トワイライトはSeeeduino XIAOに対して電文を受け入れるとOKの文字を返信します。Seeeduino XIAOはOKを受信するとCMD番号のカウントを更新してボタンが押されるのを待ちます。
ボタンを繰り返し押すことでLED1が点灯しブザーが1秒ごとになることが確認来ました。CMD番号が切り替わっていることが確認できたのでシリアル通信は成功していることを確認できました。
ソースコード全体
ソースコードは記事作成時点において動作確認できていますが、使用しているライブラリの更新により動作が保証できなくなる可能性があります。また、ソースコードを使用したことによって生じた不利益などの一切の責任を負いかねます。参考資料としてお使いください。
リンクからZIPファイル形式のファイルをダウンロードし、任意の場所に展開していただくとテキストファイルが生成されます。
関連リンク
Arduinoのライブラリを使って動作確認を行ったことを下記リンクにまとめています。
Arduinoで学べるマイコンのソフト開発と標準ライブラリの使い方
Seeeduino XIAOで学べるソフト開発と標準ライブラリの使い方
ESP32-WROOM-32Eで学べるソフト開発と標準ライブラリの使い方
トワイライトを太陽光パネルで動作させたことやMWSTAGEの環境でソフト開発して無線通信したことなどについてまとめています。
トワイライト(TWELITE)のソフト開発と無線通信でできること
広告
マイベスト3年連続1位を獲得した実績を持つ実践型のプログラミングスクール
最後まで、読んでいただきありがとうございました。
Seeeduino XIAOにおいてSerial1が外部機器に対して動作することに気づくのが遅れてしまいました。SerialとSerial1を区別してデバッグできることはソフト開発面で効率が良いと改めて感じました。