非職業的技師の覚え書き

JK1EJPの技術的検討事項を中心に記録を残します。

RS-HFIQ(14)Quisk IQバランス校正(2)

日乗

WRTC開催記念局

先々月の話になってしまいましたが、正月1月6日にNYPに参加していたところ、WRTC 2022開催記念国内局の強力な電波が飛び込んできました。

当時はまだ認知度が高くなかったためかパイルになっておらず、CQを連呼している状態だったため、40m QCX+ 5Wと室内モービルホイップの組み合わせによるQRPでも1回で取ってもらえました。ワッチが重要であるという教訓でしょうか。

そのWRTC 2022開催記念局の運用期間が終了し、eQSLとAwardがHamAwardからダウンロード可能になっていました。(QSLはeQSL.ccからもダウンロード可能でした。)

The eQSL (left) and award (right) for the amateur radio station commemorating WRTC 2022.

HamAwardからダウンロードしたeQSLは単なる画像ではなく、eQSLのQRコードを読み取ると、左図のようにクラウド上でQSOが証明される仕組みになっています。

右図のAwardは、40m CWでの1回のQSO(10点)だけなので、順位15,009位の参加賞です。クラウドサービスによって、万単位の参加賞も瞬時に発行できるようになったということですね。

ただし、HamAwardからのダウンロードのハードルは高く、QRZ.comのメールアドレスを認証段階で使用するため、QRZ.comへの登録が必要です。また、保有する3つのブラウザの中の2つではセキュリティの関係で上手くダウンロードできませんでした。発行の複雑な仕組みがセキュリティにひかかるのでしょうか。

Raspberry Pi 400 の進捗

Raspberry Pi 400用のディスプレイを組み立てました。

7.9" high resolution (1536 x 2048) IGZO LCD panel set for Raspberry Pi 400.

秋月の7.9インチ高精細(1536 x 2048)IGZO液晶パネルセットと組み立てケースです。変則的な解像度ですが、Raspberry Pi OSのScreen ConfigurationメニューからHDMI1への出力を選択して回転方向を変更したところ、問題なく表示できました。組立マニュアルに指示があるConfig.txtの編集を行う必要はありませんでした。Raspberry Pi OSも進化しているようです。

Pi 400はオーディオジャックを省略していますが、代わりに奢った2式のHDMIがディスプレイデータに加えてオーディオデータも出力します。液晶パネルセットは3.5mmオーディオ出力ジャックも備えます。これでようやくQuiskのモニタ音を聞くことが出来るようになりました。

ここで気づきがありました。スピーカアンプをRS-HFIQの後方の横に置いたところ、ケーブルをつないでいないのに大きなノック音を拾いました。USBからの5V供給のみで、13.8Vを供給していない状態でも発生します。RS-HFIQの後方のディジタル系統からノイズが放射されているようです。

 

本題です。今回は、IQバランス校正機能がQuiskにどのように実装されているかを調査しました。まず、ベースになっている理論を確認します。

IQバランス校正の理論

実装のベースになっている理論式を2003年発表の下記参考文献から拾いました。Webで検索すると、引用の多い基本文献であることが分かります。

Ellingson, S.W. Correcting IQ Imbalance in Direct Conversion Receivers; Virginia Polytechnic Institute and State University: Virginia, VA, USA, 2003; pp. 25–32.

校正式を(1)式の形に置くと、In-Phase信号に仮定した振幅誤差αと、Quadrature信号に仮定した位相誤差ψを同定することにより、(2)式が得られます。

直観的には、校正式は対角行列になるイメージがありましたが、回転する信号から位相誤差を分離する際に三角関数の加法定理を使うため、位相の校正には回転する正弦(In-Phase)と余弦(Quadrature)の両方が必要になります。

QuiskのIQバランス校正機能実装の調査

IQバランス校正データ

校正データは他の状態データ一式と共にQuisk初期化ファイル./quisk_init.jsonに保存され、Quisk起動時に毎回読み込まれます。Quisk終了時には毎回上書きされるようなので、適宜バックアップを取った方が安心かもしれません。

「bandAmplPhase」という名称の辞書型の校正データの構造を下記に示します。今回、試験作成した校正データを例に示しています。

Data structure of IQ balance calibration.

Pythonの辞書型とリスト型を入れ子にした複雑なデータ構造を取ります。なお、辞書型は名前で要素にアクセスし、リスト型はインデックスで要素にアクセスします。データ構造の解読結果は以下の通りです。

最初のVersion情報は、古い実装バージョンと整合を取るためのものではないかと思います。

その後に、バンド別の辞書型データが並びます、上図では40mバンドの例のみを示しています。

各バンドは、受信(QSD)用のIQバランス校正データの辞書と、送信(QSE)用のIQバランス校正データの辞書を含みます。上図では受信「rx」用の辞書の例のみを示しています。

受信用もしくは送信用のIQバランス校正データの辞書は、任意の数の校正点VFO周波数(LO周波数)データのリストを含みます。上図ではVFO=7.020000MHzの例のみを示しています。

校正点VFO周波数(LO周波数)データのリストには、さらに任意の数の校正点データセットのリストが付属します。上図は4つの校正点データセットのリストを示しています。校正点データセットのリストの要素は、①オフセット周波数、②振幅校正パラメータ(α)、③位相校正パラメータ(ψ)の3つです。

IQバランス校正GUIのボタンとコールバック関数

IQバランス校正パネルの各GUIボタンのコールバック関数の役割を調べました。

GUI buttons on the IQ balance calibration screen.
  1. Save - コールバック関数:OnBtnSave()
    校正データをファイルに保存するボタンと思いましたが、ファイルへの保存はこの時点では行いません。校正データは、Quisk終了時に他の状態データ一式と共に ./quisk_init.json に保存されます。このコールバック関数では、グローバル変数のbandAmplPhase辞書への校正データの登録とソートを校正点毎に逐次行います。

  2. Destroy VFO - コールバック関数:OnBtnDestroyVFO()
    現在のVFO(LO)周波数の校正データのみを破棄します。

  3. Destroy ALL - コールバック関数:OnBtnDestroyALL()
    現在のバンドの校正データを全て破棄します。過去のデータもQuisk立ち上げ時に読み込まれています。破棄してからQuiskを閉じると、過去のデータも破棄した状態が新たに保存されるため注意が必要です。

  4. Finished - コールバック関数:OnBtnFinished()
    校正データをQuiskにセットして、IQバランス校正パネルを閉じます。

  5. Help - コールバック関数:OnBtnHelp()

  下記内容のヘルプを表示します。

The "VFO" is the frequency at the center of the graph screen. The Rx or Tx frequency is the offset from the VFO.Adjust the VFO and the frequency as desired.  Then adjust the sliders to minimize the image. Press "Save" when satisfied. To adjust the VFO, use the band Up/Down buttons, or right click the graph at the desired VFO. Adjustments must be made for both receive and transmit on each band. The maximum slider adjustment range can be changed on the radio Hardware screen.

The other buttons will delete the data for the current VFO, or for the whole band. For more information, press the main "Help" button, then "Documentation", then "SoftRock".

訳はこんな感じでしょうか。

「VFO」は、グラフ画面中央の周波数です。RxまたはTxの周波数は、VFOからのオフセットです。VFOと周波数を任意に調整します。次にスライダーを調節してイメージを最小化します。満足したら "Save "を押してください。VFOを調整するには、バンドのUp/Downボタンを使うか、希望のVFOのところでグラフを右クリックします。調整は、各バンドの受信と送信の両方で行う必要があります。スライダーの最大調整幅は、無線機ハードウェアの画面で変更することができます。

その他のボタンは、現在のVFOのデータ、またはバンド全体のデータを削除します。詳しくは、メインの「ヘルプ」ボタン、「ドキュメント」、「SoftRock」の順で押してください。

スライダー位置変更イベントに呼応した関数呼び出し関係

振幅と位相のスライダー位置変更イベントによってコールバックされる関数の呼び出し関係をまとめます。

Function call relationship for IQ balance change events.

Quiskの設定機能をまとめたConfig.pyファイルの中に、IQバランス校正ボタンのコールバック関数OnBtnPhase()が定義されています。この関数は校正ボタンのクリックによって、IQバランス校正クラスQAdjustPhase()をインスタンス化し、校正パネルを表示した後、ユーザーイベント待機状態になります。

スライダーの位置が変更されるとコールバック関数OnChange()が呼ばれ、その関数の中で振幅と位相の校正パラメータを更新設定するset_ampl_phase()関数が実行されます。

QuiskのC言語関数実装部分をまとめたquisk.cファイルの中で、Pythonのset_ampl_phase()関数はC言語のquisk_set_ampl_phase()関数に翻訳され、コールされます。

このquisk_set_ampl_phase()関数はオーディオ信号処理関数をまとめたsound.cファイルに定義されています。上図では受信経路の説明を示しています。Captureデバイスサウンドカードのマイク入力)の構造体に、上記理論式(1)および(2)のIQバランス校正行列の要素を設定しています。変数AmPhAAAA、AmPhBBBB、AmPhCCCCが理論式(1)の行列要素A、B、Cにそれぞれ該当します。同時に、校正適用指示フラグdoAmplPhase をONに設定しています。また、位相校正データの単位をradに変換しているため、逆に元の単位はdeg(度)であることが分かります。RS-HFIQの実績では、分度器半目盛から1目盛り程度の補正は必要ということになります。

一方、ユーザイベント処理とは並列に、所定のサンプリング周期(= 44.8KHz x バッファサイズ)でオーディオ信号を読み込むquisk_read_sound()関数が実行されます。オーディオ信号を読み込んだ後に、校正適用指示フラグdoAmplPhaseがONであれば、correct_sample()関数をコールしています。correct_sample()関数は、複素数型のIQサンプルデータに対して上記理論式(2)の校正計算を適用しています。

以上で、校正式の設定と適用の関係が判明しました。

校正終了ボタンのイベントに呼応した関数呼び出し関係

 IQバランス校正時の校正式の設定と適用の関係は判明しましたが、通常運用時はどうしているのでしょうか。通常運用時は、離散的に設定した校正点で必ずしも運用する訳ではないことから、校正データの補間が必要になります。例えば、周波数はいつでも変更できてしまうため、校正終了時に既に周波数が校正点から変更されている可能性があります。そのため、校正を終了するFinishedボタンを押下した際に、必要に応じて校正データの補間処理が走ります。

Finishedボタンのコールバック関数OnBtnFinished()から呼ばれる関数の呼び出し関係を以下にまとめます。

Calibration data interpolation process at the end of IQ balance calibration.

OnBtnFinished()関数内では2つの関数をコールしています。校正データから振幅と位相の校正パラメータを取得するGetAmplPhase()関数と、振幅と位相の校正パラメータを更新設定するset_ampl_phase()関数です。後者の関数は前節で説明しました。

GetAmplPhase()関数は、Pythonで記述したquisk.pyの中のアプリクラスの関数として実装されています。大別すると、以下の2つの処理を行っています。(1)運用周波数近傍の校正データ探索、および(2)校正点データの線形補間です。

(1)運用周波数近傍の校正データ探索では、SearchFreqAmPh()関数を用いて、2段階の探索を行っています。(1-1)運用VFO周波数近傍の校正点VFO周波数の探索、および(1-2)校正点VFO周波数のオフセット周波数を含む校正データの探索です。Quisk SDRでは、VFO周波数の設定(連続可変、離散可変、あるいは固定)はハードウェアに依存します。IQバランスの校正を行ったVFO周波数で運用するとは限らないことから、まず(1-1)で運用VFO周波数近傍の校正点VFO周波数を探索しています。次に、見つかった校正点VFO周波数の中身を(1-2)で探索して、近傍の校正点オフセット周波数を含む校正点データセットを抽出しています。

CWの場合はオフセット周波数をトーン周波数と考えれば良いのですが、SDRの場合は一般的にトーン周波数を任意に変更できるようになっています。校正点とは異なるトーン周波数に変更するために、(2)校正点データの線形補間が必要になります。ここでは、(2-1)校正データの取得と(2-2)運用周波数における校正データの線形補間の2つの処理を行っています。上図では、運用オフセット周波数Freq0が校正点オフセット周波数freq2とfreq1の間にある場合の線形補間処理の例を示しています。他に、VFO周波数も異なる場合や、校正点周波数データが1つしかない場合等の多様な場合に対応するコードが実装されています。

IQバランス校正終了時を例にして校正データの補間処理を説明しましたが、周波数を変更する毎に校正データの補間による校正適用の処理が走ります。

QuiskのIQバランス校正のテスト

校正の試行

IQバランス校正の試行を行いました。前節のデータの構造の説明で示した校正データは、この試行で得た実データです。

受信周波数を7019500Hz(VFO=7020000Hz、Offset=-500Hz)とし、7020500HzのBIT信号を入力した場合のIQバランス校正前のイメージ信号を下記に示します。BIT信号に対して、イメージ抑圧は-38dBcに留まっています。

The image signal before IQ balance calibration when the receive frequency is set to 7019500 Hz (VFO = 7020000 Hz, Offset = -500 Hz) and a 7020500 Hz BIT signal is input.

IQバランス校正後のイメージ信号を下記に示します。イメージ信号はノイズフロアに到達し、-78dBc以下に抑圧されています。ここで、Saveボタンをクリックして校正データを登録します。

Image signal after IQ balance calibration when the receive frequency is set to 7019500 Hz (VFO = 7020000 Hz, Offset = -500 Hz) and a 7020500 Hz BIT signal is input.

続いて、受信周波数を7018500Hz(VFO=7020000Hz、Offset=-1500Hz)とし、7021500HzのBIT信号を入力した場合のIQバランス校正を行い、Saveしました。その結果を下記に示します。

Image signal after IQ balance calibration when the receive frequency is set to 7018500 Hz (VFO = 7020000 Hz, Offset = -1500 Hz) and a 7021500 Hz BIT signal is input.

サイドを反転し、受信周波数を7020500Hz(VFO=7020000Hz、Offset=500Hz)とし、7019500HzのBIT信号を入力した場合のIQバランス校正を行い、Saveしました。その結果を下記に示します。

Image signal after IQ balance calibration when the receive frequency is set to 7020500 Hz (VFO = 7020000 Hz, Offset = +500 Hz) and a 7019500 Hz BIT signal is input.

続いて、受信周波数を7021500Hz(VFO=7020000Hz、Offset=1500Hz)とし、7018500HzのBIT信号を入力した場合のIQバランス校正を行い、Saveしました。その結果を下記に示します。

Image signal after IQ balance calibration when the receive frequency is set to 7021500 Hz (VFO = 7020000 Hz, Offset = +1500 Hz) and a 7018500 Hz BIT signal is input.

今回のIQバランス校正の試行における校正点数は少ないのですが、気付きは以下の通りです。

  • 振幅誤差(α)はVFO周波数に対してサイドが変わると符号が反転(LSB側が負でUSB側が正)
  • 振幅誤差(α)はVFO周波数に近い方が値が大
  • 位相誤差(ψ)はVFO周波数に対して両サイドで符号は正
  • 位相誤差(ψ)はVFO周波数に近い方が値が大

校正の再現と補間効果の確認

Quiskを一旦閉じると、登録した校正データが初期化ファイル./quisk_init.jsonに保存されます。Quiskを再立ち上げすると、校正データがファイルから読み込まれてIQバランス校正が常に適用された状態になります。その確認を行いました。

まず、LSB側の校正点における再現性を確認しました。受信周波数を7019500Hz(VFO=7020000Hz、Offset=-500Hz)にした場合と、7018500Hz(VFO=7020000Hz、Offset=-1500Hz)にした場合のIQバランス校正の再現性を、それぞれ下記の上段と下段に示します。イメージ信号はノイズと区別がつきませんが、-70dBc以下に抑圧されています。

Reproducibility of IQ balance calibration when the receive frequency is set to 7019500 Hz (top row) and 7018500 Hz (bottom row).

次に、校正を行っていない受信周波数7018000Hz(VFO=7020000Hz、Offset=-1000Hz)における結果を下記に示します。校正パラメータの線形補間機能が働き、イメージ信号は-70dBc以下に抑圧されています。

Effect of the calibration interpolation function at a receive frequency of 7018000 Hz (VFO = 7020000 Hz, Offset = -1000 Hz) without IQ balance calibration.

続いて、USB側の校正点における再現性を確認しました。受信周波数を7020500Hz(VFO=7020000Hz、Offset=+500Hz)にした場合と、7021500Hz(VFO=7020000Hz、Offset=+1500Hz)にした場合のIQバランス校正の再現性を、それぞれ下記の上段と下段に示します。USB側のイメージ信号も-70dBc以下に抑圧されています。

Reproducibility of IQ balance calibration when the receive frequency is set to 7020500 Hz (top row) and 7021500 Hz (bottom row).

次に、USB側で校正を行っていない受信周波数7021000Hz(VFO=7020000Hz、Offset=+1000Hz)における結果を下記に示します。校正パラメータの線形補間機能が働いているはずですが、イメージ信号の抑圧は-50dBc以下に留まりました。

Effect of the calibration interpolation function at a receive frequency of 7021000 Hz (VFO = 7020000 Hz, Offset = +1000 Hz) without IQ balance calibration.

理由は精査が必要ですが、下記の可能性を考えています。

  • 線形補間が間に合わない非線形回路現象の発生
  • 線形補間コードの不具合

ダイレクトコンバージョン方式のSDRでは、アナログ回路の均衡誤差を補償するために、IQバランス校正が必須であることが分かりました。製造ラインでこのような校正を行うことは煩雑で製造コストを押し上げてしまうため、SDR方式の市販無線機の大半が高速ADCやFPGAが必要なダイレクトサンプリング方式である理由を納得できました。

IQバランス校正は4次元パラメータ空間(VFO周波数、オフセット周波数、振幅校正パラメータ、位相校正パラメータ)の探索になるため、自動化したいところです。自動化を検討するためには、次にスペクトルデータの取得が必要です。QuiskではGUIにスペクトルを描画しているため、Pythonのどこかの変数に入っているのではないかと期待しています。