Si5351Aを使用して信号を出したい。
以前、府中市のアマチュア無線のセミナで信号発生機のデバイスについて聞いたことがあった。1チップで200MHzkくらいは、出るのだと聞いた。
昔、PLLのチップで信号を出して、元の局発の水晶をVXO化していろいろな周波数を出すことができたものだった。しかし最近のデバイス、もっと細かく周波数を指定できるようになっているとのこと。手の平にすっぽり収まるサイズで、オールバンドカバー+50MHzが使用できるという。
秋月電子で探してみると、これがSi5351Aというデバイスであるという事が分かった。
一も二もなく、購入してみた。
Si5351Aを購入してみた
早速購入してみたデバイスは、8PINのモジュールになっているもので、3.3V電源で動作するものだった。コントロールはI2Cで動作する。
これは、まず手持ちのRaspberrypi3+のPythonを使用して実験してみるしかない。
しかし、RaspberryPi3+のI2Cは、5V動作なので、レベルコンバータ(PCA9306)が必要だ。
Si5351Aとは
Si5351Aは、PLLの周波数と、出力分周器の設定を行って実際の出力周波数を決定する
仕組みになっている。
fvco=fxtalx(a+(b/c) モジュールでは、fxtal=25MHz
aは15~90
bは0~1048575
cは0~1048575
でPLLの周波数が決定されるが、実際にレジスタに設定する値は、下記のようになっている。
MSNxP1[17:0]=128xa+Floor(128x(b/c))-512
MSNxP2[19:0]=128xb-cxFFloor(128xb/c))
MSNxP3[19:0]=c
PLLはA,Bの2つがあり、上記のx=A,Bについて設定を行う。
MSNA_P1からMSNB_P3のレジスタにI2Cを使用して書き込みを行う。
PLLの周波数を決定し分度は、出力分周器の設定下記のように行う。
fout=fvco/(a+(b/c))
そして、レジスタの設定値は、またまた下記のように設定する。
MS0P1[2C:2]=128xa+Floor(128x(b/c))-512
MS0P2[30:2]=128xb-cxFFloor(128xb/c))
MS0P3[29:2]=c
A/BどちらのPLLを使用するのかは、MSx_SRC[10/11/12:2x]で指定する。
とあるが、このビットを1にするとAなのかBなのかわからないぞ。
そもそもそのほかのレジスタの設定方法が全くよくわからない。
これは、例文を探しまくらないとうまくできる気がしない。
Si5351Aの使用例をググる
ググってみると早速良いサイトがHitした。
CircuitPython Code | Adafruit Si5351 Clock Generator Breakout | Adafruit Learning System
RaspberryPiでの動作も記載されていて、しかもPythonだ。
sudo pip3 install adafruit-circuitpython-si5351
をRaspberryPiのPythonで実行して、
Full Example CodeをRaspberryPiへコピペして、実行してみる。
簡単に周波数の設定ができた。
右側が、Si5351A 左側が、レベル変換チップ(PCA9306)
念のため、オシロでCH1の出力波形を確認してみると下記のように観測することができた。大まかな周波数は、カウンタ機能を使用して自動計測してみると、13.553MHzと計測できていることがわかる。
設定値は、13.553113553113555MHzだから正しく計測できているようだ。
波形は、10cm程度のリードを伸ばしているので、そのインダクタンスの影響でリンギングを伴ってしまうのは致し方ない。
こうなると、カウンタの桁数がもう少し欲しいところだ。
昔購入したカウンタを引っ張り出してきてみた。
1ppmのカウンタなので、有効なのは6桁という事になるが、しばらくぶりの登場なので、オシロスコープの20MHzの信号を観測すると、1Hzのけただけ6-9の数字になる。まあ悪くない状態のようだ。
出力をプロービングしてカウンタを見ると下記のようになった。
100Hzの桁から異なるようなので、実際に違うのだと思える。
水晶の容量を変えるとどうだろう。これは後からの課題だ。
周波数の確認はこれくらいにして肝心なところに戻ろう。
プローブは、I2CのSDAとSCKにプロービングしなおしてみた。
購入したEDUX1052G型は、I2Cの解析機能を標準で搭載しているので、何をしているのかわからないプログラムの動作を確認するためには多少役に立と思う。
上記のように短めの通信であれば取り込み可能だ。
とは言え、メモリ長200kポイントは、プロトコル解析には決して長いメモリ長ではないので、お遊びに使用する程度が頃合いだろう。
取り込んだデータは、デコードされ、テキストデータで保存することができる。
下記が、そのでコード結果だ。Si5351Aは、アドレス60に指定されているので、60番地に書き込みなどを行うことになります。
Marked,Time,Serial Bus,Restart,Address,Data,Missing Ack
,-16.00us,Serial1,,60W,,
,246.0us,Serial1,,60W,03 FF,
,623.0us,Serial1,,60W,10 80,
,994.0us,Serial1,,60W,11 80,
,1.363ms,Serial1,,60W,12 80,
,1.732ms,Serial1,,60W,13 80,
,2.101ms,Serial1,,60W,14 80,
,2.470ms,Serial1,,60W,15 80,
,2.838ms,Serial1,,60W,16 80,
,3.209ms,Serial1,,60W,17 80,
,3.651ms,Serial1,,60W,1A 00,
,4.024ms,Serial1,,60W,1B 01,
,4.395ms,Serial1,,60W,1C 00,
,4.766ms,Serial1,,60W,1D 10,
,5.135ms,Serial1,,60W,1E 00,
,5.508ms,Serial1,,60W,1F 00,
,5.877ms,Serial1,,60W,20 00,
,6.248ms,Serial1,,60W,21 00,
,6.618ms,Serial1,,60W,B1 A0,
,7.572ms,Serial1,,60W,22 00,
,7.992ms,Serial1,,60W,23 03,
,8.377ms,Serial1,,60W,24 00,
,8.750ms,Serial1,,60W,25 0A,
,9.120ms,Serial1,,60W,26 55,
,9.494ms,Serial1,,60W,27 00,
,9.864ms,Serial1,,60W,28 00,
,10.23ms,Serial1,,60W,29 01,
,10.60ms,Serial1,,60W,B1 A0,
,11.35ms,Serial1,,60W,2A 00,
,11.75ms,Serial1,,60W,2B 01,
,12.13ms,Serial1,,60W,2C 00,
,12.50ms,Serial1,,60W,2D 02,
,12.87ms,Serial1,,60W,2E 00,
,13.24ms,Serial1,,60W,2F 00,
,13.61ms,Serial1,,60W,30 00,
,13.99ms,Serial1,,60W,31 00,
,14.36ms,Serial1,,60W,10 4F,
,14.76ms,Serial1,,60W,2C,
,15.06ms,Serial1,,60R,00,X
,15.78ms,Serial1,,60W,32 00,
,16.18ms,Serial1,,60W,33 02,
,16.56ms,Serial1,,60W,34 00,
,16.93ms,Serial1,,60W,35 14,
,17.30ms,Serial1,,60W,36 C0,
,17.67ms,Serial1,,60W,37 00,
,18.06ms,Serial1,,60W,38 00,
,18.43ms,Serial1,,60W,39 00,
,18.81ms,Serial1,,60W,11 2F,
,19.20ms,Serial1,,60W,34,
,19.48ms,Serial1,,60R,00,X
,20.17ms,Serial1,,60W,3A 00,
,20.57ms,Serial1,,60W,3B 01,
,20.95ms,Serial1,,60W,3C 01,
,21.32ms,Serial1,,60W,3D C0,
,21.69ms,Serial1,,60W,3E 00,
,22.07ms,Serial1,,60W,3F 00,
,22.44ms,Serial1,,60W,40 00,
,22.81ms,Serial1,,60W,41 00,
,23.18ms,Serial1,,60W,12 6F,
,23.57ms,Serial1,,60W,3C,
,23.88ms,Serial1,,60R,01,X
,24.18ms,Serial1,,60W,3C 61,
,24.56ms,Serial1,,60W,3C,
,24.83ms,Serial1,,60R,61,X
,25.48ms,Serial1,,60W,03 00,
しかし、これだけではわかりにくいので、各レジスタの名前を当てはめて表示すると、下記のようになった。
Marked,Time,Serial Bus,Restart,Address,Data,Missing AckMarked,Time,Serial Bus,Restart,Address,Data,Missing Ack
,-16.00us,Serial1,,60W,,
,246.0us,Serial1,,60W,03 FF, #3 CLK2,CLK1,CLk0=1
,623.0us,Serial1,,60W,10 80, #16 CLK0_PDN=1
,994.0us,Serial1,,60W,11 80, #17 CLK1_PDN=1
,1.363ms,Serial1,,60W,12 80, #18 CLK2_PDN=1
,1.732ms,Serial1,,60W,13 80, #18 表記なし=80
,2.101ms,Serial1,,60W,14 80, #19 表記なし=80
,2.470ms,Serial1,,60W,15 80, #20 表記なし=80
,2.838ms,Serial1,,60W,16 80, #21 表記なし=80
,3.209ms,Serial1,,60W,17 80, #22 表記なし=80
,3.651ms,Serial1,,60W,1A 00, #26 MSNA_P3[15:8]=00
,4.024ms,Serial1,,60W,1B 01, #27 MSNA_P3[7:0]=01
,4.395ms,Serial1,,60W,1C 00, #28 MSNA_P1[17:16]=0
,4.766ms,Serial1,,60W,1D 10, #29 MSNA_P1[15:8]=10
,5.135ms,Serial1,,60W,1E 00, #30 MSNA_P1[7:0]=00
,5.508ms,Serial1,,60W,1F 00, #31 MSNA_P3[19:16]=0,MMSNA_P2[19:16]=0
,5.877ms,Serial1,,60W,20 00, #32 MSNA_P2[15:8]=00
,6.248ms,Serial1,,60W,21 00, #33 MSNA_P2[7:0]
,6.618ms,Serial1,,60W,B1 A0, #177 PLLB_RST=1,PLLA_RST=1
,7.572ms,Serial1,,60W,22 00, #34 MSNB_P3[15:8]=00
,7.992ms,Serial1,,60W,23 03, #35 MSNB_P3[7:0]=03
,8.377ms,Serial1,,60W,24 00, #36 MSNB_P2[17:16]=0
,8.750ms,Serial1,,60W,25 0A, #37 MSNB_P1[15:8]=0A
,9.120ms,Serial1,,60W,26 55, #38 MSNB_P1[7:0]=55
,9.494ms,Serial1,,60W,27 00, #39 MSNB_P3[19:16]=0,MSNB_P2[19:16]=0
,9.864ms,Serial1,,60W,28 00, #40 MSNB_P2[15:8]=0
,10.23ms,Serial1,,60W,29 01, #41 MSNB_P2[7:0]=01
,10.60ms,Serial1,,60W,B1 A0, #177 PLLB_RST=1,PLLA_RST=1
,11.35ms,Serial1,,60W,2A 00, #42 MS0_P3[15:8]=01
,11.75ms,Serial1,,60W,2B 01, #43 MS0_P3[7:0]=01
,12.13ms,Serial1,,60W,2C 00, #44R0_DIV[2:0]=0,MS0DIVBY4[1:0]=0,MS0_P1[17:16]=0
,12.50ms,Serial1,,60W,2D 02, #45 MS0_P1[15:8]=02
,12.87ms,Serial1,,60W,2E 00, #46 MS0_P1[7:0]=00,13.24ms,Serial1,,60W,2F 00, #47 MS0_P3[19:16]=0,MS0_P2[19:16]=0
,13.61ms,Serial1,,60W,30 00, #48 MS0_P2[15:8]=0
,13.99ms,Serial1,,60W,31 00, #49 MS0_P2[7:0]=0
,14.36ms,Serial1,,60W,10 4F, #16 CLK0_PDN=0,MS0_INT=1,CLRK0[1:0]=3,CLK0_IDRV[1:0]=3 ,14.76ms,Serial1,,60W,2C,, #44 R0_DIV[2:0]=X,MS0DIVBY4[1:0]=X,MS0_P1[17:16]=X,15.06ms,Serial1,,60R,00,X,15.78ms,Serial1,,60W,32 00, #50 MS1_P3[15:8],
16.18ms,Serial1,,60W,33 02, #51 MS1_P3[7:0]
,16.56ms,Serial1,,60W,34 00, #52 R1_DIV[2:0]=0,MS1_DIVBY4[1:0]=0,MS1_P1[17:16]=0,16.93ms,Serial1,,60W,35 14, #53 MS1_P1[15:8]=14 #20
,17.30ms,Serial1,,60W,36 C0, #54 MS1_P1[7:0]=C0 #192
,17.67ms,Serial1,,60W,37 00, #55 MS1_P3[19:16]=0,MS1_P2[19:16]
,18.06ms,Serial1,,60W,38 00, #56 MS1_P2[15:8]=00
,18.43ms,Serial1,,60W,39 00, #57 MS1_P2[7:0]=00
,18.81ms,Serial1,,60W,11 2F, #17 CLK1_PDN=0,MS1_INT=0,MS1_SRC=1,CLK1_INV=1,CLK1_SRC[1:0]=3,CLK1_IDRV[1:0]=3
,19.20ms,Serial1,,60W,34, #52 R1_DIV[2:0]=X,MS1_DIVBY4[1:0]=X,MS1_P1[17:16]=X,19.48ms,Serial1,,60R,00,X,20.17ms,Serial1,,60W,3A 00, #58 MS2_P3[115:8]=00
,20.57ms,Serial1,,60W,3B 01, #59 MS2_P3[7:0]=01
,20.95ms,Serial1,,60W,3C 01, #60 R2DIV[2:0]=0,MS2_DIVBY4[1:0]=0,MS2_P1[17:16]=1,21.32ms,Serial1,,60W,3D C0, #61 MS2_P1[16:8]=C0,21.69ms,Serial1,,60W,3E 00, #62 MS2_P1[7:0]=0
,22.07ms,Serial1,,60W,3F 00, #63 MS2_P3[19:16]=0,MS2_P2[19:16]=0
,22.44ms,Serial1,,60W,40 00, #64 MS2_P2[15:8]=00
,22.81ms,Serial1,,60W,41 00, #65 MS2_P2[7:0]=00
,23.18ms,Serial1,,60W,12 6F, #18 CLK2_PDN=0,MS2_INT=1,MS2_SRC=1,CLK2_INV=0,CLK2_SRC[1:0]=3,CLK2_IDRV[1:0]=3,23.57ms,Serial1,,60W,3C, #60 R2DIV[2:0]=X,MS2_DIVBY4[1:0]=X,MS2_P1[17:16]=X
,23.88ms,Serial1,,60R,01,X,24.18ms,Serial1,,60W,3C 61, #60 R2DIV[2:0]=6,MS2_DIVBY4[1:0]=0,MS2_P1[17:16]=1,24.56ms,Serial1,,60W,3C,
,24.83ms,Serial1,,60R,61,X #60 R2DIV[2:0]=X,MS2_DIVBY4[1:0]=X,MS2_P1[17:16]=X
,25.48ms,Serial1,,60W,03 00, #3 CLK2,CLK1,CLk0=0
途中読み込みを行うところがあるが、データが読み込めていないようだ。
また、設定されていないアドレスに、データを書き込んでいるところもちょっとナゾい。
オシロでデコードしたアドレスとデータをそのまま送信してみる
上記のでコードデータをPythonのプログラムで、I2Cで送信するだけのプロぐrサムに落とし込んでみると、下記のように書ける。
import smbus
#SMBusの引数に1を指定する。Raspberry Piのi2cバスの番号
i2c = smbus.SMBus(1)
#デバイスのアドレス 0x60
addr = 0x60
#
i2c.write_byte_data(addr, 0x03, 0xFF)
i2c.write_byte_data(addr, 0x10, 0x80)
i2c.write_byte_data(addr, 0x11, 0x80)
i2c.write_byte_data(addr, 0x12, 0x80)
i2c.write_byte_data(addr, 0x13, 0x80)
i2c.write_byte_data(addr, 0x14, 0x80)
i2c.write_byte_data(addr, 0x15, 0x80)
i2c.write_byte_data(addr, 0x16, 0x80)
i2c.write_byte_data(addr, 0x17, 0x80)
i2c.write_byte_data(addr, 0x1A, 0x00)
i2c.write_byte_data(addr, 0x1B, 0x01)
i2c.write_byte_data(addr, 0x1C, 0x00)
i2c.write_byte_data(addr, 0x1D, 0x10)
i2c.write_byte_data(addr, 0x1E, 0x30)
i2c.write_byte_data(addr, 0x1F, 0x00)
i2c.write_byte_data(addr, 0x20, 0x00)
i2c.write_byte_data(addr, 0x21, 0x00)
i2c.write_byte_data(addr, 0xB1, 0xA0)
i2c.write_byte_data(addr, 0x22, 0x00)
i2c.write_byte_data(addr, 0x23, 0x03)
i2c.write_byte_data(addr, 0x24, 0x00)
i2c.write_byte_data(addr, 0x25, 0x0A)
i2c.write_byte_data(addr, 0x26, 0x55)
i2c.write_byte_data(addr, 0x27, 0x00)
i2c.write_byte_data(addr, 0x28, 0x00)
i2c.write_byte_data(addr, 0x29, 0x01)
i2c.write_byte_data(addr, 0xB1, 0xA0)
i2c.write_byte_data(addr, 0x2A, 0x01)
i2c.write_byte_data(addr, 0x2B, 0x01)
i2c.write_byte_data(addr, 0x2C, 0x00)
i2c.write_byte_data(addr, 0x2D, 0x02)
i2c.write_byte_data(addr, 0x2E, 0x00)
i2c.write_byte_data(addr, 0x30, 0x00)
i2c.write_byte_data(addr, 0x31, 0x00)
i2c.write_byte_data(addr, 0x10, 0x4F)
#,14.36ms,Serial1,,60W,2C,
#i2c.write_byte_data(addr, 0x2C, 0x44)
#,15.06ms,Serial1,,60R,00,X
data = i2c.read_byte_data(addr, 0x00)
print(data)
i2c.write_byte_data(addr, 0x32, 0x00)
i2c.write_byte_data(addr, 0x33, 0x02)
i2c.write_byte_data(addr, 0x34, 0x00)
i2c.write_byte_data(addr, 0x35, 0x14)
i2c.write_byte_data(addr, 0x36, 0xC0)
i2c.write_byte_data(addr, 0x37, 0x00)
i2c.write_byte_data(addr, 0x38, 0x00)
i2c.write_byte_data(addr, 0x39, 0x00)
i2c.write_byte_data(addr, 0x11, 0x2F)
#,19.20ms,Serial1,,60W,34,
#i2c.write_byte_data(addr, 0x34, 0x00)
#,15.06ms,Serial1,,60R,00,X
data = i2c.read_byte_data(addr, 0x00)
print(data)
i2c.write_byte_data(addr, 0x3A, 0x00)
i2c.write_byte_data(addr, 0x3B, 0x01)
i2c.write_byte_data(addr, 0x3C, 0x01)
i2c.write_byte_data(addr, 0x3D, 0xC0)
i2c.write_byte_data(addr, 0x3E, 0x00)
i2c.write_byte_data(addr, 0x3F, 0x00)
i2c.write_byte_data(addr, 0x40, 0x00)
i2c.write_byte_data(addr, 0x41, 0x00)
i2c.write_byte_data(addr, 0x12, 0x6F)
#,23.8,23.88ms,8ms,Serial1,,60R,01,X
data = i2c.read_byte_data(addr, 0x01)
print(data)
i2c.write_byte_data(addr, 0x3C, 0x61)
#,24.56ms,Serial1,,60W,3C,
#i2c.write_byte_data(addr, 0x3C, 0x61)
data = i2c.read_byte_data(addr, 0x61)
print(data)
i2c.write_byte_data(addr, 0x03, 0x60)
これを実行してみると、下記のように表示された。
Readしたデータについては、結果がなかったが、下記のように表示されているのがわかる。