トップページ | SV405CCのINDIドライバー対応(2) »

2022年7月 9日 (土)

SV405CCのINDIドライバー対応

SVBONY の新しい冷却CMOSカメラSV405CCがリリースされたから一か月ほど経過しました。
SVBONY製のカメラドライバーも新しくなり、最初心配されていた問題も解決しみな使い始めているようです。

一方で私は普段天体撮影に使用しているStellarMateがSV405CC対応されておらず、すぐに撮影を開始ができません。
というわけでStellarMateで使用するINDI CCDドライバーのSV405CC対応をしました。

多くの方はSV405CCの機能レビューを書かれています。
ここではSVBONY Camera SDK を使用した INDI CCD ドライバーの SV405CC 対応について書くことにします。
ドライバー開発がSV405CCのレビューかと問われると・・・なんともなんですが

それにしてもブログを書くのは何年ぶりでしょうか。十年以上は書いていないような気がします。

なお2023年7月8日時点で、初期のコードはすでにindi-3rdpartyのリポジトリにマージされています。自分でビルドできる方なら利用可能です。
追加のコードが GitHub に Pull Requestされていますが、INDI本体のバージョンアップと重なりすんなりと通っていないようです。
今しばらくお待ちください。

環境

まずは私の撮影環境です。

撮影制御のコンピューター(デバイス側) Raspberry Pi 4B 8GB
StellarMate OS 64bit(DebianベースのLinux)
INDI Server
撮影制御のコンピューター(クライアントPC) Lenovo IdeaCentre 560 Ryzen 7 5700G Memory 64GB SSD/HDD計8TB
Windows 11
KStars, Ekos

主にベランダ撮影をしていて、PCのKStarsからラズパイのINDIにリモート接続で冬はぬくぬく夏は涼しく撮影しています。
下図は私の環境のソフトウェアダイアグラムです。左側がラズパイの環境で SVBONY Driver と書かれている二か所が今回対応したINDIドライバーです。

Software-diagram

KStars はプラネタリウムソフト、EKOS は KStars に組み込まれる天体撮影の制御プログラムでそれぞれ GUI を持ちます。
INDI はデバイス操作するための GUI を持たないプログラムです。

開発環境の構築

INDIのソースコードはGitHubに公開されています。
SVBONYの天体カメラ用のドライバーはINDIの本流ではなく有志によるINDI 3rdpartyドライバーのレポジトリに含まれています。 まずはGitHubのindi 3rdparty ドライバーのリポジトリをforkしラズパイ上にcloneを作成します。
あとはGitHubのREADME.mdで説明されている通りに進めます。
ビルドは libsv305 と indi-sv305 だけで十分です。
indi-3rdparty 全体のビルドは不要です。

コードの編集、ビルド、デバッグ などはPCのVisual Studio CodeにRemote Development拡張機能を導入し、PC からラズパイにリモート接続で行います。
他に導入したVisual Studio Codeの拡張機能はGitやC++などです。
ラズパイネイティブのVisual Studio Codeはつかいません。ラズパイにはとても重いのです。

開発内容

すでに SV305シリーズや SV905C まで対応されている indi-sv305 ドライバがあるので、このドライバーに SV405CC の対応をします。
なるべくオリジナルソースコードの方針を変えずに最小限の対応するという方針です。
手を入れるソースコードは以下の二つだけです。

indi-3rdparty/indi-sv305/sv305_ccd.cpp  
indi-3rdparty/indi-sv305/sv305_ccd.h  

これらのソースコードで宣言/定義する Sv305CCD クラスに手を入れます。

機種判定

機種判定するを行うメンバー関数 bool Sv305CCD::initProperties() にコードを追加します。
コンストラクタの中で SDK の関数 SVBGetCameraInfo により接続されている SVBONY のカメラの個体の製品名やシリアル番号などの情報が取得されます。
製品名 cameraInfo.FriendlyName が SV405CC であるばあいは、カメラの属性として以下の二つを設定します。

CCD_HAS_BAYER ベイヤーフィルターを持つ
CCD_HAS_COOLER 冷却機能を持つ

元のソースコードにならい initProperties() 内にこのコードを記載しましたが、この方法には少し疑問をもっています。 カメラに接続する Sv305CCD::Connect() 関数で Camera SDK の SVBGetCameraPropertySVBGetCameraProperty を呼び出しカメラの属性を設定するようにしたほうがよいかもしれません。
このようにカメラから取得した属性に基づいて設定を行えば、機能が同じであれば機種判定を必要とせずに将来の新しい製品への対応作業が不要になる可能性が高くなるからです。  

実際のところ SV405CC の機種判定を入れる前に SV405CC を接続すると、機種判定されないためにカラーカメラとしての情報が設定されず、モノクロカメラとして処理されてしまいました。

冷却

冷却は、SVBONY Camera SDK の SVBSetControlValue で Control type SVB_COOLER_ENABLESVB_TARGET_TEMPERATURE でクーラーのオンと目的の温度を設定すると機能します。

私は EKOS や INDI の GUI の操作とドライバーの関係が全く理解しておらず、indi-3rdpary についていたサンプルのドライバーのソースコードを見ながらの対応しました。
INDIのドキュメントをよく読んでから手をだせばすこし楽だったかもしれません。
これらを読まずにUIの操作とコード上の振る舞いをデバッガで確認しながらの実装しました。
ドキュメントへのリンクは末尾に記載しています。 INDIのパラメータ設定などについてはここでは割愛します。

温度設定

EKOSの画面で冷却温度を設定するとドライバーのメンバー関数 int Sv305CCD::SetTemperature(double temperature) が呼び出されます。

引数に温度が渡されるので以下の SDK 関数を呼び出してクーラーのオンと目標温度を設定します。

  • クーラーのオン: SVBSetControlValue(cameraID, SVB_COOLER_ENABLE, 1, SVB_FALSE);
  • 目標温度の設定: SVBSetControlValue(cameraID, SVB_TARGET_TEMPERATURE, (long)(temperature*10), SVB_FALSE);

クーラーのオン/オフの切り替え

EKOSやINDIの画面でクーラーのオン/オフを切り替えるとメンバー関数 bool Sv305CCD::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) が呼び出されます。

このメンバー関数はEKOSのUIを用いたオン/オフ切り替えに限らず、スイッチ型の二値の値をとるパラメーターが更新されたときに呼び出されます。
引数 name にクーラーが指定されたときに以下の SDK 関数でオンまたはオフを設定します。
SVBSetControlValue(cameraID, SVB_COOLER_ENABLE, 1, SVB_FALSE);

現在の冷却温度の表示

一定間隔で呼び出されるメンバー関数 void Sv305CCD::TimerHit() で現在の冷却温度の取得を行います。
この関数は冷却温度だけではなく、撮影後の画像データ取得にも使用します。

TimerHit は設定したタイマー値に合わせて呼び出される関数です。 この関数の中で SDK の SVBGetControlValue(cameraID, SVB_CURRENT_TEMPERATURE, &lValue, &bAuto) 関数を呼び出し現在の冷却温度を取得します。

TimerHit はメインループ中でタイマー値を見て呼び出されているとみられます。
つまり割り込みや別スレッドで動作するわけではありません。
このことは標準的なINDIの機能の中では TimerHit 中に処理の割り込みがないことを意味しています。
TimerHit の処理中にEKOSでパラメータを変更したり何らかの機能オン/オフのボタンを操作してもEKOSが操作されたことを認識するだけで、それに応じた動作は TimerHit を抜けた後で値やステータスの変化が起きます。
このことは TimerHit で画像データ取得中に撮影中止ボタンを押しても直ちに中止しないといった現象としてみることができます。
ただしドライバーの作成者が独自にスレッドを生成するなどした場合は同時に別の処理を実行することは可能です。

ここまでの実装で、SV405CC の冷却機能を使えるようになりました。

そのほかの改善など

以下はそのほかにもとのソースコードから改善・修正を行った箇所です。

インスタンスレベルの mutex

SV405CC の機種判定と冷却ができれば、撮影はもとのドライバーでできているので大丈夫なはずと思っていたら・・・
EKOS でカメラを切断・再接続をしようとしてもうまく動かない症状に遭遇しました。

元のソースコードをよく読むと、インスタンスレベルの排他制御を行う mutex がドライバーレベルの static 変数で定義されていて複数のカメラ、例えば SV405CC と SV905C を同時に接続すると mutex が予期したとおりに動作しなくなっていました。
mutex を Sv305CCD クラス のメンバーに変更して解決です。
SV905C は昨冬に行われたコンテストの賞品です。SV905C がなければこの問題を見逃すところでした。

画像のフォーマット

これが大問題で今回の修正で一番の目玉になると思います。
出来上がったドライバーを用いて撮影すると色の階層が滑らかではないのです。
ヒストグラムをみると一定間隔でレベル0のデータがあり、最初は他の方が見つけていた SVBONY Camera SDK の不具合と考えていました。

Twitter で SV405CC の ADC は 14bit だが、SV305 のソースコードの 12 bit のままにしているのではないかとの指摘。
確認すると確かに RAW12 でデータを取得するコードになっています。
ところが問題は RAW12 で取っていることではありませんでした。
カメラのADCのビット数にかかわらずSVBONY Camera SDK では RAW16 で取得する必要がありました。
RAW16 を指定すると画像は滑らかになりヒストグラムもなだらかな山になりました。
この問題は SV305 以降のすべての SVBONY の CMOSカメラ で発生していたはずにもかかわらず indi-sv305 ドライバーがリリースされて2年が経過してもだれも妙に思わなかったのは不思議なところです。

画像のヒストグラム比較
左:RAW16 で取得したデータ、右:RAW14 で取得したデータ

OFFSET対応

EKOSの撮影画面でOFFSETを設定できないのを修正しました。
これはOFFSETの指定にINDIの標準プロパティが使われていなかったのが原因でした。

そのほかにいくつかの型の誤りや、mutexのlock/unlockの対応のあっていない個所を修正しています。

残課題

以下はそのうち改善するつもりの課題です。

SVBONY Camera SDK 1.7.3 のフリーズ

私の環境ではなぜかCameraOpenまたはFormat指定の際にSDKの関数内でフリーズします。
単純なテストプログラムを作成しても再現するのでindiドライバーの問題ではないと考えています。
デバッガで確認した内容としては以下の通りです。

  • SVBONY Camera SDKでは内部でいくつかのthreadを使用している。
  • そのうち2つのthreadで互いにthread の wait がかかっていいる。

現時点ではSVBONYでの対応を待っているところです。
そのようなわけで INDI ドライバーでは SDK 1.6.5 を使用しています。

撮影停止(SV305用INDIドライバーの改善)

現在のsv305用のINDIドライバーには撮影停止の機能が入っていません。
撮影停止をできないことは使用感を著しく下げています。
私のプライベートコードではすでに実装済みです。基本的に撮影中フラグを false にするだけです。
これはいずれ Pull Requestを出します。

Video Streamingと静止画撮影の競合(SV305用INDIドライバーの改善)

INDIのVideo Streamingは別スレッドで動作しており、Video Stremingと静止画撮影を同時に実行すると一台のカメラで同時に撮影の制御は一つしかできないので競合が発生します。
オリジナルのコードでは SDK 呼び出しの前後に mutex をいれて SDK の競合は防いでいます。が、そもそも mutex はアトムにする必要のある一定のコードの塊を排他制御し、処理の一貫性を確保することにあります。
SDK 呼び出しのみを排他制御するのでは、処理の一貫性を保護できず、また不要なwaitの発生の原因にもなります。
現在のSV305用INDIドライバーはVideo Streamingと静止画撮影を使うと状態がおかしくなり妙なwaitの発生やVideo Streamingと静止画撮影で重複するパラメーターの設定がカオスな状態になります。
私的には Video Streaming よりも静止画撮影を優先すべきと考えています。 つまり、静止画撮影中は Video Streaming の操作をリジェクトする、Video Streaming 中に静止画撮影を開始する場合は Video Streaming を停止するなど、mutex によらず機能レベルの排他を行う必要があります。

TimerHit処理中の撮影データの読み取り(SV305用INDIドライバーの改善)

画像データを取得できるようになるまでのループ処理があります。このループ処理のため撮影停止などの割り込み操作が TimerHit の終了まで行えません。
特に SDK の SVBGetVideoData で SV905C などは露出時間とほぼ同等のデータ取得待ち時間が発生することがあり、かなりの長時間ループから抜けられないことが想定されます。これは SV405CC では発生しにくいようです。SV305は持っていないのでわかりません。
SVBGetVideoData で TIMEOUT が発生した場合はループを使わずにリトライのタイマーを設定し、いったん TimerHit の処理を抜けるようにするとこの問題は軽減されます。
私のプライベートコードではすでに実装済みです。
これはいずれPull Requestを出します。

ランピング(SV305用INDIドライバーへの実装)

クーラーによる温度の下降/上昇を緩やかにする機能です。
一分当たりの上下する温度を指定し、温度の下降/上昇を調整します。
現時点ではINDIドライバーで冷却は動作しているし、SDKにそのような機能はないので実装をしていません。
しかし実際に撮影をした際に、-10度まで冷却するとセンサーが結露してしまいました。その際は、一旦温度を上げ、気温より10度冷却温度を下げ、一定時間をおいてまた冷却するということを繰り返し、結露しないようにしました。
これを手動で行うのは面倒なので、指定した時間で目標温度を自動的に温度を設定する機構が必要だろうと考えています。

謝辞

最後になりましたが、オリジナルのコードの作成者であり、今回の実装の支援をしていただいた thx8411 にお礼を申し上げます。
仕事も家庭も忙しいなかのご協力いただき感謝します。

参考リンク

INDI関連ドキュメント

トップページ | SV405CCのINDIドライバー対応(2) »

天体観測」カテゴリの記事

コメント

この記事へのコメントは終了しました。