Quimat QY-15 リレーモジュールをLINUXで動かして、自由にスイッチON/OFFする。

# Quimat QY-15 を LINUXで動かす

## 何の話？

USB経由で４つのスイッチをON/OFFできる Quimat QY-15 リレーモジュールを使ってLINUX(CentOS7)上で動作させるところまでの話です。
IoTっぽい事をやりたいと思い、CentOSが起動する小型デバイスを用意したので、バスパワーで動かせるスイッチモジュールが欲しいと思った次第です。
LINUX系(Ubuntu Mac等)においてはやる事は基本同じだと思いますので、各々の解釈で見ていただければ幸いです。

## Amazonにて

![2020-04-17_103407_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65983/e7eabad2-bba6-4ca6-46e7-0514a53d9f7d.png)

USBでスイッチのON/OFF制御が4チャンネルでできるやつです。便利そうでしょ？
Amazonで「リレー usb」と検索すると一番最初に現れるし、「Amazon's Choice」だから安心だろと思い、ポチりました。（スポンサープロダクトは見逃してました・・）

## 買った後

まあ分かっていたんですが、案の定「本体」と「ケーブル」のみ。マニュアルもドライバもサンプルプログラムも入っておらず、ショップのページで見たダウンロードURLはリンク切れ（後でわかったのですが、今見たら復活していました・・不安定なのかな？）なので、いろいろ調べました。
幸い、レビューのコメントや別機器のプログラムを参考にして分かったことをまとめます。

## 色々調べる

どうやら、「FTDIチップ」という、「USBからゴニョっと制御できちゃうよ～」という何とも便利そうなチップを使っているようです。となると、そのドライバで制御できちゃうのでは？と思い、サイトに突入。
https://www.ftdichip.com/Drivers/D2XX.htm
ドライバを無事入手できました。（CPUの種類やOSを選んでダウンロード）

インストールはReadMeの通り実行（※libftd2xx-xxxxx.tgzはフォルダでまとめられていない為、展開したら中身をぶちまけることになるので注意）
（xxxxxはバージョン番号です。各々のバージョンに合わせてください）

```
mkdir libftd2xx
cd libftd2xx
wget [libftd2xxダウンロードのURL]
tar xfvz libftd2xx-x86_64-xxxxx.tgz
cd release/build
sudo cp libftd2xx.* /usr/local/lib
sudo chmod 0755 /usr/local/lib/libftd2xx.so.xxxxx
sudo ln -sf /usr/local/lib/libftd2xx.so.xxxxx /usr/local/lib/libftd2xx.so
```
この後、デバイスを接続し、認識していることを確認するのですが、
「ftdi_sio」 というドライバが競合するそうなので、以下も実行します。
※こちらは他で使っている場合があるかもしれませんので、心当たりのある方は別の手段をご検討ください。

```
sudo rmmod ftdi_sio
sudo rmmod usbserial
```


## ドライバはそろった。でも制御は？

LINUX環境の制御ソフトは有り物がないので、作るしかないという感じでした。LINUX開発環境と言えば？

```
sudo yum install gcc
```

gcc(c/c++)先輩の登場です。（CentOSのパッケージマネージャはyumですが、他の環境では各々の解釈でお願いします。あと開発環境はディスク容量取るので、コンパイルする環境は制御デバイスと分けた方がいいです。ディスクサイズが許容範囲であればYで進んでください。）

gitにてソース用意しました（なければインストールしてください）

```
git clone https://github.com/RAWSEQ/ftd2_qy15_relay
cd ftd2_qy15_relay/sample
make
```

コンパイルしてファイル `ftd2_qy15_relay_sample` ができるので、それを実行。
（デバイスの制御はルート権限が必要なので注意。）

```
sudo ./ftd2_qy15_relay_sample
```

カチっと音が鳴れば成功。

どうなっているかはソースを確認してみましょう。
上記、sampleフォルダには単純化したソースを用意しています。

```cpp

#include <stdio.h>
#include <assert.h>
#include <string.h>
#include "./ftd2xx.h"

int main()
{
    // Settings

    int port = 0;
    char buff = 0b00001010; //  channel 1 2 3 4 => 0 1 0 1

    int retCode = -1; // Assume failure
    FT_STATUS ftStatus = FT_OK;
    FT_HANDLE ftHandle = NULL;
    DWORD bytesWritten = 0;

    // Open

    ftStatus = FT_Open(port, &ftHandle);
    if (ftStatus != FT_OK)
    {
        printf("FT_Open(%d) failed, with error %d.\n", port, (int)ftStatus);
        printf("- Use lsmod to check if ftdi_sio (and usbserial) are present.\n");
        printf("  If so, unload them using rmmod, as they conflict with ftd2xx.\n");
        printf("- Check the port number of the device you want to use.\n");
        printf("- Try run by Super User Mode.\n");
        goto exit;
    }

    // Setup (BIT BANG MODE)

    assert(ftHandle != NULL);
    FT_ResetDevice(ftHandle);
    FT_SetBaudRate(ftHandle, 9600);
    FT_SetDataCharacteristics(ftHandle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE);
    FT_SetDtr(ftHandle);
    FT_SetFlowControl(ftHandle, FT_FLOW_RTS_CTS, 0, 0);
    FT_SetRts(ftHandle);
    FT_SetTimeouts(ftHandle, 3000, 3000); // 3 seconds
    FT_SetBitMode(ftHandle, 0xff, 1);

    // Write

    FT_Write(ftHandle, &buff, 1, &bytesWritten);

    printf("Sended.\n");

    retCode = 0;

exit:
    if (ftHandle != NULL)
        FT_Close(ftHandle);

    return retCode;
}

```

`FT_Open` でデバイスに接続し、ゴニョゴニョ設定（BIT BANGモードとやらに）して `FT_Write` で書き込みという流れです。
ここで注目すべきは `buff` という変数。二進数で「00001010」とセットされています。
（デバイスが複数ある時は `port` を変えてみてください。）

一番右（１桁目）から数えて 1,2,3,4 番のスイッチを制御できます。
つまり、上記の場合は「1=OFF, 2=ON, 3=OFF, 4=ON」となります。

ということは、今はコンパイルしないと値を変えられないですが、`buff` を何とかしてやれば、自由にスイッチ制御できるということです！

逆の方法で `FT_Read` を使って状態を確認することもできます。

引数で制御できるやつも作ったのでご利用ください。
https://github.com/RAWSEQ/ftd2_qy15_relay