DPS-150 Python Library -- PyDps150.py

# はじめに
[FNRISI](https://www.fnirsi.com/) のCNCポータブル電源 [DPS-150](https://www.fnirsi.com/products/dps-150?variant=46011574550746)を制御するPythonライブラリーを組みました。

#### お急ぎの方へ
[Gitlab](https://gitlab.com/fanfanlab/pydps150)からDLして使ってください。最小限のことはREADME.mdに書きました。もしわからなければここを最後まで読むか、ChatGPTに聞いてください。

#### なぜDPS-150を制御しようと思ったのか
ちょっとした実験をしたかったのです。LEDのIV曲線を描いたり、モーターの動的電流値を測定したり。でもグラフ用紙と、鉛筆はないし、PCとエクセルも面倒です。ならやらなければいい、という選択肢はそれでも見たいという好奇心に負けました。

#### 最初の期待と実際の苦戦
「そうだ！こういうときはPythonで自動化だ！」コンピュータにつなげる電源を探し始めました。選択肢はわずかでした。あります。でも遊びには高すぎます。[DPS-150](https://www.fnirsi.com/products/dps-150?variant=46011574550746)が安く、外部制御がUSBでできるものでした。外部制御端子があるんだ、制御プログラムもある。もしかするとPythonも探せば見つかるんじゃないかな？甘い期待で、ポチりました。

#### ライブラリ化への道
ところが、公式GUIはリモート・コントローラーの類で、さしたるドキュメントがなく、USBパケットを手探りで探る状態でした。

#### PySerialから始まり、CRCの迷路へ
はじめはCDCで動作するのか疑心暗鬼でしたが、WireSharkでChapterしたパケットを丸投げすると動くのを確認できました。「結局CRC値の計算法が違っていたんだ。」そう気づいたのは夜明け前です。

#### Lockの正体に気づいた瞬間
エラーは返らなくなりましたが、設定できないことに変わりありません。
わかれば何でもないのですが、本体のキーボードをロックした状態でないとUSBでの設定は出来ません。
ここまでわかれば急転直下で、完成に漕ぎ着けました。ですからこのライブラリーは **自動** でKeyLockします。

# Install法
#### Download
下記GitLabよりPyDps150.pyを入手して、これからPythonを書くフォルダーに置きます。
[https://gitlab.com/fanfanlab/pydps150](https://gitlab.com/fanfanlab/pydps150)
他に各種Docが入ってますので、チュートリアルを使うならフォルダーごと取ってきてください。

#### 必要モジュール
pyserialを使います。グラフを出すならmatplotlibもいります。
```bash
pip install pyserial matplotlib
```

#### 使用法
Lチカの例です。
```python: blink.py
import time
from PyDps150 import PyDps150


dps = PyDps150()

dps.iset(0.0)  # 最初は電流ゼロ
dps.vset(2.5)  # 印加電圧を固定
dps.power_on()
input("🔌 LEDを接続してください（Enterで開始）")

while True:
    dps.iset(0.01) # 10mA
    time.sleep(1)
    dps.iset(0) # 0mA
    time.sleep(1)
```
```bash
python3 blink.py
```
でLEDが点滅します。
#### method
| メソッド名     | 機能                     |
|----------------|--------------------------|
| `vset(volt)`   | 出力電圧を設定する       |
| `iset(amp)`    | 出力電流を設定する       |
| `vget()`       | 現在の出力電圧を取得する |
| `iget()`       | 現在の出力電流を取得する |
| `power_on()`   | 出力電源をオンにする     |
| `power_off()`  | 出力電源をオフにする     |
| `close()`      | デバイスとの接続を終了する |

 # **測定例（チューター）**

自動測定の例として、LEDの動作曲線(IV Curve)を測定します。
まず、プログラムを書きます。ここまで理解されていれば容易でしょう。電圧を固定し、電流を徐々に上げて、その度電圧を記録していきます。
```python:LED.py
import time
import matplotlib.pyplot as plt
from PyDps150 import PyDps150


def measure_led_iv():
    dps = PyDps150()

    try:
        dps.power_off()
        dps.iset(0.0)  # 最初は電流ゼロ
        dps.vset(2.5)  # 印加電圧を固定
        dps.power_on()
        input("🔌 LEDを接続してください（Enterで開始）")

        voltages = []
        currents = []

        current = 0.0
        step = 0.001  # 1mAステップ
        max_current = 0.02  # 20mA上限

        while current <= max_current:
            dps.iset(current)
            time.sleep(0.3)
            v = dps.vget()
            i = dps.iget()

            if v is not None and i is not None:
                voltages.append(v)
                currents.append(i)
                print(f"Set I = {current:.3f} A | V = {v:.2f} V, I = {i:.3f} A")
            else:
                print(f"⚠️ 応答なし (I = {current:.3f} A)")

            current += step

        dps.iset(0.0)
        dps.vset(0.0)
        dps.power_off()

        # グラフ表示
        plt.plot(voltages, currents, marker='o')
        plt.title("IV Curve of LED")
        plt.xlabel("Voltage [V]")
        plt.ylabel("Current [A]")
        plt.grid(True)
        plt.show()

    finally:
        dps.close()


if __name__ == "__main__":
    measure_led_iv()
```
```bash:
python3 led.py
```
で自動測定しグラフが現れます。

![iv_led.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245853/60cb2ab6-939e-4532-87c0-93eadfbc98af.png)


# おわりに
- 複雑な手順でも、簡単にプログラム化出来ます。各種工程の自動化にはぴったりです
- 高校／高専の学習用教材に適していると思います
- 多くのスクリプトと助言をChatGPTにもらいました。これなしには１０倍以上の時間を要したでしょう。

# 参考文献
https://github.com/cho45/fnirsi-dps-150