勉強しないとな~blog

ちゃんと勉強せねば…な電気設計エンジニアです。

マイコンと加速度センサでタコメータを作る - 2. 実データ解析

加速度データをSDカードに記録できるようになっているので、実際にバイクに乗せてデータを取ってみました。

名前を付けておく

呼び方がないと不便なので、今回作っている工作物の名前は「RXタコメータ」にします。

いきなり結果

こんな感じでデータが取れました。

  • 家の近所を一周してきました。
  • RXタコメータで取得した加速度時系列データ(加速度ログ)を時間ごとにFFTしたものです。
  • 縦の軸が周波数、横の軸が時間
    • 縦軸 : 3.125Hz / 1刻み
    • 横軸 : 0.32秒 / 1刻み
  • ピークの周波数位置がそれらしく動いているように見えます。
    • 最初は1速で発進します。(ギア比最低)
    • 発進した後、ある程度スピードが出たら1段ずつギアシフトしていきます。このとき、アクセルを一旦緩めます。
    • ピーク周波数が急激に落ちているところはおそらくそのときのものです。
    • 色が全体的に薄くなっている箇所は、停止しているときのものと思われます。

何をやったか

Octaveを使って、加速度時系列データから先ほどのグラフを作成しました。
MATLAB互換のフリーのツールです。

www.gnu.org

他にもpython + numpy + matplotlibでも同じようなことができそうです。

具体的にやったこと

先ほどのグラフ作成の手順は以下の通りです。

  • SDカードをPCに差して、RXタコメータで取得した加速度ログをコピー
  • Octaveで、加速度ログ(バイナリデータ)を読み込む
  • 加速度ログを適当な長さ(今回は512にしました)に区切って、それぞれFFTを実施
    • 「スペクトル強度(周波数, 時刻)」の形のデータができる
    • 周波数点数 : 512、ただし元が実数データなので半分は意味のないデータ
    • 時刻点数 : 時系列データ点数/512
  • Octaveの2次元プロット機能でグラフ表示
    • FFT結果のスペクトルは複素数で出てきますが、今回は位相は見る必要はないので、振幅だけプロットしました。

Octaveコード

加速度データ取り込み

以下のファイルを作って、read_adxl345_log_bin_2byte()関数で加速度データを取り込めるようにしました。

function [dat_g dat_ovrn] = read_adxl345_log_bin_2byte(fname)
  fid = fopen(fname, "r");
  dat_g = fread(fid, Inf, "int16", 2);
  fseek(fid, 2, SEEK_SET);
  dat_ovrn = fread(fid, Inf, "int16", 2);
  fclose(fid);
endfunction

加速度ログファイルには、以下のようにデータが並んでいます。

G[0] FLG[0] G[1] FLG[1] G[2] FLG[2]  ...

G[i] : i番目の加速度データ(16bit)
FLG[i] : i番目データの関連フラグ等(16bit)

Octaveコードのfread()では、バイナリデータを繰り返し読んで行列変数に格納する、ということが可能です。

上記で使ったfread()のフォーマット :

val = fread(fid, size, precision, skip);
# fid : ファイルID  
# size : 読み出しデータ数、Inf -> 読めるだけ読む  
# precision : 読み出しデータの型(uint8, ushortなど)
# skip : 繰り返し読み出しの際の読み飛ばし数(バイト単位)

"関連フラグ等"としては、現状"オーバランフラグ"を入れています。
今回使っている加速度センサは、決まったレートで勝手に測定を行い、これを割り込みピンでCPUに通知します。
CPUでは、SDカードの1セクタ分データがたまったら実際にSDカードへの書き込みを行いますが、これがそれなりに時間がかかってしまうので、この間に入ってくる加速度データを取りこぼしてしまうことがあります。
"オーバランフラグ"は、この取りこぼしが発生したことを示すものです。

FFT

以下のファイルを用意して、所定のデータ数ごとにFFTを行いました。
窓関数もかけています。

function ffts = fft_slice(d, u)
  # d : data for FFT
  # u : unit size for FFT
  
  n_ffts = cast(floor(size(d)/u), "uint32");
  for i = 1:n_ffts
#    ffts(:,i) = fft(d(1+(i-1)*u : i*u));
    ffts(:,i) = fft(d(1+(i-1)*u : i*u) .* hamming(u));
  endfor
  
endfunction

グラフ表示

今回のような2変数のデータを可視化するのに、いくつかのグラフが用意されています。

  • contour (contourf)
  • surf
  • pcolor

全部試してみたのですが、pcolorが一番わかりやすく表示されました。これが記事先頭のグラフです。
グラフ表示した際のコードは以下の通りです。

[gData ovrn] = read_adxl345_log_bin_2byte("adxl345_log_002.bin");
gFFT = fft_slice(gData, 512);
pcolor(abs(gFFT(3:128,:)));
colorbar
caxis([0 4000])
  • FFT結果の絶対値をpcolorで表示しています。
  • FFT結果の低周波数領域は表示から除外しています。(DC成分とDC成分が窓関数で広がったと思われる部分)
  • 加速度軸のレンジを狭く調整しています。

グラフ表示参考 :

Yapso, Yet Another Plotting System for Octave

改善項目

  • 軸の目盛りを秒単位、Hz単位にしたい
  • 加速度値もきちんとしたい
    • 今は16bitのAD変換値をそのまま使っています。加速度センサ(ADXL345)は、今回使った設定だと4mg/LSBのAD変換になっています。
  • いずれもできそうなので、次回やってみます。

困ったこと

いくつか困ったことはありました。

  • 取得した加速度ログデータを見ると、最大レートの3200Hzではオーバランが発生していました。1600Hzでもやはり発生していました。
  • SDカードの接続が怪しいのか、ファイルオープンや書き込みに失敗することがありました。RXタコメータの上部をちょっと開けるとちゃんと動いたりしました…
    ハードを作り直したい…

その他

はてなブログではコードブロックでのファイル名表示ができなかったのですが、以下のサイトのデザインCSSを使わせていただいて、表示できるようにしました。

はてなブログでソースコード表示時にタイトルを付ける - 酔いどれ技術者の備忘録


次回

もうちょっと長距離走って測定を行ったので、その結果を見てみたいと思います。