2019年10月24日木曜日

Si5351A最後の罠にはまる!?

Silicon Labs社製のSi5351Aはすっかりアマチュア無線自作関連では定番となりました。

マイコンと組み合わせればVFOとして十分実用になるし安価に手に入るため、お手軽な発振器として従来のDDSにとって代わってしまったようです。

自分もVNシリーズの発振源として重宝していますが、そろそろ新しいプロジェクトということで高い周波数の発振テストを行いました。以前50MHz台のテストを行い問題なく設定周波数で発振したのを確認したので今度は144MHz帯を狙いテストしたところ、なぜか90MHz台と設定値と異なる出力周波数でした。

いろいろと設定周波数を変えながら検証していくと、どうやら80MHz以上を設定した場合ダメらしいことが分かりました。

そこで原因を探るべくまずはSi5351Aの設定パラメータの関係と、周波数設定の考え方について以前の記事をみながら再度おさらいすることにしました。

Si5351Aの周波数設定式

1.VCO周波数設定(PLLA, PLLB)
 fvco = fXTAL x (a + b / c)
    a...15~90, b...0~1048575, c...1~1048575, fXTAL = 25MHz or 27MHz
 fvco = 375MHz~900MHz

2.VCO分周設定(MultiSynth0,1,2,...)
 fout = fvco / (d + e / f)
    d...4~900, e...0~1048575, f...1~1048575

3.設定周波数とパラメータ値の関係


a(16~32(36)) c d R
80~180MHz 2F 500000 5 0
40~80MHz 4F 250000 10 0
36~40MHz 8F 125000 20 0
16~36MHz F 1000000 25 0
8~16MHz 2F 500000 50 0
4~8MHz 4F 250000 100 0
2~4MHz 8F 125000 200 0
1~2MHz 16F 62500 400 0
0.5~1MHz 16F 62500 400 2
0.25~0.5MHz 16F 62500 400 4
0.125~0.25MHz 16F 62500 400 8
62.5~125kHz 16F 62500 400 16
31.25~62.5kHz 16F 62500 400 32
15.625~31.25kHz 16F 62500 400 64
8~15.625kHz 16F 62500 400 128

さてこれらのパラメータの設定値、一見問題なさそうに見えますが、あらためてSi5351Aのレジスタマップ説明書AN619でおそらく最新版Rev.0.7の記述をたどってみると・・・


なんと2.でいうところの d + e / f 値は8以上でないとダメだということです。つまり分周比を整数にするため e / f を0にすると、d値は8以下を設定できないことになります。これは気が付きませんでした。つまりいままでの設定アルゴリズムでは80MHz以上の場合d値が5と設定できない値であったため、期待どおりの周波数が出力されなかったというわけですね。
では80MHz以上設定するにはどうしたらいいでしょうか?
解は下のほうの記述にありました。


 この設定でd値を4とすることによって200MHzまで設定が可能になるということです。
以上を踏まえ改定版設定表を作ってみました。
(追記(2019.11.1):80MHzから100MHzまでの設定を変更しました)


a(16~32(36)) c d R
100~200MHz※
80~100MHz
4/25 F
8/25 F
625000
312500
4
8
1
1
40~80MHz 4/10 F 250000 10 1
36~40MHz 8/10 F 125000 20 1
16~36MHz F 1000000 25 1
8~16MHz 2F 500000 50 1
4~8MHz 4F 250000 100 1
2~4MHz 8F 125000 200 1
1~2MHz 16F 62500 400 1
0.5~1MHz 16F 62500 400 2
0.25~0.5MHz 16F 62500 400 4
0.125~0.25MHz 16F 62500 400 8
62.5~125kHz 16F 62500 400 16
31.25~62.5kHz 16F 62500 400 32
15.625~31.25kHz 16F 62500 400 64
8~15.625kHz 16F 62500 400 128

注:36MHz以上は10Hzステップ
※・・・2.の条件に依らずP1=0, P2=0, P3=1, MSx_INT=1, MSx_DIV4=3に設定

この設定表を基にコードを書き直し実機でテストしてみました。(144.10000MHzに設定)

というわけで、設定どおりの周波数で出力できました。(右上の青い周波数値)

2019年10月21日月曜日

久しぶりの135kHz運用・初めての自宅からのQRV

先日10月20日恒例のオール千葉コンテストが行われたのですけれども、当初千葉県内に移動して運用するつもりでしたが、今月初めに痛めた左肩がまだ完治していなかったため大事をとって断念しました。

このオール千葉コンテスト(略称:千葉コン)は135kHz部門が存在するほぼ唯一のコンテスト(四国のローカルコンテストであったような記憶がありましたが、詳細不明)であり、いまだ数少ないLFerがQRVする機会なのです。

135kHzはいつも車での移動運用だけでしたが、せっかくの機会ですし当時の気候も穏やかでほとんど風もない良いコンディションだったことから、以前から試してみたかった自宅からのQRVにチャレンジしてみました。

エレメントは従来のアルミ線がボロボロになってしまったので、以前購入した超軽量のアンテナ線を使用しました。銅線の撚り線ですが被覆が軽いので全体的に軽量です。
42mほどあるので、垂直エレメントとして12m、容量冠エレメント10m2本を切り出して両端をそれぞれ加工しいつもの135kHz用傘型超短縮エレメントとしました。

ウエダ無線で購入できます。22mタイプもあります。
エレメントをいつものSpiderBeam製12mグラファイトポールの最先端に括り付け、ポールは屋上の手すりにワイヤでしっかり固定し12m完全に伸ばします。容量冠の2条のエレメントを傘状に展開し固定。垂直エレメントの下端にリニューアルしたヴァリオメータ内蔵のローディングコイルのホット側に接続します。

雲は多かったですがひさびさの気持ち良い天気

手すりにポールを固定 いい感じに展開できました

ローディングコイルは数年前雨に濡れ壊れましたが見事復活させました
問題はアースですが、移動運用では90x60cmのガルバリウム鋼板を10枚地面に敷き詰めて大地と容量結合します。しかし屋上に重たい鋼板を持ち上げるのが難しかったため、だめもとで手すりの根元の接続ボルトにワニ口クリップをかませアースとしてみました。

アースはこのように手すりの取り付けボルトに引っ掛けただけ
こんなアースでしたが測定してみると・・・アンテナ抵抗75Ωと予想より低く、インピーダンス変換トランスですんなりと整合してしまいました。

インピーダンス変換トランスでマッチングOK コイルのQが高いのできわめて狭帯域
セッティング完了して早速CWの周波数である136.5kHzを受信してみると、強いインバータノイズの中からCW信号が聞こえてきました。


千葉コンに県外局として参加されている7L1RLL局のCQです。50Wでコールしてみましたが応答なくしばらく呼び続けていると、JA1NQI局(茨城県)とJA1HQG/1局(神奈川県)の2局からコールいただきレポート交換しQSOが成立しました!

FT991の直接受信でしたが、インバータノイズが低くなると結構よく受信できるようです。ノイズレベルは高くても受信帯域を絞りDSPをうまく調整すれば多少弱くても何とか取れるレベルでした。

今回は初めての自宅からの135kHzQSOでひさびさにテンションが上がりました。思いのほかアンテナ入力抵抗が低くいつもの移動運用並みに運用ができることが分かり今回のチャレンジは大きな収穫でした。

1.8/1.9MHzもローディングコイルを作製して12mバーチカルアンテナで運用しようと考えています。おそらくSRA以上に飛ぶのではないかと期待していますがはたしてどうなることやら。

2019年9月9日月曜日

各キット通頒再開します

ハムフェア2019も無事終了ししばらく経ちましたので、各キットの通頒(通信頒布)再開いたします。

現在頒布可能なキットは、

4chメッセージメモリキーヤー Keyer Mini-V2 Revision2
HFモノバンドQRP CW トランシーバキット VN-xx02シリーズ
通過型電力計・VSWR計キット QPM-01

です。

各々ハムフェアで在庫分は頒布しきってしまったので、オーダー後いずれも3週間前後準備にかかることをご了承ください。

また、製作代行につきましてはVN-xx02シリーズのみとさせていただきます。Keyer Mini-V2 Revision2はフルキットもしくは半完成版になります。

オーダーに関するご質問は私のメールアドレス jl1vnq☆gmail.com(☆を@に置き換えてください)宛にメールを送ってください。

2019年9月4日水曜日

ハムフェア2019に参加しました

今回のハムフェア2019では、アマチュアキットクリエイターズ(AKC)ブースでキット頒布という形で参加しました。

参加にあたってはAKCのメンバーの皆様には大変お世話になりました。特にあのCW INVADERSの生みの親であるJQ1SRN局には中心的な役割として私らを引っ張っていただき、おかげさまで大成功をおさめ感謝しております。ありがとうございましたm(_ _)m

さて今回初めて出来立ての東京ビッグサイト南館での開催で私も初めて訪れたわけですが、会場までかなり遠いです。中の通路は空調が効いているので良かったですが、会場入り口はやや狭く西館の開場前ホールの広さが欲しいところです。しかし会場内は十分広く、ブースの島の間隔も広めにとってあって移動しやすい印象でした。




出発が遅れて開場30分前のぎりぎりに到着し、あわててディスプレイを準備し開場。
予想はしていたもののAKCブースの周りにはたくさんの方々が・・・


メンバー7人おもいおもいのキットが並ぶなか、実物を見に来てみたりキットを買ったり質問やあいさつに来られりなどなど、最初の2時間はカオスな状態でした。

私も30台用意したディジタルSWR計も早々に売り切れてしまい、やはり関ハムで捌けた数の4倍という説は正しいのだと思いました。(関ハムは15台用意してほぼ捌けたので2倍とみていたのですが甘かったようです。QPM-01はしばらく通頒続けようと思います。)

VNシリーズのほうも好調で2日目で用意した分は完売しました。意外とVN-3002(10MHz版)が早くなくなりました。

お手に取っていただきありがとうございます!某縦振師匠
また嬉しかったのは、以前頒布させていただいた方から直接完成モデルと興味深いカスタマイズを見せていただきました。



厚いベーク板をカットして、クリップをレバーにしたオリジナルの自作パドルでVN-3002の本体下に装着してElecraft KXシリーズのような一体型となっています。

パドルを本体に装着するというアイディアは持っていましたが、これには脱帽です。先にやられてしまいました(笑)。ミソはCTRL基板とRF基板を支えるスペーサです。丁度中央に横にねじ穴が開いていて、そのネジ穴にパドルモジュールをビスで固定しています。実にしっかり装着されていて運用も不安なさそうです。

このスペーサを標準に取り入れてサイドと上下に各自好きなパネルを装着したりできるようにしたいですね。

とても良いものを拝見させていただきましてありがとうございました。

そういったわけで初日は全くブースを離れられずにいました。結局VN-4002が3台残るのみでステッカー除くほかはすべて初日で売切れてしまいました。

ありがとうございますm(_ _)m

2日目は初日とは異なり穏やか和やかの中で残った3台もなくなりすべて捌けてしまったので少しだけほかのブース巡りをしました。

ハムフェア直前になり話題になったトランシーバーのモックアップ?をチラ見してきました。



実際に見るとだいぶ小さな印象で、重さも電池込みで訳1kgというから本当に移動に活躍しそうな新製品でした。バッテリーも既存のハンディトランシーバのバッテリーパックが背中に収まるなどアイディアもたくさん詰まっているようで期待が膨らみますね。

また、私が40年近く前の開局当時ローカルだったどよよんさんととおちゃんにひさびさに会場で再会できたことも今回のハムフェアの印象に残ったことです。やっぱり無線っていいものですね~

そんなこんなで今年のハムフェアはいままでとは違って新しい楽しみ方ができたように思いました。自作する人は少ないとは言われていますが、コンテストやDXハンティングと並ぶアマチュア無線を楽しむ大きな柱であることは間違いないと思います。さらに一点もので終わっていたからキットを通じてほかの自作派と共有できるというように変わり(進化し)つつあり、そこに面白さを見出してくれる方だどんどんこういった場で発表できるようになってくれるといいな、という妄想を抱きつつこれからも少しずつではありますが頒布はつづけていくつもりです。



ハムフェアでいくつか購入しましたが、このサブミニチュア真空管面白そうです。以前VNシリーズ取り扱てくださったQSYというラジオ番組のブースにお礼かねて伺ったところ、このサブミニチュア管を勧められて買ってしまいました。再生式ラジオと思しきいただいた参考回路図を見るとこれで何か作りたくなってきました。

CQ出版では0-V-1受信機に加えて真空管式送信機キットを販売予定だそうです。せっかく5本手元にあるので再生式受信機とCWもしくはAM送信機の組み合わせでQRPpトランシーバーが良いかな?
追記:
ハムフェアが終了したので、AKCの活動は当初の目的達成を機にしばらく休止します。
それに伴い私の各種キット(Keyer Mini-V2 Revision2, VN-xx02 series,)の通信頒布(通頒)の再開準備を始めます。9/8から受付再開を予定します。

また今回初めて頒布したQPM-01キットについても通常頒布のラインナップに加えます。

追ってこのブログで告知します。

2019年8月30日金曜日

ハムフェア2019に参加します

直前の告知になってしまいましたが、明日明後日(8/31,9/1)に東京ビッグサイトで行われるハムフェア2019にアマチュアキットクリエイターズ(AKC)の1メンバーとして参加します。


詳細はこちらから辿ってください。

今回思い付きでAKCのバナーや横幕に使われているデザインでシールを作ってみました。


横15cm・縦5.4cmとやや大きめですが、良かったら買ってやってください。1枚200円です。

当日はAKCのロゴやキャラデザイン入りの黒いTシャツを着用しておりますので、よろしくお願いします。


2019年7月31日水曜日

ディジタルVSWRメーターQPM-01の補正プログラムの改良(ファームウエアあり)

先日のKANHAM2019で頒布したディジタルVSWRメーターは、方向性結合器で得られた進行波と反射波をそれぞれショットキーダイオード1SS106で整流し平滑化したのちにPICでAD変換、計算、表示を行うわけですが、ダイオードの特性から小信号時の歪に対して補正をかけてなるべくQRPの小さい電力でもある程度の測定をしようと考えプログラムました。

ただ前々回の投稿に掲載した補正のやり方は、計算した電力値に補正をかけており適正化されていなかったため結果VSWR表示は過小評価していました。組み立てていただいた方からも同様のレポートをいただいたことから今一度補正のやり方を最初から検討しなおしました。

結局ダイオード整流電圧からAD変換した値(電圧値)をダイオードの特性に合わせるように補正をかけてから電力とVSWRそれぞれ計算するという形に変えました。つまりはダイオードの特性を測定してその結果をプロファイルとし、得られたAD変換値をそのプロファイルに沿って補正すればよいわけです。考えてみたらそのほうがすっきりというか当たり前というか・・・(汗

具体的には、対象のダイオードを下の図の回路図に倣ってブレッドボードに組み、整流前のRFピーク電圧と整流後の直流電圧値をRF出力を変えながら2現象オシロスコープで測定して結果をグラフにプロットします。プロットしたグラフを見て大まかなダイオード特性を把握します。
 上の図のように実際に測定して図にプロットした特性曲線を近似的に表現できるように考えたものです。RF電圧がある程度以上であれば整流電圧とほぼ比例関係にあり1次関数で表現できそうですが、それ以下の場合は当てはまらなくなります。あまり根拠はありませんが、その領域に平方根関数を当てはめ、1次関数との接線の方程式をを用いてプロファイルを作成してみました。

接線の方程式を使えば、x1 y1を設定することによってpが導かれ補正用のプロファイルが出来上がります。

電圧が小さい領域は平方根関数ですが、8bitPICで計算させるのは実用的ではないことと、その領域の範囲が小さいのであらかじめPCのスプレッドシートで計算させた結果を1次配列にした変換テーブルを作りました。


今回はAD値1から30までが対象になるため、配列の要素は30個で済んでいます。

このプロファイルを組み込んだファームウエアをプログラムすることで大体0.5W程度からVSWRが計測できるようになりました。出力を変えると多少値にばらつきが出るので本当に完璧なモノとはまだまだ言えませんが、かなり実用的になったのではないかと思います。

QPM-01は今度のハムフェア2019で正式版を用意する予定ですが、先の評価版とファームウエアは共通になります。現時点での最新ファームウエア(ver.1.61)はこちらです。

正式版リリースのころに新たに専用ブログを設ける予定です

2019年7月29日月曜日

遅まきながらKANHAM2019に参加しました

もうすでに1週間以上経過してしまいましたが、7月20、21日大阪池田市で開催された関西アマチュア無線フェスティバル通称KANHAM2019に参加しました。

今回久しぶりに自家用車で往復しました。新東名が試験的ではありますが120km/h制限になっていたり新名神が拡大していたりで、距離的にも時間的にも近くなったという印象でした。

途中多賀SAでお風呂&仮眠しようと思いましたが、ナビゲーション設定を誤ってしまい先に会場の池田市に午前3時くらいに到着してしまいました(汗 周りに夜通し空いているスパ銭もなさそうなので、会場隣のコインパーキングに停めて8時前まで車内で仮眠をとりました。それが結果的に良かったのか、コインパーキングには夜中の3時過ぎなのにすでに数台しか空きがなく、仮眠から目覚めた7時過ぎにはもうすでに満車になっていました。

というわけで、今回はいつもの『リトルガンくらぶ』のほかに新たに結成された『アマチュアキットクリエイターズ AKC』ブースで主にキット頒布を行いました。


私はいつものVNシリーズとKeyer Mini-V2R2と新たにディジタルVSWRメーターキットQPM-01人柱版を用意、私のほかにJR6IRK岩永OM、7L4WVU原口OM、JQ1SRN武村OMの3名が各々のキットなどの頒布品を用意されました。

設営がひと段落したのも束の間、10時の開場とともに人の波が・・・


いやはや、さながらコミケットの開場直後をちょっぴり彷彿とさせる光景が。事前の宣伝効果はかなりなもので最初の1時間は対応にあたふた状態でした。そのおかげで皆さん結構頒布品が捌けていきました。

今回は参加メンバーは4名でしたが、今度のハムフェア2019ではフルメンバーの7名があの小さなブース一コマに集中するので当日の混乱をどう切り抜けるかが一つ大きな課題となりました。

ともあれ盛況で何よりでした。

1日目終了後空港近くのホテルでチェックインを済ませ、再び会場近くの石橋駅近くのお店でAKCメンバーの反省会ののちいつものリトルガンくらぶの飲み会に合流しました。

少し甘めのお酒ですが甘ったるすぎずスッキリしていて何杯でもイケます(笑)
石橋駅ガードわきの小さな飲み屋さんで。地元の銘酒『呉春』をいただくのが恒例になっています。帰りに石橋の商店街の酒屋さんで一升瓶で買って帰りました。

2日目もブースにたくさんの方が足を運んでいただきました。この2日間はほとんどブースにいたので講演などは観れませんでしたが楽しく過ごさせていただきました。

関係者の皆さん、ありがとうございましたm(_ _)m


最後に近くの銭湯で汗を流し帰路につきました。

では、今回の戦利品を。

下にある箱はなんでしょう?

2019年7月19日金曜日

関西アマチュア無線フェスティバル(KANHAM2019)に参加します!

毎年大阪池田市で行われる恒例の関西アマチュア無線フェスティバル(KANHAM2019)に今回もはるばる1エリアから参加します。

昨年新たに結成されメンバーに加えていただいたアマチュアキットクリエイターズ(AKC)がこの関ハムでブースを持つこととなりました。いつもはリトルガンくらぶブースでキットなどの頒布を行っていましたが、混乱を避けるため実際のキット頒布はAKCブースで、完成品のデモンストレーションをリトルガンくらぶブースで行うことにしました。

各ブースは関ハムのサイトの配置図をご覧いただくとわかりますが、ほぼ向かいあった位置に配置されています。

目印はまずリトルガンくらぶの毎度おなじみ『むせんぶ』ポスター



こちらで頒布予定のキットの完成品の展示を行います。また『むせんぶ』グッズを頒布されるそうなので是非お立ち寄りください。

でもって・・・


こちらの横幕を掲げているアマチュアキットクリエイターズ(AKC)ブースにてキットの頒布を行います。

内容はこのブログの上にある『イベント頒布情報』タブを左クリックしてご参照ください。

当日会場内で黒いAKCのTシャツを着たでかいおっさんがいたら多分それは私だと思います。アイボールや自作談義など楽しみましょう!

2019年7月7日日曜日

通過型電力計の製作(その2~マイクロコントローラ編)

回路図が決まったところで、次は得られた進行波と反射波の整流電圧を測定して計算表示させるまでを担うマイクロコントローラー(マイコン)部分のプログラムを設計していきましょう。

わざわざマイコンなんて使わなくても感度の良い電流計を取り付けて校正すればいいじゃん・・・はい、ごもっともです(汗)

しかし高周波とマイコンが融合する姿に私としては非常に引き付けられるものがあるので、ここはぜひマイコンを活用しようではないか!というわけで強引に進めていきます(笑)

具体的にマイコンを選定する前に、何をマイコンにさせるかということを決めておくことが大事です。それからマイコン動作の基本を理解することです。マイコン動作の本質は『計算』です。つまり、外から入力したデータを『計算』して出力に送る、ということです。その『計算』の手順を示すものがいわゆるプログラムということになります。

今回製作した通過型電力計に当てはめてみます。まずデータの入力ですが、進行波や反射波の電圧レベルはそのままマイコンで計算することができないので、最初にアナログーディジタル変換(AD変換)によって電圧レベルをディジタル値に変換します。このディジタル値をもって初めてマイコンによる『計算』が可能になります。それから計算した結果をキャラクターLCDディスプレイで表示するため、計算結果を含めたデータをLCDに送ることによってLCDに表示させます。あとはおまけとしてLCDバックライト電源を制御する出力とファンクションボタン入力を加えています。

ということで、マイコンに必要なポートを列挙してみると・・・

1.入力
 進行波電圧入力(アナログ)
 反射波電圧入力(アナログ)
 ファンクションボタン(ディジタル)

2.出力
 LCDへの通信ポート(今回は2線シリアルI2Cバス SCLポート,SDAポート)
 LCDバックライト電源ポート(ディジタル出力)

と、入出力合わせて6ポート必要になります。

ということは、8ピンPICですべてのポートを使い切るということになります。特に機能拡張をする予定はないので必要最小限の8ピンPICを使うことにしました。


8ピンのPICは12Fシリーズがポピュラーですが、その中でも上位クラスの拡張ミッドレンジコアを持っている12F1840を採用しました。値段も秋月で1個120円と非常に安価です。これでAD変換やEEPROM、いくつかの通信モジュールもひとつ小さなパッケージに内蔵されているのは驚きです。

最近の8bitPICにはほとんどがAD変換とシリアル通信、EEPROMモジュールが内蔵されていて、発振源も内蔵CR発振が選択出来て外部に水晶振動子やセラロックを接続しなくても良い設計になっています。ましてや8ピンしかないマイコンには内部発振は必須といってよいかも知れません。



またPICのピンには各々役割が複数あって、初期設定で各々のモジュールのレジスタに書き込み設定を行っています。今回のプログラムでの割り当ては赤色の枠になっています。

では処理の流れをブロックダイヤグラム風に示してみます。
実際のプログラムに落とし込みますが、最初にPICのコンフィギュレーションの記述やヘッダファイルxc.hのインクルード、初期設定(PIC各ピン(入出力、アナログ・ディジタル、プルアップなど)、モジュール(ADC、I2Cバス))を行い、メインループ内にAD変換、各電力値とVSWR値計算、計算結果表示関数を置きます。

通常表示するだけであればメインループ内で繰り返し処理を行うようにしてほぼリアルタイムに表示させていけばOKですが、進行波と反射波表示切替やバックライトの制御を加えて少し使いやすくしてみます。

通常自分がスイッチによる制御を加える場合は、タイマー割込み処理でスイッチ状態を監視してメイン処理を修飾するようにしています。

タイマー処理はTIMER0で割り込みをかけるようにしています。時間設定は1ミリ秒としてスイッチの状態をメモリにコピーし、コピーしたメモリを参照してあるパターンに一致したときにフラグを立ててメインループ内でフラグに応じた処理を修飾するという流れです。
スイッチは一つしかありませんが、押し続ける時間によって機能をいくつか持たせるようにしてピンの少なさをカバーしています。(スイッチポートをアナログにして電圧変化に応じて複数の機能を持たせる方法もあります)

次にメインの計算処理についてですが、AD変換された値(AD value)は電圧の整数値(符号なしの10bit値)です。電力はW=V^2 / Rで導かれますので、電力値に変換するにはAD valueを2乗し適当な定数を乗すれば良さそうです。この方法ではある程度信号が大きければ問題ないのですが、ダイオードによる整流のためダイオードのVf付近つまりはQRP電力の場合ダイオードのひずみにより、単純にAD valueの2乗ですべてOK!というわけにはいきません。

そこで実際の電力値とAD valueを測定、表にプロットして計算方法を探ることにしました。

縦軸は出力電力値、横軸はPICのAD変換で得られたAD value ( = det) の2乗値det^2です。

det^2値が14000超えの場合はdet^2とPowerはほぼ1次関数に収まりますが、14000以下の場合はダイオードの低VfでのVf-If特性を踏まえて上表の青色の式のように当てはめるようにしました。(2次曲線に近似しており、この領域では整流電圧と電力の関係を1次関数とみなしています。言い訳ですが(笑)、この程度の測定器であればこれ以上突き詰めても仕方ないでしょう。)

また計算途中で必要な変数の型については、AD変換で得られる値のbit桁数は10bitなので2乗としても20bitあれば事足ります。ですので計算プログラムの変数の型はunsigned longでOKです。整数同士の計算なので4MHz駆動の8bitPICでもサクサク動いてくれます。

またVSWRの計算はおなじみの

VSWR値 = (|Vf| + |Vr|) / (|Vf| - |Vr|)

をそのまま当てはめています。

最後に表示にはI2C接続の16x2キャラクタLCDを使い、LCDとのI2C通信にはMSSPモジュール使用しています。

それでは実際のコードを公開しちゃいます。

//
// VSWR_meter.c
// Copyright JL1VNQ / HARU
//
//
//  ver.1.00 9 June 2019
//  first release
//
//  ver.1.10 12 June 2019
//  change power calculation algorithm
//


#define EEPROM_SIZE  256
#define _XTAL_FREQ  4000000


#include <xc.h>


//for 12F1840 config
#pragma config FOSC = INTOSC, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF
#pragma config CPD = OFF, BOREN = OFF, CLKOUTEN = OFF, IESO = OFF, FCMEN = OFF
#pragma config WRT = OFF, PLLEN = OFF, STVREN = ON, LVP = OFF


#define POW   LATAbits.LATA5      // backlight LED control
#define FUNC  PORTAbits,RA3       // function switch
#define LCD_AD  0x7C    // Akiduki's I2C LCD(AQM0802, AQM1602) address
#define TMR0_set 0x83    // TMR0 1msec interval


unsigned char contrast = 5;

unsigned long forward = 0;
unsigned long reverse = 0;
unsigned long po = 0;                   // calculated power (x10^-1 watts)
unsigned int vswr = 0;                  // VSWR * 10

unsigned char for_rev = 0;              // display change (0:forward, 1:reverse)

void msec_delay(unsigned short time);

void I2C_send(unsigned char data);
void lcd_cmd(unsigned char work);
void lcd_data(unsigned char work);
void lcd_init(void);
void lcd_clear(void);
void cgram_set(void);
void lcd_position(unsigned char li, unsigned char col);

void lcd_str_disp(unsigned char li, unsigned char col, const char *string);
void lcd_char_disp(unsigned char li, unsigned char col, unsigned char ascii);

void var_disp_conv(unsigned char li, unsigned char col, unsigned int val);
void pow_disp(unsigned char li, unsigned char col);
void vswr_disp(unsigned char li, unsigned char col);


void __interrupt() isr(void){
 if(INTCONbits.TMR0IF){
  INTCONbits.GIE = 0;
  TMR0IF = 0;
       
        static unsigned int cnt0 = 0, cnt1 = 0;
        static unsigned char sw_mem = 0, sw_down = 0, dim = 0;
       
        sw_mem <<= 1;
        if(FUNC == 0) sw_mem |= 1;
       
        if((sw_mem & 0x0F) == 0x03) sw_down = 1;
       
        if(sw_down == 1){
            if(cnt0 < 2000) cnt0 ++;
           
            if(cnt0 < 1000){
                if((sw_mem & 0x0F) == 0x00){
                    if(dim == 0) dim = 1;
                    else if(dim == 1) dim = 0;
                    sw_down = 0;
                    cnt0 = 0;
                    cnt1 = 20000;
                }
            }
            else{
                if(for_rev == 1) for_rev = 0;
                else if(for_rev == 0) for_rev = 1;
                sw_down = 0;
                cnt0 = 0;
            }
        }
       
        if(dim == 1){
            if(forward > 10) cnt1 = 5000;
            if(cnt1 > 0){
                cnt1 --;
                if(POW == 0) POW = 1;
            }
            else POW = 0;
        }
        else POW = 0;

  TMR0 = TMR0_set;
  INTCONbits.GIE = 1;
 }
 else if(INTCONbits.IOCIF){   // for Interrupt On Change(hang-up occur if compiling without this code)
  INTCONbits.GIE = 0;
  IOCAF = 0;

  INTCONbits.GIE = 1;
 }
}

void main(void){

 OSCCON = 0x6A;      // 4MHz internal OSC no PLL

    PORTA = 0x00;
 ANSELA = 0x11;                      // RA4, RA0 Analog Input
 TRISA = 0x1F;
 WPUA = 0x2E;      // PORTA weak pull-up

 OPTION_REG = 0x02;     // weak pull_up, TMR0 internal clock(1us/cycle), prescaler 1:8

 POW = 1;       // LCD LED POW PORT on
 SSP1CON1 = 0b00101000;              // I2C Master mode
 SSP1STAT = 0b10000000;
 SSP1ADD = 9;      // I2C Freq = (SSP1ADD + 1)*4/Fosc = 100kHz

 ADCON1 = 0b11000000;    // ADFM = 1 (right), ADCS = 100 (fosc/4), ADPREF = 00 (Vref = VDD)
 ADCON0bits.ADON = 1;    // ADC module enable
   
    msec_delay(10);

 lcd_init();
    cgram_set();

 lcd_str_disp(0,0,"VSWR Meter QPM01"); //startup splash for AQM1602
 lcd_str_disp(1,0,"(c)HARU 20190612");
 msec_delay(750);
   
    POW = 0;

 lcd_clear();

 TMR0 = TMR0_set;     // 1msec
 INTCONbits.TMR0IF = 0;
 INTCONbits.TMR0IE = 1;
 INTCONbits.IOCIE = 1;
 INTCONbits.GIE = 1;

 IOCAN = 0xFF;      // interrupt on change negative edge detect
 IOCAF = 0;


 while(1){

  ADCON0 = 0b00000001;  // AN0
        __delay_us(10);
  ADCON0bits.GO = 1;
  while(!ADCON0bits.GO){
  }
         __delay_us(10);
  forward = ((unsigned int)ADRESH << 8) + (unsigned int)ADRESL;

  ADCON0 = 0b00001101;  // AN3
        __delay_us(10);
  ADCON0bits.GO = 1;
  while(!ADCON0bits.GO){
  }
        __delay_us(10);
  reverse = ((unsigned int)ADRESH << 8) + (unsigned int)ADRESL;
       
        if(for_rev == 1){
            if(reverse < 118) po = (reverse * 5428) / 10000;
            else po = ((reverse * reverse + 20000) * 19) / 10000;
            po = po * 11 / 10;
        }
        else if(for_rev == 0){
            if(forward < 118) po = (forward * 5428) / 10000;
            else po = ((forward * forward + 20000) * 19) / 10000;
            po = po * 11 / 10;
        }
       
        var_disp_conv(0,0,po);
        pow_disp(0,10);
       
        if(forward > 10 && forward > reverse) vswr = (forward + reverse) *10 / (forward - reverse);
        else vswr = 9;
       
        if(vswr > 9) var_disp_conv(1,0,(vswr - 10) * 30);
        else var_disp_conv(1,0,0);

        vswr_disp(1,10);

        msec_delay(40);
 }
}


void msec_delay(unsigned short time){
 unsigned short i;
 for(i=0;i<time;i++){
  __delay_ms(1);
 }
}


void lcd_init(void){
 lcd_cmd(0x38);
 lcd_cmd(0x39);
 lcd_cmd(0x14);
 lcd_cmd(0x70 + contrast);
// lcd_cmd(0x73);
 lcd_cmd(0x56);      // 3.3V
// lcd_cmd(0x52);      // 5V
 lcd_cmd(0x6C);
 msec_delay(210);
 lcd_cmd(0x38);
 lcd_cmd(0x0C);
 lcd_cmd(0x01);
 msec_delay(2);
}


void I2C_send(unsigned char data){
 SSP1IF = 0;
 SSP1BUF = data;
    while(!SSP1IF){
    }
}


void lcd_cmd(unsigned char work){
 SSP1CON2bits.SEN = 1;
    while(SSP1CON2bits.SEN){
    }
 I2C_send(LCD_AD);
 I2C_send(0x80);      // Co=1, RS=0
 I2C_send(work);
 SSP1IF = 0;
 SSP1CON2bits.PEN = 1;
    while(SSP1CON2bits.PEN){
    }
    SSP1IF = 0;
 __delay_us(30);
}


void lcd_data(unsigned char work){
 SSP1CON2bits.SEN = 1;
    while(SSP1CON2bits.SEN){
    }
 I2C_send(LCD_AD);
 I2C_send(0xC0);      // Co=1, RS=1
 I2C_send(work);
 SSP1IF = 0;
 SSP1CON2bits.PEN = 1;
    while(SSP1CON2bits.PEN){
    }
    SSP1IF = 0;
 __delay_us(30);
}


void lcd_position(unsigned char li, unsigned char col){
 lcd_cmd(0x80 | (li << 6) | col);
}


void lcd_str_disp(unsigned char li, unsigned char col, const char *string){
 unsigned char i = 0;
 lcd_position(li,col);
 while(((col + i) < 16) && string[i]){
  lcd_data(string[i]);
  i++;
 }
}


void lcd_char_disp(unsigned char li, unsigned char col, unsigned char ascii){
 lcd_position(li,col);
 lcd_data(ascii);
}


void pow_disp(unsigned char li, unsigned char col){
   
    if(for_rev == 0) lcd_char_disp(li,col,'F');
    else if(for_rev == 1) lcd_char_disp(li,col,'R');
   
    if(po < 1000) lcd_data(' ');
    else lcd_data(po / 1000 + '0');
    po %= 1000;
    lcd_data(po / 100 + '0');
    lcd_data('.');
    po %= 100;
    lcd_data(po / 10 +'0');
    lcd_data('W');
}


void vswr_disp(unsigned char li, unsigned char col){
    lcd_str_disp(li,col,"SWR");
    if(vswr < 10){
        lcd_data(' ');
        lcd_data(' ');
        lcd_data(' ');  
    }
    if(vswr < 100){
        lcd_data(vswr / 10 + '0');
        lcd_data('.');
        lcd_data(vswr % 10 + '0');
    }
    else{
        lcd_data('>');
        lcd_data('1');
        lcd_data('0');
    }
}


void lcd_clear(void){
 lcd_cmd(0x01);
 msec_delay(2);
}


void cgram_set(void){        // bargraph caharacter setting
 unsigned char i;
 for(i=0;i<7;i++){
  lcd_cmd(0x40 + i);       // bar0
  if(i == 0) lcd_data(0x01);
  else if(i == 1) lcd_data(0x15);
  else lcd_data(0x00);

  lcd_cmd(0x48 + i);       // bar1
  if(i == 0) lcd_data(0x01);
  else if(i == 1) lcd_data(0x15);
  else lcd_data(0x10);

  lcd_cmd(0x50 + i);       // bar2
  if(i == 0) lcd_data(0x01);
  else if(i == 1) lcd_data(0x15);
  else lcd_data(0x14);

  lcd_cmd(0x58 + i);       // bar3
  if(i == 0) lcd_data(0x01);
  else lcd_data(0x15);

  lcd_cmd(0x60 + i);       // bar4
  if(i == 0) lcd_data(0x07);
  else lcd_data(0x17);
 }
 lcd_cmd(0x68);
 lcd_data(0x11);
 lcd_cmd(0x69);
 lcd_data(0x15);
 lcd_cmd(0x6A);
 lcd_data(0x15);
 lcd_cmd(0x6B);
 lcd_data(0x0A);
 lcd_cmd(0x6C);
 lcd_data(0x00);
 lcd_cmd(0x6D);
 lcd_data(0x00);
 lcd_cmd(0x6E);
 lcd_data(0x00);
}


void var_disp_conv(unsigned char li, unsigned char col, unsigned int val){
    char value = 0;
    value = (char)(val >> 5);
   
 unsigned char col_max = 0, reg_col = 0;
    col_max = value / 3;
 reg_col = value % 3;

 lcd_position(li, col);

 if(value < 28)
  {
  for(unsigned char i=0;i<col_max;i++){
   lcd_data(3);
   }
  if(col_max < 9){
            lcd_data(reg_col);
   for(unsigned char i=0;i<(8-col_max);i++){
   lcd_data(0);
    }
   }
  }
 else{
  for(unsigned char i=0;i<8;i++){
   lcd_data(3);
   }
        lcd_data(4);
  }
}


(EOF)

最新のMPLAB X IDEとXC8コンパイラ(フリー版)でコンパイル可能です。(フリー版でない場合は最適化オプションによっては動作がうまくいかない可能性があります。検証していませんが(通常版持ってないし))

次はPCBデザイン編です^^

秋月Cタイプユニバーサル基板に実装テスト 1.8~50MHz帯、20Wまで使えそうです

2019年7月2日火曜日

通過型電力計の製作(その1~回路編)

運用中の送信出力やVSWRモニタリングはメーカー製のトランシーバであれば、たいていは内蔵されているものですが、そういった機能を持っていないVNシリーズなどキットや自作QRP機を運用していると、実際出力が出ているのかどうか気になってきます。またアンテナ調整はアンテナアナライザであらかじめ調整しますが、運用中のアンテナトラブルも特に移動運用では少なくありません。

送信しても呼ばれないなぁとかなんとなく感度が悪いなぁと思っていたら、極端な話エレメントが切れていたなんてこともない話ではありません。

というわけで運用中のモニタリングとして通過型電力計の必要性を感じました。メーカー製のしっかりしたものもありますがここはやはり自作で、ということで製作を試みました。

それでは最初に回路を吟味していきましょう。通過型電力計は方向性結合器と整流部、それに表示部で構成されています。HF~VHF帯で使用されている回路は、方向性結合器としてCM結合のものが多く、整流にはVfの低いゲルマダイオードやショットキーダイオード、表示部はメカニカルなメーター(パネルメーターやラジケーター)といったところが通常でしょうか。

まずは方向性結合器ですが、先ほど述べた通り自作の通過型電力計として好んで採用されている回路のほとんどがCM型と呼ばれる回路です。



CM型は図のように電流検出用としてトロイダルトランスなどを用い、コンデンサにより電圧検出を行っています。この方式は比較的単純ですが、素子によるばらつきや周波数による結合度の変化など不安定要素もあり、なるべく調整箇所を少なくしたいことから次の図のように電圧検出もトランスを用いた回路を採用してみました。(今回mcHFに採用されている回路を参考にしました)



これってMM型っていうのでしょうか?タンデム型と呼んでいる文献も見かけたことがありますが、正式には何と呼んでいるのかは分かりません。いずれにせよトランスの巻き数比によって計算通りにインピーダンス変換することが可能です。

それから各トランスの巻き数比については大きくとることで電力計挿入による影響(損失や不整合、高調波の発生など)を少なくする事が出来ますが、検出した信号をダイオードで整流する場合信号が小さい、特にダイオードのVfを下回る時には電流はほとんど流れません。したがってこの場合例えば出力が小さいQRPの場合VSWRの値は過小評価になってしまいます。

色々な製作例などを見てみると巻き数比10:1として20dBカップラーとしているものがほとんどですが、これはダイオード整流の場合の妥協点なのかなと勝手に想像しています。実際今回のプロジェクトでは5W前後の出力を対象にするつもりなのでこの巻き数比で進めることにします。

もしQRPp(~27dBm)から100W級(+50dBm~)を一台でカバーする電力計を作るとするならばトランスの巻き数比は33:1にして、アッテネーターを加え十分レベルを下げたところで整流(レベル検出)にダイナミックレンジの広いログアンプを使うべきでしょう。

整流には定番のゲルマニウムダイオード1N60よりもVfが低く高周波特性の良い1SS106というショットキーダイオードを採用しました。2019年7月現在秋月でセカンドソース品が販売されています。負荷抵抗はやや高めの10kΩとしてその後にPICマイコンのアナログ入力ポートに接続します。PICの入力ポート保護のためにツエナーダイオードなどによるクランプやオペアンプのボルテージフォロワを前置したほうが安全ですが、実測20Wまでなら整流電圧がPICの電源電圧を超えないことを確認したので、5W前後での使用であれば問題なさそうということでシンプルさを優先して省略しました。

進行波、反射波それぞれの整流電圧を8ピンPICのPIC12F1840の対応するアナログポートに接続しPIC内でAD変換、数値演算とLCD表示制御を行います。このPICは8ピンPICの中でもプログラムメモリやRAMサイズも大きく、今回のプログラムを純正のXC8コンパイラフリー版でコンパイルしてもプログラムエリアの50%弱に収まっています。しかも1個120円(秋月)と安いので使い勝手、コストパフォーマンスが非常に良いです。その代わりピン数が少なく今回の製作ではすべてのピンを使い切っています。でも逆に制限があるほうがいろいろと工夫を考えるのでこれはこれで良いのかもしれません。

というわけで下に固まった回路図と、プロトタイプ版の画像を上げておきます。

ディジタル通過型電力・VSWR計回路図

秋月基板Cタイプに方向性結合器と整流部を実装し動作テスト

 ~次はプログラム編に移ります。

2019年6月15日土曜日

AKC~アマチュアキットクリエイターズ ローンチ!

AKC? アマチュアキットクリエイターズ? って唐突になんのこっちゃって感じですが、

これは

関西アマチュア無線フェスティバル2019ハムフェア2019に向け自主制作した電子工作キットをみんなで合同頒布しちゃおうぜっ!

という企画です。

メンバーは某AK〇48よろしくうら若き美少女48名・・・ではなく6人のおっさん達です(失礼^^;)。

現在確定している具体的な活動予定は関西アマチュア無線フェスティバル2019とハムフェア2019当日、ステージで歌や踊りを披露・・・ではなくてブースをひとコマ確保し、そこで各々AKCメンバーが用意した自主制作のキットを並べて頒布するというものです。

以前私がCQ誌の記事の中にも書かせていただきましたが、ここ数年でプロレベルのプリント基板が非常に安価にしかも手軽にオーダーができるようになったこと、電子部品通販やCAD、マイコンのプログラミング環境が整備されていること、測定器関連の低コスト化などによって思ったことが容易にできてしまうようになりました。しかも一点ものではなくいくらでもコピーが作れてしまうので、これを利用しない手はないでしょう。

つまりは自分の思い描いたことが比較的容易に実現できてしまうということは、究極頒布しているキットは作り手の自己表現ではないだろうかと思っています。いわゆる自費出版やインディーズ、同人誌と自主制作キットは根っこは同じなのかもしれませんね。

まぁ御託はこれくらいにして、詳細は下の大きなバナーをクリックしてご覧ください。
https://www.amateur-kit-creators.com/
Rise upなんてちょっと過激な表現ですが、積極的に自作しましょ!という意味に捉えていただければ幸いです
錚々たるメンバーがみな凄いキットを企画しています。私も今までのキットに加え何か新しいものができればと考え中です。

それからイベント当日はキット目当にするのはもちろんですが、ブースにいるメンバーにぜひお声がけしていただいてキットに対する質問などなどいろいろ談義できることも楽しみにしています。

2019年4月21日日曜日

CQ hamradio 5月号に紹介されたVN-4002

大変ありがたいことに、先般CQ hamradio 2019年5月号にVNシリーズ(VN-4002)の紹介記事を寄稿する機会をいただきました。

商業誌に寄稿した経験はなくはないですが、作家などの文章書きを生業としているわけではない所詮は素人ですから雑誌の意向に沿った気の利いた文章などはなかなか書けません。にもかかわらず体裁含めきれいにまとめてくださった編集の皆様に感謝申し上げます。


原稿のやり取りの中で、編集者の方のメールに『読者にこのキットの魅力を伝えたい。特徴を箇条書きに。』とありました。

え?『魅力』ってなんだろう・・・考えたことがなかったのでしばらく悩みました。

もともとこのトランシーバーをどうして作りたかったのかっていう最初の動機をたどってみました。それがもしかしたら魅力につながっているかも、ということで。

カムバックした数年前ネットで海外の様々なQRPキットを取り寄せては作っていました。このときから移動用で実用的な無線機を作ってみようと思い、どうせ作るなら小型にしてマイコンを取り入れてメモリーキーヤー内蔵したりなど一台で完結させてしまおうと欲張りな仕様を考えました。

最初はブレッドボードからスタートし、ユニバーサル基板にまとめ、プリント基板を外注した初めての人柱版から現在に至るわけですが、一貫して目指したところはいかに小型にするかということと、十分な受信性能と送信出力、無線機としての機能も充実させるということでした。

実際に頒布を継続している中で、頒布させていただいた方々の使用感を眺めてみると、小型でいてそれにもかかわらず性能が十分であるというところが評価されているようで、このことが一つの魅力なのだろうかと思いました。

文章では表現がなかなか難しく、掲載された記事を見ても大きさなどは例えば実際の市販のハンディ機などと横並びさせた画像を出しておけばよかったとか実際の移動運用レポートをもう少し具体的に挙げるなど何点か反省点はありますが、紹介記事としては十分なのかもしれません。

ともあれ自分がこういったものを作りたい、という思いを忘れずに新しいプロジェクトを進めていこうと思っています。

2019年4月2日火曜日

Si5351Aによる任意周波数の3波同時出力

新年度です。

3月ブログ更新をうっかりしそこなってしまいました・・・(´・ω・`)

とりあえずここのところいろいろと私事やら何やらで更新する気にならなかったという言い訳をしておきましょう。

ところでSiliconLab製の便利なSi5351Aは入手性も良好で、製作例も最近多く見かけるようになってきました。Si5351は3つのバリエーションがあって、Si5351Cにあっては8波同時出力が可能となっていますが、いずれのバリエーションも内蔵されたVCOは2つにとどまっています。

ほら、どれもVCOは2つしかないでしょ?
任意の周波数の2波同時出力の設定は比較的単純で、各VCOの周波数設定を変更するだけで後のMultiSynthの設定は簡単な整数で固定で済ませられます。

VNシリーズの構成は、下のように受信は2波同時(局発、BFO)、送信波1波のみ(送信周波数の信号)で3波同時に出力する必要はありませんでした。

VNシリーズの受信・送信時のSi5351A動作
QCXトランシーバーのように受信機の調整などに使える信号発生機能を検討してみましたが、VNシリーズで実現するためには任意周波数の3波同時出力が必要となります。そうすると、下図のように3波目はすでに使用しているPLLのどちらかを流用するしかありません。
3波目はどちらかのPLLを他ポートと共有せざるを得ない
 VNシリーズではCLK1のTX出力がSG出力になりますが、固定周波数ののBFO(CLK2)とPLLを共有(PLL A)としました。PLL Bでも可能ですが、LOの周波数は可変のためパラメータ計算になにがしかの支障が出ることが懸念されたため周波数がほとんど変わらないPLL Aを選択しました。

さてつぎにいよいよ目的周波数から各設定値の算出方法を考えるわけですが、まずはおなじみの(笑)パラメータと条件のまとめ図をおさらいします。
図の中のa,b,c,fvcoはBFO周波数設定ですでに規定されているので、これらのパラメータの条件は満たされています。次に上の図の2つの式をもとに、fout値を代入することによってパラメータd,e,fを算出する計算式を導きます。

ここからはPCよりもずっと直感的で自由度の高い『直接紙に書く』方法が一番です。下の画像は実際に紙に書いて導き出した記録です。

(クリックすると拡大して見れるかもしれません)
書き文字が読みにくくて恐縮ですが(汗)、左下の赤線で囲ってある計算式がd,e,f値のそれぞれの算出式です。これらの算出式の導き方については上の画像を見てぜひ考えてみてください。算出式はプログラミング言語の四則計算のルールに沿って記述しているので、この結果を見ながら実際にファームウエアのコードに新しい関数として記述していきます。

void Si5351A_ex_fset(long freq_ex){
 long a=0, b=0, c=1000000, d=25, e=0, f=0, fbfo=0;
 

 if(TX_freq < 10000000) fbfo = BFO_freq;
  else fbfo = BFO_R_freq;     // -> BFO frequency check

 a = fbfo + (calib * (fbfo / 100000)) / 100;
        // display frequency adjust to real frequency
 b = a % 1000000;
 a = (char)(a / 1000000);


 if(a > 0 && a < 36){
  while(a < 16){
   a <<= 1;
   c >>= 1;
   d <<= 1;
  }
 }


 f = freq_ex / 100;
 d = (250000 * (long)a) / f;
 e = (250000 * (long)a) % f + ((250000 / c) * b);


 ms_set(1, d, e, f, 0);
}


上のコード前半ではBFO周波数値からパラメータa,b,cを割り出しています。この部分はシステムの起動時にはすでに計算されており、各変数をグローバル変数としてコードを省略することも可能です。

コード後半の赤字部分がd,e,fの算出式で、最後に得られた数値をms_set()関数に代入してSi5351Aに転送します。やってみると意外と簡単な式に収まっていますが、各パラメータの条件の制約からこの方法では100Hzステップより細かくできませんでした。

それでも任意の周波数で同時に3波発生可能となったので、何か応用できるものはないだろうかと思案中です。