サイクルコンピュータを自作する — GPS トラッキング

今から数えてちょうど1年前 — 2018 年の 11 月に日本の衛星測位システム 『みちびき』の運用が開始されました

これは米国の GPS と協調して測位精度を向上させたり、2k bps もの伝送量のある信号を送信してセンチメータ級の測位補強情報を提供する日本独自の画期的な取り組みを行ったりしています。

ごく最近までの衛星信号の民生利用では、およそ 20,000 km も離れた位置にある GPS の微弱な信号しか拾えないことが一般的で、誤差も 10.0 m ぐらいあることが当たり前でした。

ロシアの GLONASS の信号が拾えるのは良い機器で、他の衛星(たとえばヨーロッパの Galileo や中国の北斗)の信号まで拾えるモジュールは個人では手が出せないような値段が付いていました。

それが現在では誤差 2.5-3.0 m 程度の高精度モジュールが 2,000 円から 5,000 円ぐらいで市販されていて、その一部は日本の『みちびき』にも対応しています。

さらに SONY に至っては衛星信号受信モジュールを標準搭載したボードコンピュータまで販売しています。これを使うと SONY 製のサイコンを作れます


SONY SPRESENSE メインボード

これから衛星測位システムの活用が本格化し、測位精度も高まってくるとホイールの回転数から移動速度を推定するよりも、距離と時間から速度を求めるほうが正確な数値を得られるのではないか…と思うかどうかは別として、わりと簡単に実装できるので知っておいて損はないかと思われます。

そこで、みんな大好き、GPS 受信機キット (太陽誘電社 GYSFDMAXB) を用意しました。




これと Raspberry Pi を組み合わせると、それだけでも市販のサイコンよりも高機能な玩具が作れます。しかし、どうせ雨で濡れたり、ダウンヒルで飛んでいったりするので、ここではそんなに高価で高性能なものは求めません。

安価で小型で通信機能が使えればいいということで ESP32 を使います。


ESP32 ESP-32S 2個セット NodeMCU-32S ESP32-WROOM-32 開発ボード 2.4GHz WiFi + Bluetooth

これを使って GPS 受信機キットで受信した測位情報を BLE でスマートフォンに転送し、 SQLite にログを残したり、走行記録を地図上にオーバーレイ表示することを考えているわけです。

取り付けようと思えば、液晶ディスプレイなども付けられますが、大きく、重たく、電池消費量が激しくなるだけで実用性があまりないので、個人的には不要に思えます。

また反対に機能を削って走行記録を SD カードに残すだけならば、さらに小型化しつつ稼働時間を伸ばせますが、それでは地味でつまらないので、必要なときだけスマートフォンの液晶ディスプレイを借りる方針です。

BLE 通信で接続するので、うまくやらないとスマートフォンのバッテリを無駄に消費する懸念があります、というか、そこを調べることが最大の目的で GPS もサイコンも本当はオマケです。

ただ、いきなり、スマートフォンのアプリ開発という重たいタスクに取り掛かるのは大変なので、今回は測位情報を Bluetooth で送信するところまでを行います。

まずは ESP32-WROOM-32 のデータシートを見て Pin Layout を確認します。そこから TxD の接続先がわかりますので、線でつないでスケッチを動かしてみます(RxDはいまのところは不要です)。

#include "HardwareSerial.h"
#include "BluetoothSerial.h"
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run 'make menuconfig' to and enable it
#endif

BluetoothSerial SerialBT;
HardwareSerial mySerial(2);

void setup() {
  SerialBT.begin("Hoge");
  mySerial.begin(9600, SERIAL_8N1, 34, 35);
}

void loop() {
  if (mySerial.available()) {
    SerialBT.write(mySerial.read());
  }
  delay(1000);
}

このスケッチをコンパイルしてアップロードすると、ESP32 は Bluetooth で測位情報を送信し続けるようになるはずなので、無事にデータ送信ができているかどうかを確認します。

うまくアップロードを行えない場合は、こちらを参考にしてみてください

送信されたデータを Linux で確認するには rfcomm コマンドを使用してシリアルポートにバインドしてしまえば良いです。

$ sudo bluetoothctl
[bluetooth]# power on
Changing power on succeeded
[bluetooth]# scan on
Discovery started
[bluetooth]# pair 00:00:00:00:00:00 
Attempting to pair with 00:00:00:00:00:00
[bluetooth]# exit
$ sudo rfcomm connect /dev/rfcomm0 1 00:00:00:00:00:00
Connected /dev/rfcomm0 to 00:00:00:00:00:00 on channel 1
Press CTRL-C for hangup
$ sudo cat /dev/rfcomm0 

※ 00:00:00:00:00:00 は架空のMACアドレスです

できましたら、ファイルを標準出力に表示するときと同様に cat で出力できるようになります。上の例ですと、GPS受信機キットの出力をそのまま Bluetooth に流してしまっていますけれども、いちど Arduino Serial Monitor に書き出して内容を確認してから同じものが表示されるかどうかを確かめたほうが安全かも知れません。

ともかく、これで位置情報を表示できていれば、ESP32 側の準備は万端です。

ここまでは難しいことはないのですが、遠隔でセンサデータを取得できるのはいつ見ても楽しいものですね。

スマートフォン側のアプリ開発は、こう簡単にはいきません。

BLE通信が前提になりますので、少しばかり手間と時間がかかります。

いま忙しくて、実際に走行ログを集めに行く暇もないので、だいぶ後回しになりそうな気がしますが、せっかくなので既存のサイコンと同一条件で計測を行って、結果を比較してみたいですね。


つづき: サイクルコンピュータを自作する #2 – みちびき対応 GPS と市販のサイコンの比較実験


関連: Garmin / Strava の走行記録をまとめて表示する

ESP32 開発ボードを Arduino IDE で扱う

ESP32-WROOM-32 を Arduino 互換機として設定するための自分用の備忘録です。

これは ESPRESSIF という上海の企業が製造しているマイコンボードです。なんと WiFi と Bluetooth Low Energy (BLE) がデフォルトで使えて、お値段は 1,300 円という汎用性抜群の便利アイテムです。

日本の技適認証もきちんとクリアされていて、箱から出した状態のまま使えます。BLE モジュールを購入してきて苦労していた過去の自分がアホらしく思えてくるほどの性能です。

ただし、ESP32 自体は Arduino ではありませんので、互換機として使用するには自身で設定を行う必要があります。

とは言え、既に先行事例がたくさんありますので、難しいポイントは皆無です。


arduino-esp32/boards_manager.md at master · espressif/arduino-esp32 · GitHub
https://github.com/espressif/arduino-esp32/blob/master/docs/arduino-ide/boards_manager.md


開発プラットフォームを設定するには、製造元の公開している資料(上のリンク)に従って Arduino IDE (Ver. 1.8 以降)に必要なファイルを読み込みこみます。




まずは Arduino IDE を開く前に必要なファイルを準備します。この過程で Python 3 が必要になります。

$ mkdir -p /usr/local/share/arduino/hardware/espressif && cd /usr/local/share/arduino/hardware/espressif
$ git clone https://github.com/espressif/arduino-esp32.git esp32
$ cd esp32 && git submodule update --init --recursive
$ python tools/get.py 

ここまで準備ができましたら Arduino IDE を起動して、Crtl と カンマ [Comma] キーを同時に押して Preferences ウィンドウを立ち上げます。

そして Additional Board Manager URLs の最後尾に  https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json を追記して OK を押します。

そうすると Tools > Boards Manager… に ESPRESSIF が出てくるので、これをインストールします。

使用するのは ESP32 Dev Module というやつです。

こいつはスケッチをアップロードするときに pyserial (Python ver 2) を使用するので、あらかじめインストールされていない環境ではエラーを吐きます。

エラーに慌てずに、必要なライブラリをインストールしてやれば問題ありません。

$ sudo pip2 install pyserial

これで一応は万全です。

まだ下記のようなエラーを吐くことがあるのですが、この場合は Tools > Upload Speed から転送速度を 115200 に変更します(デフォルト値は 912600 になっているようです)。


Serial port /dev/ttyUSB0
Connecting…….._____….._____….._____….._____….._____….._____…..____ An error occurred while uploading the sketch
_

A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header


そしてスケッチの転送時にボード本体の Boot ボタンを押してやります。

ボタンを押しながら転送を始めるぐらいでいいかもしれません。

これでもスケッチを書き込めないときは、正しいポートを選択できているかどうかを確認してみて下さい。

うまくいった場合には書き込みが始まります。

ESP32 にはサンプルが大量に用意されていますので、無事にスケッチを書き込めるようになりましたら、まず一通りのサンプルを動かしてやると挙動がつかめるようになります。

自作のコンベアベルトにセンサを積むも無事に失敗

慣れない模型作りに四苦八苦しながら、それでも数時間かけてコンベアベルトのハードウェアの部分を完成させたのが前回の話です。

このハードウェアに電子回路を載せて、画像認識用コンベアベルトのプロトタイプとして動かしてみることが当面の目的です。

これで上手く動作するようであれば、本格的なセンサ付きコンベアベルトの製作を考えます。

挙動を調べるためのプロトタイプにおいて画像認識の問題で引っ掛かりたくないので、判別対象をシンプルな単色ブロックにして、RGBカラーセンサをカメラの代用にすることに決めました。

使用するセンサモジュールはこちらです。

このモジュールには白色LEDライトが搭載されており、近くにあるものの色を三原色の数値で表します。


TCS34725 RGBライトカラーセンサー認識モジュール

以下のリンクからライブラリを入手して、プログラムの冒頭部分で読み込んでおくと、簡単に使えるようになります。


GitHub – adafruit/Adafruit_TCS34725: Driver for Adafruit’s TCS34725 RGB Color Sensor Breakout
https://github.com/adafruit/Adafruit_TCS34725





このセンサで対象物の色情報を読み取りましたら、その出力結果をサーボに反映させ、色によって角度を4段階に変更できるように設定します。

コンベアベルトに運ばれてきた4色のブロックを色ごとに分類して、色別の箱のなかに落とすことが最初の目標です。


SG90-HV 360度旋回タイプ デジタル・マイクロサーボ

そのためにサーボをコンベアベルトの末端に取り付けて、ブロックが落ちる先の角度を制御します。

肝心のコンベアベルトを動かすのは、前回の記事の最後に取り上げた H-bridge モータドライバです。

こいつは非常に優秀でステッピングモータと組み合わせると、センサの真下で対象物を止めたり、判定の対象物以外が投げ込まれたときに回転の向きを変えて異物を押し戻したりといった細かな作業ができます。

見ての通り、小さくてハンダ付けが大変な点と発熱が凄まじい点にだけ注意が必要です。

今回はDCモータに直接つないでしまうので回転速度の調整ぐらいにしか役立ちませんが、これだけならライブラリを読み込まなくても使えます。

TCS34725 RGBカラー認識モジュールは照度も計測できるので、コンベアベルトで対象物を動かしつつ、照度が最大になった時点、つまり、センサと対象物の距離が最短になった時点の観測値を用いてサーボを動かせば、計測ごとに回転を止める必要もないかという考えです。

照度は光源からの距離の二乗に反比例するので、最大値を求める際の範囲の決定、つまり、コンベアベルト上に対象物が乗っているか否かも照度を使えば区別できます。

このアイデアでうまく動くことを期待して作成したものが以下のスケッチです。

#include 
#include 

// Params for the DC motor
const int MINPUT = 5;
const int SPEED = 110;
//const int VR = A0;

// Params for the servo
Servo myservo;
const int SINPUT = 9;

// Params for the color sensor
uint16_t r, g, b, c, colorTemp, lux;
Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_700MS, TCS34725_GAIN_1X);

// servo horn angles
const int RED = 30;
const int GREEN = 60;
const int BLUE = 90;
const int YELLOW = 120;

void setup()
{
  Serial.begin(9600);
  if (tcs.begin()) {
    myservo.attach(SINPUT);
    analogWrite(MINPUT, SPEED); // runs DC motor
  }
  else {
    Serial.println("TCS34725 not found");
  }
}

void loop() {
  tcs.getRawData(&r, &g, &b, &c);
  Serial.print(r, DEC); Serial.print(",");
  Serial.print(g, DEC); Serial.print(",");
  Serial.print(b, DEC); Serial.print(",");
  Serial.print(c, DEC); Serial.println("");

  int color = getColor(r, g, b, c);
  myservo.write(color);
}

int getColor(int r, int g, int b, int c) {
  return -1;
}

プログラム的には問題なく動きます。しかしRGBセンサから取得した数値を自身で色に変換しないといけません(この部分が未完です)。

なぜかと言えば、周辺環境(センサモジュール以外の光源)の影響を強く受けるので、あらかじめ決められた値を用いて場合分けをしても、うまく動かないことがあります

判別対象は単色のブロックなので、RGBの比率だけで判別できるかと思いきや、周辺の明るさで敏感に値が変わります。

それを全てルールベースで条件分岐として書き表していくのは やってられない と思いました。

率直に言い換えると機械学習を使いたいです。

そうなると 8bit マイコンには荷が重いので Raspberry Pi の導入を検討しなければなりません。


Raspberry Pi Zero W – ラズベリー・パイ ゼロ W ワイヤレス

私は Raspberry Pi を持っていないどころか、今までに触ったこともないんですよね。Arduino ではマイコンにブートローダを焼いてコピーを増やせることと比較すると、本体が高価で複製もできない点が不便に感じます。

センサと一緒に基盤にハンダ付けして、どこかに設置するという使い方ができなくなりますので。

また 普段から Linux を常用しているので、敢えて機能限定版を求める必要もないかと思えて、購入を見送ったまま現在に至ります。

いずれにせよ、本格的にコンベアベルト上で画像認識を行う際には必要になるものなので、急いで購入しなくてもそのうち入手するだろうとは思いますけれども、今すぐというわけにはいきません。

そして、その前に私にとって最大の問題である 工作が下手 という問題も解決手段を模索しなければなりません。

センサの取り付けやサーボのアームの加工に難があり、普通に動かしているだけで部品が外れたり、位置がズレたりするので何かしらのうまい方法を考えないと、このままでは調査にもなりません。