Arduino UNO R4

2025年6月 9日 (月)

Arduino UNO R4 minimaに12MHz水晶を

Arduino UNO R4 minimaの発振周波数安定化、
面実装タイプの水晶発振子は持ってないので
HC-49USの12MHzをハンダしました。
12mhz
逓倍値:8で96MHz。
分周比:2で48MHzを作っています。

| | コメント (0)

2025年6月 6日 (金)

Arduino UNO R4で2つの1Hz信号の位相変化を見る

まさにラジオペンチさんに試してもらいたい内容です。

Arduino UNO R4に搭載のマイコンRA4M1のタイマカウンタに
は贅沢な機能が搭載されています。

周波数や周期の測定で活用できるのがインプットキャプチャ。
各タイマ、2つのキャプチャ入力を持っています。
2つあれば、2つの信号の位相差変化を観察することができます。

48MHzのメインクロックでタイマを走らせ、A入力とB入力で
タイマカウント値をキャプチャさせます。
2つのカウント値の差の変化が位相差変化。
48MHzが分解能。

さらに面白いことに、キャプチャ信号でカウンタの
クリアもできるのです。

キャプチャAを「正の1Hz」につなぎ、キャプチャさせる
とともにクリアの機能も有効に。
するとキャプチャAのデータには1Hzのカウント値が
ラッチされ、同時にゼロクリアしてカウントが
再スタートします。
ラッチされたデータは1Hz間のクロック数ですので、
そのまま48000000が出てきます。
32bitカウンタだからできる技。

キャプチャBは比較したいクロック源につなぎます。

1.1Hzを入れるとこんな感じでデータが得られます。
   cap A    cap B    D=A-B   Dn-D(n-1)
  48000407   3824229  44176178   3261976
  48000277  45300801   2699476   3261599
  48000397  42039033   5961364   3261888
  48000381  38776951   9223430   3262066
  48000361  35515063  12485298   3261868
  48000385  32253111  15747274   3261976
  48000393  28991307  19009086   3261812
  48000349  25729291  22271058   3261972
  48000313  22467319  25532994   3261936
  48000473  19205553  28794920   3261926
  48000277  15943485  32056792   3261872
  48000485  12681605  35318880   3262088
  48000329   9419641  38580688   3261808
  48000335   6157735  41842600   3261912
  48000457  47634349   366108   3262053

cap Aは48MHz付近をうろうろ。
  ※ジッタによるクロック誤差が憎い!
cap Bは1.1Hz(およそ)でキャプチャ値がゼロのほうに
進みます。

右端の数字が差の差でおよそ一定。
  差のオーバーフロ発生時、偏差として突拍子も
  ない数字が出ないよう、押さえつけています。
  前回値を保存するややこしい処理はこれのため。

cap A検出のタイミングでデータを出力していますが、
その直前に新たなcap Bのデータが確定してないとい
けません。
B波形の変動によってこれが抜けることがあります。
  BのエッジがAのエッジを左から右に
  通り過ぎた時。
  Aの2つのエッジ間にBのエッジが一つも
  入らないタイミング。
現スケッチは、このタイミングの計数を無視し
ちゃってます。

/**********************************************/
/* Arduino UNO R4 minima, 1Hz位相差検出 */
/**********************************************/
// 入力ピン
// D2 P105 GPT1A キャプチャ入力A 外部から1Hzを入力 ↓を検出
// キャプチャと同時にGTCNTクリア
// D3 P104 GPT1B キャプチャ入力B 比較入力 ↓を検出
// タイマー1インプットキャプチャフラグ
#define CK_TCFA (R_GPT1->GTST_b.TCFA) // GPT1インプットキャプチャAチェック
#define CLR_TCFA (R_GPT1->GTST_b.TCFA = 0) // インプットキャプチャAクリア
#define CK_TCFB (R_GPT1->GTST_b.TCFB) // GPT1インプットキャプチャBチェック
#define CLR_TCFB (R_GPT1->GTST_b.TCFB = 0) // インプットキャプチャBクリア
// 文字出力バッファ
char str_bff[80]; // sprintfで使用
/***** SETUP *****/
void setup() {
// モジュールストップ解除
R_MSTP->MSTPCRD_b.MSTPD5 = 0; // 32bit PWMモジュールストップ解除
R_MSTP->MSTPCRD_b.MSTPD6 = 0; // 16bit PWMモジュールストップ解除
R_MSTP->MSTPCRD_b.MSTPD14 = 0; // POEGモジュールストップ解除
// D2:P105 GPT1A キャプチャ入力A
R_PFS->PORT[1].PIN[5].PmnPFS_b.PCR = 1; // P105入力pullup
R_PFS->PORT[1].PIN[5].PmnPFS_b.PSEL = 0b00010; // GTETRGA入力に
R_PFS->PORT[1].PIN[5].PmnPFS_b.PMR = 1; // 周辺機能有効
R_GPT1->GTICASR_b.ASGTRGAF = 1; // A↓でキャプチャ
R_GPT1->GTCSR_b.CSGTRGAF = 1; // A↓でクリア
// D3:P104 GPT1B キャプチャ入力B
R_PFS->PORT[1].PIN[4].PmnPFS_b.PCR = 1; // P105入力pullup
R_PFS->PORT[1].PIN[4].PmnPFS_b.PSEL = 0b00010; // GTETRGB入力に
R_PFS->PORT[1].PIN[4].PmnPFS_b.PMR = 1; // 周辺機能有効
R_GPT1->GTICBSR_b.BSGTRGBF = 1; // B↓でキャプチャ
R_GPT1->GTCR_b.CST = 1; // GPT1カウント開始
// Serialでデータ出力
Serial.begin(9600); // 9600BPSで
while (!Serial); // USB接続チェック
}

/***** キャプチャデータ *****/
int32_t d_cap[2]; // キャプチャA,B値
// Aにジャスト1Hzを入れるとcap[0]は48000000となる
int32_t d_ab; // 差分(A-B)データ プラスの値
int32_t m_ab; // 前回の差分保存データ
int32_t d_dev; // 差分からの偏差
int32_t m_dev; // 偏差保存データ
int32_t m_cap0; // cap A保存データ
byte f_mab; // A-B差分保存済みフラグ
/***** LOOP *****/
void loop() {
Serial.println("1Hz_PH01b.ino"); // タイトル
while(1){
if(CK_TCFA){ // キャプチャA発生
CLR_TCFA; // Aフラグクリア
if(CK_TCFB){ // キャプチャBあり?
CLR_TCFB; // Bフラグクリア
d_cap[0] = R_GPT1->GTCCR[0]; // CAP Aデータ保存
d_cap[1] = R_GPT1->GTCCR[1]; // CAP Bデータ保存
d_ab = d_cap[0] - d_cap[1]; // A-B 差分
if(f_mab == 0){ // 初めての差分
f_mab = 1;
m_ab = d_ab; // 差分を保存
m_cap0 = d_cap[0]; // Aキャプチャ値を保存
}
else{ // 差分2回目以降
d_dev = d_ab - m_ab; // 偏差:差分の差
if(abs(d_dev) >= (d_cap[0] / 2)){ // 前回との差が48Mの半分越え
if(d_dev >= 0){ // 差がプラス
d_dev = d_dev - d_cap[0]; // 偏差を修正
}
else{ // 差がマイナス
d_dev = d_dev - m_dev + m_cap0; // 偏差を修正
}
}
sprintf(str_bff, "%11u %11u %11d %11d",
d_cap[0], d_cap[1], // A,Bキャプチャ値
d_ab, // A-B差分
d_dev); // 偏差
Serial.println(str_bff);
m_ab = d_ab; // 差分を保存
m_dev = d_dev; // 偏差を保存
m_cap0 = d_cap[0]; // Aキャプチャ値を保存
}
}
else{ // ★ capAが来た時にcapBが無かったら
// Serial.println(); // 改行で知らせる
}
}
}
}


※関連
GPSとArduinoでRTCの誤差(確度)を精密測定

実用するには、UNO R4に水晶発振子をくっつけて
クロックを安定化しないといけません。
クロック精度が悪くてもかまわないのですが、
(UNO R3のように)、UNO R4のジッタがイケません。

計測データ、右端cap A値、ほんとなら48000000近辺で
止まっていてくれなくちゃいけません。

※実験中の様子
1hzz
左から
・DDS IC AD9833を使って1.0Hzとかを発生。
   0.1Hzを調整できる。
・UNO R4基板
・32.768kHz時計用水晶を使った1Hz発生回路
・12.8MHz発振子を使った1Hz発生回路

※追記:RA4M1コアボードで試す
RA4M1コアボードの水晶(16MHz)+PLLを使って、
1Hzの位相差検出を試してみました。
 ・スケッチ:
    ダウンロード - 1hz_phx01.txt
すると・・・

cap Aが12.8MHz発振器を使った1Hz発生回路
cap Bが32.768kHz時計用水晶を使った1Hz発生回路

 cap A  cap B  D=A-B Dn-D(n-1)
48001139 34840845 13160294 194
48001141 34840651 13160490 196
48001139 34840455 13160684 194
48001141 34840261 13160880 196
48001139 34840065 13161074 194
48001139 34839871 13161268 194
48001141 34839677 13161464 196
 :

・AとBを入れ換えると

48000945 13164763 34836182 -196
48000947 13164957 34835990 -192
48000945 13165149 34835796 -194
48000947 13165343 34835604 -192
48000947 13165537 34835410 -194
48000947 13165729 34835218 -192
48000947 13165921 34835026 -192
48000947 13166115 34834832 -194
 :

・PLLを使うことによりcap Aの値が安定。
  飛びが2~3に
・偏差も安定。
・cap AとcapBを入れ換えると偏差の+/-が逆に。
・RA4M1コアボードの水晶発振+PLL周波数がちょい高め。

このくらいだと位相変化が安心して読め、
1Hz発生回路の違いが見えます。

| | コメント (3)

2025年6月 3日 (火)

UNO R4はanalogWrite(n,128)でデュティー50%の方形波が出るぞ

Arduino UNO R3のanalogWriteはちょいと欠陥品。
 ・2020年2月10日:ArduinoのanalogWrite 1/255なの?

D6ポートにデューティ50%の方形波を出すつもりで
  analogWrite(6 ,128)
としても、デューティ50.4%くらいの方形波が出てきます。
きっちり50%にしたいのなら、
  analogWrite(6,127)
としなくちゃなりません。
そして、D9,D10,D11,D3ポートへのPWMだと
  analogWrite(3 ,127)
  analogWrite(3 ,128)
これのどちらも50%にならないのです。
(D5,D6とは周波数も変わって2.040ms周期)

6つの50%デューティの方形波を得たいスケッチ

/* duty 50%の方形波を出すつもり */
void setup() {
analogWrite(6, 128); // OC0A
analogWrite(5, 128); // OC0B
analogWrite(9, 128); // OC1A
analogWrite(10,128); // OC1B
analogWrite(11,128); // OC2A
analogWrite(3, 128); // OC2B
}
void loop() { }

これだとUNO R3でもUNO R4、どちらでも動きます。
しかし、UNO R3だと前述のしがらみが残り、analogWriteと
呼ぶには誤差が大きすぎます。

UNO R4だとどうでしょか。
周波数は6つとも同じで490Hz(ほど)になってます。
   例のジッタで下位桁が変動
そしてデューティは、128できっちり50%。
さて、他の数値は・・・
  0だとLに張り付き
  1だと8μsだけHのパルス。
  254で16μsだけL。
  255で8μsだけL。
  256でHに張り付き。
エエ感じで「val/256」のanalogWriteしてます。

ただ気になったのが、6つのPWM出力ポートに出てくる
周波数が「3つ・3つ」で微妙に違うのです。
  D6=D11=D3
  D5=D9=D10
この組みになっていて、例えばD5とD6の出力波形を
オシロで観察すると、ゆっくりと波形が流れるのです。
1分ちょいで一周します。
クロックの大もとは同じですし、使ってるタイマの
分周比が微妙に異なっているのかと推測しています。

※UNO R4での微妙な周波数差
黄色がD6ポートのPWM。緑がD5ポート。
Dd11_20250603151001
16秒経過↓で1/4サイクルほどのズレが発生。
Dd12_20250603151001
緑が左へズレて行きます。

※参
Arduino、analogWriteは捨てちゃえ。ちゃんとしたPWMの例
ラズピコ analogWriteの誤差



| | コメント (0)

2025年6月 2日 (月)

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

USB接続時に生じるクロックのジッタ。
これを「聞く」お手軽方法がAMラジオ。
 ・RA4M1コアボードでPLLメインクロックを試す
これでは、AMワイヤレスマイクを使って「ビート」を
かけました。
そして、
 ・Arduino UNO R4 minima 電源供給方法でクロックが変わる#4
では、DDS IC(アナデバのAD9833)で1MHz(その近傍を可変)を
発振させて、プロダクト検波でビート音を拾いました。

なにかもっとお手軽にできないかと考えてふと思ったのが
もう一台のAMラジオ。

欲しいのは1MHz近傍の電波。
UNO R4から1MHzが出るので、
  例えばこのスケッチで
    ・クロックが変わる#5
これをラジオで聞けば無変調のキャリアが入ってきます。
  このキャリア、周波数が変動してもAM検波では
  「音」にはなりません。

そこに、例えば1000.8kHzあるいは999.2kHzの電波を
1MHzを聞いているラジオのそばで出せば800Hzのビート音が
出るというしかけです。

普通のAMラジオは中間周波数455kHzのスーパーヘテロダイン。
第一局発として受信周波数より455kHz上の周波数を内部で
発振しています。
1000kHzの局発周波数が欲しければ、545kHzを受信すれば
良いわけです。
AM放送の周波数範囲は526~1606kHz。
ということは、局発として981~2061kHzを
発振できるようになっています。
AM放送のほぼ下限の、545kHzあたりを探れば、1MHzを
聞いているラジオにビートをかけることができます。

仕事場にあったもう一台のラジオはラジカセでした。
これで試すと・・・「グジュグジュ音」が聞こえましたよ。
  局発を電波としてどれだけ漏らしてい
  るかにもよりますが・・・
  図体の大きなラジカセを静置しておいて
  その周りを電池式ラジオを巡らせて
  局発の1MHzが強くなるところを探り
  ます。
  UNO R4からの1MHzは出力ピンからの
  リード線を伸ばせば強力に入ります。

大阪だと「ラジオ関西」が558kHz。
545kHzはそのまだ下の周波数。

 

| | コメント (0)

2025年6月 1日 (日)

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

UNO R4での内蔵クロック周波数のゴタゴタ、一番簡単に
確認するスケッチを示しておきます。

・D6ポートに1MHzの方形波が出てきます。
・周波数カウンタをつないで、
   USBとつないでいるとき
   USBを切って外部電源で動かす時
 で、出力周波数の違いがわかるでしょう。
・AMラジオと1MHz近傍を安定して出力できる
 発振器があればクロックの「グジュグジュ音」を聞くことが
 できます。

#include "pwm.h"    // "pwm.h"を読んで
PwmOut pwm6(6); // D6ポートをPWM出力に (UNO R3のOC0A)

/***** SETUP *****/
void setup() { // D6ポートに1MHz方形波を出力
pwm6.begin((float)1000000.0, (float)50.0); // 1MHz duty 50%
}

/***** LOOP *****/
void loop() { // 何もしない
}

「.begin()」に食わせる周波数とディーティ比は
「(float)」でキャストしておかないと、数値を記した
だけでは「double」になってしまいエラーが出ます。

前の記事ではI/Oレジスタを直接操作して「1MHz方形波」を
だしましたが、このスケッチだとややこしい所はないでしょう。
  ・RA4M1のマニュアルを見なくてもOK。

違う手法で「クロック、ちょっとやばいぞ」症状が再現で
きたわけです。

せっかくですので、「現在のUNO R4」、「UNO R4A」
としてクロック回りを作り直して欲しいでっす。

改良進化で「mark2」という言い方はちょい好きくない

| | コメント (1)

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月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月 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)