M5StackからiPhoneへBluetoothを使って気温データを送ってみる。
で予告した件の調査あんど実験コーナー。本来の目的はM5Stackとは言ってもCoreInkなのですが、いきなりCoreInkでやるのではなく、まずは同じESP-32を使っているM5StackでBluetooth通信をiPhoneとやってみます。
参考サイト
↑こんなばっちりな情報を発見。まずはこれができるようになろうとおもいます。
いきなり用語解説とか
(参考サイトからのコピペ)
BluetoothLEの基礎知識
デバイスの役割として、ペリフェラルとセントラルがある
ペリフェラルは、発信する側 → 親機
セントラルは、受診する側 → 子機
GATT → 通信のベースとなるプロファイル
write、read、notifyの3つがある
writeは、セントラル→ペリフェラルにデータを渡す
readは、セントラル→ペリフェラルに読み込みデータを要求する
notifyは、ペリフェラル→セントラルに通知する
この用語をしっかり頭に入れて、参考サイトとソース(GitHub)を眺めます。
UUID取得
自分(というかこのプログラム)専用にOnline UUID GeneratorをつかってUUIDを3つ取得してきます。
Bulk Version 1 UUID Generation で How Many? を 3 と入力して GENERATE すればOK。
今回はこの cb577~0002 とある3つの文字列がUUIDコードです。(もちろん私専用のコードなので、皆さんは別のを使ってね☆)
M5Stack側の設定
参考サイトにある説明の通りにセットアップ、
#define SERVICE_UUID "cb5776c8-4719-11eb-b378-0242ac130002" #define CHARACTERISTIC_UUID_RX "cb5778ee-4719-11eb-b378-0242ac130002" #define CHARACTERISTIC_UUID_NOTIFY "cb5779de-4719-11eb-b378-0242ac130002"
と3つのUUIDをセットすればそのまま実行できます。
鬼門のiOS(ちょっとグチ)
さぁて、苦手なiOSの方です……。
これって、いっつも思うのだけれど、なんでこんなにめんどくさいのですかねえ。。
だいたいがセキュリティに関する問題なんだとおもいますけど、商売する(アプリを売る)わけでもないのにとぉおーーーーーっても面倒。
XCodeという開発環境がしょっちゅうバージョンアップされるし、そのたびに画面もアイコンもガラッとかわってしまって、せっかくやり方覚えても無駄になること多数。
さらに使ってる言語すら変わるんですよねー。最初のころはObjective-Cって言語だったのに、Objective-Cは初心者に難しいから簡単にしたSwiftって言語新しくつくりましたんでそっちでやって! ってことになって、覚え始めた言葉がまるっきりかわっちゃう。
iOS上の画面についてもStoryBoard使ってたと思ったらいきなりSwift-UI推奨になったりと、ぼんやり学習しているとぜんぜんおいつきません><
などなど、久しぶりにやってみようかなって言うたびにまたゼロから学びなおしになるのでとっても大変なのです><
今回のバージョンメモ
MacOS Catalina Version 10.15.7
Xcode Version 12.3 (12C33)
iPhone 7 plus (iOS Version 14.2)
でやっています。(これが合っていないとまた混乱するです><)
とりあえず参考コードを実行するまでで悩んだ点
今回、参考サイトがStoryboardを使っているSwiftなので、それに合わせて調べなおさないといけません。おかしいなと簡単にググっても、親切に書いてある参考サイトはたいてい別のバージョン(の開発環境)用の説明なので、そのまま鵜呑みにはできないのです><
ちょっと何かやろうとするとすぐつまづく素人にはけっこう大変。敷居も高くてひっかかりポイント多々ありまくりでしたが、ぐぐる先生に聞きまくってなんとかかんとかやっつけました。
ヒントや答えを教わったページを列挙しておきます。
↑これをそれぞれ見つけるまでにも何時間も、へたしたら何日もかかっちゃうのですよねー。
わかってりゃ当然で楽勝なことなんでしょうけど、いちいちひっかかって大変でした><
で、ようやく!
↑ここまではできるようになりまった!
M5StackとiPhoneはBluetoothで接続(ケーブルはつながっていません)されていて、ボタンを押すとどちらの画面も連動して同じ色になる仕組みです。
※そうそう、エミュレータでBluetooth関連はうまく実行できませんでした。。やる方法はあるみたいなのだけれどそれまた大変そうなんで今回は実機にそのままつっこんでやっています。
赤くなったり
青くなったり。ちゃんと連動しています(∩´∀`)∩☆
ようやくここまで出来たので、次はM5Stackに温度センサ(ENV-II)を取り付けて、そのデータを送るように改造してみます。
温度センサをつなげてデータを送る
M5Stack側は、いつものようにサンプルソース(ファイルー>スケッチ例ー>M5Stackー>Unitー>ENVII_SHT30_BMP280)
それでひろってきたコードと、先ほどのM5StackのBluetoothのテストコードを合体させます。
具体的には、メインループの中に
void loop() {
M5.update();
//環境センサの値ゲット
pressure = bme.readPressure();
if(sht30.get()==0){
tmp = sht30.cTemp;
hum = sht30.humidity;
}
loopBLE();
loopLCDcolor();
}
環境センサの値をゲットするように仕込んで(pressure、tmp、humなどはグローバル変数)
Bボタンを押したら、
if (M5.BtnB.wasPressed())
{
//lastColor = "YELLOW";
char buftmp[10]="";
sprintf(buftmp,"%2.1f C ",tmp);
lastColor = buftmp;
Serial.println(lastColor);
updateColor = true;
}
本来”YELLOW"と送られる文字列を気温データにして無理やり送ってみます。
iOS側
ではいよいよiOS側。
これまた(なにしろ不得意なので)色々調べながら改造です。
ここらへんでざっと予習して、
このあたりや
このあたりにちょー基本的なSwiftのお作法をおしえてもらいながら進めます。
とりあえず先程の赤・黄・青の画面アプリをそのまま使って改造していきます。
まず VewController.swift の
override func viewDidLoad() {
の手前に
let textView = UITextView()
でtextViewを定義します。
でもって、
func viewDidLoad()
内の、
super.viewDidLoad()
の直後に、
// TextViewの配置
//let textView = UITextView()
textView.frame = CGRect(x: 0, y: 0, width: 300, height: 300)
textView.center = self.view.center
textView.textColor = UIColor.red
textView.font = UIFont.systemFont(ofSize: 15)
textView.text = "ログエリア"
textView.backgroundColor = UIColor.gray
self.view.addSubview(textView)
と入れてやります。
こんなかんじです。
画面の中央にログエリアというTextViewをセットしたわけですね。
続いて、
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
の中の、
if let value = characteristic.value , let str = String(data: value, encoding: .utf8) {
内に
/// Date&Time追加
let date = Date()
let formatter = DateFormatter()
formatter.dateStyle = .short
formatter.timeStyle = .short
let datestring = formatter.string(from: date)
debugLog(datestring)
// textViewにBluetoothからのテキストを追記
textView.text = textView.text + datestring + " \(str)\n"
と入れてやります。
ついでなので
DispatchQueue.main.async {
というところの中もちょっと追記して
if str == "RED" {
self.imageView.backgroundColor = UIColor.red
self.textView.text = "" // 赤の時はText消去
赤の時は画面をクリヤするようにしておきます。
こんなかんじですね。
いやー、簡単そうに書いてますけど、ここにたどり着くのが大変でした><
さてさて、じゃ、実行してみます。
実行してみる
最初に出るのはこんな画面。中央灰色の「ログエリア」というところに、Bluetooth通信で受信した文字列が表示されます。
今までもREDという文字列が来たら赤く、YELLOWなら黄色、BLUEなら青という風に画面の色をかえていました。あれ、文字列で通信していたんですね。なのでそのままそのプロトコルをお借りして、M5Stackで黄色ボタンを押したときに温度情報を送るように改造したわけです。
ちょっと操作してみます。
いろいろ連打するとこんな具合。
M5からREDを送ると、画面をクリヤするようにしてあります。
また、iPhone側から送信してもログにでるので、YELLOWはiPhone側から操作した情報です。(入出力情報を出してもいいけど、まあ今はそこまではしなくていいや)
とりあえずできたかんじ。(∩´∀`)∩☆
ちかれたー><
まだ実験なのでとりあえず動くだけですが、このままでも表示エリアを選択してコピーしたり、手動ですがクラウドにあげたりできるようになっています。大変だったのでiPhone側はこのままでもいいかも?w
次回以降はM5側をCoreInkに移植して、RTCの設定等をくわえていってみようとおもいます。
また長くなっちゃったんで今日はここまで!☆
よろしければサポートお願いします!いただいたサポートはクリエイターとしての活動費にさせていただきます!感謝!,,Ծ‸Ծ,,