2026年5月29日金曜日

LiDARを使った相対速度計(その5)

 出来上がった相対速度計を室内(廊下)でテストしてみたが、測定距離が4~5m位になると測定値が安定しなくなるというよりランダムな値が出るようになる。その原因はS/Nの悪化か、空中の埃やエアロゾルの影響か、或いは測定原理に起因するものか分からない。

そもそも赤外線が1nsで進む距離は30cmである。これを使ってmm単位の距離を測るためには数ps単位の時間分解能が必要であり、そのため初歩的な方法では100GHz以上のクロックが必要で現実的ではない。 またLEDやフォトダイオードの応答速度なども大きく影響しまともな測定は出来ないだろう。

この点をCopilotに相談すると波形の相関処理を行う事でサンプリング周期の100倍以上の分解能を得る事が出来るようだ。逆に考えると、何らかの要因で波形が乱れて相関処理が上手く行かなくなると極端に精度が悪くなるのだろう。これ以上測定範囲を伸ばしたいなら上位のLiDARセンサーを買う必要があろう。いずれにしても距離を正確に計れなければ相対速度もヘッタクレモ無い。

 さて、相対速度計を実際の車に持ち込んで動かしてみた。赤外線がガラス窓に直交するようにLiDARを向けるとガラス窓の反射を拾って窓までの距離を測った。一方、赤外線がガラス窓に直交しないように置くと数十cm~数mの範囲の出鱈目な数字を表示した。ガラスの赤外線の減衰が大きいのかガラスを通しては正しく測定できないように見える。そこでLiDARを車外に出してみたが結果は変わらない。外光の影響が大きいのかな。とにかくこのままでは上手く行かない。

 上位のLiDARを使ってみる必要があるようだ。上位のLiDARには距離を20mまで計れるTSD20と50mまで計れるTSD50がある。どちらを使うにしてもTSD10と互換では無いので一工夫が必要だ。例えばTSD20は電源電圧が3.3Vだし、測定頻度が200回/秒だ。TSD50では電源は5Vでよいが測定頻度が500回/秒なので9600bpsではデータの転送が間に合わない。


何処をどうトレードオフしようか?

(続く)

 

2026年5月23日土曜日

LiDARを使った相対速度計(その4)

 とりあえず基板を百均のクリアトレー(ミニ)を加工した箱に入れた。


LiDAR(TSD10)は反射物までの距離の測定を毎秒50回行う。前出のセンサー部はこの10回分を平均して、即ち0.2秒毎に距離をcm単位で報告してくる。

相対速度はこの0.2妙毎の距離の変化(差分)から算出すればよい。具体的には差分(m/0.2sec)を18000倍(=5×60×60)して100000で割ることで時速(Km/h)に変換できる。

7セグLEDの表示はこの相対速度(Km/h)と距離(cm)をスイッチで切り替えられるようにした。 またセンサー部からの入力が無い場合は全桁ドット(.)を、センサーの探知範囲外は全桁ダッシュ(-)を表示する。

左端の緑、黄、赤のLEDは次の様に点灯させる。緑は相対速度が正の場合に点灯、 赤は相対速度が負の場合に点灯、赤と緑の点灯には閾値を設定している。黄色は相対速度が0の状態が3秒以上続いた場合に静止状態と判断し点灯する。黄色から緑へ点灯が変化する場合、即ち信号待ちで停車中に前車が発射した場合にブザーをピッと鳴動させる。ブザーは当初は市販の小型電子ブザーを使ったが音がプアーだったのでタイマーで作った約2KHzの方形波でスピーカを鳴らすようにした。


次の写真で赤丸は 追加した相対速度と距離の切り替えスイッチ、橙丸は追加したダイナミックスピーカ。スピーカはPICの出力からコンデンサーで直流分を切って直接駆動している。


これで予定した基本的な機能は実装できたはずである。

(続く) 

 

2026年5月19日火曜日

LiDARを使った相対速度計(その3)

 ソフトの制作と並行して基板を組み立てた。

そしてPICにソフトを書き込んでデータを表示させてみた。
実際にはTM-I2Cの実装とテストに思いのほか手間がかかった。しかし動き始めればこっちのものである。
あとは上位アプリをどう作って行こうか?
 
(続く) 
 
 

2026年5月12日火曜日

LiDARを使った相対速度計(その2)

 今回の速度計で一番問題となるのはTM1637のI2Cモドキの2線インターフェイスだ(以降「TM-I2C」インターフェイスとする)。最初はPICのI2Cインターフェイスが流用できるかもしれないと考えたが仕様を検討して諦めた。TM-I2CもI2Cのようにクロックとデータの2線構成だが転送する最初のバイトがI2Cのアドレス+R/WではなくTM-I2Cはコマンドだ。またビットの並びも逆になっている(これはソフト的に解決可能だが)。従ってTM-I2Cはソフト的に実装する事とした。TM-I2Cの通信速度に下限規定は無いので実装は楽だろう。

TM-I2Cでデータ線は双方向通信を行う必要があるが、これはWired-OR接続で解決できる(注1)。Wired-OR接続の設定は例えばC1ポートでは次の様に設定した。 

    // 15: RC1 - DSPDAT
        LATCbits.LATC1   = 1;       // normal H
        TRISCbits.TRISC1 = 0;       // Output Enable
        ANSELCbits.ANSC1 = 0;       // Digital
        ODCONCbits.ODCC1 = 1;       // Open Drain
        WPUCbits.WPUC1   = 1;       // Weak Pull-Up

プログラム中ではデータ線、クロック線については次の様にマクロ定義している。また適当に遅延を入れてタイミングを調整している。

    #define CLK_OUT     LATCbits.LATC0
    #define CLK_IN      PORTCbits.RC0
    #define DAT_OUT     LATCbits.LATC1
    #define DAT_IN      PORTCbits.RC1

    #define DLY_4US     __delay_us(4)
    #define DLY_10US    __delay_us(10)
    #define DLY_50US    __delay_us(50)


 クロックが1の間データ線は変化してはならない(スタート・ストップ時を除く)から、1ビットの送信は、

    static void tm_send_bit(boolean d){
        DAT_OUT     = d;
        DLY_10US;
        CLK_OUT     = 1;
        DLY_50US;
        CLK_OUT     = 0;
        DLY_50US;
    }
で良いだろう。逆に1ビットの受信は、

    static boolean tm_rcv_bit(){
        boolean dat;
        DAT_OUT     = 1;
        DLY_50US;
        CLK_OUT     = 1;
        dat     = DAT_IN;
        DLY_50US;
        return dat;
    }
 スタートビット、ストップビットについては、

    static void tm_start_bit(){
        DAT_OUT     = 0;
        DLY_50US;
        CLK_OUT     = 0;
        DLY_50US;
    }

    static void tm_stop_bit(){
        DAT_OUT     = 0;
        DLY_10US;
        CLK_OUT     = 1;
        DLY_50US;
        DAT_OUT     = 1;
        DLY_50US;
        DLY_50US;
    }


としている。そして出来上がったTM-I2Cの波形をpulseviewで見ると、例えば次の様になった。ちなみにデコーダにはI2Cの物を使っているのでデコード結果は不正確だがデバッグには十分である。

(続く)

  〔注1〕この接続法はWikipediaを見るとWired-AND接続と書かれているが、初期の8ビットのコンピュータ時代、カードエッジコネクタを通して負論理バスで接続していた頃はWired-OR接続と呼んでいた。今回は信号は正論理だが動作はOR的なのでどちらの呼称が適切だろうか?これはIC-R6のCI-Vバスでも同じ事が言えるのだが。