PC制御式LDドライバに物理インターフェイスを付けてみた

電子回路
レーザー
マイコン
Published

2024-03-24

Modified

2024-03-24

概要

将来的なLDのリモート制御のために、PCで制御するタイプのLDドライバを買ってみました。が、実験室で使うのにいちいちPCと接続しないといけないのは大変なので、ケースに入れてフロントパネルから簡単な操作ができるようにしました。

構成

ケースの中には

  • リニア電源
  • PC制御LDドライバ(基板タイプ, Koheron: CTL-200)
  • インターフェース用基板
    • マイコン(Adafruit: Qt Py SAMD21)
    • ロータリーエンコーダー
    • タクトスイッチ × 2
  • OLED

が入っています。

ケース内の様子。写真はテスト段階のものなので、まだフロントパネルにスイッチ類がついていません。

ケース内の様子。写真はテスト段階のものなので、まだフロントパネルにスイッチ類がついていません。

リアパネルにUSB端子を引き出してあり、PCでの制御も引き続き可能です。が、フロントパネル操作とPC操作の競合については未検証。おそらくですが、致命的なことにはならないと思われます。

電源

7 V × 2, 15 VAのトロイダルコアトランスで作った+5 V電源を使っています。リニアレギュレータには、可変タイプのLD1085 (最大3 A)を使っています。

当初、スイッチング電源を使っていたのですが、出力にスイッチング周波数のサイドバンドが発生していることが分かり、大人しくリニア電源を作りました。LDドライバにはスイッチングタイプのACアダプタが付属しているのですが、それで動かしたときはサイドバンドは出ないのだろうか?チャンスがあったらテストしてみようと思います。

マイコン

必要な入出力は多くないので、AdafruitのQt Py SAMD21を使いました。OLEDの動作をArduino IDE経由でしかやったことがなかったため、Arduino環境を優先してRP2040にはしませんでした。

AdafruitのQt Py SAMD21は秋月で買ったのですが、今はもう在庫限りのようです。マイコンボードは安定供給でないものが多くて、たまにしか作らない自作装置はどうしても1点ものになりがちです。その話はまた別の機会に。

LDドライバとの通信

LDドライバとはUARTで通信しています。

Qt Py CTL-200
TX ←→ RX
RX ←→ TX

という具合に、クロスで接続します。Qt Py SAMD21のArduino用ドライバでは、TX, RX端子を使ったシリアル通信にSerial1が割り当てられているようです。(USB端子を使ったシリアル通信にはSerialが割り当てられている。)なので、スケッチには

Serial1.begin(115200);
Serial1.setTimeout(3000);

などと記述します。

LDドライバにコマンドを送るための関数を作り、LDの状態を読み取ったり、スイッチやロータリーエンコーダの操作を書き込んだりします。

// 読み取り
float readCmd(String cmd) {
  Serial1.println(cmd);
  delay(5);
  if (Serial1.available() > 0) {return Serial1.parseFloat();}
  else {return 0;}
  while (Serial1.available() > 0) {char t = Serial1.read();} //シリアルバッファのクリア
}

// 書き込み
void writeCmd(String cmd) {
  Serial1.println(cmd);
  delay(5);
  while (Serial1.available() > 0) {char t = Serial1.read();} //シリアルバッファのクリア
}

操作用インターフェイス

マイコン操作用のインターフェイスとして、ロータリーエンコーダ1個とタクトスイッチ2個を取り付けました。ロータリーエンコーダは初挑戦でしたが、Arduino用のライブラリをそのまま使ったらすぐできました。また、タクトスイッチのバウンス対策もライブラリのものをそのまま使っています。

デバウンス
#include <Bounce2.h>

// void setup() 内
  debSel.attach(D1, INPUT_PULLUP); //オブジェクト"debSel"を設定 
  debSel.interval(10);

// void loop() 内
  debSel.update();
  if (debSel.fell()) {
    statePar++;
    if (statePar >= 5) {statePar = 0;}
  }  
ロータリーエンコーダ
#include <RotaryEncoder.h>

// void setup() 内
  // setup the rotary encoder functionality
  encoder = new RotaryEncoder(rotA, rotB, RotaryEncoder::LatchMode::FOUR3);
  
  // register interrupt routine
  attachInterrupt(digitalPinToInterrupt(rotA), checkPosition, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rotB), checkPosition, CHANGE);

// void loop() 内
  encoder->tick(); // just call tick() to check the state.
  I_set += I_resolution * (int)(encoder->getDirection());

ロータリーエンコーダは、割と回転を取りこぼす印象です。エンコーダ自体はALPS ALPINE製で変なメーカーのものではないです。マイコン側のループ速度のせいか、もしくはそもそもエンコーダはこんなものなのかもしれません。とりあえず使用上は問題ありません。

OLED

LDのON/OFF、電流値、温度はいつでも見られるようにしたいので、OLEDも取り付けました。I2Cで通信しています。Qt PyにはI2C通信用の信号 (SCL, SDA, VCC, GND) がQwiic端子で出ているので、そこからOLEDに接続します。Qwiic端子の正体はJSTのSHコネクタ(4極)です。秋月でケーブル付きで買えます。

OLEDを使うには画面表示用のライブラリAdafruit_SSD1306、文字列出力用ライブラリAdafruit_GFXが必要です。加えて、フォントライブラリを使っています。このあたりはネットでいろいろ調べ、ライブラリをコピペしつつ何とか使えるようにしたレベルなので、ちゃんと説明できません。。。

#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <Fonts/FreeSans24pt7b.h>
#include <Fonts/FreeSerif9pt7b.h>

外部入力

電流と温調には外部変調入力端子を用意し、フィードバック制御できるようしてあります。

温調は、まず、レベル合わせをした上でマイコンのADCで読み取り、マイコン内で積分してLDドライバの設定温度をデジタル制御する形にしてみたのですが、まだ試験していません。デジタル制御の方が時定数を大きくしやすいのでやってみました。

外観

フロントパネルは、なかなかよい感じではないでしょうか。写真の後、テプラでスイッチなどの表示を追加しています。

ファンレスなので、放熱対策にタカチのヒートシンクケースを使ってみましたが、ちょっと大袈裟でした。使ってみて、発熱はさほど気にならないので普通のケースで良かったかもしれません。電源トランス次第ですが、もう少し高さを抑えられたかもしれません。

タクトスイッチは、一方でモードを選んで、もう一方でON/OFFしたりレンジを切り替えたりといった感じです。数値の操作はロータリーエンコーダで行います。

まとめ

フロントパネルで電流のON/OFFと値の操作をするだけですが、とりあえず今のところちゃんと動いています。正直、インターフェイスを作らなかったら操作が面倒でレーザー自体あまり触っていなかったかもしれません。

残る宿題は、

  • 付属ACアダプタ使用時のスイッチング雑音の影響を確認
  • 温調と電流のフィードバック制御を確認
  • PC制御とフロントパネル操作の競合の有無を確認

です。