2024年4月24日水曜日

小ネタ

 amazonで「買っておいたことにする」みたいな機能が欲しいなとか思ったり。普通に購入して支払いもカードなりポイントなりで決済するんだけど、1ヶ月くらいamazon倉庫に置いておく。「近い内に(遅くとも2,3週間程度で)また買い物するはずだからそのときにまとめて送って」的な。あとでまとめて注文すればいいだろ、という話ではあるんだけど。


 夜中に裏山を歩いていたらフクロウに遭遇した。全くの無音で飛んでくるので結構不思議。飛び立ったあとに枝のひずみエネルギーが開放されてカラカラ鳴る程度。よくよく耳を澄ますと少しだけ羽音が聞こえるかな、くらい。生き物らしい音が全くしない。そりゃ不吉の象徴とか言われるわけだ、みたいな納得がある。


***


 STM32G031J6Mで1-Wireデバイスの制御。一時期秋月で売っていたチップ。

 今回はTIMで作ってみた。ch3でPWMを出して送信、受信時はch4でパルス幅を計測する。あんまりスッキリしないけど、一応1-wireに必要な機能はストロングプルアップも含めて実装。ストロングプルアップはEXTIとか割り込みが必要かと思ってたけど、結果的には非常に簡単に処理できた。

 今回はRTOSは乗っていないのでポーリングで処理している。DMAを使えば1バイト分の転送とかをまとめてハードウェアで処理できるだろうけど、DMAで処理するのは結構面倒な気がする。特に送信用のARRとCCR3はメモリtoペリフェラル、受信用のCCR4はペリフェラルtoメモリだから、少なくとも2本のDMAが必要になる。タイマとかDMAの同期とかも考えるとなかなか大変そうだ。

 STM32はGPIOをオープンドレインとプッシュプルで使えるので、オープンドレインで使えば外付けのダイオードが不要になる。また、プッシュプルに設定すればストロングプルアップとしても使える。ということで、最終ビットの立ち上がりエッジでGPIOをODからPPに切り替えれば、ストロングプルアップとして使える。ただ、ストロングプルアップ直前の1バイトはファンクションコマンドでマスターから送るだけだから、ODである必要はない。ということで、最終1バイトを送る前にPPへ変更している。1-WireにI2Cのクロックストレッチみたいな機能があるとちょっと困ったことになる。まあ、そういう機能はないはずなので、PPで送信しても問題ないはず。

 タイマはch3が出力、ch4が入力で、どちらも同じピンに割り当てている。ただ、STM32CubeMXでは一つのピンにタイマの出力と入力を同時に割り当てることはできないから、この部分はユーザーコードで初期化している。


 窓の外に置いたプローブで計測

 1dC/div、1hour/div、左端が22時過ぎあたり。夜中なので直線状に温度が下降している。開始後2時間目あたりから1時間ほど温度が上がっているけど、ここは窓を開けていた時間。少し隙間を開けていた程度だけど、かなり影響するな。5時頃から温度降下が止まっているが、太陽が出てきたからかな。9時頃から急激に温度が上昇しているけど、天気が変わったりとかかな? 温度センサだけ見ても面白いけど、他のセンサも欲しくなるな。


 ハードウェアはこんな感じ

 SOP8変換基板にSTM32を実装して、裏面に8x8のユニバーサル基板を貼り付けて、そこにSOT-89のレギュレータを乗せている。FT232系チップでUSBから5Vを取って、マイコンからはUARTの送信だけ。SOP側から出てる2本の端子はプログラムの書き込み用のSWD端子。

 1-Wireデバイス側は一応3線式(GND, DQ, VDD)の接続にも対応しているけど、今回は2線式(GND, DQ)のセンサを接続している。というか、3線式ならFT232に直結できるので、わざわざマイコンを挟んで温度を測る必要もないしな。。。


 小さいパッケージのSTM32

 ブレッドボードに乗せるならこのあたりが楽で良い。QFP48だと変換基板が2列の四角形になるのでブレッドボードに載せられない。まあ、基板作れって話なんだけど。。。


***


 気まぐれに、ワンセグチューナーで1090MHzを2Mspsで受信。

 なんかそれっぽい信号が見えるな。

 1000あたりは1.45us周期で15個のパルス位置があるので、Mode 3/A/Cの信号っぽい。Mode 3/A/Cはコードや高度が送られてくるけど、どっちが出てくるかは下から見てるとわからないのがな。

 3000あたりのやつはMode Sだと思うけど、波形が変な形。おそらくクロックエラーでパルスを分離できていないだけだと思うんだけど。位相を見てみると、63kHz(58ppm)くらいの角速度。RTL-SDR blog v3ドングルがそこまでずれることはないだろうから、大部分は送信側のクロックエラーのはず。

 Mode Sってどの程度の周波数エラーが許容されてるんだろうか? 2Mspsみたいなことをやらない限りはクロックエラーはある程度広く許容できそうな気がするし、飛行機みたいに温度環境が厳しい場所でこれだけ大量に普及させてるんだからある程度広く設定してあるはず。そうするとワンセグチューナーベースのADS-Bのデコーダがどうやって処理しているのかが謎いけど。

 古い資料だと、モードSの周波数の許容偏差は15000ft以下のみを飛行するなら±3MHz、これを超える場合は±1MHz、ということらしい。最近だと±1MHzに統一かな? 専有帯域幅が10MHzを超えるようなシステムなので、許容偏差もそれに応じて広め。そもそも帯域幅2MHzとかの受信機で受信する信号じゃないからな。。。


 別のサンプル

 位相の回転はほとんど無い。しかし相変わらずパルス位置の復調がうまくいかない。


 更に別のサンプル。rtl_tcp.exeが3.2Mspsくらいまで取れることがわかったので、試しに3.0Mspsでサンプリングしてみた(3.2Mspsだと2.048Mspsとかに比べて感度が低い気がする。デシメーションで処理利得が稼げないからかな。いちおう、rtl_tcp.exeではエラーログは出ず、FMラジオを復調すれば途切れずに聞こえるから、3.2Mspsが通っているはず)。

 さっきよりはマシ。ちゃんとパルス間が0付近まで落ちてるし、プリアンブルの形も綺麗に見えてる。

 試しにいくつかのサンプルを機械的にデコードしてみると、1個だけCRCが0になる(誤りが無いと考えられる)パケットが見つかった。DF17, CA5で、ICAOコードをFr24で検索するとちゃんと家の近くを飛んだログがある。ということで、正常にデコードできていると考えられる。

 ただ、大半のパケットはCRCが0にならない。ビット位置がずれると正常に復号できないので、0.3bit幅ずつ数ビット分の幅をずらして総当たりでデコードしても、復調率は改善しない。開始位置のオフセットとクロックのオフセットで2次元のfor回してスキャンしたりすればあるいは……

 短いパルスは3/A/Cの応答として復調すると、Fr24に記録されているSquawkと同じ値が時々出てくる。値は4箇所くらいに固まっているかな。普通民間の飛行機1機からはA/Cの2つの値が出てくるから、4個のグループがあるということは2機が飛んでいたということになる。ただ、Fr24のログだと航空機は1機しか記録されていない。もっとも、家のエリアはMLATは非対応だろうし、A/Cしか出していない機体(ADS-B out非対応機)が飛んでいた可能性は捨てきれない。


 1機(特定のICAOアドレス)から送られてきたMode Sスキッターの位相をグラフ化してみると、傾向として位相回転は見えるけど、一貫性はあまりなさそうな感じ。送信機は今の時代にわざわざインコヒーレントに作る意味もないだろうし、水晶を逓倍して1090MHzを作ってゲートを通してからHPAに通して送信、みたいな回路だろうから、ある程度の安定性はあるはずなのだが。もう少し高いサンプリングレートで見れば安定して見えたりするんだろうか?

 位相回転は送受信間の周波数オフセット(DC成分)に距離変化分のドップラー成分が乗っているはずだから、パルスの位相変化を見れば最接近の検出ができないかな、とか思ったんだけど。


 うちのあたりは飛行場からも遠いし、その飛行場も便数がさほど多くないので、ATC SSRを受信するにはあまり条件が良くない。サンプルデータを集めるのも一苦労。

 手軽にADS-Bを受信して遊ぶなら、ワンセグチューナーを3Mspsで走らせれば良さそう。もうちょっと簡単にデコードしたいなら4Mspsくらいあると安心だけど、とはいえそうするとAirspy miniあたりが必要になるので、ワンセグチューナー系の5,6倍くらいの値段になる。まあ、1回買えばしばらくは遊べるから思い切って買うという手もあるんだけど。ただ、おそらくAirspy系のドングルはlibrtlsdr(rtl_tcp.exeとか)からは触れないので、他の方法を考える必要がある。SpyServerでネットワークに接続できるけど、これは独自のプロトコルで、データを圧縮していたりするらしいから、触るのが面倒くさそう。SpyServerのOSSクライアントもあるらしいから、それを参考にクライアントを作るという手もあるけど。SpyServerはRTLドングルにも対応しているらしいから、とりあえず手持ちのドングルでSpyServerを起動して使えるかどうか確認して、使えそうならAirspy miniを買う、みたいな手もあるか。

 ADS-Bは世界各地で受信できるデジタル変調だけど、デジタル復調の遊びとして使うにはあまり向いてないかな。そもそも変調方式の情報もほとんど見当たらないし、ちゃんとした資料が必要ならICAOから買わないとだめだろうし、個人で買えるようなものでもないだろうし。デジタル復調で遊ぶならワンセグとかを復調したほうが楽しい。いちおうワンセグとかフルセグは英語版のドキュメントが配布されているし。フルセグの方は基本的に暗号化データだから、復調後にエラー率を見たりして動作確認は行えるけど、復調したデータを見れないのが残念なところ。ADS-Bは一応は意味のあるデータが出てくるからな。ADS-Bはシングルキャリアのマンチェスタ符号、ISDB-TはOFDMで処理内容も全く違うから、そもそも比較対象でも無いんだけど。


*


 軍用機(戦闘機とか)によく積んであるA/A TACANって飛行機間の距離を測定する機能だけど、Mode 3 XPDRでも距離は測れるわけで、軍用機で測距にMode 3を使わない理由ってなんだろう? TACANはチャンネルを設定できるけど、Mode 3だってコードを設定できるわけだから、周波数分割を使うか符号分割を使うかの違いでしかない。Mode 3だとATCに見えちゃうから、みたいな理由なのかな。そもそも軍用機には元からナビゲーション用にTACANインテロゲータが積んであるんだから、Mode 3を使うかTACANを使うかはどちらでも良くて、自由度が高いTACANを使った、みたいなことなんだろうか。


2024年4月17日水曜日

小ネタ



 20ftコンテナフォームファクタの折りたたみ太陽光発電システム。広げると120mくらいの長さになる。傾斜なしで平面に設置だから発電効率は若干ペナルティがありそう。長期間設置するなら手間をかけてでも既存のシステムで作ったほうが良いだろうな。駆動系統とかでコストも掛かるだろうし、展開したらレールとかも下に残るから、一緒に設置する他のコンテナに流用するみたいなこともできないだろうし。スポット的な需要には良さそうだけど、とはいえそのスポット的な需要の期間に綺麗な晴天を期待できるかというとまた別の話だし。20ftコンテナフォームファクタの蓄電システムと組み合わせて、需要の数日前に搬入して蓄電しつつ、当日の需要は蓄電したものを使って、みたいな感じになるか。


 AZKiと石神のぞみのドライブvlog概念。ツッコミ不在のギャグ大連発激オモロ動画。地理とか地図とかドライブとかが好きそうな人たちなので面白そう。


 リコリスのワッペン、サードのやつ出してくれないかなー。FDEとかタンとかマルチカムみたいなベースに合いそう。


 DJIのドローンとか、特に小型なやつで、そろそろボールとかフリスビーみたいに投げたらそのまま浮かぶ機能が欲しいよね。いちいち地面から離陸させなきゃいけないのが古くせー感じがする。バックパックから送信機を取り出して電源をON、続けてドローンを取り出して電源を入れて、ペアリングでき次第スナップを効かせて投げたら、そこで浮かんでてくれる。近未来の世界観のドローンってこういうイメージなんだけど、未だに何十年も昔のラジコンヘリみたいな離陸の仕方しかできない。フェイルセーフとかセンサのキャリブレーションとかいろいろ理由はあるんだろうけど。


 家に設置してあるストーブが操作しづらいとのことで、ためしに分解。めっちゃ分解しやすいな。順番にネジを外していくだけ。価格/質量と修理性レートは大部分で反比例しそう。密度が高いとネジを使わず接着したり、密度が低ければ組み立てのときの余裕も大きいし。

 操作部のPCBを取り外して観察。問題のスイッチは2本足のタクタイルスイッチだった。4本足しか持ってないや。ということで、別の操作(時計とかタイマーの設定用、全く使ってない機能)のスイッチと交換。とりあえず必要な操作は正常に戻ったかな。今シーズンはもう使わないだろうし、気が向いたら合いそうなスイッチを買って在庫しておこう。

 2本足のタクタイルスイッチは秋月でも売ってるけど、秋月のは高さが5mm、PCBに乗ってたやつは4.3mmくらいだった。ちょっと高さが違う。高い分には削ればいいし、低い分にはテープか何か貼ればいいんだろうけども。

 '12年製なので10年くらい使っていて、1年の1/3で稼働していたとして、1日に10回操作したとして、1万回くらい押されているスイッチ。1日に10回も押さんだろとか稼働時期の端は少なくなるだろと考えると、もう少し少ないかな、といったところか。家のあたりは温泉地というわけでもないし、秋月で売っているやつが10万サイクルくらいのオーダーであることを考えると、もう少し長持ちしてほしいところ。/* メーカー曰く設計寿命は8年とのことだから、製品本体の設計寿命は十分に超えている */


 NTTだかプロバイダだかを名乗るところから電話があった。

 曰く料金プランが変更になるので手続きを行うと安くなる、大きな手続きは必要ない、なるべく早く手続きをやってくれ(そのほうが早く安くなるから)、という感じ。手続の内容を軽く聞いてみたら、電話相手が3,4回たらい回しにされるから先々で従ってくれ、あと現在契約中のプロバイダの解約(or契約変更)手続きを行ってくれ、とのこと。おい。

「今は時間がないから後で手続きをしたいのだが、手が空いたときに電話したい」旨を伝えると「こちらの電話番号を教えることはできない」だそう。まともな会社なら問い合わせ窓口くらいあるだろうよ。。。

 うーん、詐欺っぽ、と思って通話終了。大事な手続きならまたあとで電話来るだろ…… そういう心理をついて詐欺業者が繰り返し電話してきてもまた困るんだけど。


***


 STM32F303K8で定電流回路

 外付けのNch MOSFET(とりあえず手持ちのIRLB3813PBF)をオペアンプでドライブして、ソースを1Ω5%の抵抗で電流計測。オペアンプでフィードバック制御して、電流指令値はDACを分圧して入力。電流センスは0.1Aで0.1Vになるので、12bitのADCで125binくらいにしかならない。本来であればPGAで増幅したいところだけど、303K8の唯一のOPAMPはフィードバック用に使用しているので使えない。

 安定化電源を接続しているので電圧は一定のはずだけど、ブレッドボードの接触抵抗でだいぶドロップしてる。

 とりあえず三角波の指令値を出していて、平均するとFETは0.56Wくらいの消費電力になる。この程度でも触るとほんのり温かいな。


 適当な定抵抗負荷(100Ω5%を2本並列+470ΩのLED)

 電流指令値に対して飽和している(電圧に対して抵抗が大きい)。

 電流(縦軸) 対 電圧(横軸)

 きれいな直線状。傾斜の傾きからして抵抗値は34Ωくらいか。実測値は49.8Ωくらいなのでかなり低く出ている。


 死んだNi-MH電池がたくさんあるので適当な電子負荷を作って特性を測ってみたいなとか思ったり。STM32F303K8はVINMが1本しかないのでCC/CVをハードウェアで組むことができないから、CC専用の負荷でCVはソフトウェアで実装みたいな感じになるのかな。電池の放電試験くらいならソフト実装の帯域幅(250Hz前後)でも十分じゃろ。あるいはシャントからPGA(x16)に通してADCで計測して、CC/CVどちらもソフトウェアで制御するみたいな方向性もあるか。

 ある程度の電流を引きたい場合、安い電池ボックスだと接点容量の心配がな。マルツ(DigiKey)でkeystoneのアルミ板金のいかにも大電力対応みたいな見た目のやつも売ってるけど、さすがのお値段。樹脂製の安価な電池ボックスの20倍くらいする。

 タミヤの電池ボックスって性能どんなものなんだろうか。細い針金でコイル作ってるわけじゃないからそこそこ抵抗低そうな気はするのだが。それを試すための電子負荷か……


***


 簡単なテストコードをCortex-M4で走らせてみた。

 こんな感じのコード

uint32_t start, end;
__asm__ volatile(
    R"(
      mov r12, #128
      ldr %[start], [%[CYCCNT]]
      .balign 8
      # ↓ NOPの数を調整
      nop
      nop
      nop
      nop
      nop
      nop
    label6:
      subs r12, #1
      bne label6
      ldr %[end], [%[CYCCNT]]
 )" : [start] "=r"(start),
      [end] "=r"(end)
    : [CYCCNT] "r"(&DWT->CYCCNT)
    : "r12");
printf("6 %lu\n", end - start);

 インラインアセンブリで単純なループをさせる。経過時間をDWT.CYCCNTで計測。ラベル前のNOPの数を変えて走らせる。ここで、NOPは16bit命令へ変換される(32bitのNOPが欲しい場合、nop.wを指定する)。PICマイコンとかだとNOPは1サイクル分の「何もしない」命令になるけど、Cortex-Mの場合、NOPはそのまま実行されることもあるし、実行されないこともあるらしい(実行されないというか、パイプラインに取り込まれずにスキップされる)。NOPは「何もしない」というよりは、「後続の命令の位置を動かすためのパディング」くらいの感じらしい。ということで、今回のNOPの使い方は本来(想定)の使い方ということになる。

 で、結果は、

 というような感じ。NOPの数が4でmod取って0と1が最小、2と3で処理時間が増える、という感じ。16bit命令4個で1サイクルなので、64bitが1周期となる。

 今回はカウンタをデクリメントするだけの一番小さなループだから効果が大きく出ているけど、命令のアライメントはそれなりに効きそう。gccのインラインアセンブリなら.balign nで次の命令のアライメントを指定できるから、パフォーマンスがほしいループなら.balign 8とか指定すると良さそう。ジャンプ先のアライメントはループ数に比例して増えるのに対して、balignで挿入されるNOPはループ数に反比例して影響が減るから、ループが小さく回数が多いほどbalignでアライメントするほうが有利になる。ただ、同じCortex-M4でもチップによって(F3とG4とか)フラッシュの帯域幅が違うらしいんで、ターゲットによってアライメントを調整したほうがいいかもしれないけど。

 処理時間はsubが1サイクル、bが最大4だから、計算上は最小384、最大512程度のはずなんだけど、明らかに遅い。命令に要するサイクルはあくまでもスムーズに流れたときに最短でこの程度、という感じなのかな。


STM32G4のFDCANでチョット遊ぶ

 STM32G4のFDCANを軽く触ってみた。

 FDCAN1とFDCAN2を有効化、GPIOはAF_ODで初期化して、47Ωでプルアップ。ボーレートは250kbaudと2.5Mbaudに設定。FDCAN1から送ってFDCAN2で受信。

 ドライバ無しのCANネットワークはArduinoとか小規模なマイコン(回路)でTXをダイオードORして1本にまとめてRXへ分配するのと同じような考え方。


 試しに、標準、FD(低速)、FD(高速)、標準、FD(低速)、FD(高速)、FD(低速)、FD(高速)、という8個のパケットを送信。

 オシロで見ると、ちゃんとボーレートが切り替わっているのが見える。ジャンパワイヤを何本か飛ばした程度であれば、オープンドレインの470Ωで2.5Mbaudは問題なさそう。もう少し早く(or容量が大きく)なるとちょっと厳しいかな。抵抗値は220Ωくらいまでは問題ないと思うけど、あんまり小さくしてもねぇ。ちゃんと使いたいならドライバ入れろって話だし。

 SiglentのオシロはCAN 2.0Bまで対応かな? CAN FDはデコードできない。ただしCAN FDのパケットは単にエラーになるだけで、ほとんどの場合はそれに続くCAN 2.0パケットは正しくデコードできる。CAN FDでは2.0のリモートフレームで8バイトを超えるデータ数を要求できるけど、Siglentのデコーダではこれはエラーとして処理している。


 プロトコルトリガはスタートならFDにもトリガがかかる。プロトコルトリガ自体はたぶんFPGAとかで簡易的に処理しているはずなので、データ流しっぱなしにすれば画面更新レートも非常に高い(デコーダは追いつかないけど)。


 IDとかでトリガすることもできるけど、操作性がかなり悪い。まあ、このオシロはデフォで操作性が悪いので、プロトコルトリガだからという問題ではないのだが。Siglentのドキュメントを読むとTelnetでCANバストリガ関係も設定できるんだけど、試しに叩いてみても反応しない。


 LAP-Cは一応CAN FDにも対応。ただしCAN FDを使う場合はBRSのON/OFFが混在していると正常にデコードできない。一旦エラーになると多くの場合で後続のパケットも巻き込んでエラーになる。BRSのON/OFFを混在させなきゃいけない状況というのも特に思いつかないので、実用上は問題ないのかもしれないけど。

 LPA-Cのプロトコルトリガは結構手抜き実装な感じがあるな。LAP-C Proだと改善してるのかな? /* LAP-CとLAP-C Pro、当初は併売してたけど、もうLAP-Cは売ってないんだな。価格帯が全く違うから、電子工作用のロジアナとしてZEROPLUSはもう高級品だ */

*

 STM32G4のFDCANで、CAN 2.0BとCAN FDを混在させた時に、時々CAN FDの長いパケットの後ろがゼロ埋めになることがある。

 例えば受信結果は

     635 12 ESI0 BRS0 CLS     0 63 1  RMT

0000019F 64 ESI0 BRS0 CLS     0 63 1  DAT: 70 D7 5D D6 95 8E 47 8A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

0BB80000  3 ESI0 BRS0 CLS     0 63 1  RMT

000006E7  4 ESI0 BRS0 CLS     0 63 1  DAT: C6 E7 3E 20

 みたいな感じになる。

 その区間をオシロで見てみると

 前後のId635やId0BB80000は正しく見えているけど、Id0000019FはBitRateSwitchがOFFで64バイトなのに、明らかに短い。

 起動時直後に頻発するような印象。少し送信してると問題なくなる感じ。

*

 G4のFDCANはTIM3と連携して、送信時と受信時のTIM3のカウント値を記録する機能がある(FDCANに内蔵したカウンタも使えるけど、BRS ONだとtickの長さが変わるので、with BRSで使うならTIM3が必要)。受信側は受信時のタイムスタンプが得られるけど、送信側はあくまでも送信したタイムスタンプを後で読み出すことしかできない。STM32F1のbxCANではSOFのタイムスタンプ値を8バイトの末尾2バイトに埋めて送信する機能があるけど、G4のFDCANではそういう機能は無いはず。


 例えばTIM3のtickを16us(170MHzならプリスケーラ2720)に設定してやれば1.048秒で1周期になるので、GPSの1PPSでTIM3をクリアすれば、あるパケットを送信した時刻をUTCに対して16us秒の分解能で計測できる。続くパケットで「さっきのパケットはUTCで何マイクロ秒の時刻でした」というのを送ってやれば、受信側でも1個目のパケットの受信時刻を計測しておいて、続くパケットに含まれる時刻情報と1個目の時刻を比較してやれば、UTCに対して良い精度で自分のカウンタを同期できる。差を微分すればUTCに対する自分のカウンタの速度差も計測できる。

 このタイムマーカーパケットはあくまでも送受信間でタイマを比較するために使うだけ(決められた時刻ピッタリに送る必要はないもの)だから、破棄されない程度の優先度であれば良いので、大きなパケットが流れているバスでも時刻比較に使うことができるはず。ただしルータを通すとディレイやジッターが増えるから、ルータを使うのであればルータ自身が時刻決定を行ったうえで、下位のネットワーク(タイムサーバーから遠い方)へ伝播させる必要がある(ジッタはルータ1段ごとにランダムに増えていく)。


 ランダムなパケットを送りつつ、タイムマーカーを送るテスト。

 Std123h DLC0が基準パケット、Std123h DLC2が基準パケットを送信した時刻を送るパケット。ランダムなパケットはFIFOの空きが1より多い場合に送信しているから、タイムマーカーを割り込んで送ることができる。

 受信側はStd123h DLC0のパケットを受信した際のタイムマーカーと、Std123h DLC2で送られてくるタイムスタンプを比較して、時刻サーバーと自身の時刻差を求めることができる。あるいは、Std123h DLC2だけを送って、前回のStd123hのタイムスタンプを送る、みたいな運用でもいい。ただしこの場合はStd123hを送る間隔分、タイムスタンプ値を得るまでの遅延が発生する。


 また、TIM3のリセット(外部入力で蹴られる)をトリガから出力して、TIM2で受ければ、外部から入力された1PPSの数をカウントできる。適当な原点からの経過時間をGPS基準で32bitの秒と16bitの分数で表現できる。今回の場合だと分解能16usで130年程度(ほぼ47.93ビットレンジ)を計測できる。例えば1970年1月1日0時からの経過秒数とか、1980年1月6日0時からの経過秒数とか。ロールオーバーが気になるならシステム起動時とか任意の時点を原点にしてもいいし。


 タイムマーカーのパケット(Std123h DLC0)を送った時刻を、32bitの秒と16bitの分数の合わせて8byteとして送信している(8バイトに収まるのでCAN 2.0で送れる。もちろんCAN FD with BRSで送ったほうが短く遅れるけど)。

 今回はTIM3のクロックソースにコアクロック(外付け水晶を逓倍したもの)を使用しているけど、GPSから10MHzを受けられるのであればそれを使うのが一番精度が出る(10MHzである必要はなくて、今回の場合であれば62.5kHzの整数倍であればいい)。

 STM32G4のFDCANを使えば、かなりシンプルな方法で広い範囲に正確な時刻を共有することができる。

*

 CAN/CAN FDは車載の安全要求の厳しい環境で使う前提だからか、STM32G4のFDCANは、他のSTM32のペリフェラルとはだいぶ雰囲気が違う。ビットフィールドが中途半端な位置に配置されていたり、あるいはリファレンスマニュアルで一切解説されていないビットが定義されていたり、いろいろと謎い。外部のガイドラインみたいなものに従って実装してるのかな?

2024年4月10日水曜日

小ネタ

 




 クォーツ時計だから「これはただの電波時計です」はできない。まあ、女子高生が使うにはゴツいしな。



 GPSスプーフィングの話題とかも。

 GPSクロックが逆向きに動いたり、みたいな例もあるらしい。素人考えだと時計が逆向きに動いていたり、そうでなくてもRTC(航空機グレードなら数ppmとか?)に対して明らかに範囲を逸脱した時刻が与えられた場合、その信号は棄却しそうなものだけど、そういう実装にはなっていないんだな。与えられた信号をそのまま解釈して次に送って、情報の確度は後ろで判断する、みたいな思想なんだろうか。

 イプシロン#5の時の地上レーダのトラブルで、GPSのRFラインが緩んで、30弱の間にGPS時刻が1時間弱もズレたみたいな話題があって、そんなばかな、とか思ってたんだけど、産業グレードのGPS受信機ってだいたいそういう感じの実装になってるのかな?



 造形エリア310x330x700mm^3のSLSが$2999!?


 「木そのものを直接糖化発酵した新しいお酒~国内林業の起爆剤となる新産業創出を目指して~」 2023年度なのセルロース工房講演会 - YouTube

 使用済みのウイスキー樽とかを使ったらまたそういう風味の酒になるのかな?

 樹齢100年の木の中心部だけを使えば、平均して90年前の木材だけで醸造されて、放射性炭素年代測定を行うと90年物の酒になるんだろうか。今どきだと蒸留直後に計測した放射性炭素年代測定の結果をブロックチェーンで保存してボトルの封印にNFTを紐づけて売るみたいなこともできそうだな。「この酒は◯◯年に蒸留し、その時の放射性炭素年代測定の結果は××年でした」みたいな感じで。

 あるいは、醸造に使う木材と同じ個体から木樽を作るって手もある。中身が入れ替えられていないことが確実であれば、醸造に使った木材は木樽の木材と同一だから、その木のDNAを醸造時にデータベースに保存しておけば、あとからその木樽をちょっと削ってDNA鑑定することで個体をトレースできる。耐タンパー性がネックか。とはいえ、酒の中身と容器が個体レベルで同一ってのは面白そう。中心部の木材を主要な原料として使うのであれば、外側の木材を樽に流用することもできるし、あるいは丸太1本から容器を削り出して、削った材料を醸造するとかもできるし。

 他の原料と違って、構造材として使えたりとか、単一の材料である程度のボトル本数を作れるとか、木材由来の酒は商品の付加価値として色々と方向性があって面白そう。麦やらぶどうやらを容器として使うのは難しいからな。/* 酒を作るのと近い工程で途中から分岐すればバイオプラスチックとかも作れるわけで、DNAの保存とかにこだわらなければ大抵の穀物(特に酒の原料に使える材料)から容器を作れるわけだけど */

 ソメイヨシノとかの酒は商品として面白そうだけど、DNAトレーサビリティが劣悪。。。ま、瓶詰めして売るなら関係ない話だが。

 御神木とか、樹齢の長い木とか、由緒有る木が倒れたり伐採せざるを得なくなったときの後始末の手段の一つとしても面白そうよね。御神木を酒にして飲むってーのはちょいと罰当たりな気もするけど、まあ、日本の神様ならできた酒を何本か奉納しておけば怒るまいて……

 アルコールは飲む以外にも使えそうよね。ロケット燃料とか…… 木を(間接的に)焚べて飛ぶロケット。太陽のエネルギーをかき集めてアルコールを作れるので、ゼロエミッションの燃料にもなる。単に太陽から植物経由でエネルギーを集めたいだけならサトウキビとか植えれば楽じゃねって話ではあるけど、木を使えば治水事業もまとめてできる利点がある。サトウキビとかトウモロコシとかだと土壌の保水性はさほど大きくないだろうけど、ある程度成長した木なら表面の土を抱え込んで保水できるので、単に太陽エネルギーを集める以上の意味がある。特性の良い木材は建材にして、使いづらい木材や端材は燃料にして、みたいな方向性も。もっとも、建材と燃料価格がカップリングする欠点があるけど。化石燃料の供給が絞られてゼロエミッションの木材由来のバイオエタノールの需要が急登すると木造建築が建てられなくなる、みたいな未来。高層ビルも木で作ろーぜって話もあるしな。建築やら燃料やら治水やらが一つのリソースに集中すると舵取りをミスったときに面倒なことになりそう。


https://www.jrias.or.jp/books/pdf/201504_JIYUKUKAN_SAITO.pdf

 酒類の放射性炭素の測定とか。過去の実験でC3植物とC4植物で分けられるはずなんだけど、中間値的な値が得られた事の原因とか。


https://www.hro.or.jp/upload/7866/1105-12.pdf

 木材のDNA鑑定に関する話題。曰く、木はクローンで増やしやすいから、DNA鑑定で個体を識別するのは難しい、とのこと。逆に、あるエリアの木材はクローンの苗木を植林したものだという前提で、そのDNAと一致すれば産地を決定できる、みたいな方向性はあるらしい。

 そもそも木はDNAが少ないし、製材する過程や経年でDNAが壊れやすいという点もあるらしい。

 ブロックチェーンで木のDNAと酒の製造時期を紐づけるのは結構面倒そうだな。もっとも、40年くらい古い木材でもPCR増幅はできるみたいだし、将来の技術発展に期待してDNAと紐づけて酒樽の保存・醸造みたいな方向性は面白そうではある。


 月などで活動する基準の「月の標準時」 アメリカ政府 策定へ準備 | NHK | 宇宙

 一般相対論的な効果を含んだ標準時を作ろう、みたいな話。月面なら比較的やりやすいだろうけど、軌道上、特にゲートウェイは極端な楕円軌道だから、重力ポテンシャルや速度が頻繁に変化する。それらも考慮して「月探査系」標準時を作るんだろうか? それとも「月面」標準時を作るんだろうか。当面の月探査を考えると月面よりも月周回軌道上のほうが重要だと思うが。


https://www.jstage.jst.go.jp/article/nictkenkyuhoukoku/45/1.2/45_103/_pdf/-char/ja

 1999年。太陽系の時刻静止軌道。

 地球の場合は地球半径の1.5倍の軌道長半径(高度3200kmくらい)に時刻静止軌道がある。太陽系周回軌道の場合は0.955A.U.、木星の場合はr17万km(alt.10万km)くらい。軌道の許容幅は地球と木星で1.5km、太陽で1000km以内であれば地球に対して10-13を達成できる。

 この時刻静止軌道というアイデアは現在のところ、通信や気象観測に活躍している位置の静止衛星のようには応用目的が見つかっていない。このため技術的には可能でも、実際に時刻静止衛星をこの軌道に打ち上げる予定は残念ながら今のところは無い。将来宇宙空間で非常に精密な時刻合わせを必要とするような応用技術が開発されれば、見直される日が来よう。

 例えば測地衛星は精密な時刻合わせが必須だけど、GNSS衛星は3200kmのような(比較的)低い高度はとらず、ほとんどが2万km程度の高度を飛んでいて、時刻のズレは原子時計の微調整で補正している。よほどのことがない限りは、時刻静止軌道を使うよりもその場所に合わせた時計を使うほうが色々と利点が大きそう。

 宇宙機の管制(軌道伝播)にはその場所の重力値を知っている必要があるし、軌道計算できているのなら運動量(速度)だって既知だから、相対論的効果は計算である程度推定できる。その場所に合わせていちいち時計を作るより、軌道要素から時刻の進み方を補正して地球に合わせてくれるような時計を1個作るほうが簡単そう。リアルタイムに軌道要素から補正する時計があればゲートウェイみたいな長楕円軌道でも安心。

 そもそも宇宙空間の実験で10-10クラスの精度が必要かどうかという問題もあるしな。GNSS以外で宇宙機で精密な時計が必要なミッションと言うと例えばMUSES-Bとかがあったけど、とはいえこれの場合はKu CWを地上から上げてそれに位相ロックして観測してたわけで、必ずしも宇宙空間に高精度な原子時計を置く必要も無いし(GNSSみたいに多数を連続的に運用したい場合はオンボードで原子時計を置くほうが楽な場合もあるだろうけど)。VLBI観測とかをやるなら高精度なクロックがほしいけど、じゃあ月面でVLBI観測を行う利点があるのかというと、ほとんど無いだろうし。VLBIでは基線長の長さも重要だけど、単に長いだけだとあまり使いやすくなくて、その点で人工衛星ベースの宇宙VLBI(MUSES-Bとか)は衛星の運動量を観測に使える利点があって、月面ではそれがほとんど使えない(地上VLBIは地球の自転成分を使うけど、月の自転速度は地球の30分の1程度しかない)。

 地球の環境(主に重力)とある程度切り離した環境で精密な物理量を計測して違いがあるかどうかを見てみたい、みたいな実験だと、10-15程度の精度があるといいかもしれないけど、そういう観測を行う場合は実験ごとに原子時計を持ち込んでもいいだろうし。まあ、たかだか1桁にも満たない重力の差で物理量に差が出るかどうかは怪しいところだけど。とはいえ10-15精度で長期間比較すればなにか見えてくるかもしれないしな。

 話を戻して、月の標準時の話題は、どちらかといえば政治的な話題(西側でイニシアチブを取りたい)な感じがするな。


 Omni-SLR: First Success of Satellite Tracking | 一橋大学地学研究室 (Geoscience Hitotsubashi)

 Omni-SLR、'23年12月末に観測に成功。当初の予定では23年度中にLEOの観測を行いたい、みたいな話だったので、オンスケジュールで進んでいる感じか。


 属人的なテレビ番組は好きじゃないので、今期からの「ザ・バックヤード」の方向性はちょっと苦手。あと、今までは「素人が案内されるだからこのくらいでもしょうがないよね」という免罪符があったけど、今回の東京スカイツリー回は「東大博士を使ってもこの程度の番組しか作れないのかよ」という感がある。あんまり専門的すぎる内容にすると見てくれないって問題もあるんだろうけど。

 ナショジオとかディスカバリーで好きだった番組もたいてい属人的じゃねーか、という気はするけど。結局はメインキャストの役割とかかな。


 ペルチェ素子内蔵マドラーとかないかな、みたいな妄想。サーモスみたいな断熱性の高い容器であれば比較的少ない電力で保温できそう。USB電源かなにかで、温度スパイク直後(マドラーを液体に入れた時)の温度を維持するような制御。熱交換先がネック。あるいは蓋から棒を突き出して液体を保温してもいいけど。

 コップを保温するソリューション、大抵は小型のホットプレートみたいなものにペルチェ素子を内蔵したような形なので、断熱性の高いコップでは使えないのがびみょい。断熱性の高いコップとはいえども熱交換は起こるから、アクティブに保温はしたい。

 サーモスの底部の真空層にペルチェ素子を内蔵して、底面から電極を出す、みたいな製品があれば一番いいんだよな。で、ペルチェの温度特性を使って温度を測って、それを維持するような制御をすればいい。電極(&制御回路)のパッドを用意するのが面倒であれば、外部から5Vを突っ込んだらコップの中で制御してくれるとか、あるいはQiまでコップに内蔵してもいいけど。これなら電極が外に出ないから食器としても便利だし。コップの外層と熱交換することになるから外側が熱くなったり冷たくなったりして、断熱コップの利点が若干下がるのがネック。とはいえ熱湯を入れたら90℃位になるとか、氷水を入れたら0℃近くまで下がるみたいなことにはならないから、それほど不便にはならないはず。

 一番のネックはやっぱりコストかな。あとは断熱性が悪化するのでパッシブに使うときに性能が悪くなるとか。


 STM32G431KBが結構良さそう。QFP32で小さい用途に使いやすいし、オペアンプ3本(G4なのでPGAは64倍まで)とかDAC4本とかコンパレータ4本とかアナログ系色々乗ってるし、タイマも11本乗ってるし、CORDICやFMACも乗ってるし。色々遊べる。RAMが22Kなのでメモリでゴリ押す系の処理には向かないけど。電源周りもスッキリしてるし、QFP32だから適当な変換基板でブレッドボードに乗せてもいいし、Nucleoボードがあるからそれで手軽に遊んでもいいし。


STM32F303K8で超音波距離計の試作

 STM32F3で超音波距離計を作ろうと思ったんだけど、結構厳しい。特にOPAMP(PGA)のゲインがx16までしか設定できないから、アナログ系で利得を稼げない(PGAでなくて、普通のオペアンプみたいに外付け抵抗で設定してやればもっとゲインを稼げる)。とりあえず今回は比較的短距離(数m)を測りたいので、そこまで高い感度は必要ないかな、ということで続行。

 最初はDACでパルスを出そうかと思ってたんだけど、超音波素子をドライブできないことが判明し、TIMのPWMを出力するように変更。STM32のDACってインピーダンス結構高いのな。


 回路構成

 PB5, PB7からTIM3のPWMを出力、PA5からPGAのバイアスを出力、PA7からPGAへ入力。

 全体のタイミングの管理にTIM2を、送信パルスとADCのトリガにTIM3を、超音波素子は送信用の素子で受信器も兼ねる、というような構成。TIM3の役割がコロコロ変わるし、送信時はGPIOをAFにしたり、受信時はOutputでGNDに引っ張ったりAnalogで受け取ったり、あちこち動作モードを切り替えなきゃいけないので、ソフトウェアがかなり煩雑。

 STM32F303K8T、RAMが12Kしかないのが厳しい。ADCが12bitで、1024ポイントのダブルバッファだとそれだけで4K必要になるし、IFは512ポイント持つと32bit複素数で4K、合わせて8Kになる。


 試しに机に置いたセンサで天井までを計測

 パルスの先頭からADCのサンプリング開始までのディレイが4ms、デシメーション後は64us/sampleで、85あたりにピークがあるから、4ms+64us*85=9.44ms、340*9.44m/2=1.60、ということで、実測値の1.53mとほぼ一致。誤差と言い切るにはちょっとズレてるけど、天井は面的な反射だから斜めの伝搬は距離が伸びるとか言い訳すればだいたいいい感じの値になる(天井は超音波くらいの波長だと鏡面反射だから斜め方向の後方散乱ほとんど無いだろという気もするけど)。


 デバッグ用のオシロ画面

 黄色が主に送信パルスを見ている。PRI20ms(PRF50Hz)で打ってる。

 紫はADC前のPGA Voutを見ている。4msの位置から下側にノイズが増えているが、これはADCのコンデンサを充電している部分。その後にブロック状に上下にノイズが増える部分がある。これはデシメーションの処理に同期しているので、マイコン内部の消費電力か何かが漏れてるんだと思う。UARTの転送とかやると盛大にノイズが乗るから、ちょっとした消費電力の変動がアナログ回路にかなりの影響力がありそう。アナログ重視で使うならVDDとVDDAはしっかり分離しておかないとマズそう。F3はGPIOもVDDAで駆動されているらしいから、VDDとVDDAを分離してもGPIO動かしたら暴れるかもしれないけど。/* 以前Nucleo-G474REでAMラジオを作ったときもOPAMPに謎のノイズが入ってたけど、VDD/VDDAあたりが原因だったのかも。G4はGPIOはVDDAではないらしい。 */

 ローカルの生成はNCO、デシメーションはCIC(R64, N3)で処理している。超音波の圧電素子は十分に帯域幅が狭いと考えられるから、Nはあまり大きい必要はないはず。ADCは1Mspsで、IFは15.625ksps。もうちょっと低くてもいいけど、Rを大きくするとビット幅が足りなくなる。現状でも計算上はビット幅が足りない。アナログ信号強度が低いから飽和していないだけで。

 今回はパルス幅が狭いから単純なCWパルスだけど、必要であればチャープ信号も出せることは確認済み。ただしDACみたいに固定サンプリングレートのアナログ波形でなく、パルス周期やパルス幅のデータセットを与えてやる必要があるので、計算が面倒くさい。昔どっかで計算式見たような気もするんだけど、どこで見たんだか思い出せね。。。forブン回してrevの整数部とか位相の前後を判定するとか、あるいはそれを二分探索するとか、いろいろ方法は考えられるけど、それなりに面倒くさそう。チャープ信号を出したところで狭いメモリ空間でどうやって圧縮するんだって問題があるしな。リファレンスをコンパイル時に生成してFlashに置いておけば処理自体はできそうな気はするけど、今回はパルス幅も狭いし。G474REあたりだとRAMも広いから、快適にパルス圧縮とか、複数波形を並べて移動物体抽出とか、いろいろ遊べそう。


 IFのMagnitudeをDACで出力。レーダで言うところのビデオ信号みたいなやつ。

 紫がADCに入る信号、黄色がDACから出てきたIFのMagnitude。DACからの信号はCICの遅延が含まれている。IFは5パルスをコヒーレント積分している(5パルス毎にDACの波形が更新される)。ブレッドボードで組んで長いジャンパを何本も飛ばしているからか、商用電源の50Hzが見えている。ローカル+CICで狭帯域のBPF特性があるから50Hz程度はほとんど除去できるはずだけど(あとPRFが25Hzなのでコヒーレント積分すれば除去できるはず)。

 天井からの反射は多少の変動はあれど安定した強度を示している。一方で手に持った反射体では強度の変動が非常に大きい。コヒーレント積分しているので、ドップラ成分で強度が落ちたりしてるんだと思う。

 32bit複素数(整数)から16bitのMagnitudeへ変換するのに、Cのforとかで実装すると99サイクル/ポイントくらい。アセンブリで書くと43サイクル/ポイントくらい。倍以上早くなる。

 IFはローカルとかCICで結構大きな値になるので、Magnitudeの計算には適当なゲインで16bitに収まるようにしている。これは引数で受け取っているが、ARM ABIでは浮動小数点引数が1個の場合はs0で渡される。計算の途中(インラインアセンブラの上書きレジスタ)にs0, s1を使うと引数を一旦別のレジスタにコピーするので、関数の呼び出し1回毎にvmovが1回走る。気にするほどじゃないけど、気になるので、計算をs0,s1ではなくs1,s2を使うようにして、s0で渡される引数をコピーしないようにしてみると、明らかに遅くなる(43.24c/p→47.21c/p)。

 オブジェクトレベルで逆アセンブルするとレジスタの指定以外は全く同じバイナリになっている。ラベルの前にnopを入れたりすると実行時間が変わるので、命令(ループのジャンプ先)のアラインメントの関係なのかな? プログラムのチューニング面倒すぎ。。。


 STM32F3のHAL_TIM_Base_Stop、CCxが有効だと機能しないのが謎い。リファレンスマニュアルにはCENをクリアするにはCCERのCCxEが云々みたいな話は書いてないし、TIM3->CR1 &= ~TIM_CR1_CEN;みたいに書けばちゃんと止まるから、HAL側の都合だと思うんだけど。しかしなんでCCxEがセットされているとCENをクリアする処理をスキップする、みたいな実装になっているんだろう? HAL_TIM_PWM_StartをHAL_TIM_Base_Stopで止めないため、みたいなことなんだろうか。

 なんだかんだ、結局HAL系のライブラリを使うんでなく、構造体を直接書き換えるほうが楽じゃねーかといういつものやつ。

 CMSISのDSPライブラリの三角関数系の関数(arm_sin_cos_f32とか)、角度が1回転以上だと絶妙に変な動作になるのが結構不便。たぶん周波数領域で折り返して計算してるんだろうけど、math.hのsinfとかcosfとかとかなり違う結果になる。


 とりあえず、ブレッドボードレベルではSTM32F303K8ワンチップ(+いくつかの受動素子)で超音波距離計を作る目処はたった。あまり長距離は感度が得られないけど、5m程度なら問題ないはず。

2024年4月3日水曜日

小ネタ


 石川 輪島と珠洲 孤立に備えた衛星携帯電話など配備されず | NHK | 令和6年能登半島地震

 ひまわり10号あたりにアマチュア無線のトランスポンダとか積んでもらおーぜ。市1個に1箇所位の割合でアマチュア無線の機材を置いておいてさ、普段はアマチュア無線家に使ってもらったりして、起動すれば即使えるような状態で維持しておいて。非常時(災害発生時)は非常通信だから無線のライセンスを持ってなくても勝手に使っていいよってマニュアル化して。三菱電機のDS2000でもアマチュア無線のベントパイプ(トラポンはAMSATが作ったやつ)を乗せたやつもあるし。まあ、日本の衛星にアマチュアトランスポンダ積むよりスマホが衛星と直接通信するほうが早そうだが。

 本来こういう用途(災害時の行政の通信)はQZS-3が担当するはずだったんだろうけどな。


 そういえば、ひまわりって昔からベントパイプ(DCS/DCP、アップリンクUHF、ダウンリンクL帯、8号機以降はダウンリンクKa帯)を積んでるよな…… 昔は気象庁の拠点間での通信に使うような例もあったらしいけど(チャットみたいな感じで、津波の情報とかを拠点間で共有したいみたいな用途も考えていたらしい)。すでにベントパイプのペイロードを乗せてるんだから、そこに相乗りしてアマチュア用のV/UとかS/Sのトランスポンダを積む余地はありそうな気がするな。日本のお役所相手だからだいぶ面倒だろうけど。

 あと、ひまわりからもNOAA APTみたいに電波出してくれればいいのにな。GSD25kmくらいで、1枚5分くらいの送信速度で、ワンセグチューナーで受信しやすい周波数で。狭義の宇宙教育とかいろいろ使えて便利だと思うんだけど。


https://www.itu.int/en/ITU-R/space/workshops/2015-prague-small-sat/Presentations/Eshail-2.pdf

 Es'hail 2(三菱電機がカタール向けに製造したDS2000静止衛星)に搭載したAMSATのトランスポンダの概要。

 通信範囲、仰角5度あたりだと東はリオデジャネイロから西はバングラデシュあたりまで、北はノルウェー北端から南は昭和基地あたりまで、かなり広い範囲をカバーしている(そりゃ、静止軌道だからな)。

 昭和基地って衛星通信用の設備もいろいろ設置してあるはずだけど、EH2のトランスポンダ経由で通信したりとかってやってるんだろうか? HFの機材はあるだろうけど、S/X帯のアマチュア機材なんて南極にあるのかなぁ……

 昭和基地とノルウェーでシングルホップで通信できれば1.5万kmくらいになる。東西基線でも同じような距離で通信できるけど。アマチュア無線はHFなら2万kmくらい届くだろうし、EMEでも同じような距離が飛ぶから、静止衛星のトランスポンダで長距離交信はあんまり面白みなさそうな気もする。とはいえ、HFみたいに気象条件に左右されたりEMEみたいに極めて微弱な通信と違って、比較的簡単な設備で1万kmのような距離を通信できるのは面白そうだけど。X帯を受信しなきゃいけないのが大変だけど、HFみたいに巨大なアンテナが必要なわけでもないし、LEO付近のアマチュア衛星と違ってトラッキングする必要もないし、トータルで見たらわりあい使いやすいのかな? カバレッジの端(低仰角)だと開口ゲインが低いから大きなアンテナが必要だけど、それでも1m位あればいいらしいし。直径1mのディッシュアンテナ1個で1.5万kmの通信ができるのは面白そう。


 QO-100 / Es'hail-2 Narrowband WebSDR

 Es'hail 2で中継しているアマチュアバンドをオンラインで聞けるページ。

 おそらくサーバー側で復調してAFをストリーミングしているので、周波数の調整とかは一瞬ディレイがあるから微妙に使いづらい。あと、CWの帯域幅がデフォルトだと狭いので、2人が微妙にずれた周波数で会話していると片方しか聞こえない(フィルタ幅を広げる必要がある)。


 国際宇宙ステーション内の自律移動型船内カメラにIMUが採用:組み込み採用事例 - MONOist

 記事のタイトルもうちょっとどうにかならんのか……

 Int-Ball 2にエプソンのIMUモジュールが採用されたよ。

 Int-Ball初号機ではInvenSenseかどっかの6軸慣性センサを6個乗せて、フィルタで単体の慣性センサに比べて高い精度を得ていたけど、2号機ではIMUモジュールを1個だけ積んでるのかな? 初号機と2号機ではセンサ(積分、非積分)の構成が変わっているはずなので、そのあたりで積分型センサへの依存度が減ってるんであろう。

 しっかし、2号機の通風孔の数よ…… まるで頭蓋骨みたいな雰囲気がある。僕としては初号機のツルンとした見た目のほうが好きだなー。CGのエッジを強調したレンダリングだからそういうふうに見えるだけという可能性もあるけど。


 Amazon.co.jp: 十五光年より遠くない (ガガガ文庫) 電子書籍: 新馬場新, あんよ: Kindleストア

 こういうジャンルのラノベってあんまりないよねーという点で今後に期待して星4くらいの評価。航空宇宙のフレーバーを添えて、位の感じ。最初から航空・宇宙分野のラノベを期待して読むと期待外れだと思う。


 色々なゲームが有る昨今、airport driving simulatorみたいなコンセプトのゲームってないのかな。プッシュバックとか、コンテナドーリーとか、除氷とか、空港以外だとあんまり見かけないような車両が色々あるし。飛行機とかに接近しすぎると減点とか、緊急車両(化学消防車とか)ならイベント(火災とか)発生後経過時間で評価が悪化するとか、いろいろな遊び方のモードが作れそう。あるいは軍民両用空港ならbomb lift truckで戦闘機や爆撃機に弾薬を搭載したりとか、緑地に寄りつく鳥に散弾銃を撃ったり、侵入してきたドローンをジャミングして撃退するとか、ランボルギーニで滑走路を疾走するミニゲームとかもできるし。だいぶいろいろな遊び方ができそう。基本的には飛行機のジェット音やATC無線を聞き流しながらゆっくり安全運転に励む。だいぶ時間泥棒なゲームになりそう。


 STM32F303K8のPA6、OPAMP2VOUTとDAC2OUT1とADC2IN3の3個が割り当てられるんだけど、STM32CubeMXだと全部有効にできる。OPAMP2VOUTとADC2IN3を同時にできるのは便利だし(G4なら内部で接続できるから、それに比べれば不便だけど)、DAC2OUT1とADC2IN3を接続できるのは使い道思いつかないけど特に不便ではないけど、OPAMP2VOUTとDAC2OUT1を同時に有効化できるのは謎い。OPAMPとDACを同時に有効化したらどうなるんだろうか。

 STM32CubeMX、デジタルペリフェラルとアナログペリフェラルを同時に有効化できないのが地味に不便なんだよなー。出力インピーダンス1kΩくらいのアナログ信号源をアナログペリフェラルで読みつつ、必要に応じてデジタルペリフェラルのオープンドレインでGNDに引っ張るみ、たいな機能が作れない(自分でGPIOを初期化する必要がある)。


 STM32のDMA、1回のDMA転送で複数回の転送を行ったり、アドレスを2段階で持てるような機能があれば便利なんだけどな。1) 配列(src)からアドレスを読み取る、2) アドレスから値を読み取る、3) 配列(dst)からアドレスを読み取る、4) 2で読み込んだ値をアドレスへ書き込む、みたいな感じで。

 TIMには似たような機能(DMAバーストモード)があって、1回のトリガ(例えば更新フラグ)によって複数の連続するレジスタ(例えばARRからCCR4までの5本)に対して転送を行うみたいな機能があるんだけど、あくまでもTIMの連続するレジスタに対してしか使用できない。


 Cortexのプログラムの最適化、いかんせんレジスタが13本しかないのが厳しい。たまにCell(プレステ3に乗ったりしたやつ)の128ビット幅128本とか馬鹿みたいにレジスタが大量に乗ってるのが羨ましくなる。


 スパコンの最適化、ぐぐってみると、富岳がチューニングメンドクセ、みたいな感じで評価は良くない意見があるらしい。レイテンシが悪いとか、レジスタが少ないとか。汎用CPUだから既存のコードをコンパイルすればそのまま走るのが利点だけど、実行効率は京やx86系に比べて桁違いに悪い、みたいな。しっかりチューニングしてやれば早くなるんだろうけど、それだと既存のコードが動くという利点が活かせないし、みたいなところか。

 京や富岳はアクセラレータを使わず汎用CPUで計算を行っているけど、この方向性が正しいのか検証する必要がある、みたいな意見もあるらしい(というか最近のスパコンでアクセラレータなしの構成は富岳だけだから、方向性が誤っているのではないか、みたいな見方も)。

 ARMベースのA64FX(の発展)だと使えるレジスタが少ないのはどうにもならない気がするな。次世代で方向性を変えた場合、ARM以外の命令セットを使えば富岳に最適化したコードの実行効率が悪くなるし、アクセラレータを積んだら実行効率以前の話(大部分書き直し)だし。

 

https://www.jstage.jst.go.jp/article/bplus/5/4/5_328/_pdf/-char/ja

 プレステ2のEmotion Engineの開発とかの話とか。


https://archive.xsig.ipsj.or.jp/history/SACSIS/2008/cell/outputs/doc/jiyu_1.pdf

 Cell/B.E.を多体問題に適用した例。利点はなんといっても安価な点(システムでGRAPE-7より1桁低い)。一方で演算精度(倍精度が遅い、単精度が切り捨てなので誤差が出る)とか、PS3以外のシステムの入手性とか、開発環境とか、いろいろデメリットも。後続機で改善されれば使いやすくなるよね、という感じ。

 PS3のCell/B.E.でヘテロジニアスマルチコアの有効性を示したおかげでCPU/GPU構成が一気に普及してPS4では普通のCPU/GPU構成になってしまったからな。Cell/B.E.で「パフォーマンスが良ければ新規アーキテクチャでも受け入れられる」とか言ってたのに、結局は既存アーキテクチャが性能向上したおかげで……


STM32F303K8でピークホールド&時間決定回路

 STM32F303K8にはアナログ系の機能がいくつか乗っているので、それを使用してピークホールド回路を作ってみた。


 まず、テスト用の信号として乱雑な波形を作成する。Xorshiftで乱数を生成し、CICでインターポレーション(R16, N6, LPF特性)を行い、DACから1kspsで出力。

 とりあえず狙い通りに動いている感じ。

 R16, N6のインターポレーションでゲインが2^20だから、12bitの乱数を突っ込んでやれば32bit変数で計算できる。適当に右シフトしてDACへ出力。ある程度最適化したCコードを書いてやれば2048ptsの波形の生成に753us(@72MHz)くらい。1サンプルあたり26.5サイクルで処理できる。

 実数だけのCICはレジスタの使用量が半分で済むからARMの少ないレジスタでも最適化しやすい。/* 複素数でも結局は実部・虚部それぞれで和差を取るだけだから、複素CICフィルタでも実部・虚部に分けて処理すれば早くなりそう。メモリアクセスでペナルティありそうだけど、どうせレジスタに乗り切らないならレジスタをメモリに退避させなきゃいけないんだし */


 手始めに、コンパレータ、ダイオード(1N4148)、コンデンサ(0.1uF)でピークホールド

 電圧落ちるのが結構早い。プローブを2本あてると2倍近い速さで落ちるから、プローブ(10MΩ)で放電してるんだろう。定抵抗負荷でコンデンサの放電時間を計算してみると0.09秒くらいだから、抵抗とかコンデンサの特性を合わせれば十分な精度で一致していると言える。10MΩって数字だけ見るとかなり巨大な抵抗値だけど、サブ秒オーダーで見るとだいぶ影響力があるな。


 ダイオードを2本直列に使って、中間点をオペアンプ(フォロア)でドライブ

 全く電圧が落ちてこない。DC付近で簡易的とはいえ、パッシブプローブとアクティブプローブの差を実感できる。ただ、ダイオードを直列で2本使っているから、VDD近くまで引っ張れない。

 ダイオード2本直列で中間点をオペアンプで駆動するのは、漏れ電流対策らしい。コンパレータはHigh/Lowの2値だから、Lowに引っ張っていると電圧差が大きく漏れ電流が発生する。フォロアで中間点を引っ張っておけば、2本目のダイオードは電圧差がほぼゼロになるから、漏れ電流を防げる、というような理論らしい。実際の効果はよくわからないけど。


 タイマのPWMでピークホールドのリセット

 ODで引っ張っている。あと、別のチャンネルでコンパレータのブランキングも出している(コンパレータからのHigh出力をLowに引っ張るのを防ぐため)。


 タイマからADCをトリガして、結果をDAC(テスト信号用とは別)へ転送

 紫がフォロアの出力、黄色がDACの出力。リセット直前にサンプリングしてDACへ転送しているので、1周期(100ms)分遅れる。


 コンパレータの出力をタイマのカウンタリセットに使用して、ピーク時からの経過時間を計測

 アナログ波形はオシロから取り込んでいる。

 コンパレータとタイマの外部入力を直結できないので、GPIO経由で接続する必要がある。ADCのトリガとタイマカウンタの読み出しがずれるとジッタになるので、ADCと同時にDMAをトリガして、カウンタをRAMに読み出している。

 飽和するとコンパレータがHighで固定されるので、ピーク値のタイミングがズレる(ピーク値の値も正しくない)。今回の回路の場合、正しく計測できるのは2.3Vあたりまでかな。

 似たようなことは、例えばコンパレータの出力でコンデンサを充電し抵抗で放電して、電圧を測ることで経過時間を推定するみたいなアナログ回路も考えられるけど、この場合はアナログ素子の特性(個体差や温度特性)に影響を受けるので、あまり正確な計測はできない。タイマを使えばマイコンのクロックの精度で時刻を計測できる。今回は32bitのカウンタを72MHzで走らせているので、時間分解能約14nsで最大59秒くらいまで計測できる。時間の計測はデジタルだけど、ピーク値の保持はアナログ回路だから、あまりサンプリング頻度が低くても精度が劣化するだけだし、最大でも32秒に1回とかで使えば良い。ピークの高さにはあまり関心がなくて、ピークの位置だけしっかり測りたい(しかしピークの高さも一応ほしい)みたいな用途には良さそう。必要な時間分解能でADCで計測して最大値の位置を探す、みたいな総当たりで処理するより、ピークの高さの計測精度は若干劣るとはいえ、ものすごく少ない計算リソースで計測できる(ハードウェアリソースは若干必要だけど)。

 ただ、全体のタイミングの管理を16bitタイマで行っているので、ブランキング期間の分解能があまり良くない。例えばプリスケーラを36000に設定すると最大で32.768秒間隔でサンプリングできるけど、この場合はブランキング幅が1.8ms以上になる。この間に細いパルスが入っても検出できない。


 乱数波形でなく、Sincでテスト

 帯域幅2.5kHzのSincだと、1発目では最大値まで上がりきらない。


 750Hzでもまだ上がりきらない。かなり遅い信号じゃないとホールドしてくれない。


 ダイオード2本分の電圧降下かと思って、試しに2.5kHz幅を下側にオフセット

 やっぱり1発では上がりきらないから、帯域幅の問題だろう。コンデンサの誘電体吸収みたいな効果かな?


 ピンアサイン

 PA0とPA4からPB1までの7本を使っている(PA5はテスト信号生成用)。

 未使用ピンで2x UART、I2C、SPI、CANが使用できる。あとPA1のADCやPA5のDACも使用可能。UARTでGPSモジュールを接続したり、I2Cで他のセンサを接続したり、SPIでMMCにデータを保存したり、DACで副変調波を出して無線機でデータを飛ばしたり、いろいろできる。計算リソースはCortex-M4F@72MHzが丸ごと使えるから、結構複雑なこともできる。もっとも、RAMが16kBしかないから、あまりに複雑な処理(大規模な相関処理とか)は厳しいけど。


 回路図

 テスト信号をTIM7, DAC, DMAで生成している。コンパレータ4からダイオード2本を経由してコンデンサを充電してピークホールド、オペアンプ2でダイオードの漏れ電流を対策しつつインピーダンスを下げてからADCへ。GPIOのNchでリセットを行っている。ADCのトリガ、コンデンサのリセット、リセット中のコンパレータのブランキングはTIM3で管理している。それと、コンパレータでTIM2をクリアして、TIM3からDMAを蹴って、ADCサンプリング時のピークからの経過時間も計測している。


 ある程度作り込んだところで、不注意でソースコードを全部消してしまった。久々にやらかした。。。

1) STM32CubeMXは新しいプロジェクトを作るとそのディレクトリにある全部のファイルを削除(ゴミ箱でなく、完全に削除)するから気をつけよう。

2) 確認ダイアログはちゃんと読もう(← !!!超重要!!!)。

 コードはgitで管理してるから、とか油断してるとgitリポジトリ事まるごと削除されて詰む。


 ということで、折角の機会なので、COMP4で作っていたピークホールドをCOMP2で作り変えてみた。COMP2を使うとタイミング管理にTIM2(32bitカウンタ)を使えるから、リセットパルスを狭く設定できる。ただしピーク値の時間分解能がだいぶ悪くなる。


 ピンアサイン

 必要なGPIOが1本増える(リセットのピンが共用できない)。あとUART2が使えなくなる。それ以外はあまり違いはない。タンパーピンが使えるようになるから、改造されると困るような用途に使えるようになる。


 回路図

 ADCトリガ、ブランク、リセットに対して個別にパルスを出すから、タイミング管理の自由度が高い。


 COMP2とCOMP4、どっちを使っても機能的には大差ない。16bitのタイマと32bitのタイマの使い分けの違いでしかない。時刻決定の精度が欲しいならCOMP4、ブランク期間(パルスを検出できない)を狭くしたいならCOMP2、という感じ。ソフトやハードが変わるから、どちらを重視するか(どっちのコンパレータを使うか)はあらかじめ決めておく必要がある。


 ということで、STM32F303K8のワンチップで、ピークホールド回路、ピーク値の計測、ピークの時刻決定(ピーク間隔の計測とか)、といったことができるのは確認できた。外部に能動素子は不要で、ダイオード2本、コンデンサ1個、抵抗1個、くらいの受動素子で構成できる(時刻精度が必要なら外部クロックも必要)。あと、もちろん電源周りにいくつかの受動素子と、少なくとも3端子レギュレータ程度は必要だけど。

 ソフトウェア的にはほとんど無負荷(ADCと時刻の読み出しだけ)だから、並行して重い処理も走らせられる。重い処理が不要ならコアは大部分の時間をスリープに入れられるけど、とはいえCortexってただでさえ消費電力が低いから、スリープに入れてもあんまり消費電力下がらないんだよな。タイマがあるからクロックを止められなくて、そこでだいぶ消費電力が大きい。時間分解能を多少犠牲にしていいならコアクロックを下げてだいぶ省電力になるけど。まあ、数十秒周期で1発のくらいのイベントを想定しているし、時間差で入射方向を決定したいみたいなことをやらない限りは、時間分解能はあんまり必要ないだろうし。ただ、GPIOの消費量がかなり多いので、外部接続が必要な用途にはちょっと厳しい。せいぜいGPSで位置や時刻を得て外付けストレージにCSVファイルを保存する、くらいかな。外付けストレージと言っても、STM32F303K8はUSB Host非対応だけど。SPIが1本使えるから、それでゴニョゴニョ……


 今回は、ピーク値の時刻はプログラムが起動してからの経過時間で計測しているけど、別の信号源(e.g. GPS PPS)でも同様に経過時間を計測して、そこからピーク値の絶対時刻を決める、みたいなこともできるはず。PPSで正秒を決めて、それ以上の曖昧さはUARTからの信号で解決するとか。

 ただ、STM32F303K8には32bitタイマが1本しか乗っていないので、精密な時間管理をやろうとするとこれがネックになる。16bitタイマでPPSを計測すると20usくらいの時間分解能になるから、PPSに比べて3-4桁悪くなる。