Arduino UNO R4
2025年6月 9日 (月)
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近辺で
止まっていてくれなくちゃいけません。
※実験中の様子
左から
・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発生回路の違いが見えます。
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ポート。
16秒経過↓で1/4サイクルほどのズレが発生。
緑が左へズレて行きます。
※参
・Arduino、analogWriteは捨てちゃえ。ちゃんとしたPWMの例
・ラズピコ analogWriteの誤差
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はそのまだ下の周波数。
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」という言い方はちょい好きくない
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発振回路をでっち上げ。
今は安価で売られている発振回路も載った
モジュールじゃなく、チップ単体で買って
そのままになってたのです。
クロック用25MHzも発振器じゃなく、HC-49USの
水晶発振子を用意してました。
クロック発振回路も自分で作ればエエやん
という考えで。
いつから部品箱にあったのか・・・
何年か越しで、やっと役立つ日がやってきました。
ロータリーエンコーダで周波数を可変します。
専用発振器を外付けせず、ATmega328Pから8MHzの方形波
を出力してAD9833のクロックとしました。
クロック周波数が低いので、発生周波数の
分解能が0.0298Hzになります。
もう一つが、UNO R4 minima(とRA4M1コアボード)が出力
する1MHz波形と外置き発振器の信号をmixしてビート音
を出す回路。
高周波用パーツの手持ちはあんましありません。
電源不要のDBMがあれば話が早そうなんですが。
部品箱を探すと、MC1594(有名なMC1494の高精度版)とTIの
「SN16913」を発掘できました。
ここはお手軽なSN16913でプロダクト検波でしょう。
こんな回路で1MHz波をmixします。
小さなユニバーサル基板の切れ端にICとボリュームを乗せ、
クリップで信号接続。
※手抜きです
このデータブックに、等価回路などが出てました。
RA4M1コアボードからの1MHz方形波とAD9833の出力を混ぜ、
・USB接続した時
・USBコネクタを抜いて外部電源にした時
・水晶発振子・PLLをオンした時
低周波ビート音としてどんな波形が出てくるか、確かめます。
ラジオはモニター用。
ラジオのダイヤルを1000kHzにして机上を飛ぶ
2波の1MHz電波(500Hzくらいのビート音)を聞い
ています。
USB接続や外部電源時に生じる「グジュグジュ」音の
要因である内蔵クロックのジッタ。
「これ、使いたくないなぁ」というのが波形として
見えたかと。
RA4M1コアボード用(メインクロック用水晶発振子が
乗っている)のテストプログラム。
・ダウンロード - 16mhz_pll03.txt
(.inoではなくテキストで)
UNO R4 minimaでもPLL on以外は動きます。
グジュグジュ音を聞くだけならプロダクト検波回路はいりません。
AMラジオ+可変周波数発振器(安定な)でOK。
※関連:ラジオペンチ・ブログ
・Arduino UNO R4 のクロック周波数精度とジッタを測定
・Arduino UNO R4 のCPUクロックの品質をデジタルオシロで詳しく調査
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との接続はこんな具合。
USBコネクタを外しても通信できるよう、D0ポートの
TXDでデータを出力しています。
SrealではなくSerial1で。
・制御スケッチ(ファイルタイプをtxtにしています)
・ダウンロード - hoco_02.txt
HOCOUTCRを-10~+10まで変化させた時の1MHz周波数を
順次シリアルデータとして出力します。
・外付け電源のときのデータ。
・ダウンロード - aux01.txt
・USB接続でのデータ。
・ダウンロード - usb01.txt
まっとうに変化しました。
それが、USB接続ではもうはちゃめちゃに。
ほぼ1MHzなんですが、ところどころで、タイミングか
なにかは不明ですが、とんでもない周波数が出ています。
これを見ての評価。
USB接続のときにHOCOUTCRを触ると、クロック周波数が
とんでもない値になることがある。
内蔵クロックを分周して作った1MHz、USB接続では
1MHzになるよう合わせ込みをしているようです。
しかし、HOCOUTCRをユーザーが変更すると、競合して
しまうようです。
HOCOUTCRの値は、書いたものがそのまま読み出されま
したので、USBでの周波数合わせではこれは触っていない
ようです。
ということで、
・HOCOUTCRを触ってメインクロック周波数を
変えてはダメ。
・クロック周波数の精度がいるのなら水晶発振子を
使うように。
が結論でしょうか。
ちなみに、1Hz信号発生回路はこんなの。
「ダイソーのミニケース」 に組んでます。
8ピンの小マイコンを使うとか、リアルタイムクロックICを
使うとか、あれこれ考えられますが、プログラムを組まなくて
も1Hzが得られる4060Bを使いました。
これの欠点。4060Bひとつだと出てくるのは2Hz。
もう1/2したいわけですが、それに何を使うか。
フリップフロップ4013や4027で1/2するのも手ですが、
ワンゲートロジックに「74LVC1G80」という5本足の
「D type FF」があるんで、これで1/2が作れます。
電源とGND。
クロック入力(立ち上がり)とD入力。
そして/Q(反転)出力。
反転出力というのが面白い。
何かのついでに買っておきますわ。
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の純正品を買っちゃいました。
純正品には水晶発振子は付いていません。
内蔵クロックの話、純正品でも同じでした。
・USBで通信+電源供給したら周波数精度が良。
ジッターはあるけど、水晶発振と見間違えるくらい。
・USBを外し、外部電源で動かすと周波数が0.2%ほど下がる。
こんな不可思議現象が起こったのです。
この電源供給の方法、新たにこんなことを試してみました。
(1)USBはつながず外部電源で運転開始。
リセット起動で、周波数は下がったまま。
(2)外部電源につないだままUSBコネクタ(PCからの)を挿す。
すると、周波数精度良に。
D8のloopパルスがずっと見えているので
リセットはかかっていない。
(3)外部電源につないだままUSBコネクタを抜く。
すると、周波数が下がる。
リセットはかかっていない。
ブートローダーが走るのは(1)のときだけ。
(2)と(3)でリセットがかかっていないということは、
この発振周波数変化の原因、
ブートローダーが何かをしているのか?
は、除外できるでしょう。
そして、マイコンに入っているUSBの信号をオシロで見れるよう
にしてみました。
USB+とUSB-、それにloopパルスと+5V電源を見ます。
USBのケーブルをつなぐタイミングでこんな波形が得られました。
USBケーブルをつなぐと、1ms間隔で何かし始めます。
そして30ms後に何かゴニョゴニョ。
その後50msほどは静かで、ふたたび1ms間隔の通信に
なります。
これがUSBケーブルをつないでいる間、続きます。
ゴニョゴニョ部を拡大すると、loopパルスが途切れて
いるのが見えました。
割り込みで何かしているのだと推測できます。
USBの割り込み処理がどうなっているのかを追いかければ、
この周波数変化の原因と周波数精度アップの手法が見えて
くるかも・・・でっす。
しかし、(1)→(2)の変化はわかるんですが、(2)で安定した
のに(3)で元に戻ってしまうというのも、なんか不思議です。
1ms周期では割り込みはかかっていません。
(3)で抜いた瞬間のloopパルスを見れるようにかな。
※USBコネクタを抜いた瞬間
記録するにはトリガ源が難しい。
こんな波形が得られました。
loopパルスが消えているということは、なんらかの
割り込み処理が行われたという判断になるでしょう。
しかし、ここでクロックを元に戻しているのかどうかは
判断できません。
どこで周波数が変わるのかを調べるのは、ちょいとハードルが
高い。
メインクロックを外に出して、微妙な周波数差を見つけな
ければなりません。
周波数差が大きければなんとかなるんですが。
「ブートローダーが何かをしているのか?
は、除外できるでしょう。」
と記しましたが、USBの抜き差しを検出して何かの
処理をするよう仕掛けたのはブートローダーに
なるのか、それともUNO R4のsetup()を実行する前の
初期化ルーチンなのか。
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」。
残念ながらバッファリング処理してない。
文字出力が終わるまで、元ルーチンに戻ってこない。
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は出てるけどゲート信号の接続は不要。
より以前の記事一覧
- Arduino UNO R4、GPTのレジスタ定義にミス発見 2025.05.06
- Arduino UNO R4互換:RA4M1コアボードのクロック 2025.05.05
- RA4M1コアボードでPLLメインクロックを試す 2025.05.04
- RA4M1コアボードの16MHz水晶をPLLでメインクロックに 2025.05.03
- Arduino UNO R4互換品:RA4M1コアボード 2025.05.02
その他のカテゴリー
1023 vs 1024 10秒ゲーム Arduino Arduino UNO R4 AVRマイコン AWK(GAWK) BSch3V gnuplot Help me! (助けて!) HPやBLOG、PC IrDA LED あれこれ おもちゃ病院 お笑い たべもの アナログ回路 アニメ・コミック アマチュア無線 イベント ウェブログ・ココログ関連 カメラ グルメ・クッキング ゲーム サイエンス ツール トラブル遭遇 トランジスタ技術 ニュース パソコン・インターネット ファッション・アクセサリ ペット ラズパイ・ピコ レールスプリッタ 修理 出窓 割り込み処理 地域/猪飼野/ご近所/路上観察/昔話 地域防災リーダー 壮絶死 失敗 導通チェッカー 心と体 技術史 撃墜マーク 文鎮:ハンダ付け補助ツール 本 温度測定 発振回路 行商(ジャンク品頒布) 重箱の隅 電力計測 電子回路工作 電子工作 電子部品 電池 電源 青少年指導員 音楽
最近のコメント