2022年10月25日火曜日

送迎バスとセンサー

今夏、送迎バスに園児が取り残されて人命を失う、あるいは自力で脱出を余儀なくされるという人為的事故が続きました。居眠りや飲酒で児童の列に車ごと突っ込むヒトもいなくなりません。

ヒューマンエラーの一言で片付けるには重すぎる過誤です。
エラー回避策の立案と実行は簡単なのですが、それができなかったヒトがいるというのが根本的な原因ですので、ヒトに働きかけて事故を無くすという考え方では、残念ながら撲滅は難しいのでしょう。

私の自家用車には居眠りを検知するセンサーが付いているそうです。幸い、検知される機会がないのでどのような音なのか知らないのですが、おそらく色々な車種についているのでしょう。レーンキープ、衝突軽減ブレーキなど先進安全装置は既に多くの車種に装備されています。ロック忘れやハザードの消し忘れなども、アプリに通知される時代です。義務化が延期された社用車運転時の検知器による事前アルコールチェックも、いずれは車内環境をセンサーが常時測定しアプリ(サーバー)に記録、閾値を超えると責任者に通知される時代が来るでしょう。技術的には可能ですので。

園児の送迎バスにも座席毎に距離センサーを付けておけば、距離異常を検出可能になります。タイマーでスリープするようにしておけば、エンジン停止後のバッテリー上りを防ぐことが可能でしょう。20台で30万円くらい?
天井などにカメラを付けておけば、動体検知が可能です。これは5台で10万くらいでしょうか。いずれも検知したら アプリに通知やLINEで一斉配信すれば良いでしょう。これくらいのオプション、電子工作レベル(と最近わかりました)なので義務化してしまえば良いと思います。
プロならもっと安く、良い性能のオプションを作ることが可能でしょう。既に社外に向けた距離センサーは多くの車に付いていますので、それを車内に向けると良いわけですから。

性善説を前提としたヒューマンエラー対策、性悪説を前提とした予防、その両軸で進めないと、またどこかで繰り返されることになります。来夏までには対策を済ませ、皆が笑って過ごせるようにしてもらいたいものです。

*****************************
20221108 追記

今日もまた、小学生が置き去りに。
ドアを後ろに移動して、後ろからしか降りられないようにしたらダメなのでしょうか。昔は挟み込みの危険があったかもしれないけど、今は安価なセンサーがあるので解決できるのでは?

2022年10月24日月曜日

MEMS加速度センサーの +- 方向

MEMS加速度センサーの +- 方向についてよく理解できていなかったのですが、以下のサイトで理解できました。
https://lastminuteengineers.com/adxl335-accelerometer-arduino-tutorial/

測定器の中にボールが入っていて、それが測定器を押す方向をイメージすれば整合します。下向きに1gかかっていたら、下が+。測定器を急に上に動かすとボールが測定器の下面を押すのでさらに+の力がかかります。急に下に動かせば、ボールが浮いて上面を押すので-の値になります。
理解を難しくしていたのは、センサーの軸方向が google 先生の情報と逆だったこと。単純にセンサーを傾けてチェックすればOKでした。

ジャイロもあります。Z周りが相対的に弱いのも感覚的に掴めます。
https://lastminuteengineers.com/mpu6050-accel-gyro-arduino-tutorial/

あと、分からないのはノイズ。
https://www.analog.com/jp/education/landing-pages/003/td_accelerometer_specifications_definitions.html
https://www.analog.com/jp/analog-dialogue/articles/mems-vibration-monitoring-acceleration-to-velocity.html

ノイズ = ノイズ密度 * sqrt (BW * 1.6)

1.6は何でしょう?後者では考慮されていません。
いずれにしても、観測ではそこまで小さくなりません。なぜでしょう。


2022年10月23日日曜日

Scoops3D

Scoops3D
https://www.usgs.gov/software/scoops3d

試行円弧の3次元版です。FEMではなくて、LEMです。このようなコードが公開されるUSGS、さすがです。

現状、円弧(球)ですので実務では使用しません。これが楕円でも使用しないでしょう。山が円弧すべりをすることは稀ですし、仕様が2Dの間は利益に直結しません。しかし、技術者としては、こういった計算が海外では Open になっていることに一定の危機感を抱くべきでしょう。

マニュアルを読んでみましたが、難しいことは書かれていません。2D の試行円弧の知識があれば、問題なく読めますし結果も理解できるでしょう。2dで実施している一通りの機能は備わっていますし、ソースを少し改変すれば多くの基準に適合させることがますので、逆に加点要素として導入しやすいのかもしれません。何かしら円弧が適当な場で提案してみるのもアリでしょう。
難しくはないのですが、計算には時間がかかりそうです。単純に探索領域が3次元に拡大するためです。example の実行では比較的早く終わりましたが、ひと山となると大変でしょう。

残念ながら、こういった計算や解析に関し多くのサラリーマン技術者は他人事です。理論ではなく経験に基づいた仕事の処理で利益を生んでおり、新たなものを許容する技量と器量に欠けています。経験優先が悪いわけではないのですが、それによる思考停止は避けたいものです。

いずれにしても、海外ではコチラの内情に関係なく技術が発達します。止まっている日本の中でその恩恵を受けることができるならば、迷わずに学ばせてもらうべきでしょう。


2022年10月16日日曜日

ADXL312 & MPU6886

手元にあるMEMSセンサー(加速度)の比較です。

近所の公園に出かけ、ADXL312 と MPU6886 で振動を測定してみました。

測定条件は以下の通り。
・ADXL312: 1.5G, 2.9mG/LSB
・MPU6886: 2G, 0.06mG/LSB

・常時微動(10分程度)
・センサー周辺で連続ジャンプ


まずは常時微動。

ADXL312

MPU6886

ADXL312 の方が見かけのノイズが小さく見えます。Z(緑)がドリフトしています。
MPU6886 はその倍くらいのノイズになっています。ドリフトは小さい。
ちなみに、スペクトルは両者ともフラットなホワイトノイズのような形状でした。おそらく実際の微動はこれらの1/10以下でしょうから、微動計としては使えません。工業用センサーなら微動を測定できるのでしょうか?

次、ジャンプ。故意に振動を与えた場合です。

ADXL312

MPU6886

ADXL312は、鈍いですね。Zの揺れが小さい理由は何でしょう?
MPU6886は大きく反応しています。が、コチラは大きすぎるような。
絶対値として両者とも誤っている可能性があります。微動計とあわせて測定しないと評価できませんでした。

一概にMEMSセンサーといっても、モノによって特性が大きく異なるようです。使用する場合、その計測値を微動計の計測値と比較するなどして事前に特性を把握しておかないとダメですね。

2022年10月10日月曜日

M5StickC Plus + Blender

姿勢の算出方法に目途がつきましたので、M5StickC Plus をパッド代わりに Blender を操作します。いくつか、必要なライブラリ等をインストールして準備します。

Pyserial
Blender の modules フォルダに serial フォルダをコピー。 
C:\Program Files\Blender Foundation\Blender *.*\*.*\scripts\modules

Blender 側
Pyrhon スクリプト。

M5StickC Plus 側
姿勢算出方法を書き込んだ M5 から、Bluetooth 経由で Win に Sertial 通信。ワイヤレスの方が動かしやすいかなと思いましたので、BTを選択しました。
XYZ の回転角をコンマ区切りで投げると、Blender に角度が入りました。M5 を90度傾けると Blender 内の矩形モデルが約45度傾斜します。Blender 側の Python スクリプト内の係数を2倍に設定すると M5 とモデルがシンクロするようになりました。OK、これで完成です。

Blender に地形やバイクの3Dモデルを取り込んで動かしてみました。が、テスト時の矩形と異なり安定性がイマイチでした。原点がずれている、あるいは大きなモデルだと、ビビりが目立ちます。マウスの方が安定して動かせるので、不自由ささえ感じます。制御が甘かったようです。
その点、ゲームはよくできていると改めて感心。さすがプロですね。そういえば、近年のドローンではジャイロも使って制御していたはずです。MEMSセンサーやGPSセンサー、小さなセンサーを組み合わせて姿勢や位置を制御しているのでしょう。


今回、M5 と Blender で実用的なモノは作れませんでしたが、制御技術の一端に触れることができました。また、一連の作業でセンサーの特性だけでなく、その利用法、接続の仕方、コードの書き方なども(浅いなりに)学ぶことができました。仕事で触っていた MEMS センサーに対しても理解が進みました。
やはり手は動かすべきです。今後も続けましょう。

2022年10月9日日曜日

Madgwick filter

M5StickC Plus の MPU6886 には、ジャイロがついています。

ジャイロといえばパッドで利用されています。これまで加速度しか需要がなかったのですが、世間ではジャイロがコントローラーの1機能として使われています。ふと、機能があるなら作ってみようかと思い立ちました。

Google先生に聞いてみると、同じようなことを考えられる方はいらっしゃるというか、ロボットの姿勢制御等に利用されているようでした。自動車にも入っているのでしょうね。制御工学の範疇になるようです。
現在時刻の姿勢を算出する方法として、加速度、角速度から直接回転角度を求める方法と、何らかのフィルターを通す方法があるようで、一般的には後者の方が安定しているとのこと。このあたり、制御工学を勉強しないと理解できないでしょう。

で、M5StickC Plus でどの程度できるのかを試してみることに。
角速度は時間積分しただけ、加速度からの算出式は web の中で分かりやすい説明があった以下から、フィルターは Arduino で配信されているモノ(MadgwickAHRS algorithm)のできあわせ比較です。
https://watako-lab.com/2019/02/15/3axis_acc/
https://github.com/arduino-libraries/MadgwickAHRS

結果はコチラ。


加速度からの算出値もそこそこ良い挙動ですが、細かな振動が現れています。その点、Madgwick filterは安定しています。そこそこ再現できそうです。どういう理屈なのか知りたいところですが、ひとまず恩恵を受けて進めましょう。


2022年10月8日土曜日

M5StickC Plus + LINE Notify

SGP30 を利用したタバコ検知の続きです。

窓を閉める季節になってしまい、音のデータ取得を中止しました。貯めたデータでは、低周波側でいくらか特徴のあるピークを得られたものの、ノイズと綺麗に分離できるほどでもない程度でした。

今期のコードは TVOC と eCO2 の両方が閾値を超えたら ライト点滅、ブザー発信、LINE に観測値を送る、という仕様にとどめました。eCO2 も急上昇することが分かったので、両方を組み合わせました。

LINE に関しては、異なる部屋にいたときになかなか気づかないことがあったので、その対応策です。ただ、これにハマりました。
API が用意されていますのでそれを叩くだけ & コードはネットに転がっている & どれも同じ内容、なので間違えようがないのです。でも、スマホに着信しない。Windows から叩いてみると着信しますので、環境的に使えないわけではありません。

3日ほど試行錯誤した結果、原因がわかりました。
常時データを送信している Ambient は WiFiClient でないとダメ、LINE Notify は WiFiClientSecure でないとダメ、でした。
もう一つ、void setup()  に setInsecure(); も必要でした。 

Ambient ambient;
WiFiClient client;
void ambientConnect(){
・・・
}

WiFiClientSecure clientS;
void lnotify(String msg){
・・・
}

void setup() {
  ・・・
    clientS.setInsecure();

これをクリアすれば、着信しました。

今期はココまで。また春に出番が来たら、起こしましょう。

2022年10月7日金曜日

M5StickC Plus 加速度センサー(MPU6886)その2

時間ステップはコレ↓で数10μsecの誤差に収まりました。CPUクロックは80MHzでもOKです。10msec=100Hzサンプリングの例です。

    //delay(9);
    while (millis()-10*sTime<10){
      delayMicroseconds(100);
    }
    sTime++;

EXCEL の代わりに MobaXterm でシリアル接続。最大表示&他の作業の裏で動かしていると、欠測が生じました。また、M5側でLCDへの波形の作画自体は問題ないのですが、全消しタイミングで計測の遅れが生じました。MobaXterm 最小表示 & 他の作業ナシ & M5 LCD 波形表示なしでは、欠測なく受信できました。うーん。

SDカードスロットを付けると良いのかな?
今回は、ここまでにしておきましょう。

********************************************************
20221008追記

コード全体です。Aボタンを押す毎に、波形表示・非表示を切り替えます。XYZ 軸の+-方向と重力加速度の方向の扱いについては、イマイチ理解できませんでした。 ←解決。
https://phreeqc.blogspot.com/2022/10/mems.html

公式サンプルコードに加え、波形表示は以下を参考にさせていただきました。感謝。https://gist.github.com/TakehikoShimojima/d136e81e13eeea603a8e594a8f5ef90f#file-m5vibration-ino

/***********************************************************
Copyright (c) 2022 fal
Released under the MIT license
https://github.com/m5stack/M5StickC-Plus/blob/master/LICENSE
************************************************************/

#include <M5StickCPlus.h>

float accX = 0;
float accY = 0;
float accZ = 0;
float gyroX = 0;
float gyroY = 0;
float gyroZ = 0;
unsigned long sTime = 1;

int n = 0;
float ax[240];
float ay[240];
float az[240];
int amin = -1000;
int amax = 1000;
int btn = 0;

void header(const char *string, uint16_t color) {
    M5.Lcd.fillScreen(color);
    M5.Lcd.setTextSize(1); // フォントサイズ(文字倍率)
    M5.Lcd.setTextColor(TFT_WHITE, TFT_BLACK);//フォント色、背景色
    M5.Lcd.fillRect(0, 0, 120, 20, TFT_BLACK);// 四角形(線分)(左上x,左上y,幅,高さ,色)
    M5.Lcd.setTextDatum(TC_DATUM);
    M5.Lcd.drawString(string, 120, 2, 4);//(string, x, y, font)
    //font1:Adafruit 8ピクセルASCIIフォント
    //font2:16ピクセルASCIIフォント
    //font4:26ピクセルASCIIフォント
    //font6:26ピクセル数字フォント
    //font7:48ピクセル7セグ風フォント
}

void setup() {
    M5.begin();                // Init M5StickC Plus.
    Serial.begin(115200);
    M5.Imu.Init();             // Init IMU.
    M5.Lcd.setRotation(3);     // Rotate the screen.
    header("MPU6886",TFT_BLACK);
}


void loop() {
  M5.update();
  if (M5.BtnA.wasPressed()) {
    if (btn==0){
      btn=1;
    }else{
      btn=0;
    }
  }

  M5.Imu.getAccelData(&accX, &accY, &accZ);
  //M5.Imu.getGyroData(&gyroX, &gyroY, &gyroZ);
  ax[n]=(accX)*1000;
  ay[n]=(accY)*1000;
  az[n]=(accZ)*1000;
   
  Serial.print(millis());
  Serial.print(",");
  Serial.print(accX*1000, 2);
  Serial.print(",");
  Serial.print(accY*1000, 2);
  Serial.print(",");
  Serial.println(accZ*1000, 2);
  //Serial.print(",");
  //Serial.print(gyroX, 2);
  //Serial.print(",");
  //Serial.print(gyroY, 2);
  //Serial.print(",");
  //Serial.println(gyroZ*1000, 2);
  //M5.Lcd.printf("Temperature : %.2f C", temp);

  if (btn==0){
    if (n == 239){
      header("MPU6886",TFT_BLACK);
      n = -1;
    }else if (n != 0){
      int x0 = map((int)(ax[n - 1]), amin, amax, M5.Lcd.height(), 30);
      int x1 = map((int)(ax[n])    , amin, amax, M5.Lcd.height(), 30);
      int y0 = map((int)(ay[n - 1]), amin, amax, M5.Lcd.height(), 30);
      int y1 = map((int)(ay[n])    , amin, amax, M5.Lcd.height(), 30);
      int z0 = map((int)(az[n - 1]), amin, amax, M5.Lcd.height(), 30);
      int z1 = map((int)(az[n])    , amin, amax, M5.Lcd.height(), 30);
      M5.Lcd.drawLine(n - 1 + 5, x0, n + 5, x1, BLUE);
      M5.Lcd.drawLine(n - 1 + 5, y0, n + 5, y1, YELLOW);
      M5.Lcd.drawLine(n - 1 + 5, z0, n + 5, z1, MAGENTA);
    }
    n++;
  }
 

  while (millis()-10*sTime<10){
    delayMicroseconds(100);
  }
  sTime++;    
}


20240408追記
M5Tough + ADXL355 を用いた振動計のコードを以下に公開しました。FIRフィルタを実装していますので、周波数領域も扱えます。
https://github.com/T40O0/ADXL355_SPI_M5_SD_FIR.git

2022年10月2日日曜日

M5StickC Plus 加速度センサー(MPU6886)

M5StickC-Plus 内の加速度センサー(MPU6886)によるデータ取得。

加速度計の場合、msecオーダーの制御が必要です。受信側で時刻を付与すると、転送時間や受信側の処理速度により正しい計測時刻を設定できません。それが規則的にずれているなら補正できますが、ランダムであれば手の施しようがありません。センサー側でデータを保存するか、測定時刻を測定データとともに受信側に送るかでしょう。手元にはSDカードモジュールがないため、後者の選択になります。まずは EXCEL で取り込んでみましょう。

これまで使用してきた delay() を用いて、約10msec 間隔でデータを採取。1 loop の中で 10msec 止めるので、処理時間を加えるとそれ以上の間隔での測定になります。それが何m秒なのか知りたくて、RTC にて時刻を付与したデータをシリアル送信。

ダメでした。RTC の時刻付与は秒単位。msec単位で表示できないのでしょうか?
そうなると最初に RTC で計測開始時刻を定め、あとは一定間隔で値を取り出すしかないでしょう。仕事で使用する加速度計も同じ(計測開始時刻+時間ステップ指定)かもしれません。

センサー側 CPU クロック 80MHz、delay(5)、EXCEL側 10msec で取ってみると、7ms間隔でデータが保存されていました。
センサー側 CPU クロック 240MHz、delay(5)、EXCEL側 10msec だと6ms間隔。
センサー側 CPU クロック 240MHz、delay(9)、EXCEL側 10msec だと10ms間隔。この程度でしょうか。
全てのケースで、たまに欠損があります。これはEXCEL側の問題。やはり表示がダメか。

delay()でもそれなりの結果を得られましたが、やはり正確なデータ間隔をプログラム中で設定したい。このままでは長時間の計測でズレが生じるでしょうし、EXCEL側でも他のソフト次第で欠測の多く発生することが予想されます。

時間刻み、データの保存方法について調べましょう。

2022年10月1日土曜日

Data Streamer

自宅にて測定を続けていると、窓から入る色々な匂い?にも反応していることがわかりました。全く匂わないときにもセンサーが反応することがあるので、ドリフトの影響を受けているのかもしれません。ひとまず対象を絞ることにしました。

まずは、タバコ。
隣家が換気扇を回している場合にタバコ臭が室内まで届くことがあるようで、この換気扇の音を利用する目論見です。

FactoryTest から音の FFT 部分を取り出します。整理しながらコードを見ていたのですが、サンプリング周波数がよくわかりません。FFTにかけるデータ数を指定できるのですが、それらが何秒ステップで採取するのか指定するところを把握できませんでした。include したライブラリの中に書かれているのかもしれませんが、ひとまず飛ばします。

抜き出したコードに FFT 結果のシリアル転送する部分を追加。これで値が PC にて見えるようになりました。が、転送結果をファイルに書き出す方法がわかりません。もしかしてないのか?

他の方法を調べてみると、簡易な方法がありました。EXCELです。Data Streamer という com アドインがありました。これで通信結果をターミナルのように取得できます。昔はVBAでしか通信できなかったのですが、いつの間にか実装されていました。Iot 時代の常識なのでしょうか。

使用してみると、少々難あり。1度目はデバイスの接続、解除に手間取り、接続できなくなりました。次はマウスとして認識されてしまい、計測中にカーソルが暴れて制御不能になりました。後者の現象と対処法は web 上でたくさん引っかかりました。Windows あるあるのようです。マウスとして認識されていたデバイスを削除し、COMポートの番号を変えてからは安定していますが、対処療法なのでいずれ復活するかもしれません。

EXCEL につなぐことができたら、データを容易に採取できます。サンプリングは0.01秒毎でも可能でした。200行分表示させていたのですが、その中身は時間とともに更新されます。その範囲で散布図を作っておくと、イコライザーとまではいきませんが、周波数領域のグラフが時間毎に更新されます(そういえば、振幅の単位もわからない)。EXCEL は表示が遅いので、データが飛んだりグラフに空白が生じたりしていましたが、手軽にここまでできるとは驚きでした。
FFT 結果は1度の処理で128行×3列のデータを流すようにしていたのですが、このままでは EXCEL 側で欠損します。そこで表示を 200 行から 5 行に変更。表示の負荷を小さくすることで欠損なく取得できました。これ、振動を図る際に都合が良いですね。次はRTCと振動かな。ま、時間方向にFFT結果が欠損したとしても、その数を集めてプロットすれば周波数領域での特性を把握できそうです。今回はこのまま進めます。

データを集めましょうと思いましたが、そう都合よく隣家が換気扇を回してくれるタイミングに出会えるわけではありません。自宅の換気扇でまずは試しました。
結果は上々。近いので当たり前なのですが、安いセンサーでも音が届けば分離できる可能性はあるようです。ということで、コードはひとまずこれでOK。

それでは、気長にデータを集めましょう。