#はじめに
- RDA5807では、特定周波数の受信には成功したので、SEEK機能に挑戦。
- モジュールは、Aliexpressにて調達してみた。1枚40円。送料込みで4枚で250円。安すぎ。
- SEEK機能での選局だが、単純な形であればそれほど難しくなかった。
#使用したもの
- RDA5807Mモジュール (Aliexpress)。
- IC(RDA5807M)のデータシート
- AN230(Silicon Labs)
- Arduino Uno互換機(ELEGOO)
#モジュールについて
- Aliexpressで入手したモジュールだが、Aitendoさんで「取り扱い終了版」となっているものと同じように見える。また、AMAZONで売っているものとも同じ外見。
- ピン配置は、AITENDOさんの「RDA5807-M」と同じ(「RDA5807-M2」とは異なる)。
#配線
#Slaveアドレスについて
- ここでは 0X11(個別レジスタ書込/読込用)を使います。普通のコードで読み書きできます。
#コード作成のポイント
- RDA5807はSi4702の上位互換のようなICなので、Si4702のProgramming Guide(AN230)が参考になる。SEEKの場合、Table 14を参照すればよい。具体的には以下を設定する。
- SKMODE:SEEKを周波数帯の端で止めるか、1周して続けるか(Wrap)。→ Wrap
- SEEKUP:SEEK方向を上にするか、下にするか。→ 上にする。
- SEEK bit:SEEKを開始するときに1にする。
- その他の設定はそのまま。BAND、SPACEを特定周波数を受信するときと同様に設定する。
- SEEK機能はこれだけでOK。これで何かしら放送を受信するはず。ただし、ICから情報を読み取らないと、何を受信しているかがわからない。
#情報の読み取り
- 必要な情報はレジスタ0Ahと0Bhに格納されるので、これらのレジスタを読みだす必要がある。ここでは、シリアルモニタに表示することにするが、LCDに表示するのも容易。
- 受信している周波数(CHAN): 0Ah.[9:0]
- 受信完了フラグ(STC): 0Ah.[14]
- SEEK失敗フラグ(SEEKFAIL): 0Ah.[13]
- 受信強度(RSSI): 0Bh.[15:9]
- 局かどうか(STATION): 0Bh.[8]
- これらをレジスタから読み込んで、適当に表示をすればよい。
#プログラムの構造
- 上記の情報は、選局(SEEK)が完了(STC==1)してから読み出すべきだが、選局は直ぐ終わる場合も、時間がかかる場合もあり、情報を読み出すタイミングがわからない。早く読み出しすぎると、受信が完了していない時点の周波数を読んでしまう。
- なので、一定時間ごと(0.5秒)に0Ahを読み込み、STCフラグが1になればそこで、読み取りを終わらせることにした。
- なお、本ICのファミリーである5807FPには、STC==1になるとパルスを出すGPIOピンがあり、このピンで割り込みをかけることもできるようになっている。
- コードはloop()は使わず、setup()の中で処理しています。
- プログラムは、1回選局するとそこで終わりになります。プログラムを続けて走らせると、前回に選局した局からSEEKを開始します。
#選局基準(SEEKTH)
- レジスタ05h.[11:8]に選局の基準となるSEEKTHが定められている。大きすぎると、弱小局を拾わないような気がしたので、少し小さくしています(詳細はよくわかりません)。
#動作コード
- 76 → 108MHzの間でSEEKし、最初に見つけた局の周波数などをシリアルモニタに表示し、そこで終了する簡単なコードです。
- 選局終了後、もう一度走らせると、前回選局した周波数からまた、SEEKを開始します。上限まで行って見つからないと、下限からSEEKを続けます。詳細はコードとデータシート見てください。
#include <Wire.h>
int buffer1;
int buffer2;
int buffer3;
int buffer4;
void setup()
{
delay(200);
Wire.begin();
Wire.beginTransmission(0X11);
Wire.write(0X03);
Wire.write(0b00000000); // CHAN NA
Wire.write(0b00001000); // TUNE0, BAND10, SPACE00
Wire.endTransmission();
Wire.beginTransmission(0X11);
Wire.write(0X05);
Wire.write(0x84); //SeekTh 0100
Wire.write(0x8F); //VOL1111
Wire.endTransmission();
Wire.beginTransmission(0X11);
Wire.write(0X02);
Wire.write(0xc3); //seek up, seek on
Wire.write(0x05); //seekmode0(wrap)
Wire.endTransmission();
delay(100);
boolean stc=0;
while (stc==0)
{
Wire.begin();
Wire.beginTransmission(0X11);
Wire.write(0X0a);
Wire.endTransmission(false);
Wire.requestFrom(0x11,4); //reading 5807
Wire.endTransmission(true);
buffer1= Wire.read(); //0AH
buffer2= Wire.read(); //0AL
buffer3= Wire.read(); //0BH
buffer4= Wire.read(); //0BL
int freq= 760 + 512*bitRead(buffer1,1)+ 256*bitRead(buffer1,0)+ buffer2;
stc=bitRead(buffer1,6);
boolean seekfail=bitRead(buffer1,5);
byte rssi = buffer3>>1;
boolean station = bitRead(buffer3,0);
Serial.begin(9600);
Serial.print("STC:");
Serial.print(stc);
Serial.print(" SeekFail:");
Serial.println(seekfail);
Serial.print("Freq*10:");
Serial.print(freq,DEC);
Serial.print(" RSSI:");
Serial.print(rssi,DEC);
Serial.print(" Station:");
Serial.println(station);
delay(500);
}
}
void loop() {
// put your main code here, to run repeatedly:
}
#おまけ
- 天井から垂らした電線をアンテナにしていますが、当方の環境(東京)では、主要な局はちゃんと選局できています。どこの局かわからない周波数を選局するときもありますが…
- 割込みによるプログラムも試してみたかったので、RDA5807FPも使ってみました。5807FPについては、乾電池駆動の箱ラジオを作成したので、後日公開予定です。