「RaspberryPi Pico」には外部通信用として2系統(UART0,1)のシリアル通信がありますが、他にもパソコンとの通信やシリアルモニタで文字を送受信して動作確認を行う時に使用する「USBシリアル」があります。
さらに「Arduinoのコマンド」を使用することでプログラムで任意の端子を割り付けてシリアル通信を行う「ソフトウェアシリアル」も使用することができます。
これら4系統のシリアル通信(UART)の使い方について詳しく紹介します。
「Raspberry Pi Pico」のためのArduinoIDEのインストール方法は以下のリンクで詳しく紹介しています。
1.シリアル通信(UART)とは
2.ラズパイPicoの4系統のシリアル(UART)通信について
3.使用可能な端子について
4.サンプルプログラム(コピペ)
① 4系統のシリアル通信データ送信のみ確認用
② 4系統のシリアル通信データ送受信確認用
5.自作外付けシリアルモニタで動作確認
6.サンプルプログラムの詳細
7.まとめ
1.シリアル通信(UART)とは
UART通信とは、SPIやI2C通信のような通信タイミングに必要なクロック信号が無いため「非同期通信」と呼ばれます。
クロック信号が無いので、通信を行うデバイス間で同じ通信速度(ボーレート)を設定しておく必要があります。
I2CやSPI通信とは異なり、マスター/スレーブのような関係はありません。
UART通信では以下の2つの信号線を使ってデータの送受信を行います。
・RX:データ受信(レシーブ)用
送信用端子「TX」と受信用端子「RX」の2本線を使用しますが、お互いのGND(0V)を接続しておく必要があります。
2つのデバイス間で、以下のように送信用端子と受信用端子が交差するように接続します。
受信用端子「TX」↔︎ 送信用端子「RX」
GND(0V)↔︎ GND(0V)
2.ラズパイPicoの4系統のシリアル(UART)通信について
「Raspberry Pi Pico」には以下の4系統のシリアル通信があり、これらは同時に使用することができます。
・UART0:外部通信用1
・UART1:外部通信用2
・ソフトウェアシリアル:ソフトウェアで任意の入出力端子を割り付けて使用
「USBシリアル」はパソコンと通信するために使用するため通信速度以外はプログラムで操作することはできません。
「UART0,1」は使用する端子をプログラムで指定して使用しますが、使える端子は決まっています。
「ソフトウェアシリアル」は入出力端子であれば任意の端子をプログラムで指定して使用することができます。
3.使用可能な端子について
「Raspberry Pi Pico」の端子配列は以下のようになります。(公式サイトより抜粋)
シリアル通信に使用可能な端子は以下表になります。
シリアル通信名 | 送信用端子 | 受信用端子 |
---|---|---|
UART0 | UART0 TX | UATR0 RX |
UART1 | UART1 TX | UART1 RX |
ソフトウェアシリアル | GP0〜GP22 GP26〜GP28 | GP0〜GP22 GP26〜GP28 |
「UART0,1」は以下の端子が使用可能です。
・UART1(TX, RX):(GP4, GP5)/(GP8, GP9※初期値)
4.サンプルプログラム(コピペ)
プログラムは以下に2種類準備したので「コピペ」して書き込んでください。
1つ目の①は単純に4系統のシリアル通信の送信用端子(TX)から順番に文字データを出力するものです。
2つ目の②は送信用端子(TX)から出力した文字データを自分の受信用端子(RX)に入力して、データをリレーしていく、4系統のシリアル通信の送受信を確認するものです。
① 4系統のシリアル通信データ送信のみ確認用
4系統のシリアル通信の送信のみのプログラムです。
送信のみの確認ですが、プログラム的には送受信両方使用可能な状態になっています。
各シリアル通信の使い方の確認用としてできるだけシンプルに作成しています。
サンプルプログラムは以下になります。コピペ(コピー&ペースト)して書き込んでください。
※コピーは下コード(黒枠)内の右上角にある小さなアイコンのクリックでもできます。
#include <SoftwareSerial.h>
SoftwareSerial mySerial(14, 15); // RX, TX(ソフトウェアシリアル)
// 初期設定 -------------------------------------------------------------------
void setup() {
Serial .begin(9600); // USB(シリアルモニタ)初期化
// Serial1.setRX(17); // 標準設定以外の端子を使用する場合(UART0)
// Serial1.setTX(16);
Serial1 .begin(9600); // UART0初期化 TX:GP0 / RX:GP1
Serial2 .begin(9600); // UART1初期化 TX:GP8 / RX:GP9
mySerial.begin(9600); // ソフトウェアシリアル初期化
pinMode(20, INPUT_PULLUP); // スイッチ GP20を入力端子(プルアップ)に設定
pinMode(25, OUTPUT); // LED GP25を出力端子に設定
}
// メイン処理(繰り返し)-------------------------------------------------------
void loop() {
Serial.println("USB"); // USB(シリアルモニタ)出力
delay(100);
Serial1.println("Serial1"); // UART0出力
delay(100);
Serial2.println("Serial2"); // UART1出力
delay(100);
mySerial.println("mySerial"); // ソフトウェアシリアル出力
digitalWrite(25, HIGH); // LEDを点灯
delay(100);
digitalWrite(25, LOW); // LEDを消灯
delay(600);
}
② 4系統のシリアル通信データ送受信確認用
4系統のシリアル通信の送受信を確認するプログラムです。
自分で送信したデータを自分へ入力してデータをリレーしていきます。
このために「UART0」と「UART1」「ソフトウェアシリアル」はそれぞれの送信端子と受信端子を接続しておきます。
「ArduinoIDE」のシリアルモニタ機能を使用して、入力した文字を「USBシリアル」で受信して「UART0」から送信します。この時にLEDを1回点灯させるようにしています。
「UART0」は受信したデータを「UART1」から出力してLEDを1回点灯させます。
「UART1」は受信したデータを「ソフトウェアシリアル」から出力してLEDを1回点灯させます。
「ソフトウェアシリアル」はデータを受信したらLEDを1回点灯させます。
最終的に「ソフトウェアシリアル」から入力した文字データが送信されてシリアルモニタ「BASIC」に表示されれば全てのシリアル通信が機能していることが確認できます。
サンプルプログラムは以下になります。コピペ(コピー&ペースト)して書き込んでください。
※コピーは下コード(黒枠)内の右上角にある小さなアイコンのクリックでもできます。
#include <SoftwareSerial.h> // ソフトウェアシリアルのヘッダーファイルを準備
SoftwareSerial mySerial(14, 15); // RX, TX(ソフトウェアシリアル)
// 変数宣言
String c; // 受信データ(文字)格納用
// 関数 ----------------------------------------------------------------------
void led() { // LED点灯
digitalWrite(25, HIGH); // LEDを点灯
delay(200); // 遅延時間
digitalWrite(25, LOW); // LEDを消灯
delay(200); // 遅延時間
}
// 初期設定 -------------------------------------------------------------------
void setup() {
Serial .begin (9600); // USB(シリアルモニタ)
// Serial1.setRX(17); // 標準設定以外の端子を使用する場合(UART0)
// Serial1.setTX(16);
Serial1 .begin (9600); // UART0 標準設定 TX:GP0 / RX:GP1
Serial2 .begin (9600); // UART1 標準設定 TX:GP8 / RX:GP9
mySerial.begin(9600); // ソフトウェアシリアル
pinMode(25, OUTPUT); // LED GP25を出力端子に設定
}
// メイン処理(繰り返し)-------------------------------------------------------
void loop() {
// 受信データ処理
if (Serial.available()) { // 受信データ(USBシリアル)がある間繰り返し
c = Serial.readStringUntil('\n'); // 受信データを\nの手前まで取得(Serial)
led();
Serial.println(c); // 文字列出力(USBシリアル)
Serial1.println(c); // 文字列出力(Serial1)
}
if (Serial1.available()) { // 受信データ(Serial1)があれば
c = Serial1.readStringUntil('\n'); // 受信データを\nの手前まで取得(Serial1)
led();
Serial2.println(c); // 文字列出力(Serial2)
}
if (Serial2.available()) { // 受信データ(Serial2)があれば
c = Serial2.readStringUntil('\n'); // 受信データを\nの手前まで取得(Serial2)
led();
mySerial.println(c); // 文字列出力(mySerial)
}
if (mySerial.available()) { // 受信データ(Serial2)があれば
c = mySerial.readStringUntil('\n'); // 受信データを\nの手前まで取得(ソフトウェアシリアル)
led();
}
delay(100); // 遅延時間
}
5.自作外付けシリアルモニタで動作確認
動作確認は下画像の自作のシリアルモニタを使用すると簡単に確認することができます。
これは「M5Stack社」の「BASIC」を使用して受信したシリアルデータを液晶表示器に表示できるようにしたものです。
「BASIC」では外部通信用として3系統のシリアル通信を使用することができます。
下画像は「BASIC」の端子配列で本体裏側に同じような表示があります。
「BASIC」の端子R0, R2, 21(GROVEコネクタG21共通)はデータ受信(RX)用端子です。
外部デバイスのデータ送信(TX)用端子を接続することで、受信したデータが「BASIC」の液晶画面に表示されます。
どれか1つでも3つ全部でも可(3つの場合それぞれに0.1s程度のタイムラグが必要)
※外部デバイスとお互いの0Vを接続する必要があります。
「M5Stack BASIC」を使用したシリアルモニタの作り方(コピペで書き込むだけ)は以下のリンクで詳しく紹介しています。
実際に以下のように動作確認を行いました。
まず、①のサンプルプログラムの動作確認は以下のようになります。
自作のシリアルモニタ「BASIC」に下画像のように各端子を接続します。
シリアルモニタ「BASIC」のデータ受信(RX)端子にラズパイPicoのデータ送信(TX)端子「UART0(端子1)」「UART1(端子11)」「ソフトウェアシリアル(端子20)」と「GND(端子23)」を接続しています。
「BASIC」の電源を入れると下画像のようにプログラムで指定した文字データ「Serial1」「Serial2」「mySerial」が順番に表示され続けます。
「BASIC」に接続している配線を抜くと、それに対応した「ラズパイPico」からの送信データが表示されなくなるため、それぞれのデータが正しく送信されているのが確認できると思います。
パソコンに送信されている「USBシリアル」のデータも確認してみましょう。
「ArduinoIDE」のシリアルモニタ機能を使用して確認します。
下画像のように「ツール」→「シリアルモニタ」と選択します。
下画像のようにシリアルモニタのウインドウが表示され、プログラムで指定した「USB」という文字が表示され続けると思います。
これで全てのデータが正しく送信されていることが確認できます。
送信端子番号をいろいろ変えて動作確認してみましょう。
次に送信だけでなく受信の動作確認も行います。
確認方法は、自分で送信したデータを自分へ入力してデータをリレーしていきます。
このために下画像のように「UART0(端子1-2)」と「UART1(端子11-12)」「ソフトウェアシリアル(端子19-20)」はそれぞれの送信端子と受信端子を接続しておきます。
「ソフトウェアシリアル」の送信端子(端子20)と「GND(端子23)」はシリアルモニタの「BASIC」にも接続します。
接続したら、下画像のようにシリアルモニタを起動して、まずは右下でデータを送信する時の末尾に送信する「改行コード」を「LFのみ」に設定し、通信速度を「9600bps」に設定します。
設定したら送信データ入力部に「Hello」と入力してエンターを押してみましょう。
シリアルモニタに文字を入力してエンターを押すと入力した文字データを「USBシリアル」で受信して「UART0」から送信します。この時にLEDが1回点灯します。
「UART0」は受信したデータを「UART1」から出力してLEDを1回点灯させます。
「UART1」は受信したデータを「ソフトウェアシリアル」から出力してLEDを1回点灯させます。
「ソフトウェアシリアル」はデータを受信したらLEDを1回点灯させます。
最終的に下画像のようにシリアルモニタで入力した「Hello」という文字データが送信されていき、外付けのシリアルモニタ「BASIC」に表示されれば全てのシリアル通信が機能していることが確認できます。
送受信端子番号をいろいろ変えて動作確認してみましょう。
6.サンプルプログラムの詳細
サンプルプログラムのシリアル通信用プログラムについて紹介します。
まず、サンプルプログラムの 1行目でソフトウェアシリアルを使うためのヘッダーファイルを準備しています。
次に 2行目で「SoftwareSerial」を「mySerial」というコマンドで使用できるようにしています。(インスタンスの作成)
この時に以下のように送受信端子を指定します。
・RX端子番号, TX端子番号:使用する入出力端子番号「GP〜」の「〜」の部分の数値で指定します。
シリアル通信(UART)を使用するには「通信速度」を指定して以下のように初期化を行うことで使用できるようになります。
Serial1.begin( 通信速度) ; // UART0 初期値 GP0(TX),GP1(RX)
Serial2.begin( 通信速度 ) ; // UART1 初期値 GP8(TX),GP9(RX)
mySerial.begin( 通信速度 ) ; // ソフトウェアシリアル(設定した入出力端子を使用)
・通信速度:通信速度(ボーレート)を数値で指定します。
通信速度には以下のようなものがあるので通信相手と合わせます。(単位 bps)
1200/2400/4800/9600/19200/38400/57600/115200
※省略すると9600bpsとなります。
通信端子として初期値以外の端子を指定する場合は以下のように設定します。
Serial1.setTX( TX端子番号);
Serial1.begin( 通信速度); // UART0
※UART1を設定する場合はSerial1のところをSerial2として設定します。
・RX端子番号, TX端子番号:使用する入出力端子番号「GP〜」の「〜」の部分の数値で指定します。
「UART0,1」に使用できる端子は決められています。
どの端子が使用可能かは「3.使用可能な端子について」で確認しましょう。
シリアルデータの送受信には主に以下のようなコマンドを使用します。(他にもたくさんあります。)
Serial1.available( ) ; // 受信データのバイト数(文字数)を取得
Serial1.read( ) ; // 受信データを1文字取得
Serial1.readStringUntil( ‘\n‘) ; // 受信データを指定した文字の手前まで文字列で取得
今回は受信データの取得には 「Serial.readStringUntil(‘\n‘)」を使用しました。
これで、受信したデータを区切り文字「’\n‘」の手前まで変数(文字列)に格納することができます。
7.まとめ
「Raspberry Pi Pico」の4系統のシリアル通信について紹介しました。
「Raspberry Pi Pico」には標準で2系統(UART0,1)のシリアル通信とパソコン通信用の「USBシリアル」プログラムで任意の端子を割り付けられる「ソフトウェアシリアル」が使えます。
同時に全部使うことは稀だとは思いますが、UART0とUART1は使える端子が決まっているため、部品の配置によって、近い端子を使用したい時にどちらも使えると配線に自由度が出て便利です。
ソフトウェアシリアルは入出力端子を自由に割り付けられるのでもっと便利ですが、プログラム容量は少し大きくなります。「UART0,1」の端子がどうしても使えない場合にプログラムメモリに余裕があれば使用しましょう。
動作確認には「M5Stack BASIC」を使用した外付けのシリアルモニタで簡単に行えます。
作り方(コピペで書き込むだけ)は以下のリンクで詳しく紹介しています。
コメント