IMBLEの動作テスト

# IMBLEとは
[インタープラン株式会社](http://www.interplan.co.jp/ "インタープラン株式会社")から発売されているBLEデバイスです。[(シリアル通信で簡単制御 Bluetooth Low Energy無線モジュール)](http://www.interplan.co.jp/solution/wireless/imble.php "シリアル通信で簡単制御 Bluetooth Low Energy無線モジュール")
UART(シリアル通信)でコマンドを送ることで簡単にスマートフォン等とデータのやりとりを行うことが可能だそうで、とりあえず買って動かしてみました。

# 回路図
3.3Vのレギュレータと8ピンPSoCマイコン(CY8C27143)とプッシュスイッチ、IMBLEコネクタ-変換基板([IMBLE-ADP](http://www.interplan.co.jp/solution/wireless/imble_adp.php "IMBLE用変換アダプタ")なるもの)とを下図のように配線してテストしました。(2016/12/25追記：プッシュスイッチの接続ポート間違えてたので修正しました)
![IMBLE_test.PNG](https://qiita-image-store.s3.amazonaws.com/0/71503/64befa30-f6d9-4ccc-6d31-c2e0b32262c0.png)
他のマイコンを使う場合は出力ピンの電圧が3.0～3.3Vのものを使用してください。(5Vトレラントじゃないようなので5V系の回路と直結したら壊れることと思われます)
本来はBUSY(RTS)端子の状態を確認しながらUARTのコマンドを与えないといけないようですがとりあえずテストということで処理と配線を省いています。
同様にSLEEP REQUEST(CTS)端子も常時SLEEP解除(=Lレベル)としてGND直結、RESET端子もオープン(プルアップ内蔵、Lレベルでリセット)としています。
MODE端子はRev. 1.2 2016.12.6のIMBLE取扱説明書(ハードウェア編)ではデータモード(=Lレベル)のみ使用可能とのことでGNDに落としています。

# PSoCの設定とCのコード
デジタルブロックはUARTモジュールを1個置いて、回路図と同じになるようにGlobal_In/Outを配線します。
![PSoCChipEditor.png](https://qiita-image-store.s3.amazonaws.com/0/71503/886c40ee-c18e-08d7-6d86-7a411e3a1012.png)

CPUクロックはとりあえず内蔵24MHz、UARTのボーレートを9600bpsにしたいので((((24×10の6乗)÷8)÷VC1(=13))÷VC3(=24))≒9600として分周クロックを設定します。
あとSupply Voltageは3.3Vにします。
![PSoCSettings.png](https://qiita-image-store.s3.amazonaws.com/0/71503/09dc0d45-5c2d-9b65-d93a-b68c0e468795.png)

使用するポートはUARTのTxD、RxD、プッシュスイッチ入力用の内蔵プルアップに設定したポートの3本です。
![PSoCPinOut.png](https://qiita-image-store.s3.amazonaws.com/0/71503/743c4b6d-cf25-aaa8-f856-2b7299fe4772.png)

Cのコードは下記の通り。動作としては

- ボタンが押されていれば0xC0FFEEを送信
- ボタンが押されていなければ0xBEAFを送信
- (別にいらないけど送信間隔伸ばしたかったので)カウント用変数をインクリメントしていって指定値になったらカウント用変数をクリアして送信動作を行う
- ADDRESS_MYDEVICEのアドレスのデバイス以外が接続してきたら切断(接続されてるかどうかはチェックしてない)

データを送信するときは　"TXDT (16進数をASCIIで書く)" または "TXDA (16進数をASCIIで書く)" の形式で送るようです。( TXDT 01020304ABCDEF00 みたいな形で、TXDTは8バイト固定長(空きは00埋め)、TXDAは16バイトまでの可変長 とのこと)

```c
//----------------------------------------------------------------------------
// C main line
//----------------------------------------------------------------------------

#include <m8c.h>        // part specific constants and macros
#include "PSoCAPI.h"    // PSoC API definitions for all User Modules
#include "string.h"    // PSoC API definitions for all User Modules

#define CMD_CONNECT "CONECT"
#define ADDRESS_MYDEVICE "XX:XX:XX:XX:XX:XX"

#define COUNT_TXD 25000
#define COUNT_TXD_MULTIPLY 3

BOOL isBitHigh(BYTE port, BYTE bit){
    port = (port >> bit) & 0x01;
    if (port == 1){
        return TRUE;
    }else {
        return FALSE;
    }
}

void main(void){
    unsigned int count = 0;
    unsigned int intervalCount = 0;
    unsigned int intervalCountMultiply = 0;
    char * cmd;
    char * para;
    BYTE port = PRT0DR;
    BOOL isOK = FALSE;

    // 内蔵プルアップ使うときは該当ポートにあたるビットに1書いとかなきゃいけないらしい
    PRT0DR |= 0x04;
    
    UART_1_CmdReset();                      // Initialize receiver/cmd buf. 
    UART_1_IntCntl(UART_1_ENABLE_RX_INT);   // Enable RX interrupts  
    UART_1_Start(UART_1_PARITY_NONE);

    M8C_EnableGInt;

    while(1) {
        if (UART_1_bCmdCheck()) {                       // Wait for command    
            if (cmd = UART_1_szGetParam()) {            // get command  
                if(!cstrcmp(CMD_CONNECT, cmd)) {
                        if (para = UART_1_szGetParam()) {
                            // 他人のデバイスがつなごうとしてきたら切断
                            if (!cstrcmp(ADDRESS_MYDEVICE, para)){
                                UART_1_CPutString("DSCN");
                                UART_1_PutCRLF();
                            }
                        }
                    }
                }
            UART_1_CmdReset();          // Reset command buffer    
        }

        if (intervalCountMultiply >= COUNT_TXD_MULTIPLY){
            intervalCountMultiply = 0;
            
            port = PRT0DR;
            
            // ボタンが推されたとき
            // ボタン押すとGNDに落ちるので
            if (!isBitHigh(port, 2)){
                UART_1_CPutString("TXDT ");
                UART_1_PutSHexByte(0xC0);
                UART_1_PutSHexByte(0xFF);
                UART_1_PutSHexByte(0xEE);
                UART_1_PutCRLF();
                while (!isOK){
                    if (UART_1_bCmdCheck()) {                       // Wait for command    
                        if (cmd = UART_1_szGetParam()) {            // get command  
                            if(!cstrcmp("OK", cmd)) {
                                isOK = TRUE;
                            }
                        }
                        UART_1_CmdReset();          // Reset command buffer    
                    }else {
                        count++;
                        if (count >= COUNT_TXD){
                            count = 0;
                            isOK = TRUE;
                        }
                    }
                }
                isOK = FALSE;
            }else {
                // ボタンが推されてないとき
                UART_1_CPutString("TXDT ");
                UART_1_PutSHexByte(0xBE);
                UART_1_PutSHexByte(0xAF);
                UART_1_PutCRLF();
                while (!isOK){
                    if (UART_1_bCmdCheck()) {                       // Wait for command    
                        if (cmd = UART_1_szGetParam()) {            // get command  
                            if(!cstrcmp("OK", cmd)) {
                                isOK = TRUE;
                            }
                        }
                        UART_1_CmdReset();          // Reset command buffer    
                    }else {
                        count++;
                        if (count >= COUNT_TXD){
                            count = 0;
                            isOK = TRUE;
                        }
                    }
                }
                isOK = FALSE;
            }
        }else {
            if (intervalCount >= COUNT_TXD){
                intervalCount = 0;
                intervalCountMultiply++;
            }else {
                intervalCount++;
            }
        }
    }
}
```

# 基板写真と実行結果
**注意** IMBLEはデフォルトでは19200bpsで通信するようになっているので、USB-UART変換(3.3V)とターミナルソフト(TeraTermなど)で予め9600bpsで通信するようにします。

1. ターミナルソフトで19200bpsで指定ポート(->IMBLEとつながっているCOMポート)と接続
2. ENWR と打つ(内蔵不揮発メモリの書込みを許可)
3. SBRT 3 と打つ(ボーレート9600bpsへ変更)
4. ターミナルソフトのボーレートを9600bpsに変える
5. DSWR と打つ(不揮発メモリ書込み禁止)
![IMG_20161218_015830 - コピー.jpg](https://qiita-image-store.s3.amazonaws.com/0/71503/dfafb2ff-9c6c-10e5-ac09-7e2536dc2291.jpeg)

公式からIMBLEのモニタ用Android/iPhoneアプリが出ているのでそれを使用して観測した結果が下写真の通り。

ボタンを押したとき
![Screenshot_20161218-015605.png](https://qiita-image-store.s3.amazonaws.com/0/71503/a01dc81d-4da5-3172-5688-67e61c8649a7.png)

ボタンを押してないとき
![Screenshot_20161218-020757.png](https://qiita-image-store.s3.amazonaws.com/0/71503/d5ebc68c-2968-0fbd-6d7d-4c771d5d305e.png)

# ハマったところ

- ボーレート変えようとしたときにENWR/DSWRしてなくて、シリアルポート繋ぎ変える際の電源断で設定が19200bpsに戻ってしまった(ENWRしてない状態では電源が入ってる間は設定が保持され、電源断で揮発する)
- PSoCのプロジェクトの設定でSupply Voltageが5.0Vのままになってて3.3V供給してもまともに動かない状態だと気づくまで数時間
- 3.3Vの入出力電圧で大丈夫だよね？IMBLEのポートブッ壊さないよね？とビビりすぎてレギュレータがまともに電源供給できないレベルまでVinの電圧を下げてしまったこと(3.9～4.0Vくらいまで下げてしまっててダメでした、ちゃんとVoutが3.3VになるようVin上げました)

# (´ω｀)
動いてくれたのでたのしい　用途はこれから考えます