Delphiでワンチップラジオを制御する(2)
前回(1)ではラジオワンチップICを使って、BAND、Up/Down、プリセット呼び出しまで行いましたので、今回はSEEK、A.MEMO(Auto Memory)を行ってみます。
4.SEEK
受信可能局を捜す機能ですが、今の受信周波数から+1ステップずつ周波数を変更して、受信可能局が見つかった所でSTOPします。
SEEKに求められる性能としては、
1)受信可能局を正しく選択する
2)速い方がベター
かと思われます。
日本ではラジオ放送局は多くなく、SEEKやA.MEMO機能はそれほど重要ではないかもしれませんが、海外は国営から地方のローカル放送までかなりの放送局が存在します。その為、正しく、速くは重要なファクターとなります。
受信状態を判断するパラメータとして、ラジオワンチップにはLevel、USN、WAM、FOFの4つがありますが、受信している状態と、していない状態でそれぞれを比較してみます。
USNやWAMが受信局でも違っていますが、音声や音楽などの音の大きさにも影響をうけますので、あまり厳しくすると受信可能局をみつけることができなくなります。なお、受信局Bは若干のノイズが認められる局です。また、未受信の局でもLevelが高めになっていますが、製品も分解した状態ですし、アンテナも単なるワイヤーなのが原因だと思われます。
局有りと判断するための閾値ですが、ノイズが出ていても多くの局を見つけるようにするか、少しのノイズも嫌がるか、好みになると思われますが、とりあえず下記のように設定します。
次はSEEKの速度ですが、76.0MHzから95.0MHzまで190ステップありますので、SEEKを1周で終了させるとして190回送信することになります。
begin
Header:=$55; //I2Cモジュールヘッダー
DB0:=$20; //DataByte0の設定値(Search)
T1:=TimeGetTime;
for i := 1 to 191 do
begin
if Last_FM=950 then Last_FM:=759;
Last_FM:=Last_FM+1;
//周波数表示
LabelFreq.Caption:=Format('%3.1f',[(Last_FM / 10)]);
//周波数設定
RX[0]:=$00; //戻り値を0でクリア
Set_Freq(Last_FM); //別procedureで受信周波数を送信
repeat
if RX[0]<>$01 then
begin
Application.ProcessMessages; //別procedureでRXを読み込み
end;
until RX[0]=$01; //I2Cモジュールからの戻り値を確認
MemoRX.Lines.Add('Set Freq Return:'+inttohex(RX[0]));
end;
//SEEK終了時のMute解除
DB0:=$10;
Set_Freq(Last_FM);
MemoRX.Lines.Add('SEEK Time : '+floattostr(TimeGetTime-T1)+'msec');
end;
上記のように、ワンチップラジオに対して周波数を送信して、I2Cモジュールからの正常戻り値を確認する処理を実行すると、バラつきはあるものの370msecくらいとなり、約2msec/ステップとなりました。
しかしながら、何度かやっていく中で途中でSEEKが止まってしまう現象がでてきました。I2Cモジュールからの正常な戻り値が返ってこないため、repeat文から抜け出せないようです。
強制的に抜けることも考えましたが、それでは周波数が正しく設定されていない場合もあり得るので、それは使えません。かなりの時間試行錯誤しましたが、結局は同じI2C BUS上にマイコンとPCのマスターが2つあることが原因でした。
前回の記事で「とりあえず問題ない」と書いたのですが、確かにちょっとしたコマンドを送るだけであれば問題はありませんでしたが、長い間BUSを占有する処理を行うと、隙間を狙ってマイコンが何か送ろうとして、ラジオワンチップから見るとおかしなコマンドになっているのかもしれません。
基本に立ち返り、起動時はマイコンからイニシャライズをさせ、その後マイコン側を切り離して、PCから処理を行うようにします。
次は受信状態を確認して、その局に止まるべきか、を確認します。
ラジオワンチップには取得した受信状態のパラメータの信頼度を表すQRSというデータがあり、長い時間を待つほど信頼度は上がります。
例えば、QRS=010ではLevelは取得できるが他のパラメータは信頼できない、QRS=011ではLevelは信頼できるが他のパラメータは取得できただけ、となります。QRS=101まで待てば信頼度は上がりますが時間がかかりますので、QRS=100で判断しようと思います。
判断は同じようにrepeat文を使って、Set_Freqの後に以下を追加しました。これはrepeat文の中でSet_Statusで読み込みを何度も行うようにしています。
until RX[0]=$01;
MemoRX.Lines.Add('Set Freq Return:'+inttohex(RX[0]));
//ここから追加
repeat
Set_Status(Last_FM); //別procedureでパラメータの読み込み
if ($80 > RX[0]) or (RX[0] > $AA) then //$80
begin
WaitTimer(0);
end;
if Det_Station(Last_FM)=$01 then //別procedureで受信状態を判断、$01はSTOP
begin
DB0:=$10;
Set_Freq(Last_FM); //SEEK終了時のMUTE解除
MemoRX.Lines.Add('SEEK Time : '+floattostr(TimeGetTime-T1)+'msec');
Exit;
end;
until RX[0]>($80-1);
//ここまで追加
end; //for文のend
90.2MHzでSTOPした状態が下記となります。
最初にQRS=001($20)を読んで、次にQRS=100($80)を読んでSTOPする判断を行っています。ひとつ前の90.1MHzではQRS=011($60)も読み込めています。ここはタイミング次第ですね。
SEEK一周の時間ですが、アンテナを外した状態で4000~4100msec程度でした。治具にしているCD Tunerが5秒程度ですし、Wide FM対応にしていて50ステップ(90~95MHz)増えているので、まずまずの結果だと言えます。
閾値ですが、FOFが2kHzでは止まらないことがあるため、8kHzに設定しなおしました。この値では、判断に使う意味はなさそうですが。
次はAM、と言いたいところですが、現在の環境では受信できる局がないので見送ります。
AM放送自体が停波の方向に向かっていると思われ、実際に欧州ではどんどん停波されているようです。欧州の人々は車で遠い場所にバカンスに行っても自国の放送が聞きたいという需要から、LW(153~282kHz)やSW(5800~6250kHz)も求められていましたが、AM受信機の需要がなくなりそうですね。そういえば何かで見たのですが、ノルウェーはFMも停波して、DAB(Digital Audio Broadcast)に完全に移行するようです。
DABが市場に出てきて20年以上経っていますが、とうとう本格的な普及期に入ったようです。欧州の人たちの、じっくり取り組む姿勢は見習うべきな点がありますよね。アメリカは打ち上げ花火のようにFMX、AMステレオ、iD Logic、RBDSとかが出てきましたが、今はレガシーになっています(SiriusXMなど続いているものもあります)。
5.A.MEMO
SEEKの応用で、76.0MHzから95.0MHzまで受信可能局を捜し、電界強度の強い順や、周波数順などで並び替えてプリセットにメモリーする機能です。
今回はメモリーするのではなく、グラフにLevel、USN、WAMを表示してみます。
一旦76.0MHzに設定して、そこからSEEKをさせます。ただし、パラメータの読み込みはQRS=101($A0)で行うこととします。
begin
//グラフのクリア
FMBand.series[0].Clear; //Level
FMBand.series[1].Clear; //USN
FMBand.series[2].Clear; //WAM
T1:=TimeGetTime;
Header:=$55;//I2Cモジュールヘッダー
DB0:=$20; //DataByte00hの設定値(Search)
FrmMain.Set_Freq(760); //一旦Fminに設定
FrmMain.Show_Freq(760);
for freq_amemo := 760 to 950 do
begin
//周波数表示
FrmMain.LabelFreq.Caption:=Format('%3.1f',[(freq_amemo / 10)]);
RX[0]:=$00;
//周波数を設定
FrmMain.Set_Freq(freq_amemo);
FrmMain.MemoRX.Lines.Add('Set Freq:'+inttostr(freq_amemo));
//I2Cモジュールの戻り値の確認
repeat
if RX[0]<>$01 then
begin
Application.ProcessMessages;
end;
until RX[0]=$01;
FrmMain.MemoRX.Lines.Add('Set Freq Return:'+inttohex(RX[0]));
//パラメータ読み込み
repeat
FrmMain.Set_Status(freq_amemo);
if ($A0 > RX[0]) or (RX[0] > $AA) then //$A0
begin
FrmMain.WaitTimer(0);
end;
until RX[0]>=$A0; //QRS=101
FrmMain.MemoRX.Lines.Add('QRS:'+inttohex(RX[0])+','+inttostr(RX[1])+','+inttostr(RX[2])+','+inttostr(RX[3]);
//グラフを描画
FMBand.Series[0].AddXY(freq_amemo/10,RX[1]); //Lvl
FMBand.Series[1].AddXY(freq_amemo/10,RX[2]); //USN
FMBand.Series[2].AddXY(freq_amemo/10,RX[3]); //WAM
end;
//A.MEMO前の周波数に設定
DB0:=$10;
FrmMain.Set_Freq(Last_FM);
FrmMain.LabelFreq.Caption:=Format('%3.1f',[(Last_FM / 10)]);
FrmMain.MemoRX.Lines.Add('A.MEMO Time : '+floattostr(TimeGetTime-T1)+'msec');
end;
1周するのに9.3秒ほどかかっていてQRS=101とした影響が出ていますが、FM帯域内のグラフ化を目的としていますのでこれで良いと思います。製品でA.MEMO動作をさせるならば、高速化が必要ですが。
それ以上に驚いたのは、受信環境です。思った以上のノイズが存在していて、AMが受信できないのも理解できます。PCからのノイズですかね。
グラフの見方で注意しなければならない点は、LVL(Level)は大きい値が良い状態ですが、USNとWAMは小さい値が良い状態となります。
6.おわりに
ラジオワンチップICへのイニシャライズ処理を行っていませんので、中途半端になっていますが、余裕があるときに作ってみようと思っています。
今後ラジオ放送はインターネットで聞く時代に移って、AMやFMなどを受信するという事はなくなっていくと思われます。高周波やアナログというキーワードの技術が廃れていくような気がしているのは私だけでしょうか。現在このフィールドに関わっているエンジニアの方々のノウハウを、生かせるようになって欲しいです。
この記事が気に入ったらサポートをしてみませんか?