DWM3000EVBを用いたCIRの取得

# 1. 本記事の目標
　DWM3000UWBモジュールが実装されたモジュールであるDWM3000EVBをnRF52840-DKによって制御し，CIR(Channel Impulse Response)を取得する．


# 2. セットアップ＆準備物
　セットアップに関しては，以下の記事を引用させていただきます．
[DWM3000EVBを用いたUWB位置測位① ~セットアップ編~](https://qiita.com/tukurida/items/e17481a2f9a9c7532dc1)

　環境については上記の記事と同様で，以下の通りです．
+ セットアップ用PC (ここでは今回使用したものを記載)
    - Panasonic社 Let's note CF-SV1 (Windows 11)

* 制御用マイコン
    - Nordic Semiconductor社 nRF52840 DK　2台
        - nRF52840を手軽に動かすためのキット
+ UWB信号受信デバイス
    - Qorvo社 DWM3000EVB 2台
        - DW3000を手軽に動かすためのキット
* アクセサリ
    - ケーブル (MicroUSB <-> USB Type-A)　4本(3本でもOK)
    - USB Type-A ハブ 1つ
+ PC上のソフトウェア (インストール手順については先ほど紹介した記事を参照)
    - [Segger Embedded Studio (SES) for ARM V5.10a](https://www.segger.com/downloads/embedded-studio/)
        - nRF52840にプログラムを書き込むための統合開発環境．今回はバージョン5.10aを用いるので注意．
    - [DWM3000 API Software and API Guide](https://www.qorvo.com/products/d/da007992)
        - UWB送受信デバイスをnRF52840で動作させるためのサンプルプログラム．今回はバージョン17.0.2を用いるので注意．
    - [nRF52840のSoftware Development Kit (SDK) V17.02](https://www.nordicsemi.com/-/media/Software-and-other-downloads/SDKs/nRF5/Binaries/nRF5SDK160098a08e2.zip)
        - nRF52840でサンプルプログラムを動かすときに必要となるプログラム一式．
    - [J-Link Software and Documentation Pack V7.92j](https://www.segger.com/downloads/jlink/#J-LinkSoftwareAndDocumentationPack)
        - このパックに含まれるJ-Link RTT Viewerを今回出力用のターミナルとして用います．バージョンは当時最新版を用いていますが，何でもいいです． 
+ SESとSDKの関しては先ほど紹介した[記事](https://qiita.com/tukurida/items/e17481a2f9a9c7532dc1)とソフトウェアのバージョンが異なるため注意してください．
 
- 本実験は<font color="red">__電波暗室__</font>で実施

# 3. セットアップ
### 3.1. DWM3000 API Software and API Guide (API) のインストール
- 以下の記事を参照してください．
[DWM3000EVBを用いたUWB位置測位① ~セットアップ編~](https://qiita.com/tukurida/items/e17481a2f9a9c7532dc1)  

- ダウンロードリンクは[こちら](https://www.qorvo.com/products/d/da007992)


- 今回は，上記の記事で紹介されているデモプログラムは使用しませんので，ダウンロードしたzipファイル (DW3xxx_QM33_XR6.0C.zip) をCドライブ直下などの日本語がパスに含まれない場所に展開するだけで大丈夫です．なお，今後この記事ではCドライブ直下にDW3xxx_XR6.0C_24Feb2022のディレクトリを展開したものとして解説を行います．

- 展開後のフォルダ内の`C:\DW3xxx_XR6.0C_24Feb2022\Release_XR6.0C\Software\DW3XXX_API\Sources\DW3XXX_API_rev9p3.zip`を展開．適切な位置にフォルダを移動しておく．(私はzipファイルが入っていたSourcesフォルダにそのまま展開しました)
    
### 3.2. nRF52840のSoftware Development Kit (SDK) のインストール
- DWM3000の公式サイトからSDKのzipファイルをダウンロード
    - 展開後のルートディレクトリ`C:\DW3xxx_XR6.0C_24Feb2022\Release_XR6.0C\Software\DW3XXX_API\Sources\DW3XXX_API_rev9p3\API\Build_Platforms\nRF52840-DK\sdk`
の下に説明書 (readme.md) があり，このREADMEに従ってSDKをAPI内の指定ディレクトリ配下にインストールする必要があります．以下の画像の[リンク](https://www.nordicsemi.com/Products/Development-software/nRF5-SDK/Download)からSDKをダウンロード．

![SDK_download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/5a00b9d9-e631-e09d-bcb3-ff69a107de5a.png)

- バージョン17.0.2を選択

![SDK_download_17.0.2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/36bcc67c-7d5e-e415-fcf0-5ebfbad103bb.png)

- バージョンを選択したのち，Webページ下部に移動．今回はnRF5_SDK_17.02_d674dde.zipのみを使用するので，赤枠のチェックのみつければ大丈夫です．
 
![SDK_download_17.0.2_nRF.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/515ea960-ce09-11b7-380c-3d4fb16e558e.png)


+ ダウンロードしたzipファイル(DeviceDownload.zip)を展開
    - 展開したフォルダ内の nRF5SDK1702d674dde.zip を展開し，そのフォルダ内のcomponents, config, documentation...などの全ファイルを，APIのzipファイルにおける展開後のルートディレクトリ`C:\DW3xxx_XR6.0C_24Feb2022\Release_XR6.0C\Software\DW3XXX_API\Sources\DW3XXX_API_rev9p3\API\Build_Platforms\nRF52840-DK\sdk`
に入れる
![SDK_download_move.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/d43d1211-4861-d96b-6418-8a8e1f57d109.png)


- 最終的に以下のようにSDKが配置されていればOK
![SDK_download_file.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/cc872694-497e-cbae-9629-71cad2866934.png)


### 3.3. Segger Embedded Studio (SES) のインストール
+ こちらに関しても，以下の記事を参照してください．
[DWM3000EVBを用いたUWB位置測位① ~セットアップ編~](https://qiita.com/tukurida/items/e17481a2f9a9c7532dc1)

+ なお，上記の記事とは使用するバージョンが異なります．バージョンをV5.10aと指定してダウンロードするようにしてください．

![SES_setup.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/c2665880-ed21-99fe-cf5e-e74c94c25324.png)


+ `C:\DW3xxx_XR6.0C_24Feb2022\Release_XR6.0C\Software\DW3XXX_API\Sources\DW3XXX_API_rev9p3\API\Build_Platforms\nRF52840-DK\`の下の説明書 (README.txt) で紹介されている，動作確認があらかじめとれているバージョンです．

- 最新版やV6.20でやるとコンパイルでエラーが発生しました．

### 3.4. J-Link Software and Documentation Pack のインストール
- SEGGER社の以下のWebページからダウンロード．
[J-Link / J-Trace Downloads](https://www.segger.com/downloads/jlink/#J-LinkSoftwareAndDocumentationPack)
![J-Link_download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/51896bf6-6c90-d40f-7ab9-9c447423a193.png)

- バージョンとOSを適当に選択し，利用規約をacceptするとダウンロードが始まる．そのままダウンロードしたexeファイルを実行．特にインストールの設定は変更せずすべて初期設定のままnextを押していき，最後にinstallを押せばOK．

### 3.5. dw3000_api.emProjectの設定
- Exampleプログラムのビルドにあたって，設定をしなければならない箇所がありますので，紹介します．
    - 今回使用するDWM3000 API Software and API Guide内の
`C:\DW3xxx_XR6.0C_24Feb2022\Release_XR6.0C\Software\DW3XXX_API\Sources\DW3XXX_API_rev9p3\API\Build_Platforms\nRF52840-DK\`
の下に説明書 (README.txt) があり，これに従ってdw3000_api.emProjectの設定を更新します．まずメモ帳を用いてこのdw3000_api.emProjectを開きます．すると大量の設定が表示されますが，ここでは"macros"の文字列を探します．
![macros.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/697fed22-dbdc-1187-fcd4-55c0ef27b9cc.png)

    - "NordicSDKDir=sdk"のsdkを，先ほど3.2でインストールしたSDKディレクトリのフルパスに書き換え，"DW3000APIDir=..."の=の後をAPIディレクトリのフルパスに書き換えます．
書き換えた後は以下のようになります．
![macros_change.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/716c7567-17ff-e691-a42f-5581cabd2216.png)


### 3.6. デバイスのセットアップ
 - デバイスのセットアップに関しては，以下の記事の5節にて紹介されていますので，そちらを参照してください．
[DWM3000EVBを用いたUWB位置測位② ~PCデモ編~](https://qiita.com/tukurida/items/9ebd68ab97daff315d7e)
<br>

セットアップは以上になります．

# 4. exampleプログラムの実行
### 4.1. exampleプログラムの修正
- 先ほど編集したdw3000_api.emProjectを，今度はSESを用いて開きます．
![academic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/247ff1b4-0db7-b2ce-b3e8-fb72f3b0f62c.png)
- そうすると以上のような画面が表示されるので，アカデミック目的であれば特に気にせずContinueを押してください．

- Continueを押すとこのような画面が表示されると思います．
![dw3000api_main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/a6ff0312-ef2b-3440-1c38-ddc9c8ef7086.png)
- Project Explorerから，`Source/examples/ex_02c_rx_diagnostics`下にある`rx_diagnostics.c`を開いてください．
![rx_diagnostics.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/90228538-3cfe-42c7-eb66-939ba7d2f47d.png)
- これが今回用いるCIR抽出のためのExampleプログラムになっています．こちらのプログラムを編集し，CIRの値をprintfで制御用マイコンからコンピュータに送信できるようにしていきます．
![readaccdata.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/40a58eb9-6ab2-e14a-3b65-4997a65b9645.png)
- `dwt_readaccdata`という関数が書かれた部分を探してください．これが今回制御用マイコン内にあるメモリからCIRの値を抽出するための関数となっています．引数として，accum_data(u_int8t型の配列)，ACCUM_DATA_LEN(取り出してくるデータの数)，fp_int-2(FPI(First Path Index)の二個前からデータを取り出す）が指定されています．FPIとは，CIRの最初のピーク値のことです．その詳細については割愛しますが，ここではFPIの値をCIA(Channel Impulse Analyzer)によって計算した値をreaddiagnostics関数により読み取ることで取得しています．
- このコードを書き換えます．`dwt_readaccdata`のコード部分を消去し，以下のように書き換えてください．
```
printf("fp_int = %u\n", fp_int);
for(int i=fp_int-10; i<fp_int+50 ;i++){
    const int bytesPerValue = 6; // dw3000
    int32_t reValue;
    int32_t imValue;
    dwt_readaccdata(accum_data, bytesPerValue+1, i);
    reValue = accum_data[1];
    reValue |= ((int32_t)accum_data[2]<<8);
    reValue |= ((int32_t)(accum_data[3] & 0x03)<<16);
    imValue = accum_data[4];
    imValue |= ((int32_t)accum_data[5]<<8);
    imValue |= ((int32_t)(accum_data[6] & 0x03)<<16);
    if (reValue & 0x020000)  // MSB of 18 bit value is 1            
        reValue |= 0xfffc0000;
    if (imValue & 0x020000)  // MSB of 18 bit value is 1
        imValue |= 0xfffc0000;
    printf("%d:%d + %d i\n", i, reValue, imValue);
}
printf("\n");
```
- こちらも詳細は割愛しますが，DW3000APIガイド(`C:\DW3xxx_XR6.0C_24Feb2022\Release_XR6.0C\Software\DW3XXX_API\Docs\DW3XXX_Software_API_Guide_2p2`)の74ページに記載されているreadaccdata関数の説明より，メモリ内に格納された実部と虚部であらわされるCIRの値を10進数で出力できるようにするためのコードです．なお，ここではFPIから10個前のCIRから50個後のCIRまでを出力するようにしています．
- これ以外のコードについては修正不要です．

### 4.2. 送信側exampleプログラムのビルドとダウンロード
+ コードの修正が終わったのでビルドを行います．
    - UWBパケット送信用に用いるマイコンを，セットアップが終わったパソコンにつなげてください．microUSBのポートがマイコン側に2つ付いていますが，そのどちらもPCにつなげてください．![DW3000.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/8fd5e3ae-b5f7-6052-536e-03f83dc895a0.jpeg)


    - `C:\DW3xxx_XR6.0C_24Feb2022\Release_XR6.0C\Software\DW3XXX_API\Sources\DW3XXX_API_rev9p3\API\Src`
の下に，どのexampleプログラムをビルドするかを選択するヘッダファイル(`example_selection.h`)があります．この"#define TEST_SIMPLE_TX"の部分を以下のようにコメントアウトを消して保存してください．
![comment_out.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/22ce014d-28b8-433c-a661-2d7306413bc7.png)
    - その後，SESでdw3000_api.emProjectを開き，Build > Set Active Build ConfigurationをReleaseに設定します．
![Release.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/6a4371c6-b09f-45d6-b08b-aa1387c8d59a.png)
    - この操作が終わったら，送信用のDW3000を<font color="red">__電波暗室内に設置し__</font> Build > Build and Runを選択してください．そうすると送信用のDW3000制御用マイコンにUWBパケットを送信するためのプログラムが書き込まれ，同時にUWBパケットを500msec間隔で送信し始めます．この段階で，接続していたUSBケーブルのうちDW3000モジュールの裏側(画像上側)のケーブルを抜いて側面のケーブルのみ繋いでおいてください．![DW3000_one.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/3fa44655-bcc6-a817-5dd9-1351be146743.jpeg)


- 同様に受信用のプログラムも書き込みます．
    - 先ほどと同じ手順で`example_selection.h`を開き，以下のように"#define TEST_RX_DIAG"の部分のコメントアウトを消してください．このとき，先ほどコメントアウトを消した"#define TEST_SIMPLE_TX"の部分は再度コメントアウトしておいてください．
![comment_out_RX.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/9e0733ff-bd07-3eb6-69a8-47ede2231b19.png)
    - この操作が終わったら，受信用のDW3000を送信用のデバイス付近に設置し，受信用制御マイコンとコンピュータを2本のケーブルを繋いでからBuild > Build and Runを選択してください．そうすると受信用のDW3000制御用マイコンにUWBパケットを受信するためのプログラム(`rx_diagnostics.c`)が書き込まれ，同時に送信されたUWBパケットを受信できる状態になります．

### 4.3. CIRの可視化とログ取得
先ほどインストールしたJ-Link Software and Documentation Packの中のJ-link RTT Viewerを起動してください．
![RTT_Viewer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/09ad6a16-d996-6fc2-c151-e4d2c580ed28.png)
起動すると上のような画面が表示されるので，上記の設定と同じ状態にしてください．Specify Terget Deviceは，横の"..."ボタンから"nRF52840_xxAA"を選択してください．
![RTT_Device.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/de417262-f5c7-42e8-47bf-75959db6b44a.png)
送信用デバイスのケーブルが一本のみ接続された状態であれば，正しく受信デバイスと接続できると思います．
パケットを送信側デバイスから送信していれば，この設定終了と同時にCIRの値が以下のように表示され始めると思います．
![logging.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/27ae6156-7561-9490-cbe3-55c76a432d6a.png)

ログを取りたいという方は一度送信側のデバイスの電源をOFFにして，logging > Start Terminal Loggingからlogファイルの出力場所を設定してください．送信デバイスの電源をONにすると受信したパケットのCIR信号が複素数で表示され，そのログが指定したファイルに出力されるはずです．
![log.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/6bec160c-f4bc-594a-0b6d-9bd35e48c16e.png)

# 5 おまけ
取得したCIRの振幅(絶対値)をmatplotlibで表示したものを示しておきます．
![test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584431/babffff7-7484-d528-fe83-d47622495986.png)
赤い点線がFPIを表しています．うまくピークが取れています．

# 6 参考記事
[DWM3000EVBを用いたUWB位置測位① ~セットアップ編~](https://qiita.com/tukurida/items/e17481a2f9a9c7532dc1)
[DWM3000EVBを用いたUWB位置測位② ~PCデモ編~](https://qiita.com/tukurida/items/9ebd68ab97daff315d7e)