pySerialを使った顕微鏡用多波長LED光源の高速波長切り替えについて

## はじめに

なぜこの内容で書こうと思ったかというと、プログラミング言語Python(パイソン)での画像処理の記事はよく見ますが、ハードウェアの制御について書かれた記事はほとんどなかったからです。Pythonでもハードウェアの制御ができるんだ、ふむふむ、と感じてもらえると幸いです。

このページではPythonを用いて、顕微鏡用多波長LED光源の制御を行う方法について共有します。
顕微鏡(特に蛍光顕微鏡)を使っているバイオ系の研究者や学生さんをイメージしながら記事を書いています。
もちろん電気系の分野でも応用可能です。
Pythonを使うことで、各メーカーの標準のソフトウェアでサポートされていない製品同士の同期ができます。また、画像取得から画像解析までを自動化することができます。大量の画像を取得して統計解析するような分野の研究者にとって特にご利益があるでしょう。
ご参考になれば幸いです。
![kenkyu_man.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509635/e04368c2-ce00-2228-b844-4f38cc56fbca.png)

## 開発環境

- Windows10 (x64)
- Python3.6
- Anaconda3
- pySerial3.4


 

##顕微鏡用多波長LED光源の高速波長切り替え
![ダウンロード (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509635/438bedb0-e409-f732-ed2b-312f3ae6d471.gif)


バイオサイエンス分野や医療分野で細胞を観察するために、光学顕微鏡が一般的に用いられます。光学顕微鏡用のLED光源は基本的に付属の標準ソフトウェアで操作されますが、中には自分なりにカスタマイズしたいという要望もあるかと思います。そこで今回はPythonを用いてLEDの波長を高速(ミリ秒オーダー)に切り替える方法について書きます。

**使用する機材**

- 顕微鏡用多波長LED光源 :　niji(Blue Box Optics)

- シグナルコンバーター: 2 Channel USB Powered Relay Module(numato Lab)

- PC




**システム構成**
顕微鏡用多波長LED光源に、TTL(Transistor-transistor-logic)信号を入力できればオッケーです。つまり0Vの電圧を入力した場合はLEDがOFF、5Vの電圧を入力した場合はLEDがONとなります。これを高速に切り替えることで波長の切り替えを行います。
システムの概略は下の図を参考にしてください。
PCからPythonを使ってシグナルコンバーターにシリアル信号を送ります。その信号をシグナルコンバーターによってTTL信号に変換し、顕微鏡用多波長LED光源に送るという流れです。電気的な配線は割愛します。
![fig1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509635/2f0a5c5f-d13f-1da9-18fe-d5580a77a1a9.png)

実際の写真はこちら
![fig２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293080/14054227-d656-a6bd-758d-4163d638a537.png)

**プログラム**
まず、シリアル通信用ライブラリ「pySerial」をインストールします。
以下のプログラムを実行してください。LEDが点滅したら成功です。
関数LED_ON()の引数gpio_numberを変えることで光らせる波長を選択できます。


```python:LED.py


import datetime
import serial.tools.list_ports
import time

# COMポートに接続されている機器の情報を取得
coms = serial.tools.list_ports.comports()

# シグナルコンバーターの名前を設定
signal_converter_name = 'Numato Lab 2 Channel USB Powered Relay Module'

# シグナルコンバーターの名前を検索
print('[{}] searching the COM list...'.format(datetime.datetime.now()))

for com in coms:
    flag = signal_converter_name in com.description

    # 該当の名前が見つかったらCOMポートの番号を格納
    if flag is True:
        COM_PORT = com.device
        print('[', datetime.datetime.now(), ']', 'connected COM ports is: ', com.description)
    else:
        pass


def led_on(gpio_number=0):
    """
    LED ON function.
    Serial command to TTL signal conversion. TTL ON.

    Parameters
    ----------
    gpio_number : GPIO port number. Default is 0.

    Returns
    -------
    HIGH(5V) signal output from GPIO pin.

    """
    # シグナルコンバーターからTTL信号を出力するピン番号の設定
    gpio_port = str(gpio_number).encode()

    # ONに設定
    gpio_command = b'set'  # 'set' means HIGH(5V)

    # Open port for communication
    serPort = serial.Serial(COM_PORT, 19200, timeout=1)

    # Send the serial command
    serPort.write(b'gpio' + b' ' + gpio_command + b' ' + gpio_port + b'\n\r')
    print('[', datetime.datetime.now(), ']', 'LED_on')

    # Close the port
    serPort.close()


def led_off(gpio_number=0):
    """
    LED OFF function.
    Serial command to TTL signal conversion. TTL OFF.

    Parameters
    ----------
    gpio_number : GPIO port number. Default is 0.

    Returns
    -------
    LOW(0V) signal output from GPIO pin.

    """
    # シグナルコンバーターからTTL信号を出力するピン番号の設定
    gpio_port = str(gpio_number).encode()

    # OFFに設定
    gpio_command = b'clear'  # 'clear' means LOW(0V)

    # Open port for communication
    serPort = serial.Serial(COM_PORT, 19200, timeout=1)

    # Send the serial command
    serPort.write(b'gpio' + b' ' + gpio_command + b' ' + gpio_port + b'\n\r')
    print('[', datetime.datetime.now(), ']', 'LED_off')

    # Close the port
    serPort.close()


if __name__ == '__main__':

    for i in range(20):
        # LED ON
        led_on(0)

        # wait 1sec
        time.sleep(1)

        # LED OFF
        led_off(0)

        # wait 1sec
        time.sleep(1)

        # LED ON
        led_on(1)

        # wait 1sec
        time.sleep(1)

        # LED OFF
        led_off(1)

        # wait 1sec
        time.sleep(1)
```

**動作例の動画**
以下のHPに動画があります。参考にしてください。
http://www.opto-line.co.jp/technical/tech78.html




>参照
>pyserial公式HP
https://pythonhosted.org/pyserial/pyserial.html#overview
>pyserial short introduction
>https://pyserial.readthedocs.io/en/latest/shortintro.html
>

次回の記事
[Pythonでカメラを制御する【研究用】](https://qiita.com/opto-line/items/7ade854c26a50a485159)