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したデータについては、結果がなかったが、下記のように表示されているのがわかる。
オシロ ででコードしたデータをI2Cの送受信コードに書き換えて実行