Raspberry Pi Pico WとパソコンをBluetoothシリアル通信で接続してステッピングモータを制御する実験を紹介します。
Bluetoothには古くから存在するBluetoothクラシックと、後から開発され消費電力を大幅に削減出来るBluetooth Low Energyがあります。それぞれ互換性はありません。Raspberry Pi Pico Wは両方の規格に対応しています。
今回はパソコンのCOMポートと簡単に接続できるBluetoothクラシックのシリアルポートプロファイルを使用してパソコンとRaspberry Pi Pico Wを接続してステッピングモータの動作を制御することを行いました。
以前の記事でパソコンからのUSBシリアル通信によってステッピングモータの回転、停止を行うプログラムを紹介しました。今回はそのプログラムを改造しました。(ステッピングモータをUSBシリアル通信で制御する記事はこちら)
プログラミングツールとしてはArduino IDEを使用し、ステッピングモータの駆動にArduino言語のStepperライブラリを使用しています。
実験装置
ステッピングモータは28BYJ-48とそのドライバーボードのセットを使用しました。このステッピングモータとドライバーボードは複数のネット通販から購入することが出来ます。
コントローラとしてはRaspberry Pi Pico Wを使用して実験装置を組みました。(ステッピングモータ駆動の詳細に関してはこちらを参照して下さい)
今回使用したステッピングモータの主な仕様は表1の通りです。このモータは1/64のギアで減速されていて、1-2相励磁の場合にステップ角は5.625°/64なので4096ステップでモータ軸が1回転します。最大自起動周波数が500ppsなので、500パルス/sec以下で起動する必要があります。起動後は徐々に加速を行った場合に、最大で1000パルス/secまで仕様上は可能と思われます。
ただし、Stepperライブラリーのstep()関数を使用した場合の励磁方式は2相励磁のようです。そのため2048ステップでモータ1回転となります。
項目 | 仕様 |
相数 | 4相 |
励磁方式 | 1-2相励磁方式 |
ステップ角 | 5.625°/64 (減速比1/64) |
電圧 | 5VDC |
相抵抗 | 22Ω ± 7% 25°C |
最大応答周波数 | 1000pps |
最大自起動周波数 | 500pps |
引き込みトルク | 800gf.cm / 5VDC 400pps |
実験装置回路図
図1に実験装置の回路図を示します。1個のステッピングモータをRaspberry Pi Pico Wと接続しています。
28BYJ-48ステッピングモータのドライバーボードはテキサスインスツルメンツのULN2003ANと言うダーリントントランジスタアレイが使用されています。ドライバーボード自体の資料が無かったので、テスタと基板のパターンを見て回路を調べました。
ステッピングモータのドライバーボードの入力信号IN1~IN4をRaspberry Pi Pico WのGP0~GP3に接続しました。
Bluetoothシリアル通信を使用してパソコンと接続します。
Arduino IDEでBluetoothシリアル通信関係関数を使用するための設定
Raspberry Pi Pico WでBluetoothシリアル通信を行うためのArduino IDEの設定を以下に示します。使用したArduino IDEのバージョンは2.2.1です。
Arduino IDEを起動して「ツール」→「IP/Bluetooth Stack:」で「IPv4 + Bluetooth」を選択します。
Bluetoothシリアル通信関係関数
Raspberry Pi Pico WでのBluetoothのシリアル通信は、
#include <SerialBT.h>
を行うと通常のシリアル通信ライブラリSerialとほぼ同様の関数が使用出来ます。
今回のプログラムでは文字列(String型)のデータを送受信するので、String型のデータを送受信する関数を表2に示します。
関数 | 説明 |
SerialBT.begin(speed) | Bluetoothシリアル通信を開始します。 引数:ボーレート(int) 省略した場合は115200となります。 |
SerialBT.available() | シリアルポートに到着しているデータ数を返します。(戻り値 int) |
SerialBT.print(data) | 文字列を送信します。引数:data 文字列(String型) |
SerialBT.println(data) | 文字列の末尾に’\r’と’\n’を付けて送信します。 引数:data 文字列(String型) |
SerialBT.readString() | データを文字列(String型)として読み込みます。 |
SerialBT.readStringUntil(terminator) | データを改行コードまで文字列として読込ます。 引数:terminator 改行コード(char型) |
Raspberry Pi Pico Wのプログラム
以前の記事のパソコンからのUSBシリアル通信指令によってステッピングモータの回転、停止を行うプログラムをBluetoothシリアル通信用に改造しました。(ステッピングモータをUSBシリアル通信で制御する記事はこちら)
基本的には、#include <SerialBT.h>を行って以前のプログラムで、Serial.となっていた部分をSerialBT.に変更するだけでBluetoothのシリアル通信が行えます。以下にプログラムを3個の部分に分けて説明します。
1.初期処理 setup()関数等
初期処理を行うsetup()関数等のソースコードを以下に示します。プログラミングツールとしてはArduino IDEを使用しています。
3行目の「#include <SerialBT.h>」でBluetoothシリアル通信関係ライブラリをincludeしています。これでprintln()等の通常のシリアル通信の関数が使用出来るようになります。
26行目の「SerialBT.begin(9600);」でBluetoothシリアル通信をスタートしています。引数9600はボーレートですが、指定しない場合は115200となります。
その他の部分は以前のUSBシリアル通信使用の記事とほぼ同様です。(以前の記事はこちら)
ステッピングモータを起動するのにArduino言語のStepperライブラリーを使用しています。ステッピングモータの回転速度をsetSpeed()関数で500rpmに設定していますが、実際には1ステップずつの送りしかしないので、setSpeed()関数では回転速度は決まりません。他の処理を行うためにstep()関数からは出来るだけ速く抜け出るようにsetSpeed(rpms)のrpmsの値は大きめに設定しています。
一定時間間隔毎に処理を行うための間隔時間を
delay_time = 60 * 1000 * 1000 / STEPS / RPM_SPEED;
でモータの回転速度(rpm)と1回転のステップ数から計算しています。時間の単位はμsecです。
//--Raspberry Pi Pico W Bluetooth JOG運転テストソフト-------------
#include <Stepper.h>
#include <SerialBT.h>
#define RPM_SPEED 10 //モータ回転速度(rpm)
#define STEPS 2048 //モータの1回転のステップ数
//軸の現在位置記憶用データ(符号付きステップ位置)
long current_pos = 0;
//経過時間判断用データ
unsigned long last_time = 0; //前回の時間記憶
unsigned long delay_time = 0; //処理待ち時間(次の処理をするまでの時間)
//シリアルデータ受信処理用データ
String s_rcvData; //受信文字列
//回転指令フラグ
bool cw_mov_flag = false; //CW回転指令フラグ
bool ccw_mov_flag = false; //CCW回転指令フラグ
//ステッピングモータ初期設定
Stepper stepper(STEPS, 0, 2, 1, 3); //ステッピングモータ設定(1回転2048ステップ)
void setup() {
SerialBT.begin(9600); //Bluetoothシリアル通信スタート
pinMode(0, OUTPUT); //ステッピングモータ(青線)
pinMode(1, OUTPUT); //ステッピングモータ(桃線)
pinMode(2, OUTPUT); //ステッピングモータ(黄線)
pinMode(3, OUTPUT); //ステッピングモータ(橙線)
//ステッピングモータ回転速度設定
stepper.setSpeed(500); //ステッピングモータの回転速度500rpm
//処理待ち時間の設定
delay_time = 60 * 1000 * 1000 / STEPS / RPM_SPEED;
}
2.メイン処理 loop()関数
メインの処理を行うloop()関数のソースコードを以下に示します。この部分は以前のUSBシリアル通信使用の記事とほぼ同様です。(以前の記事はこちら)
3行目のreadBluetooth()関数でパソコンからのBluetoothシリアル通信データを受信しています。
パソコンからBluetoothシリアル通信データを受信すると5行目のcom_interpreter()関数で受信データの内容を確認しています。com_interpreter()関数では受信データを調べて、CW方向回転フラグ(cw_mov_flag)とCCW方向回転フラグ(ccw_mov_flag)を設定しています。
前述した前回の処理からの経過時間を計算して、経過時間が予定した時間を過ぎたときに、cw_mov_flagとccw_mov_flagの状況に応じてステッピングモータの1ステップ回転処理を実行します。
void loop() {
//Blutoothデータ受信処理
bool res = readBluetooth();
if (res == true) { //受信完了
com_interpreter(); //受信コマンド解釈処理
}
//前回処理からの経過時間計算
unsigned long pass_time;
unsigned long now_time = micros(); //現在時刻読出し(usec単位)
if (now_time >= last_time) {
pass_time = now_time - last_time; //経過時間計算
} else {
//オーバフローを加味して経過時間計算
pass_time = now_time - (0xffffffffUL - last_time + 1);
}
//モータ回転処理
if (pass_time >= delay_time) { //時間到達?
last_time = now_time;
if (cw_mov_flag == true) { //CW回転?
stepper.step(-1); //-1ステップ回転
current_pos--; //現在位置マイナス
//現在位置をPCへシリアル通信
serial_pos();
} else if (ccw_mov_flag == true) { //CCW回転?
stepper.step(1); //1ステップ回転
current_pos++; //現在位置プラス
//現在位置をPCへシリアル通信
serial_pos();
}
}
}
3.Bluetoothシリアル通信処理と通信コマンド解釈処理関係関数
Bluetoothシリアル通信を使用して現在位置の送信処理を行うserial_pos()関数と、コマンドの受信処理を行うreadBluetooth()関数と、受信したコマンドを解釈するcom_interpreter()関数のソースコードを以下に示します。
2行目のserial_pos()関数は、ステッピングモータの現在位置(変数名 current_pos)の値をBluetoothシリアル通信でパソコンに送信しています。
5行目の「SerialBT.println(text);」でBluetoothシリアル通信で文字列データ(String型)を送信しています。
println()関数は、引数で与えられた文字列に改行コード’\r’と’\n’を末尾に添付して送信します。
10行目のreadBluetooth()関数は、Bluetoothシリアル通信でコマンドデータを受信します。コマンドデータは最終文字が’\n’となっています。
16行目の「s_rcvData = SerialBT.readStringUntil(‘\n’);」は’\n’までのデータを文字列(String型)として受信します。
readStringUntil()関数は、データの受信が終了するまで抜け出てきません。この関数をいきなり置くと受信データが無い時にそこで留まってしまいその他の処理が出来ません。
13,14行の
int rNo = SerialBT.available();
if (rNo >0){
の部分で、受信したデータ数を見て受信データが存在する時のみreadStringUntil()関数でデータを呼び出しています。
26行目のcom_interpreter()関数は、パソコンから受信したコマンドの文字列を解釈します。
“CW”を受け取った場合は、ステッピングモータをCW方向に回転させるので、cw_mov_flagをtrueにします。
“CCW”を受け取った場合は、ステッピングモータをCCW方向に回転させるので、ccw_mov_flagをtrueにします。
“STOP”を受けっとった場合は、ステッピングモータを停止させるので、cw_mov_flagとccw_mov_flagを共にfalseにします。
//現在位置をBluetoothシリアル通信で送信
void serial_pos() {
String text_x = String(current_pos);
String text = String("X:" + text_x);
SerialBT.println(text); //現在位置をPCへ送信(Bluetooth)
}
//Bluetooth受信処理
//戻り値: ture 受信完了、false 受信未完了
bool readBluetooth() {
bool rdEndFlag = false; //受信完了フラグ
int rNo = SerialBT.available(); //受信データ数読込
if (rNo > 0) { //受信データ有り
//'\n'までの受信データを読み込む
s_rcvData = SerialBT.readStringUntil('\n');
rdEndFlag = true; //受信完了フラグセット
} else {
rdEndFlag = false; //受信完了フラグリセット
}
return rdEndFlag;
}
//パソコンからの受信データコマンド解釈
void com_interpreter() {
if (s_rcvData.startsWith("CW") == true) { //"CW"?
ccw_mov_flag = false; //ccw回転フラグリセット
cw_mov_flag = true; //CW回転フラグセット
} else if (s_rcvData.startsWith("CCW") == true) { //"CCW"?
cw_mov_flag = false; //cw回転フラグリセット
ccw_mov_flag = true; //CCW回転フラグセット
} else if (s_rcvData.startsWith("STOP") == true) { //"STOP"?
cw_mov_flag = false; //cw回転フラグリセット
ccw_mov_flag = false; //ccw回転フラグリセット
}
}
Bluetoothシリアル通信を行うためのパソコン側の処理
今回はパソコンとRaspberry Pi Pico WをBluetoothシリアル通信接続します。Bluetooth接続するためのパソコンの設定手順を以下に示します。
使用パソコンのOSはWindows 11です。
「設定」を開き「Bluetoothとデバイス」をクリックします。
「Bluetooth」を「オン」にします。
「その他のデバイスを表示」をクリックします。
「Bluetoothデバイスの検索」を「詳細」にします。これを「詳細」にしないと、「デバイスの追加」を実行した時にBluetoothシリアルポートのデバイスが表示されません。
「Bluetoothとデバイス」画面に戻り「デバイスの追加」をクリックします。(前記のプログラムが書き込まれたRaspberry Pi Pico Wが近くに存在し、電源が投入されている必要があります)
次の画面が表示されたら、「Bluetooth オーディオデバイス、マウス、キーボード、電源、ペン、コントローラなど」をクリックします。
「デバイスを追加する」と表示され、しばらくすると「PicoW Serial —–」と表示されます。PicoW Serialの後に表示される文字列(ここでは28:CD:C1:0E:32:6D)はRaspberry Pi Pico WのBluetoothのアドレスです。BluetoothのアドレスはBluetoothのICチップ毎に異なります。
「PicoW Serial—-」が表示されたら、この部分をクリックします。
以下画面が表示されたら「接続」をクリックします。「接続」の左上に表示されている数字(ここでは804238)は、データ暗号化のためのキーでパソコンとRaspberry Pi Pico Wとの間でこの数値が交換されています。Raspberry Pi Pico W側はSerialBTライブラリ内で数値の処理が行われているようで特に操作する必要はありません。
一度追加されたデバイスを削除して、再び追加した時、この数値は変わります。
「デバイスの準備が整いました!」の表示がされて、「PicoW Serial—-」の下に「接続済み」が表示されます。
但し、この「接続済み」の表示は、しばらくすると「切断」の表示に切り替わります。ペアリング時に一時的に接続してペアリング完了時に切断するためだと思われます。(ペアリングとはデバイス間で暗号化のキーを交換することです)
「デバイスの準備が整いました!」と表示されている画面を閉じて、「Bluetoothとデバイス」画面を見ると、「Pico W Serial—–」が「ペアリング済」と表示されています。ここで「その他のデバイスを表示」を再びクリックします。
表示された画面の「その他のBluetooth 設定」をクリックします。
以下の画面が表示されたら「COMポート」タグを開くとBluetoothシリアルポートのCOMポートの割り当てが表示されます。
方向が「発信」となっているCOM4がパソコンから接続する時使用するCOMポート名称になります。(COM5は相手から接続された場合のCOMポートですが、今回は使用しません)
以降COM4をBluetoothシリアルポートとして記述します。
Bluetooth通信テスト方法
Arduino IDEのシリアルモニタを使用してBluetoothシリアル通信の接続テストを行う方法を以下に示します。使用したArduino IDEのバージョンは2.2.1です。
Arduino IDEを起動して「ツール」→「シリアルモニタ」をクリックしてシリアルモニタ画面を表示します。
シリアルモニタ画面が表示されたら、右側にある選択項目欄の「LFのみ」と「9600 baud」を選択します。
Bluetoothシリアルポートのポート名は「COM4」なので、「ツール」→「ポート:」で「COM4」を選択します。
「Connecting to ‘Raspberry Pi Pico W’ on ‘COM4’…」の表示が出ます。
しばらくするとパソコン画面の右下辺りに下記のような「デバイスの追加」の通知表示が出ますので、それをクリックします。
「デバイスをペアリングしますか?」と表示されるので、「はい」をクリックします。「はい」の左上に表示されている数字(ここでは527811)は、データ暗号化のためのキーでパソコンとRaspberry Pi Pico Wとの間でこの数値が交換されます。Raspberry Pi Pico W側はSerialBTライブラリ内で数値の処理が行われているようで特に操作する必要はありません。ペアリングをする毎にこの数値が変わります。
「通信成功」の画面が出たらこの画面を閉じます。
Arduino IDEのシリアルモニタ画面の送信データ欄に「CW」か「CCW」か「STOP」の文字列を入力してEnterキーを押すとステッピングモータが、以下に示す動作をします。
CW 時計方向回転
CCW 反時計方向回転
STOP 回転停止
ステッピングモータ回転中は受信データ表示欄にRaspberry Pi Pico Wから送られてくる現在位置データが表示されます。
動作の動画
以下動画は、Raspberry Pi Pico Wに今回作成したプログラムを入れて、パソコン側はArduino IDEのシリアルモニタを使用してポートをBluetoothシリアル通信に対応したCOM4を使用した場合と、以前の記事で紹介したUSBシリアル通信を使用したパソコンの操作パネルソフトを使用した場合のステッピングモータを動作される様子です。(USBシリアル通信を使用したパソコンの操作パネルソフトの記事はこちら)
最後に
パソコンとRaspberry Pi Pico WとをBlutoothシリアル通信で接続して、ステッピングモータの動作を操作することが出来ました。無線でのモータの操作のため様々な用途に応用出来ると思います。
今後は消費電力を大幅に削減したBluetooth Low Energyのプログラムの作成にも挑戦したいと思います。