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の波形は例えば次の様になった。ちなみにデコーダにはI2Cの物を使っているので結果は不正確だがデバッグには十分である。

(続く)

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