« 2025年4月 | トップページ | 2025年6月 »

2025年5月

2025年5月27日 (火)

DDS IC「AD9833」の出力にバッファアンプを

2025年5月25日:DDS IC「AD9833」をArduino UNO R3で制御 
この続き。
便利そうなツールになりそうなのでケース(百均の)に
入れるつもりですが、作業はまだ。

AD9833の出力レベルが小さいので、もうちょい大きくして
みました。

定格だと、Vout(max)が0.65V。
正弦波や三角波だとGNDからちょっと上がったところ
から波形が始まり、ピークが約0.6Vちょい。
P-P値で0.6Vほど。
RF用途では、このままで良いかもしれませんが、
正確で安定した周波数を出せるんで、低周波発振器としても
役立ちそうです。

そこで、現状の
・0.6V(P-P)を6倍ちょいして0~4Vの振幅に。
・マイナス電源を用意して
  0~+4V、-2V~+2V、-4V~0V
 くらいの範囲で出力電圧をオフセットできるように。
   0Vを中心に4V(P-P)の波形を上下。
・オフセット電圧の調整はボリュームで。
・1MHzを越える周波数はちょっと置いておいて。
・低周波用に直流結合で。

こんな回路を付加してみました。
Ad98_01
手持ちの Rail to Rail In/Outのオペアンプで
使えそうなのが(帯域が欲しいゾ)AD823あたり。
  とりあえず、様子見で
出力波形を切り替えて方形波にしても、ドカンと大レベル
のが出ちゃうということがなくなります。
  正弦波や三角波だと0.6Vですが、方形波にすると
  電源電圧いっぱいの信号になります。
  4V(p-p)になるようにしてるのが、5Vで頭が
  制限されるので、信号が大きくなってびっくり
  することがありません。

帯域があって使いやすそうで安価なアンプ、
このあたりかな。
・OPA810 FET入力 70MHz 1コ入り
・OPA863 バイポーラ入力 110MHz 1コ入り
     OPA2863が2コ入り
     入力バイアス電流が大(0.3uA)
何かのついでに買ってみます。

| | コメント (0)

2025年5月25日 (日)

DDS IC「AD9833」をArduino UNO R3で制御

備忘録としてアップしておきます。
2025年5月21日:Arduino UNO R4 minima 電源供給方法でクロックが変わる#4 
この実験で使った「1MHz近傍周波数発振回路」です。

Arduino UNO R4 minima、あるいはRA4M1コアボードから
出力させた1MHzを、このDDS回路で出力した1MHzをmix
してビート音を出しました。
Ad9833_01
DDS IC AD9833は、モジュールじゃなく単体の石を
買ってありました。
25MHzの水晶もあったのですが、あえてATmega328P
から16MHzのクロックを出すようにして横取りしました。
  全体の消費電流は25mAくらい

出力はフィルタやアンプを入れずにそのままです。
  高速オペアンプを買ってあれこれ試して
  みたいところです。
最低周波数が1Hz。 最小桁が0.1Hz。
最高周波数は5MHzあたり。

周波数をスイープする機能を入れてありますんで、
何かの実験で役立つかもしれません。

・制御スケッチ
  ・ダウンロード - ad9833_01.zip

※スケッチ追加修正してます
・sweep時のトリガ用(オシロでの観察)として
 Rise時、PD4をHにしています。
 Hの↑エッジで周波数 A->Bのスイープが
 始まります。
 ↓エッジがWait-Hのタイミングになります。

ABCラジオ(AM 1008kHz)にビートをかけて
遊んでいるところ。 (ラジオを横に置いて)
Aa11_20250525180601

液晶アクセスの「TWI」、AD9833アクセスの「SPI」。
ともにライブラリは使わずATmega328PのI/Oレジスタを
直接操作しています。

ATmega328Pの「SPI」なんて、ほんとに簡単。
  (出力制御の場合)
I/Oポートを操作してる感覚で制御できますんで、
ライブラリなんて要りません。
要るのはATmega328Pのハードウェアマニュアル。


※関連
2024年10月6日:おっと。map関数の計算桁に注意

| | コメント (0)

2025年5月23日 (金)

DDS IC「AD9833」の周波数レジスタ書き込みで

Arduino UNO R4 minimaの1MHz波ビート音実験で
急ぎでっちあげたアナデバのDDS IC「AD9833」。

Arduino UNOで制御する時にちょいと気になる
ことがありました。
  ・・・たいしたことじゃないけど
AD9833の周波数レジスタは28bitで、LSBとMSBに
分けて2回、14bitで書き込みを行います。

こんな感じ。

AD9833ctrl(0x2000);     // B28 on コントロール
spi16(0x4000 | (d & 0x3FFF));     // ch0 LSB 14bit
spi16(0x4000 | ((d >> 14) & 0x3FFF)); //   MSB 14bit

「d」が32bit(つまり4バイト)の書き込みデータで、
最初に「これから2回のデータを書くで」っという
制御コード(B28 on)を送ってから、LSB、MSBの順に
14bitのデータをSPIで書き込みます。

このタイミングをオシロで見たら、SPIの間隔がずいぶん
空いていたのです。
  16bitのSPI転送は5μsほどなのに、
  LSBとMSBのあいだが9μsほどに
  広がっていました。

32bit値を右に14bitシフトする「(d >> 14)」に、
いがいと時間がかかります。

このようにコードが展開されてました。

bae:  ldi  r17, 0x0E ;14
bb0:  lsr  r7
bb2:  ror  r6
bb4:  ror  r5
bb6:  ror  r4
bb8:  dec  r17
bba:  brne .-12   ;0xbb0
bbc:  ldi  r24, 0x3F ;上位3Fでマスク
bbe:  and  r5, r24
bc0:  movw r24, r4  ;R5,R4をR25,R24に
            ;コピーしてspi16()へ

ここで時間がかかっているのが
32bitデータを保持しているR7,R6,R5,R4レジスタの
14回のシフト。
シフト命令もDEC命令も1クロック。
loop中のBRNEが2クロック。
7クロックが14回で98クロックを要します。

そこで、ちょっとでもスピードアップということで、
14bitのシフト方法を変えてみました。

uint16_t a;          // 2バイトの一時レジスタ
  AD98ctrl(0x2000);       // B28 on コントロール
  spi16(0x4000 | (d & 0x3FFF)); // ch0 LSB 14bit
  d = d << 2;          // d >> 14のかわり
  a = d >> 16;         // シフト2回とレジスタ交換に
  spi16(0x4000 | (a & 0x3FFF)); // MSB 14bit


これだと、このように展開されて、シフト回数が2に
なり、ちょいとだけ高速化できます。

bae:  ldi  r17, 0x02  ; 2
bb0:  add  r4, r4
bb2:  adc  r5, r5
bb4:  adc  r6, r6
bb6:  adc  r7, r7
bb8:  dec  r17
bba:  brne .-12     ; 0xbb0
bbc:  movw r24, r6
bbe:  andi r25, 0x3F

さらに「d = d << 2;」という2bitのシフトを、
「d <<= 1; d <<= 1;」と2つに分割してたら
 ldi r17,1
 dec r17
 brne  .-12 が無くなるかと
期待したのですが、同じコードに展開されました。
  brneを使う方が1命令少なくなります。

オシロで見るとこんな波形。
A01_20250523114301
上段の(d >>14 )のところ、なぜか広いので
「これはなんだろか?」っと思いませんか?

気になってコードを見たら、14回のループに
時間がかかっていたというお話しでした。



※関連
2025年5月21日:Arduino UNO R4 minima 電源供給方法でクロックが変わる#4

| | コメント (0)

2025年5月21日 (水)

Arduino UNO R4 minima 電源供給方法でクロックが変わる#4

周波数が変わるという問題ともう一つがクロックのジッタ。
 ・2025年5月4日:RA4M1コアボードでPLLメインクロックを試す 
この続き。
「ラジオ」でビート音を聞くのじゃなく、オシロで安定した
波形が見られないか、手持ちの部品で試してみました。
  ラジオだと、机に置く場所でビートの状態が変わって
  しまうんで。

まず必要なのが、ビートをかけるため1MHz前後を安定して
発振できる発振器。
  5月4日の実験はAMワイヤレスマイクを使ったんで
  周波数合わせと安定度が微妙。

そこで、昔々に「そのうち作ろうぜ」っと買ってあった
アナデバのDDS IC「AD9833」を引っ張り出してきました。
  クロック源の25MHz水晶も買ってありました。
とりあえず、Arduino UNO R3(のチップで)で、これを
使ったDDS発振回路をでっち上げ。
A16_20250521114701
  今は安価で売られている発振回路も載った
  モジュールじゃなく、チップ単体で買って
  そのままになってたのです。
  クロック用25MHzも発振器じゃなく、HC-49USの
  水晶発振子を用意してました。
    クロック発振回路も自分で作ればエエやん
    という考えで。
  いつから部品箱にあったのか・・・
  何年か越しで、やっと役立つ日がやってきました。

ロータリーエンコーダで周波数を可変します。
専用発振器を外付けせず、ATmega328Pから8MHzの方形波
を出力してAD9833のクロックとしました。
  クロック周波数が低いので、発生周波数の
  分解能が0.0298Hzになります。

もう一つが、UNO R4 minima(とRA4M1コアボード)が出力
する1MHz波形と外置き発振器の信号をmixしてビート音
を出す回路。
  高周波用パーツの手持ちはあんましありません。
  電源不要のDBMがあれば話が早そうなんですが。
部品箱を探すと、MC1594(有名なMC1494の高精度版)とTIの
SN16913」を発掘できました。
A11_20250521114801
ここはお手軽なSN16913でプロダクト検波でしょう。
こんな回路で1MHz波をmixします。

A13_20250521114801

小さなユニバーサル基板の切れ端にICとボリュームを乗せ、
クリップで信号接続。
  ※手抜きです
A14_20250521120401

このデータブックに、等価回路などが出てました。
A12_20250521114801

RA4M1コアボードからの1MHz方形波とAD9833の出力を混ぜ、
  ・USB接続した時
  ・USBコネクタを抜いて外部電源にした時
  ・水晶発振子・PLLをオンした時
低周波ビート音としてどんな波形が出てくるか、確かめます。

実験中の様子。
A15_20250521115001

ラジオはモニター用。
ラジオのダイヤルを1000kHzにして机上を飛ぶ
2波の1MHz電波(500Hzくらいのビート音)を聞い
ています。

さてその結果です。
Aa11_20250521115001

USB接続や外部電源時に生じる「グジュグジュ」音の
要因である内蔵クロックのジッタ。
「これ、使いたくないなぁ」というのが波形として
見えたかと。

RA4M1コアボード用(メインクロック用水晶発振子が
乗っている)のテストプログラム。
  ・ダウンロード - 16mhz_pll03.txt
    (.inoではなくテキストで)
UNO R4 minimaでもPLL on以外は動きます。

グジュグジュ音を聞くだけならプロダクト検波回路はいりません。
AMラジオ+可変周波数発振器(安定な)でOK。


※関連:ラジオペンチ・ブログ
Arduino UNO R4 のクロック周波数精度とジッタを測定
Arduino UNO R4 のCPUクロックの品質をデジタルオシロで詳しく調査


| | コメント (2)

2025年5月19日 (月)

発掘:Z80 CPU・・・いりませんか?

お片付けしていたら「Z80 CPU」(何種類か)と
「Z80 PIO」「Z80 CTC」が出てきました。
どなたか・・・いりますか?
Zz80

全部まとめてクリックポストでお送りしますんで、到着後、
送料(185円)+お駄賃を「ビール券」にして送って下さい。
  ※お駄賃はお気持ちで

匿名でかまいませんのでメールアドレスを記して
この記事にコメントしてください。
  一週間ほど待って抽選かな。

※その後、「64180」を4コ発掘。
Zz81
これらも追加。

| | コメント (1)

2025年5月16日 (金)

Arduino UNO R3で周波数を計る

UNO R3での周波数計測回路、過去、あれこれ作ってきました。
その応用で、トランジスタ技術2025年6月号
VCO回路V-f特性の自動スイープ測定器」というタイトルで、
VCOの制御電圧を変えながら出てくる周波数を計るという
回路を載せてもらいました。

これの発端が、
2019年12月20日:Arduino UNOで周波数カウンタ
2021年5月1日:Arduino UNOで周波数カウンタ:アナデバの電力計用ICのために

今回のトラ技記事でも、タイマー1(16bit)のインプットキャプチャ
機能で周波数カウント用のゲートを作っています。
しかし、そのキャプチャ周期を1msとして、前回値との差分で
出したカウント値を積み重ねて、周波数としています。
 10ms(100Hz)ゲートなら1msを10回。
 0.5秒(2Hz)ゲートなら1msを500回。
ゲート時間の基本単位が1msで、好きな周期で周波数が
得られます。
  ※低周波なら周期計測のほうが良いのですが
   それはまた別問題。
アナデバの電力計では、ハードウェアで1秒のゲートパルス
を作りましたが、今回のは1ms=1kHzというATmega328Pでも
出しやすい周波数です。
   タイマー1個で作れる
無符号で加算すれば、タイマーカウンタのオーバーフローを
無視して積算することができます。
こんな具合です。
Aa11_20250516091701
これで、1ms=1kHzのゲート時間を作っておけば、その整数倍で
いくらでも好きなカウント時間に拡張できます。

インプットキャプチャで得られた総パルスから周波数を
求められるので、0.1秒(10Hz)周期で得たカウント値を
  この場合は10Hzが最小桁
10回の移動平均しながら処理すれば、1秒ゲートと同じ
最小桁1Hzの周波数が0.1秒ごとにえられます。
周波数の変化を見るとき、1秒待たなくても0.1秒ごとに
動きが分かります。
  電力計では1秒のを10回移動平均して、
  0.1Hzを読んでます。

| | コメント (0)

2025年5月15日 (木)

Arduino UNO R4 minima 電源供給方法でクロックが変わる#3

2025年5月9日:Arduino UNO R4 minima 電源供給方法でクロックが変わる#2 
この続き。

UNO R4の内蔵クロック、とりあえず判明していることは
 ・USBでPCとつないだときはクロック精度が上がる。
    水晶発振並みに
 ・USBを外して外部電源にした時はクロック精度が落ちて
  しまう。
 ・外部電源のときは「HOCOUTCR」トリミングレジスタで
  周波数を調整できる。
 ・でも、USBにつないだ状態でHOCOUTCRを触ったら、
  なんかおかしい。
この他、ジッタ(周波数の微少変動)の問題もあります。

気になるのは、USB接続時のHOCOUTCR操作。
これがどんなものか、テストプログラムを書いてみました。

 ・D4ポートに内蔵クロックを分周して作った1MHzの方形波を出力。
  この周波数をチェックして内蔵クロックの変化を見る。

 ・D3ポートは32ビットのGPT1タイマーのクロック入力に。
  ここにD4ポートが出す1MHzパルスを入れる。

 ・D2ポートをGPT1タイマーのキャプチャ入力に。
  外部から(正確な)1Hzのパルスを入力。
  その↓エッジでカウント値をラッチ。
  1秒周期なのでHz単位でカウント値が読める。

 ・D8ポートはキャプチャのチェックに使える1Hzパルス。
  でもHOCOUTCRを操作して周波数を変えると、この
  パルスの周波数も変わってしまう。
  1MHzパルスと同じ比で変化するので、D8→D2とつな
  ぐと、HOCOUTCRが変わってもいつも1000000Hzジャスト
  のカウント値が得られる。

UNO R4 minimaとの接続はこんな具合。
H11_20250515151201
USBコネクタを外しても通信できるよう、D0ポートの
TXDでデータを出力しています。
  SrealではなくSerial1で。

・制御スケッチ(ファイルタイプをtxtにしています)
   ・ダウンロード - hoco_02.txt

HOCOUTCRを-10~+10まで変化させた時の1MHz周波数を
順次シリアルデータとして出力します。

・外付け電源のときのデータ。
   ・ダウンロード - aux01.txt

・USB接続でのデータ。
   ・ダウンロード - usb01.txt

それをグラフにすると

・外付け電源のとき
Cap004_20250515151601

まっとうに変化しました。
それが、USB接続ではもうはちゃめちゃに。
Cap006_20250515151701
ほぼ1MHzなんですが、ところどころで、タイミングか
なにかは不明ですが、とんでもない周波数が出ています。

これを見ての評価。
  USB接続のときにHOCOUTCRを触ると、クロック周波数が
  とんでもない値になることがある。

内蔵クロックを分周して作った1MHz、USB接続では
1MHzになるよう合わせ込みをしているようです。
しかし、HOCOUTCRをユーザーが変更すると、競合して
しまうようです。

HOCOUTCRの値は、書いたものがそのまま読み出されま
したので、USBでの周波数合わせではこれは触っていない
ようです。

ということで、
 ・HOCOUTCRを触ってメインクロック周波数を
  変えてはダメ。
 ・クロック周波数の精度がいるのなら水晶発振子を
  使うように。

が結論でしょうか。


ちなみに、1Hz信号発生回路はこんなの。
1hz_osc

「ダイソーのミニケース」 に組んでます。
Osc1hz

8ピンの小マイコンを使うとか、リアルタイムクロックICを
使うとか、あれこれ考えられますが、プログラムを組まなくて
も1Hzが得られる4060Bを使いました。
これの欠点。4060Bひとつだと出てくるのは2Hz。
もう1/2したいわけですが、それに何を使うか。

フリップフロップ4013や4027で1/2するのも手ですが、
ワンゲートロジックに「74LVC1G80」という5本足の
「D type FF」があるんで、これで1/2が作れます。
  電源とGND。
  クロック入力(立ち上がり)とD入力。
  そして/Q(反転)出力。
反転出力というのが面白い。
何かのついでに買っておきますわ。

| | コメント (0)

2025年5月 9日 (金)

Arduino UNO R4 minima 電源供給方法でクロックが変わる#2

2025年5月5日:Arduino UNO R4互換:RA4M1コアボードのクロック 
この続きです。

UNO R4(互換機)、初めての通電がこれ。
2025年5月2日:Arduino UNO R4互換品:RA4M1コアボード

D5ピンに1MHzの方形波を出してあれこれしてて、ムムムっと
なったのです。
   これはまだPLLを試す前

結局、Arduino UNO R4 minimaの純正品を買っちゃいました。
  純正品には水晶発振子は付いていません。
A012

内蔵クロックの話、純正品でも同じでした。

 ・USBで通信+電源供給したら周波数精度が良。
   ジッターはあるけど、水晶発振と見間違えるくらい。
 ・USBを外し、外部電源で動かすと周波数が0.2%ほど下がる。

こんな不可思議現象が起こったのです。

この電源供給の方法、新たにこんなことを試してみました。

(1)USBはつながず外部電源で運転開始。
   リセット起動で、周波数は下がったまま。

(2)外部電源につないだままUSBコネクタ(PCからの)を挿す。
   すると、周波数精度良に。
   D8のloopパルスがずっと見えているので
   リセットはかかっていない。

(3)外部電源につないだままUSBコネクタを抜く。
   すると、周波数が下がる。
   リセットはかかっていない。

ブートローダーが走るのは(1)のときだけ。
(2)と(3)でリセットがかかっていないということは、
この発振周波数変化の原因、
  ブートローダーが何かをしているのか?
は、除外できるでしょう。

そして、マイコンに入っているUSBの信号をオシロで見れるよう
にしてみました。
USB+とUSB-、それにloopパルスと+5V電源を見ます。
USBのケーブルをつなぐタイミングでこんな波形が得られました。
Aa000_20250509165401

USBケーブルをつなぐと、1ms間隔で何かし始めます。
そして30ms後に何かゴニョゴニョ。
その後50msほどは静かで、ふたたび1ms間隔の通信に
なります。
これがUSBケーブルをつないでいる間、続きます。

ゴニョゴニョ部を拡大すると、loopパルスが途切れて
いるのが見えました。
Aa001_20250509165501

割り込みで何かしているのだと推測できます。

USBの割り込み処理がどうなっているのかを追いかければ、
この周波数変化の原因と周波数精度アップの手法が見えて
くるかも・・・でっす。

しかし、(1)→(2)の変化はわかるんですが、(2)で安定した
のに(3)で元に戻ってしまうというのも、なんか不思議です。
1ms周期では割り込みはかかっていません。
(3)で抜いた瞬間のloopパルスを見れるようにかな。

※USBコネクタを抜いた瞬間
記録するにはトリガ源が難しい。
こんな波形が得られました。
Ra15
loopパルスが消えているということは、なんらかの
割り込み処理が行われたという判断になるでしょう。

しかし、ここでクロックを元に戻しているのかどうかは
判断できません。
どこで周波数が変わるのかを調べるのは、ちょいとハードルが
高い。
メインクロックを外に出して、微妙な周波数差を見つけな
ければなりません。
周波数差が大きければなんとかなるんですが。

「ブートローダーが何かをしているのか?
 は、除外できるでしょう。」
と記しましたが、USBの抜き差しを検出して何かの
処理をするよう仕掛けたのはブートローダーに
なるのか、それともUNO R4のsetup()を実行する前の
初期化ルーチンなのか。

| | コメント (9)

2025年5月 8日 (木)

スマートロードスターのスピードメータ修理

忘れたころに修理依頼があります。(これで6件目)
 ・2019年5月28日:修理:スピードメータが動かない
 ・2023年10月 5日:修理:スピードメータが動かない #2
ぱっと見、今回もプリント基板スルーホール部のマイグレーション。

Sm12
Sm13

Sm14
なかなかひどいです。
うまく修理できますかどうか・・・

・真ん中の写真を拡大
Sm15
パターンがつながったところに異常が出ています。
「銀スル」かどうかはどうやって判断すれば?

| | コメント (2)

2025年5月 7日 (水)

Arduino UNO R4備忘録

・システムタイマー
  「AGTタイマー0」で1ms割り込み。
    volatile uint32_t agt_time_msをカウントアップ。

・「agt_time_ms」がmillis()の元。

・micros()はこの値にAGTタイマーそのものの値を加味
  して経過時間を得ている

・delay()もこの値を使ってる。

・delayMicroseconds()はUNO R3と同じでソフトウェアタイマー。
   void delayMicroseconds(unsigned int us)
     UNO R3のように14bitという制限はなさそう。

・割込有効/禁止はこんな命令に
  #define interrupts()   __enable_irq()
  #define noInterrupts()  __disable_irq()

  そして、ARMマイコンの機械語では、

  __STATIC_FORCEINLINE void __enable_irq(void)
     __ASM volatile ("cpsie i" : : : "memory");

  __STATIC_FORCEINLINE void __disable_irq(void)
     __ASM volatile ("cpsid i" : : : "memory");

  「CPSIE I」で割込許可。
  「CPSID I」で割り込み禁止。

  ※Z80のように「EI」「DI」でエエやんっと思っちゃいます。
   長い文字、キライです。

・USBではなくD1端子にシリアル出力する「Serial1.print」。
 残念ながらバッファリング処理してない。
 文字出力が終わるまで、元ルーチンに戻ってこない。

 

※関連
Arduino UNO R4、GPTのレジスタ定義にミス発見

※参考
Arduinoの変数サイズをCPU毎に調べてみた:ラジオペンチblog

| | コメント (0)

2025年5月 6日 (火)

Arduino UNO R4互換:RA4M1コアボードで周波数カウンタ

32bitの汎用PWMタイマ「GPT1」を使って、
インプットキャプチャによる周波数カウンタを
試してみました。
  計測値の出力はシリアルで
  クロック入力 :D2 P105 GPT1A
  キャプチャ入力:D3 P104 GPT1B
  1Hzパルス出力 :D5 P102 GPT2B

D2がクロック入力で、ここに入れたパルスの↓エッジ
を32bitでカウントアップします。

D5の1Hzパルス出力をD3のキャプチャ入力とつないで、
この↓エッジでGPT1のカウント値をキャプチャします。
つまり物理的な1秒ゲートになるわけです。

キャプチャタイミング(1秒ごと)に、前回のキャプチャ値
との差を計算すれば、それが1秒間のパルス数で、
すなわち周波数となるわけです。

ここで問題。
内蔵クロック発振器か水晶発振(PLL)を使うかで
安定度が変わります。
  ※カウントの精度は別問題

カウントしたクロック源は
2025年1月28日:パルスジェネレータをI2C液晶で動かす 
これで8MHz(最大周波数)を出してます。

まず、内蔵クロック発振器(PLLなし)の場合。
  8000.143kHz 1秒ごとに周波数が出てきます
  8000.164kHz
  8000.155kHz
  8000.150kHz
  8000.165kHz
  8000.160kHz
  8000.150kHz
  8000.161kHz
  8000.162kHz
  8000.154kHz
これだけ変動します。
それが、PLLを働かせると、
  8000.024kHz
  8000.024kHz
  8000.023kHz
  8000.024kHz
  8000.024kHz
  8000.024kHz
  8000.023kHz
  8000.024kHz
  8000.023kHz
  8000.024kHz
  8000.024kHz
  8000.023kHz
と、1カウントの変動に。
どこまでカウントできるのかは適当な
発振器がないのでまだ試していません。

とりあえず、わたりの電線(D3とD5)を一本つなぐ
だけで周波数カウンタができるということで。
UNO R4応用のサンプルになりますかな。

■制御スケッチ
  ・ダウンロード - gpt1_cap01.txt
    (.inoではなくテキストファイルにしています)

※どこまでカウントできるか
手持ちの発振素子で試したところ、
10.24MHzはOK。 でも、12MHZだとアウト。

クロック入力となる「D2 P105 GPT1A」ポート、
upカウント「GTETRG」入力として使っています。
これが「POEGモジュール」を介してカウンタに
つながります。
「ノイズフィルタ」として「PCLKBで3回サンプリング」と
なっているので、これでカウントの上限が決まってしまいます。

1秒ゲートだと、カウンタが16bitだと32kHzが最大
カウントになるところ、タイマー1が32bitなんで、計数が
ラクチン。

※参考
2019年12月20日:Arduino UNOで周波数カウンタ
2021年5月1日:Arduino UNOで周波数カウンタ:アナデバの電力計用ICのために
  ATmega328pだと1秒ゲートを作るのがたいそう


※追実験
「POEGモジュール」を通さず、GTIOCAをカウントアップの
直接入力にした周波数カウンタを試してみました。
  GTIOCAとGTIOCBは2相パルスu/dカウントの
  入力で使われます。
  片相(B側入力)をHに固定してupカウントのみにしました。
キャプチャは1秒ゲートを作っているタイマ2のオーバーフロー。
これをELC(イベントリンクコントローラ)で取り込んで、
カウンタ1カウント値のキャプチャにしました。
すると・・・カウントの上限速度がアップ。
24MHzはダメですが、20MHzを数えられるようになりました。

■制御スケッチ #2
   ・ダウンロード - gpt1_cap02.txt

カウントしたいパルスをD2に入れるだけ。
D3はオープンで(プルアップでHレベル)
D5に1Hzは出てるけどゲート信号の接続は不要。

| | コメント (1)

Arduino UNO R4、GPTのレジスタ定義にミス発見

汎用PWMタイマのプリスケーラ設定、これが言うことを
聞かないので、追いかけてみました。

・きっかけは先日の1MHz方形波出力
・それを100Hzにしたかった。
・ハードウェアマニュアルにはこんな表。

G11_20250506114501

・タイマプリスケーラをPCLKD/16にすると、
 48MHz/16で3MHzクロックに。
 これを1/15000して200Hzにして、さらに
 トグル出力で100Hzに。
   こんな目論見。
・しかし出てきたのは400Hz。
   なぜ???

そこで、レジスタ定義ファイルを調べてみたら

__IOM uint32_t GTCR;  /*!< General PWM Timer Control Register */
struct
 {
 __IOM uint32_t CST : 1;  /*!< [0..0] Count Start */
 uint32_t : 15;
 __IOM uint32_t MD : 3;  /*!< [18..16] Mode Select */
 uint32_t : 4;
★ __IOM uint32_t TPCS : 4;  /*!< [26..23] Timer Prescaler Select */
 uint32_t : 5;
} GTCR_b;

「TPCS」が4bitになってました。
  ほんとは3bit

ということは、
  0b0000  1/1  これはok
  0b0010  1/4
  0b0100  1/16
  0b0110  1/64
  0b1010  1/256
  0b1010  1/1024

こんな具合にLSBに1bitの0を足して4bitにしなく
ちゃなりません。

GPTを触るときはちょいと注意ということで。

 

| | コメント (0)

2025年5月 5日 (月)

Arduino UNO R4互換:RA4M1コアボードのクロック

あれこれクロックについて試していますが、おかしな
現象に遭遇しています。
  電源電圧による内蔵クロックの変化を調べてて
  「なにっ?これっ?」っとなったのです。

RA4M1コアボードを初めて通電した、
 ・2025年5月2日:Arduino UNO R4互換品:RA4M1コアボード

この記事を見ると、内蔵クロックによる1MHz出力は
 > 今回、RA4M1コアボードは3枚買いました。
 > そのうちの2枚の出力周波数が1MHzより10~30Hz高い
 > だけで「水晶発振で動いてるんとちゃうん?」と思う
 > くらいでした。
 > 残り1枚がプラス400Hzほど。

「2枚の出力周波数が1MHzより10~30Hz高いだけ」と
記していますが、これがどうも
  ・PCから来たUSBケーブルのコネクタをつないで
   動かした時
     つまり、スケッチを書き込む時
に起こっているようなのです。
コネクタを挿して電源が供給されるとともに、USB認識の
通信がPCと行われます。
これが絡んでいる気がします。

単純な電源供給、
  ・USBは外してVcc端子で5V電源を供給
  ・USB(Cコネ)を通じての電源供給だけ
      (通信機能なし)
これでは、kHz単位の誤差が生じるのです。

実験中の1枚だと、
 ・PCのUSB(通信有)  1.000010MHzを中心に変動
 ・電源供給だけ   0.998200MHzを中心に変動
              変動幅も大きい
 ・PLL切替(どちらも)  1.000026MHz ぴったり止まる

PCと通信が行われるUSBでの電源供給だとクロック精度が
上がるようなのです。
ブートローダーに何か仕掛けがあるのか、RAマイコンの
USB機能にヒミツの機能があるのか・・・

UNO R4 minima基板でも試していただければっと。

 

| | コメント (4)

2025年5月 4日 (日)

RA4M1コアボードでPLLメインクロックを試す

内蔵クロックからPLLクロックに変えた時の「音」。
https://x.com/JH3DBO/status/1918921814815982028

Rr25

・リセット起動で内蔵クロック。
・1MHzの方形波を出力。
・それをラジオを聞く。
・1MHz出力の無変調ワイヤレスマイクを
 そばに置いて、ビートをかける。
・「グジュグジュ」言っているのが内蔵クロックのとき。
・ボタンを押すとPLLに変更。
・青ランプが光る。
・「ピー」という安定したビート音になる。
・再リセットで内蔵クロックに。

※制御スケッチ
  ・ダウンロード - 16mhz_pll02.txt
    (ファイルタイプ.inoではなくテキストにしています)
3秒経過でPLLに変えるというのはやめて、スイッチを押したら
PLLにというふうにしました。
PLLに変わると青ランプが点灯。
内蔵発振器に戻すにはリセットから。

※参:
2021年3月23日:中波振幅変調電波発生回路 いわゆるAMワイヤレスマイク
  コアを回して1000kHzの電波を出すように。

| | コメント (3)

2025年5月 3日 (土)

RA4M1コアボードの16MHz水晶をPLLでメインクロックに

2025年5月2日:Arduino UNO R4互換品:RA4M1コアボード
この続き。
16MHz水晶を発振させ、PLLで48MHzのメインクロックを
作ってみました。

問題は、チップのスペックを外れているということ。
発振子の周波数は大丈夫なのですが、PLL部の最大入力周波数
と、分周値に対する最大出力周波数を超えてしまっているの
です。
「ユーザーズマニュアル・ハードウェア編」にはこんな表が
出ています。
Rr23

入力周波数の最大が12.5MHz
  これが16MHzで大丈夫か?
そして4分周時の最大周波数が32MHz
  これが48MHzになってしまうがどうだ?
これで安定に動くかどうか、ということになります。

私が買ったRA4M1コアボードは「電圧5V版」。
3.3V版より条件は良さそうです。

これが作ったスケッチ。

//  RA4M1コアボードの16MHz水晶でのPLLを試す
// 16MHz * 12逓倍で192MHz, 192MHz ÷ 4分周で 48MHz
// D5ピン P102 GT2B 1MHzでトグル出力
// D4ピン P103 GT2A 2相パルスでトグル出力
// D8ピン P304 loopでH/L
// D9ピン P303 millis変化でトグル(500Hz)
// D10ピン P112 1秒後にH PLL切り替えを示す
// ポートH/L制御出力
#define D8_H (R_PORT3->PODR_b.PODR4 = 1) // D8:P304 H/L
#define D8_L (R_PORT3->PODR_b.PODR4 = 0)
#define D9_H (R_PORT3->PODR_b.PODR3 = 1) // D9:P303 H/L
#define D9_L (R_PORT3->PODR_b.PODR3 = 0)
#define D10_H (R_PORT1->PODR_b.PODR12 = 1) // D10:P112 H/L
#define D10_L (R_PORT1->PODR_b.PODR12 = 0)
// PLL切り替え処理データ
int f_pllon; // PLL切り替え完了フラグ
// 起動後1秒経過で切り替え
/***** メインクロックをPLLに切り替え *****/
void PLLon(void)
{
byte b;
R_SYSTEM->PRCR = 0xA501; // クロック関連レジスタのプロテクト解除
// メインクロック水晶発振
R_SYSTEM->MOSCWTCR = 0b1001; // 発振安定32.768ms待ち (初期値2.08ms)
R_SYSTEM->MOSCCR_b.MOSTP = 0; // XTAL発振開始
b = R_SYSTEM->MOSCCR_b.MOSTP; // MOSTPの状態, 0の確認はいるのか?
while(1){ // 発振安定待ち
if(R_SYSTEM->OSCSF_b.MOSCSF == 1) break; // MOSCSFが1で安定
}
// PLL切り替え
R_SYSTEM->PLLCCR2_b.PLLMUL = 12 - 1; // 12逓倍 16MHz*12 = 192MHz
R_SYSTEM->PLLCCR2_b.PLODIV = 0b10; // 4分周 192MHz/4 = 48MHz
R_SYSTEM->PLLCR_b.PLLSTP = 0; // PLL開始
while(1){ // PLL安定待ち
if(R_SYSTEM->OSCSF_b.PLLSF == 1) break; // PLLSFが1で安定
}
R_SYSTEM->SCKSCR_b.CKSEL = 0b101; // クロックソースをPLLに
R_SYSTEM->PRCR = 0xA500; // プロテクト戻す
}

/***** SETUP *****/
void setup()
{
pinMode(8, OUTPUT); // D8:P304
pinMode(9, OUTPUT); // D9:P303
pinMode(10, OUTPUT); // D10:P112
// PFSプロテクト解除
R_PMISC->PWPR_b.B0WI = 0; // PFS書き込みプロテクト解除
R_PMISC->PWPR_b.PFSWE = 1; // (プロテクト戻してないよ)
// D5:P102 (参:19.2.5)
R_PFS->PORT[1].PIN[2].PmnPFS_b.PDR = 1; // ポート出力
R_PFS->PORT[1].PIN[2].PmnPFS_b.PSEL = 0b00011; // GTIOC2B出力に
R_PFS->PORT[1].PIN[2].PmnPFS_b.PMR = 1; // 周辺機能有効
// D4:P103
R_PFS->PORT[1].PIN[3].PmnPFS_b.PDR = 1; // ポート出力
R_PFS->PORT[1].PIN[3].PmnPFS_b.PSEL = 0b00011; // GTIOC2A出力に
R_PFS->PORT[1].PIN[3].PmnPFS_b.PMR = 1; // 周辺機能有効
// GPT2 B出力を1MHzでトグル A出力と合わせて2相パルスに (参:図22.15)
R_MSTP->MSTPCRD_b.MSTPD6 = 0; // PWMモジュールストップ解除
R_GPT2->GTCR_b.MD = 0b000; // ノコギリ波モード
R_GPT2->GTUDDTYC = 0b11; // 強制的にupカウント
R_GPT2->GTUDDTYC = 0b01; // up継続
R_GPT2->GTCR_b.TPCS = 0b000; // PCLKD/1 48MHz
R_GPT2->GTPR = 24 - 1; // 48MHz/24=2MHz トグルで1/2して1MHz
R_GPT2->GTCNT = 0; // 初回カウント値
R_GPT2->GTIOR_b.GTIOB = 0b01100; // GTIOC2B 周期の終わりでトグル出力
R_GPT2->GTIOR_b.GTIOA = 0b10011; // GTIOC2A コンペアマッチでトグル出力
R_GPT2->GTIOR_b.OBE = 1; // B出力許可
R_GPT2->GTIOR_b.OAE = 1; // A出力許可
R_GPT2->GTCCR[0] = 12; // GTCCRA:Aのトグル位置
R_GPT2->GTCR_b.CST = 1; // カウント開始
}
// コンペアキャプチャレジスタのGTCCRAのアクセスは
// 「R_GPT2->GTCCR[0] = n;」と
// GTCCRAなら[0]と番号で指定 しなければエラーになる。
//  「R_GPT2->GTCCRA」や
//  「R_GPT2->GTCCR_b.GTCCRA」とはできない。

/***** LOOP *****/
// 3秒後にPLLに切り替え
void loop()
{
uint32_t ms , a; // 1msチェックデータ
int f_x9 = 0; // D9ポート反転フラグ
int tm_1ms; // 1msダウンカウントタイマー
ms = millis(); // 現1ms値
tm_1ms = 3000; // 3秒セット
// loop
while(1){
D8_H; // D8:P304 H/L
D8_L;
a = millis(); // 新1ms値
if(ms != a){ // 1ms変化?
f_x9 ^= 1; // 0/1
if(f_x9) D9_H; // D9:P303 H/L
else D9_L;
if(tm_1ms) tm_1ms--; // 1msダウンカウント
ms = a; // 次の1msを待つ
}
// PLL変更タイミング
if((tm_1ms == 0) && // 3秒経過
(f_pllon == 0)){ // まだPLLにしていない
D10_H; // D10をHにして知らせる
PLLon(); // PLLに
f_pllon = 1; // 1回だけ実行
}
}
}
// <2025-05-03 JH3DBO>

リセットして3秒経ったらPLLクロックに切り替えると
いう仕様にしました。

オシロをD5ポートあるいはD4ポートにつないでいれば
1MHzの方形波が見えるはずです。
   D5、D4は90度位相差の2相パルス。
   ハード的に出しているのでジッタは無し。

D8ポートはwhile loopで出すパルス。

D9ポートはmillis()値の変化でトグルさせている
ので500Hzのパルスが出てきます。
  ソフトの処理が絡むのでジッタ有り。

D10がHになったタイミングでPLLに切り替えています。
  発振安定時間を32msみてますんで、Hになった
  あとちょっとしてからPLLに切り替わります。

切り替えはこんなタイミング。
Image000_20250503164501
拡大すると
Image001_20250503164901

millisパルスを拡大すると、loopパルスが途切れて
いるのが見えます。
Image002_20250503165701

millis処理のための割り込みが裏で走ってるのが
これでわかるかと。

とりあえず、手元のRA4M1コアボード(5V電源版)では
PLL駆動ができました。

Arduino UNO R4でも発振子をくっつければ試せるの
ではと思います。

RA4M1コアボードの発振部回路
Rr21_20250503170101

16MHzの発振子が小さい
R25

Arduino UNO R4の発振部回路
Rr22

16MHz水晶がくっつくように回路図が描かれています。
しかし16MHzではスペックオーバー。
12MHzのがあれば8逓倍・2分周で48MHzが作れます。
  形状の小さい水晶がぁぁぁ。


しかし、しかし。
まだややこしことはしていません。
GPTを使って1MHzパルスを出しただけ。
ほんとに大丈夫かはこれからです。


※1MHzのビート音でクロックの純度を音にしてみました。
RA4M1コアボードでPLLメインクロックを試す

| | コメント (3)

2025年5月 2日 (金)

Arduino UNO R4互換品:RA4M1コアボード

「Arduino UNO R4」、そろそろ試してみないとなぁ
と思ってネットをさまよっていたら、
Arduino UNO R4 の代替品1(RA4M1 コアボード):それ、やってみよう!
というページを発見。
WeACT-RA4M1_CoreBoard
RA4M1コアボードが紹介されていました。

Arduino UNO R4、チップは高性能になっても、
基板サイズがUNO R3と同じ。
これでは、「ケースにちっこく組み込んで」という
工作ができません。

UNO R3は28ピンDIPのATmega328Pをソケットから
引っこ抜いて、ユニバーサル基板に組んだ回路に
乗せてということができるんでありがたいのです。

トラ技編集部からは、
FLINT ProMicro R4(SWITCH SCIENCE扱い)
というのもあるよっとお聞きしてました。
このくらいの大きさなら、ユニバーサル基板に乗
せられるっと。

しかし、64ピンマイコンの多くの足が端子に出ないままに
なってます。

ところが、RA4M1コアボードはダブルの端子を使って
いるのでほとんどの信号が足に出ています。
こりゃエエかもっと買ってみました。
  ※ブートローダーの書き込み方法は前述の紹介
   記事を参照。

まずやってみたのがI/Oポートのアクセス速度チェック。
digitalWriteとポートの直書きを比較してみました。

//  出力ピンのテスト
// D8ピン P304 digitalWriteでH/L
// D9ピン P303 直接I/OでH/L
// RA4M1 CoreBoardのLEDはP012(VREFH:DAC用Vref)につながっている

/***** SETUP *****/
void setup()
{
pinMode(8, OUTPUT); // P304
pinMode(9, OUTPUT); // P303
}

/***** LOOP *****/
void loop()
{
while(1){
digitalWrite(8, 1); // P304 H/L/H
digitalWrite(8, 0);
digitalWrite(8, 1);
R_PORT3->PODR_b.PODR3 = 1; // P303 H/L/H
R_PORT3->PODR_b.PODR3 = 0;
R_PORT3->PODR_b.PODR3 = 1;
R_PORT3->PODR &= ~(0b11 << 3); // 304,303 L
}
}

コネクタはまだ付けてないので、スルーホールに
クリップを引っかけて波形観察。
R41

こんな波形が得られました。
Image001_20250502130201
digitalWriteでのH/Lだと1.34μs。
直書きだと0.42μs。
  ※思ったより速くありませんでした。

RA4M1コアボード、メイクロック用として16MHzの
水晶発振子が乗っています。
これを基準にPLLして48MHzを出すとどうなるかを
試してみたいと思います。
  ※RA4M1のスペックでは12.5MHzが最大。
   16MHzをPLL入力が受け入れてくれるのかどうかが問題。
  ※UNO R4の回路を見ると、実装されていないけれど
   同じように発振子(Y1)のパターンが見えます。
   部品名がFTX16.000M12SM3S-30/30てなってい
   てこれも水晶発振子。
  ※PLLは逓倍数が8~31で、それを1/2か1/4して
   メインクロックの48MHzに。
   ということは16MHz×12して192MHz。
   それを1/4して48MHzという流れ。
  ※水晶の周波数を12MHzとか8MHzに落とせばエエですが、
   R4の現パターンに乗るような小型の水晶が無いようです。
  ※しかし、もう、誰かやってるかな?


※1MHzパルスを出してメインクロックの様子を見る

//  1MHz出力のテスト
// D5ピン P102 GT2B 1MHzでトグル出力
// D8ピン P304 loopでH/L
// D9ピン P303 millis変化でトグル(500Hz)
// ポートH/L制御出力
#define D8_H (R_PORT3->PODR_b.PODR4 = 1) // D8:P304 H/L
#define D8_L (R_PORT3->PODR_b.PODR4 = 0)
#define D9_H (R_PORT3->PODR_b.PODR3 = 1) // D9:P303 H/L
#define D9_L (R_PORT3->PODR_b.PODR3 = 0)
/***** SETUP *****/
void setup()
{
pinMode(8, OUTPUT); // D8:P304
pinMode(9, OUTPUT); // D9:P303
// D5:P102
R_PMISC->PWPR_b.B0WI = 0; // PFS書き込みプロテクト解除
R_PMISC->PWPR_b.PFSWE = 1; // (プロテクト戻してないよ)
R_PFS->PORT[1].PIN[2].PmnPFS_b.PDR = 1; // ポート出力に
R_PFS->PORT[1].PIN[2].PmnPFS_b.PSEL = 0b00011; // GTIOC2B
R_PFS->PORT[1].PIN[2].PmnPFS_b.PMR = 1; // 機能出力有効
// GPT2 B出力を1MHzでトグル
R_MSTP->MSTPCRD_b.MSTPD6 = 0; // PWMモジュールストップ解除
R_GPT2->GTCR_b.MD = 0b000; // ノコギリ波モード
R_GPT2->GTUDDTYC = 0b11; // 強制的にupカウント
R_GPT2->GTUDDTYC = 0b01; // up継続
R_GPT2->GTCR_b.TPCS = 0b000; // PCLKD/1 48MHz
R_GPT2->GTPR = 24 - 1; // 48MHz/24=2MHz トグルで1/2して1MHz
R_GPT2->GTCNT = 0; // 初回カウント値
R_GPT2->GTIOR_b.GTIOB = 0b01100; // GTIOC2B 周期の終わりでトグル出力
R_GPT2->GTIOR_b.OBE = 1; // B出力許可
R_GPT2->GTCR_b.CST = 1; // カウント開始
}
/***** LOOP *****/
void loop()
{
uint32_t ms , a; // 1msチェックデータ
int f_x9 = 0; // D9ポート反転フラグ
ms = millis(); // 現1ms値
while(1){
D8_H; // D8:P304 H/L
D8_L;
a = millis(); // 新1ms値
if(ms != a){ // 1ms変化?
f_x9 ^= 1; // 0/1
if(f_x9) D9_H; // D9:P303 H/L
else D9_L;
ms = a; // 次の1msを待つ
}
}
}

タイマー2を使って、メインクロックを1/48して1MHzの
方形波を出してみました。

今回、RA4M1コアボードは3枚買いました。
そのうちの2枚の出力周波数が1MHzより10~30Hz高い
だけで「水晶発振で動いてるんとちゃうん?」と思う
くらいでした。
残り1枚がプラス400Hzほど。
ただし、みんなけっこう変動しています。
周波数カウンタのゲート時間1秒で観察すると平均化さ
れてしまって分かりにくいのですが、0.1秒にすると
400~600Hzほどで変動してるのが目立ちます。

さて、うまいこと水晶発振によるPLL化はできるかな?

もう一つ。
メインクロックの短期間周波数変動を見ようとするとど
うしたらよいでしょか。
計測時間を長くすると平均化されてしまうし。
別に置いた基準発振周波数とMIXして、差を見る
なんて方法かな。
「BFO」ですな。

※続き
2025年5月3日:RA4M1コアボードの16MHz水晶をPLLでメインクロックに
とりあえず、16MHz水晶からPLLで48MHzメインクロックを
作るのはできました。
安定性の検証はこれから。


| | コメント (5)

トラ技原稿執筆時の注意点

古いファイルを整理(廃棄)していたら、トラ技編集部から
やってきたメモが出てきました。
「原稿ご執筆上のお願い」というタイトルで、編集部へ提出
する原稿の書き方が記されています。
Tt11_20250502104401
せっかくですので、全体(2ページ)をpdfで。
  ・ダウンロード - トラ技原稿執筆の注意.pdf

初めて投稿記事をトラ技に載せてもらったのが1993年。
pdfにある記事の例が1995年のですので、初投稿以降に
もらったメモということになります。


こんなのもありましたし。
2023年3月3日:トラ技編集部行きのフロッピーディスク
ラベルには、
 「圧縮はLHAかWinZipを使ってください。」と。


| | コメント (0)

« 2025年4月 | トップページ | 2025年6月 »