« 2025年5月 | トップページ | 2025年7月 »

2025年6月

2025年6月30日 (月)

DDS IC「AD9833」をArduino UNO R3で制御:箱に入れる

DDS IC「AD9833」をArduino UNO R3で制御
DDS IC「AD9833」の出力にバッファアンプを
DDS IC「AD9833」の出力にバッファアンプを #2

この時は、むき出しのユニバーサル基板でした。
便利に使おうとすると、
 ・箱に入ってて欲しい
 ・電池運用したい
となってしまいます。

百均屋で買ってきた透明樹脂の「箱」に入れました。
  回路は、元のとほぼ同じ。
  出力アンプはOPA2863で。
  1MHzちょいが安定して出ればOK。
  ほんとは出力レベルを可変したかったけど、
  DCオフセットの調整だけ。

Sw11
手組みした基板の様子。
Ss12_20250630150301
回路図。 (クリックで拡大↓)
Ad9833_dds03
スケッチ
  ・ダウンロード - ad9833_02.zip

AD9833のクロックをATmega328Pから出してますんで
ヒューズを書き換えて、16MHzクロックを出すようにし
なくちゃなりません。
  テストするだけならPB1に出してる8MHzも
  使えます。

役に立つかどうかは不明ですが、周波数スイープ機能を
入れてます。
  ラジオのIFトランスの調整あたりに
  使えないかなぁ。
ジャンクボックス内で拾った455kHzのセラミック・フィルタ
とTrラジオのIFTで試してみました。
Sw13

Sw14
フィルタの中心、455kHzが見えています。

スイープ速度を速くすると、周波数計算を行っている
サイクルが見えてきます。
Sw15
計算はもっと早くできるんですが液晶表示が遅い。
液晶表示は0.1秒に1回。

もうひとつ。
AD9833をはじめ、さまざまなDDS IC、無線家の皆さんが
VFOとして使われることが多いようで「スプリアス」を
気にされています。
しかし・・・原理的に、クロック周波数に近い、高い周波数
を出そうとすると、DDS処理に絡むジッタの割合が大きく
なり、きれいな波形が得られません。

これ、正弦波じゃなく方形波(DACデータのMSB)で見ると、
「なんじゃこりゃ」が見えてきます。
今回の回路では16MHzが基準クロック。
割り切れる8MHzや4MHz、2MHz、1.6MHz、1MHzは
きれいな波が出てきます。

4MHzだとまっとうな方形波。
Aa001_20250630170201
16クロックで1μsになり、そこに4発の方形波
が並びます。
1発あたり4クロック。

ところが5MHzになると・・・
  発生周波数を自由にできるのが
  DDSの取り柄なんですけれど。
Aa000_20250630170401
1μs間に5発のパルスが続くんで間違いなく5MHz。
でもそのパルスの間隔、周期は1クロック幅で右に
行ったり左に行ったり。

例えば、1秒ゲートの周波数カウンタで計ったら
こんな波形でもほんとにジャスト5MHzになります。
  それがDDSの原理。

オシロで単発波形を採るんじゃなくちょいと
流してみるとこんな波形になります。
Aa002
「なんじゃこりゃ」のデジタルデータを使って正弦波の
データが入ったROMをアクセスしてD/A変換。
周波数が高いほど、影響が大きく出てきます。
この波形が元になるんで、
  「スプリアス、そりゃ出まっせ」
かと。
クロック周波数に近い、高い周波数が欲しいときは、
出す周波数ギリギリのフィルタで高調波を落と
すしかないでしょ。

※追記
もう一つ、スイープ波形。
制限波出力で1kHz→4MHzを4秒かけてスイープ。
 上段がスイープトリガ用出力。
 中段がAD9833の出力。
 下段だOPA2863を2段通った出力。
  リニアでのスイープなんでこういった周波数特性
  を見る時はLOGスイープが欲しくなります。

Wv12
4MHzになるとレベルが約半分に。
OPA2863の性能が見えてます。
  オペアンプ前段に入れた220Ω+100PF2段の
  LPFのせいです。
  OPA2863はもっと優秀。

※MAX038発振器では ・・・
昔に組んだMAX038発振器では出力オペアンプとして
「AD811」を使ってました。
  帯域幅    140MHz
  スルーレート 2500V/μs
DigiKeyでの現在価格2200円。

※続き
DDS IC「AD9833」をArduino UNO R3で制御:箱入れ #2


| | コメント (0)

2025年6月26日 (木)

Arduino UNO R4の割り込み処理・・・まだまだ勉強不足

Arduino UNO R4の割り込み処理、まだ、使いこなせません。
ライブラリというか、備え付けの関数を使ってということではなく
もっと複雑な(ちゃうちゃう、シンプルに)処理をしたいぞと
なるとRA4M1マイコンのレジスタを直接操作してとなります。
  UNO R3のATmega328Pは分かりやすく
  あれこれできました
そのあたりがまだまだ勉強不足。

・備え付けの関数の例
  attachInterrupt(なんたら);
  #include "FspTimer.h"であれこれ

割り込みの設定状態を調べるため、とりあえず、こんなスケッチを。
割り込みのイベントリンクを設定する「IELSR」というレジスタ
が32個あって、割り込み元を設定するということなんです。
それをシリアル出力してみました。

//  イベントリンクコントローラの設定を見る
#include "Wire.h" // ヘッダファイル ★あれこれ記述してみる
const char *const elc_event_msg[]={ // ELC_EVENT名
"-", // 0 Link disabled
"ICU_IRQ0", // 1 External pin interrupt 0
"ICU_IRQ1", // 2 External pin interrupt 1
"ICU_IRQ2", // 3 External pin interrupt 2
"ICU_IRQ3", // 4 External pin interrupt 3
"ICU_IRQ4", // 5 External pin interrupt 4
"ICU_IRQ5", // 6 External pin interrupt 5
"ICU_IRQ6", // 7 External pin interrupt 6
"ICU_IRQ7", // 8 External pin interrupt 7
"ICU_IRQ8", // 9 External pin interrupt 8
"ICU_IRQ9", // 10 External pin interrupt 9
"ICU_IRQ10", // 11 External pin interrupt 10
"ICU_IRQ11", // 12 External pin interrupt 11
"ICU_IRQ12", // 13 External pin interrupt 12
"ICU_IRQ13", // 14 External pin interrupt 13
"ICU_IRQ14", // 15 External pin interrupt 14
"ICU_IRQ15", // 16 External pin interrupt 15
"DMAC0_INT", // 17 DMAC transfer end 0
"DMAC1_INT", // 18 DMAC transfer end 1
"DMAC2_INT", // 19 DMAC transfer end 2
"DMAC3_INT", // 20 DMAC transfer end 3
"DTC_COMPLETE", // 21 DTC last transfer
"DTC_END", // 22 DTC transfer end
"ICU_SNOOZE_CANCEL", // 23 Canceling from Snooze mode
"FCU_FRDYI", // 24 Flash ready interrupt
"LVD_LVD1", // 25 Voltage monitor 1 interrupt
"LVD_LVD2", // 26 Voltage monitor 2 interrupt
"LVD_VBATT", // 27 VBATT low voltage detect
"CGC_MOSC_STOP", // 28 Main Clock oscillation stop
"LPM_SNOOZE_REQUEST", // 29 Snooze entry
"AGT0_INT", // 30 AGT interrupt
"AGT0_COMPARE_A", // 31 Compare match A
"AGT0_COMPARE_B", // 32 Compare match B
"AGT1_INT", // 33 AGT interrupt
"AGT1_COMPARE_A", // 34 Compare match A
"AGT1_COMPARE_B", // 35 Compare match B
"IWDT_UNDERFLOW", // 36 IWDT underflow
"WDT_UNDERFLOW", // 37 WDT underflow
"RTC_ALARM", // 38 Alarm interrupt
"RTC_PERIOD", // 39 Periodic interrupt
"RTC_CARRY", // 40 Carry interrupt
"ADC0_SCAN_END", // 41 A/D scan end interrupt
"ADC0_SCAN_END_B", // 42 A/D scan end interrupt for group B
"ADC0_WINDOW_A", // 43 Window A Compare match
"ADC0_WINDOW_B", // 44 Window B Compare match
"ADC0_COMPARE_MATCH", // 45 Compare match
"ADC0_COMPARE_MISMATCH", // 46 Compare mismatch
"ACMPLP0_INT", // 47 Analog Comparator Channel 0 interrupt
"ACMPLP1_INT", // 48 Analog Comparator Channel 1 interrupt
"USBFS_FIFO_0", // 49 DMA transfer request 0
"USBFS_FIFO_1", // 50 DMA transfer request 1
"USBFS_INT", // 51 USBFS interrupt
"USBFS_RESUME", // 52 USBFS resume interrupt
"IIC0_RXI", // 53 Receive data full
"IIC0_TXI", // 54 Transmit data empty
"IIC0_TEI", // 55 Transmit end
"IIC0_ERI", // 56 Transfer error
"IIC0_WUI", // 57 Slave address match
"IIC1_RXI", // 58 Receive data full
"IIC1_TXI", // 59 Transmit data empty
"IIC1_TEI", // 60 Transmit end
"IIC1_ERI", // 61 Transfer error
"SSI0_TXI", // 62 Transmit data empty
"SSI0_RXI", // 63 Receive data full
"SSI0_INT", // 65 Error interrupt
"CTSU_WRITE", // 66 Write request interrupt
"CTSU_READ", // 67 Measurement data transfer request interrupt
"CTSU_END", // 68 Measurement end interrupt
"KEY_INT", // 69 Key interrupt
"DOC_INT", // 70 Data operation circuit interrupt
"CAC_FREQUENCY_ERROR", // 71 Frequency error interrupt
"CAC_MEASUREMENT_END", // 72 Measurement end interrupt
"CAC_OVERFLOW", // 73 Overflow interrupt
"CAN0_ERROR", // 74 Error interrupt
"CAN0_FIFO_RX", // 75 Receive FIFO interrupt
"CAN0_FIFO_TX", // 76 Transmit FIFO interrupt
"CAN0_MAILBOX_RX", // 77 Reception complete interrupt
"CAN0_MAILBOX_TX", // 78 Transmission complete interrupt
"IOPORT_EVENT_1", // 79 Port 1 event
"IOPORT_EVENT_2", // 80 Port 2 event
"IOPORT_EVENT_3", // 81 Port 3 event
"IOPORT_EVENT_4", // 82 Port 4 event
"ELC_SOFTWARE_EVENT_0", // 83 Software event 0
"ELC_SOFTWARE_EVENT_1", // 84 Software event 1
"POEG0_EVENT", // 85 Port Output disable interrupt A
"POEG1_EVENT", // 86 Port Output disable interrupt B
"GPT0_CAPTURE_COMPARE_A", // 87 Compare match A
"GPT0_CAPTURE_COMPARE_B", // 88 Compare match B
"GPT0_COMPARE_C", // 89 Compare match C
"GPT0_COMPARE_D", // 90 Compare match D
"GPT0_COMPARE_E", // 91 Compare match E
"GPT0_COMPARE_F", // 92 Compare match F
"GPT0_COUNTER_OVERFLOW", // 93 Overflow
"GPT0_COUNTER_UNDERFLOW", // 94 Underflow
"GPT1_CAPTURE_COMPARE_A", // 95 Compare match A
"GPT1_CAPTURE_COMPARE_B", // 96 Compare match B
"GPT1_COMPARE_C", // 97 Compare match C
"GPT1_COMPARE_D", // 98 Compare match D
"GPT1_COMPARE_E", // 99 Compare match E
"GPT1_COMPARE_F", // 100 Compare match F
"GPT1_COUNTER_OVERFLOW", // 101 Overflow
"GPT1_COUNTER_UNDERFLOW", // 102 Underflow
"GPT2_CAPTURE_COMPARE_A", // 103 Compare match A
"GPT2_CAPTURE_COMPARE_B", // 104 Compare match B
"GPT2_COMPARE_C", // 105 Compare match C
"GPT2_COMPARE_D", // 106 Compare match D
"GPT2_COMPARE_E", // 107 Compare match E
"GPT2_COMPARE_F", // 108 Compare match F
"GPT2_COUNTER_OVERFLOW", // 109 Overflow
"GPT2_COUNTER_UNDERFLOW", // 110 Underflow
"GPT3_CAPTURE_COMPARE_A", // 111 Compare match A
"GPT3_CAPTURE_COMPARE_B", // 112 Compare match B
"GPT3_COMPARE_C", // 113 Compare match C
"GPT3_COMPARE_D", // 114 Compare match D
"GPT3_COMPARE_E", // 115 Compare match E
"GPT3_COMPARE_F", // 116 Compare match F
"GPT3_COUNTER_OVERFLOW", // 117 Overflow
"GPT3_COUNTER_UNDERFLOW", // 118 Underflow
"GPT4_CAPTURE_COMPARE_A", // 119 Compare match A
"GPT4_CAPTURE_COMPARE_B", // 120 Compare match B
"GPT4_COMPARE_C", // 121 Compare match C
"GPT4_COMPARE_D", // 122 Compare match D
"GPT4_COMPARE_E", // 123 Compare match E
"GPT4_COMPARE_F", // 124 Compare match F
"GPT4_COUNTER_OVERFLOW", // 125 Overflow
"GPT4_COUNTER_UNDERFLOW", // 126 Underflow
"GPT5_CAPTURE_COMPARE_A", // 127 Compare match A
"GPT5_CAPTURE_COMPARE_B", // 128 Compare match B
"GPT5_COMPARE_C", // 129 Compare match C
"GPT5_COMPARE_D", // 130 Compare match D
"GPT5_COMPARE_E", // 131 Compare match E
"GPT5_COMPARE_F", // 132 Compare match F
"GPT5_COUNTER_OVERFLOW", // 133 Overflow
"GPT5_COUNTER_UNDERFLOW", // 134 Underflow
"GPT6_CAPTURE_COMPARE_A", // 135 Compare match A
"GPT6_CAPTURE_COMPARE_B", // 136 Compare match B
"GPT6_COMPARE_C", // 137 Compare match C
"GPT6_COMPARE_D", // 138 Compare match D
"GPT6_COMPARE_E", // 139 Compare match E
"GPT6_COMPARE_F", // 140 Compare match F
"GPT6_COUNTER_OVERFLOW", // 141 Overflow
"GPT6_COUNTER_UNDERFLOW", // 142 Underflow
"GPT7_CAPTURE_COMPARE_A", // 143 Compare match A
"GPT7_CAPTURE_COMPARE_B", // 144 Compare match B
"GPT7_COMPARE_C", // 145 Compare match C
"GPT7_COMPARE_D", // 146 Compare match D
"GPT7_COMPARE_E", // 147 Compare match E
"GPT7_COMPARE_F", // 148 Compare match F
"GPT7_COUNTER_OVERFLOW", // 149 Overflow
"GPT7_COUNTER_UNDERFLOW", // 150 Underflow
"OPS_UVW_EDGE", // 151 UVW edge event
"SCI0_RXI", // 152 Receive data full
"SCI0_TXI", // 153 Transmit data empty
"SCI0_TEI", // 154 Transmit end
"SCI0_ERI", // 155 Receive error
"SCI0_AM ", // 156 Address match event
"SCI0_RXI_OR_ERI", // 157 Receive data full/Receive
"SCI1_RXI", // 158 Received data full
"SCI1_TXI", // 159 Transmit data empty
"SCI1_TEI", // 160 Transmit end
"SCI1_ERI", // 161 Receive error
"SCI1_AM", // 162 Address match event
"SCI2_RXI", // 163 Received data full
"SCI2_TXI", // 164 Transmit data empty
"SCI2_TEI", // 165 Transmit end
"SCI2_ERI", // 166 Receive error
"SCI2_AM", // 167 Address match event
"SCI9_RXI", // 168 Received data full
"SCI9_TXI", // 169 Transmit data empty
"SCI9_TEI", // 170 Transmit end
"SCI9_ERI", // 171 Receive error
"SCI9_AM", // 172 Address match event
"SPI0_RXI", // 173 Receive buffer full
"SPI0_TXI", // 174 Transmit buffer empty
"SPI0_IDLE", // 175 Idle
"SPI0_ERI", // 176 Error
"SPI0_TEI", // 177 Transmission complete event
"SPI1_RXI", // 178 Receive buffer full
"SPI1_TXI", // 179 Transmit buffer empty
"SPI1_IDLE", // 180 Idle
"SPI1_ERI", // 181 Error
"SPI1_TEI", // 182 Transmission complete event
"SCE_PROC_BUSY", // 183
"SCE_ROMOK", // 184
"SCE_LONG_PLG", // 185
"SCE_TEST_BUSY", // 186
"SCE_WRRDY_0", // 187
"SCE_WRRDY_4", // 188
"SCE_RDRDY_0", // 189
"SCE_INTEGRATE_WRRDY", // 190
"SCE_INTEGRATE_RDRDY", // 191
};
/***** SETUP *****/
void setup(){
pinMode(13, OUTPUT); // D13:P111 LEDポート出力に
Serial.begin(9600); // 9600BPSで出力
while (!Serial); // USB接続チェック
Serial.println("ELC_EVENT01"); // タイトル
// 追加割り込み処理 ★あれこれ記述してみる
Serial1.begin(9600); // シリアル1 9600BPSで
tone(8, 10000, 0); // D8へ10kHz出力
Wire.begin(); // I2C
}
/***** LOOP *****/
void loop(){
int i;
volatile uint32_t d, *p;
char str_bff[80]; // 文字出力用バッファ
p = (volatile uint32_t *)0x40006300u; // IELSR先頭
for(i = 0; i < 32; i++){ // 32個
d = *p; // IELSRの内容
sprintf(str_bff, "%2d %08LX %02X %s",
i, // 番号 0~31
p, // IELSRアドレス
d & 0xFF, // ICUリンク番号
elc_event_msg[d & 0xFF]); // リンク説明
Serial.println(str_bff);
p++;
}
Serial.println("Stop");
while(1){
R_PORT1->PODR_b.PODR11 = !(R_PORT1->PODR_b.PODR11); // D13トグル
}
}


こんな出力が得られます。

ELC_EVENT01
0 40006300 33 USBFS_INT USB関連
1 40006304 34 USBFS_RESUME
2 40006308 31 USBFS_FIFO_0
3 4000630C 32 USBFS_FIFO_1
4 40006310 1E AGT0_INT delayやmillis用1msタイマ
5 40006314 A4 SCI2_TEI serial1関連
6 40006318 A5 SCI2_ERI
7 4000631C A3 SCI2_TXI
8 40006320 A6 SCI2_AM
9 40006324 7D GPT4_COUNTER_UNDERFLOW tone()
10 40006328 3B IIC1_TXI    I2C関連
11 4000632C 3A IIC1_RXI
12 40006330 3C IIC1_TEI
13 40006334 3D IIC1_ERI
14 40006338 00 -
15 4000633C 00 -
16 40006340 00 -
17 40006344 00 -
18 40006348 00 -
19 4000634C 00 -
20 40006350 00 -
21 40006354 00 -
22 40006358 00 -
23 4000635C 00 -
24 40006360 00 -
25 40006364 00 -
26 40006368 00 -
27 4000636C 00 -
28 40006370 00 -
29 40006374 00 -
30 40006378 00 -
31 4000637C 00 -
Stop

最初の4つがSerial.begin()でのUSB通信関連。
そしてAGTを使った1ms割り込み。delayやmillisを処理します。
そしてsetupの中に入れたSerial1.begin() の割り込みが4つ。
番号9がtone()。
GPT4のアンダーフロー割り込みが有効になっているのだと推測
できます。
最後が「Wire.begin()」によるI2C関連が4つ。

まだまだ勉強不足です。


※割り込みが足りなくなるかも・・・
IELSRは0~31の32個。
割り込みベクトルに直接飛ぶんじゃない(ようだ)。
割り込みの数、足りなくなる?
仕事で使ったcortex M4 STM32F407となんか違う。

※追記
Arduino UNO R4のシリアル通信ポートを増やす

この記事に、Serialとserila1以外にシリアルポートを2つ増やす
方法が記述されていたんで、前述のスケッチに追記してみ
ました。

最初のヘッダーファイルのところにこの2行。
  UART Aux0(A4, A5);
  UART Aux8(11, 12)
そしてsetup()にこの2行。
  HeySeri1.begin(115200); //A4, A5ポートを使った追加のシリアル通信
  HeySeri2.begin(115200); //11, 12ポートを使った追加のシリアル通信

結果、イベントリンクが8つ増えて、空き残が10個に。
ELC_EVENT01
0 40006300 33 USBFS_INT
1 40006304 34 USBFS_RESUME
2 40006308 31 USBFS_FIFO_0
3 4000630C 32 USBFS_FIFO_1
4 40006310 1E AGT0_INT
5 40006314 A4 SCI2_TEI
6 40006318 A5 SCI2_ERI
7 4000631C A3 SCI2_TXI
8 40006320 A6 SCI2_AM
9 40006324 7D GPT4_COUNTER_UNDERFLOW
10 40006328 3B IIC1_TXI
11 4000632C 3A IIC1_RXI
12 40006330 3C IIC1_TEI
13 40006334 3D IIC1_ERI
14 40006338 99 SCI0_TEI
15 4000633C 9A SCI0_ERI
16 40006340 98 SCI0_TXI
17 40006344 9B SCI0_AM
18 40006348 A9 SCI9_TEI
19 4000634C AA SCI9_ERI
20 40006350 A8 SCI9_TXI
21 40006354 AB SCI9_AM
22 40006358 00 -
23 4000635C 00 -
24 40006360 00 -
25 40006364 00 -
26 40006368 00 -
27 4000636C 00 -
28 40006370 00 -
29 40006374 00 -
30 40006378 00 -
31 4000637C 00 -
Stop

「ACIn_AM」って何だろ?
  アドレス一致イベント:調歩同期式モードにおいて
  比較データと受信データの1フレームが一致したとき
だと

 

| | コメント (2)

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

2025年5月27日:DDS IC「AD9833」の出力にバッファアンプを
この記事でチラリと書いた、高速オペアンプ。

この時は手持ちの「AD823」を使いました。
その後、OPA2863(バイポーラのdual op-amp)と
OPA810(SOT23のsingle FET入力OP-AMP)とを手
に入れて比較してみました。

AD823
 FET-input
 Output swings rail-to-rail
 -3dB bandwidth of 16MHz, G = +1
 Slew rate of 22V/μs
 maximum input bias current: 25pA

OPA2863
 rail-to-rail input and output,
 Unity-gain bandwidth: 110MHz
 Gain-bandwidth product: 50MHz
 Slew rate: 105V/μs
 Input bias current: 300nA

OPA810
 FET-input
 Rail-to-rail input and output
 Small-signal bandwidth: 140MHz
 Gain-bandwidth product: 70MH
 Slew rate: 200V/μs
 Input bias current: 2pA

AD9833 DDS ICが出す出力波形は、
  正弦波、三角波、方形波が
選べます。
正弦波と三角波は、L電圧が0.038V、H電圧が0.65Vで
P-P値で0.6Vほど。
方形波にすると、0V~5Vのフルスイング波が出てきちゃう
のです。
こんな回路でバッファしたので、方形波を出すとAMP1が
飽和してしまいます。
Cc05
3種のアンプで、出力波形がどうなるか、方形波を
出力して比較してみました。
Cc02
それぞれの波形、
  上からDDS出力につながるAMP1の+入力。
  真ん中がAMP1の出力。
  下が出力波形。 (AMP2は反転増幅)
AD823は1MHzになるとまともな波形が出てきません。
  ※正弦波だとレベルは下がるけどちゃんと
   見えます。
他の二つはさすがに高速アンプ。
飽和した方形波でも頑張って出してくれました。

DigiKey調べだと
 AD823  1400円  昔はもっと安かった
 OPA2863 360円
 OPA2810 730円
  (実験で使ったのはsingleのOPA810を二つ)

OPA2863がリーズナブルでしょか。
ただし、バイポーラなんで入力バイアス電流が300nAと
だいぶと大きいです。
汎用のLM358の入力バイアス電流が20nAですんで、
15倍の差があります。
  LM1458は200nA。
帰還抵抗をあまり大きくできません。
バイアス電流の小さなFET入力のだと、自由に決められるんで
便利です。

| | コメント (0)

2025年6月24日 (火)

「タカチ」の「ゴム足」にもの申す!

電子回路工作で「ゴム足」を使うとなると、
タカチのから選びませんか?
昨晩、文鎮の佐藤テック君と話してたら、彼の
意見も同じ。
  「10個単位のセット売りはやめてくれ!」っと。

箱の裏に貼り付けるゴム足、使うのはほとんどが4つ。
  ゴム足、4つ以外で使う用途って何?
  メカのどん突き防止や振動防止的用途くらいか。

10個単位で売ってるのを買うと、2つ余る。
2袋で20個買っておけという意見も分かり
ますが、8個セットとか12個セットのほうが
余らずにエエかと。

パーツボックスを見たら、いつ買ったのかわからんのが
2つ残ってるという状態がイヤです。

  ※参考写真
Gg11

 

| | コメント (2)

2025年6月23日 (月)

電池液漏れの季節

気温が上がるこの季節。
電池の液漏れに気をつけてください。
つい先ほども、
トランジスタ技術2022年12月号のトラ技Jr.コーナ
に載せてもらった「赤外線リモコン・チェッカ」で
液漏れを発見。

Ir11_20250623095301
Ir12_20250623095501

漏れた電解液の流れ出し方向が良かったのか、スプリングの
メッキも生きていましたんで、洗浄だけ。
電池ボックスの交換はしなくてすみました。
  この電池は完全に放電。ゼロボルト。
  消費期限、余裕で過ぎてますし。

「糸ようじ」のプラケースを使うシリーズ:赤外線リモコンチェッカー

おもちゃ病院では
 「使わない時は電池を抜いといてくださいね」
っと、エラそうに言ってるんですが、常用ツールは
ついつい電池を入れっぱなし。


| | コメント (4)

2025年6月21日 (土)

遠くから「モールス」音が聞こえてきた

土曜日も朝から仕事場。
熱いので窓や扉を閉めてエアコンを入れてます。
そんな中、遠くのほうから
 「・・・- ・・・- ・・・-」
とモールスの「VVV」が聞こえてくるでは
ありませんか。
窓を開けて聞き耳を立てると・・・
低周波発振器が出すスピーカーの音じゃなく、
小学校で使う「リコーダ:縦笛」のような感じ。

「VVV」に続けて出てきた符号ははっきり
しない(文にはならない)のですが
「K」とか「Q」とか「N」とか「Z」なんか
が符号として聞こえます。
そしていきなり和文の「ス」「---・-」。
  「MK」とか「OA」じゃなくって
  「ス」に聞こえた

音階はなくって単調な音。
しかし、モールスのダッシュとドット(3:1)を理解して
区別してる感じだったんです。
しばらくしたら止んじゃったんで
こちらから「応答」することはしませんでした。

ちゃんと文になっていたり「CQ CQ」とか
「DEなんたら」なんて聞こえてきたら
こちらからも低周波発振器で本気で応答
したかも。

 

| | コメント (0)

2025年6月13日 (金)

あかんやん「Microchip Studio」

AVRマイコンのポート操作、I/Oマクロとして以下のように記述したとき
 #define PA0_H (PORTA |= (1 << PA0)) // PA0 Hに
 #define PA0_L (PORTA &= ~(1 << PA0)) // PA0 Lに
以前の「Atmel Studio」では「SBI」「CBI」命令に展開されて
最速の実行コードが生成されていました。
  ※Arduino UNO R3でも同じ

新しいPC(win11マシン)にインストールして使い始めた
「Microchip Studio」でも同じだと思ってたら、ポート
への出力がエラい遅いんです。
展開されたアセンブラのソースを見ると、
  Hへの制御は「IN, OR, OUT」と、
  Lへの制御は「IN, AND, OUT」と。
この3命令に展開されています。

単純に実行が遅れるだけでなく、割り込み処理の中と
メイン側で同じポートへのアクセスがあると、相互の競合が
発生します。
メイン側では「割り込み禁止・割り込み再開」を
指示しなくちゃならないので、よけいに遅くなってしまいます。

コンパイラのオプション指定で変化するんだろうと考え
ているのですが、どこを触れば良いのか探し出せてません。

困ったぞ!

※その後・・・おそらく解決
「ALT-F7」でプロジェクトのプロパティを出し、
「GNU Cコンパイラ」のオプティマイズを変更。
Opt11
初期設定が-Og:デバッグ時の設定になっていました。
-O1, -O2, -O3, -Osのどれでも「SBI」「CBI」に
展開してくれるようになりました。
一件落着!! よかったゾ。

あとはMPLAB@Snapの扱い。
Microchip Studio内からの書き込み操作じゃなく、
別のツールを使うか・・・

※関連
2019年3月25日:割り込みで処理させるwordデータの扱い
この中で示しているポートのH/L操作、

 #define PB5_H (sbi(PORTB,PORTB5))
 #define PB5_L (cbi(PORTB,PORTB5))

ここでの「sbi()」「cbi()」そのものが、こんな具合に
「SFR &= ~b」「SFR |= b」なっているのです。

 #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
 #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
   wiring_private.hの中で定義

この1命令でビット操作ができるのはアドレス0x00~0x1Fまでの
32バイトの区間にあるものだけ。
AVRマイコンのアーキテクチャではむちゃ貴重なエリア
なのです。

 

| | コメント (0)

2025年6月12日 (木)

Microchip StudioでMPLAB@Snapが動かない

「UPDI」で書き込む新しいタイプのAVRマイコン、
  今回は8ピンのATtiny402
Microchip Studio環境で書き込みできるよう
MPLAB@Snapを買ってきました。
Tl1

むき出しの基板なんで、ちょうどええ大きさの
プラケースも見つけて、「よしよし」と。

Tl32
ダイソーで買ったプラケースにうまいこと入りました。
Tl33
ケーブル出しの穴加工、使うのはカッターナイフだけ。

さて、これでっとなったんですが、
Microchip StudioでSnapが言うことをきいてくれない
のです。

USBをつないで出てきたのは、
 「ファームウェアをアップグレードせよ」
と。
Microchip Studioの中でアップグレード処理が
始まったんですが、失敗。
Up1
ネットを見ると、「MPLAB X IDE」でゴソゴソせよ
という情報が出てきます。
  トラ技の2021年4月号の特集記事(p44)にも
  注意が出ていました。
T51

面倒ですが「MPLAB X IDE」をインストールして、
あれこれ。
実際の「ATtiny402」とSnapをUPDIでつないで、
試しにパルスを出すテストプログラムを書いたら
ちゃんと動きました。

これで「よっしゃ」だったんですが、Microchip Studioに
つなぎ直すと、こんどはこんなエラーメッセージ。
Up2

Snapのファームウェアバージョン、On toolが「1.0b」。
MPLAB X IDEでアップグレードされたんでしょう。
しかし、On Diskが「1.0a」となっていて、
「ファームウェアをアップグレードせよ」に従い
「Upgrade」ボタンを押したら・・・
Up3
失敗
現状、Microchip StudioでSnapが使えません。

MPLAB X IDEはキライだし、AVR Studio時代から使い慣れた
ツールを利用したいのです。
困った、困った。

AVRISP mkIIなどのSPI方式の書き込みツールは使えています。


※追記
その後・・・
プログラムの編集とコンパイルは手慣れた「Microchip Studio」で。
できあがった「.HEX」ファイルを「MPLAB IPE」に食わせて
UPDIで書き込み。こんな手順で作業してました。
MPLAB IPEを起動しっぱなしにしておくと、Microchip Studioで
コンパイルしたら「HEXファイルが変わったぜ!」と警告を出して
くれます。
Mp11
そこで、書き込み操作を実行。

しかし、まだ落とし穴。
「Hold in Reset」にしてたら、書き込みが終わっても
リセットのままになってしまって、
書いたプログラムが走れへん。
スカタンしたかとびっくりしますんで、
「Release from Reset」にしとかんとあきません。

Mp12

https://ww1.microchip.com/downloads/jp/DeviceDoc/50002227B_JP.pdf


| | コメント (11)

アイリスオーヤマ BIGCAPA単3 BCR-R3MH 充放電実験開始

 Better Power Battery社の単3ニッ水「Pool」2150mAh
の充放電実験があんまりだったので気を取り直して、
 アイリスオーヤマ BIGCAPA単3 BCR-R3MH 950mAh
の充放電実験を始めます。
Ii11_20250612110501

初回の0.2C放電から3回目の放電まで。
Cap018_20250612110501

残存容量(初回放電)、電圧1.0Vまでで見ると88%ほど。
1.2Vなら70%となかなか優秀です。

950mAhあたりの容量の電池というと
 パナのeneloop lite。
 同じく充電式エボルタお手軽モデル。
 タミヤ NEO CHAMP。
 ダイソー looper。
 東芝インパルス TNH-3LE。
 FDKの長寿命電池HR-AAULT。
このあたり。
   TNH-3LEとHR-AAULTは実験継続中。

電池あれこれ

| | コメント (0)

2025年6月 9日 (月)

Arduino UNO R4 minimaに12MHz水晶を

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

| | コメント (0)

Better Power Battery社の単3ニッ水「Pool」2150mAh

3月末に充放電実験スタートした「Pool」2150mAh。
使ってはいけない電池でした。

0.5Cでの充放電時間と充電停止電圧の変化、
こんなグラフになりました。
Cap001_20250609124001

200サイクル手前で「もうダメ」状態に。
230サイクルあたりから、放電時間がゼロに
なって充電池の機能を喪失。
その後の充電、-ΔV検出できないものだから、
132分目いっぱいの充電時間に。
これで発熱が続いたのでしょう、外装フィルムが
プックリと膨れていました。
Pp11_20250609124501

内部抵抗、1066mΩになっていました。

| | コメント (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発生回路の違いが見えます。

| | コメント (7)

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月 | トップページ | 2025年7月 »