DSP(デジタルシグナルプロセッサー)FMラジオの製作
FMradio
 雑誌の記事(三才ブックス「ラジオマニア」2021年8月発行号)に触発されて、数十年ぶりにラジオを製作しました。と言っても、FMラジオ受信回路は通販のユニットを使用しています。
 ラジオ少年だった昔に作ったAM5球スーパーラジオや短波帯受信機と違い、FMのステレオ受信ともなると回路も非常に複雑になり、とてもではないけれどトランジスタやICで最初から組み上げていく自信はありません。千円ちょっとで優秀なFMステレオラジオ基板が簡単に入手できるので、それを利用して外観は少 し昔風の据置き型FMラジオを作ってみることにしました。
 とことんアンティーク風に丸みを帯びた外観に仕上げられると面白いのですが、難しい木工作は出来ないので、最初から諦めて角型の外観です.....。
 前面のアルミパネルには、インクジェットプリンターで印刷可能な透明粘着シートを貼り付けて文字を表示しています。DSPと印字すべきところを間違ってDPSとなっていますが、貼り直すのも面倒なので気にしないことにしています。

 ユニットに電源とアンテナとスピーカーを接続すれば、ラジオが出来てしまうのですが、いくら何でもそれでは面白くありませんので、今回はマイコン(Arduino)を使って、プリセット局を選べるようにもしてみました。LCDディスプレイもつけて、選局中のラジオ局のデータも表示します。
 製作の上で面倒なのは、筐体(私はいつも木工)とArduinoのプログラミングぐらいです。
 ラジオユニットとArduinoの電源は両方とも5Vで動作しますので、電源には乾電池を使わず、モバイルバッテリーを使っています。

parts unit
主なパーツには以下の物を使っています。
・DSP方式 MFステレオラジオユニット ---- D DOLITY   DSP  PLLステレオFMラジオレシーバーモジュール (ワイドFM対応。Amazonで購入。中国製? 説明書は無し。)
・マイコン Arduino ---- 通常のArduino UNOです。
・LCDディスプレイ ---- 16桁 x 2行のモノクロディスプレイ。バックライトなし。(  I2Cインターフェースモジュール無しのタイプなので、配線数はちょっとだけ多くなります。)
・ステレオスピーカー ---- 百均CanDoで買った550円のステレオスピーカー。付属の3Wアンプは低域がカットされているようなので、取り外しました。ラジオユニット内蔵の3Wアンプを使います。
・木材 ----12mm厚前後のものが細工しやすいと思います。
・モバイルバッテリー ---- ラジオユニットの他にマイコンと LCDディスプレイの電源となりますので、ある程度の容量が要りますが、5000mAHもあれば十分です。
・ロータリーエンコーダー --- 1個使っています。ラジオ少年だったころは高価な部品でしたが、今はとても安価です。ただし粗悪品に注意。チャタリングだらけの信号を出す安物もあるようです。

スピーカーの構造
 CanDoのスピーカーはお値段の割には良い音ですが、やはり低域の物足りなさを感じますし、筐体がプラスチックなので出てくる音もプラスチック味です。
 そこでラジオユニットとスピーカーを一体型とし、スピーカー部分は低音を増強したいのでバスレフ構造にしました。ただ、複雑な音響計算はしていない(出来ない....)ので、単なる「箱」と比べて効果が出るかどうかは分からないまま製作をしました。謂わば”バスレフもどき”構造です。
 結果としては、何となくですが、締まりはないものの低音が強めに出るとは思います。男性アナウンサーの声はちょっとボンつく感じにも聞こえます。クラッシック曲は低域が広がっていい感じです。この辺りは使う木材の厚みや材質などでも変わると思われます。
speaker
 組み立てはほとんど木工用ボンドを使用しました。たっぷり塗って、切り出しの下手さによる隙間を埋めています。
 仕上げ前に、スピーカー部の箱の中に柔らかい布を入れて音の乱反射を防いでいます。私は書道用のフェルト風の下敷きを使いました。テストした結果では、入れても入れなくてもあまり音の変化は感じられませんでした。



ユニット類の組み上げ
 筐体が木製なので、取り付けはステンレス木ねじを使います。アルミケースのような穴開けが要らないので、自由度が高くて楽ちんです。
wirering
 LCDは配線数が多くて細かであり、かつ全面パネルに取り付けるので、先に配線の半田付けを済ませてからパネルに取り付けます。
 狭い箱内にFM受信ユニットとマイコンユニットがあるので、ノイズが気になりましたが、結果としては大丈夫でした。受信音にノイズは感じられません。



Arduinoのプログラミング

 FMラジオユニットにあるツマミで周波数変化(選局)は出来ますが、0.1MHz単位でしか変化しません。また局シーク(サーチ)機能もありますが、上方向にしかシークしません。これでは広いFMバンド内を選局するのに非常に面倒です。
 そこでマイコンでよく聞く局をプリセットしておいて、それを選ぶこともできるようにしました。FMラジオユニットのツマミでの選局もそのまま出来ますので、両方を使えば割とスムーズにバンド内を移動できます。
 FMラジオユニット基板にはTx,Rx端子がありますので、外部のマイコンからコマンドを送り込んで幾つかの操作が出来ます。私はArduinoでプログラミングしました。
 使えるコマンドは購入するユニットによって違うようですが、私の入手したものは「ラジオマニア」で紹介しているものと同じでした。
 必要なコマンドは多くありません。
  選局UP -- AT+FREQADD   選局DOWN -- AT+FREQDEC          選局サーチUP -- AT+SEEKUP   選局サーチDOWN -- AT+SEEKDOWN   選局サーチ中止 -- AT+PAUSE
  選局周波数指定(例82.1MHz)-- AT+FREQ=821  (760~1080まで設定可能)

  その他に音量に関するコマンドもありますが、ラジオユニットについているボリウムつまみで操作できるため、今回製作のラジオでは音量コマンドは使いませんでした。
 プログラムをArduinoに書き込む時の注意点ですが、ArduinoのTx,Rx端子を開放していないと、プログラム書き込みが出来ません
 面倒ですが、プログラムを書き込んだ後でFMラジオユニットとArduinoのTx,Rx端子同士を繋げます。ArduinoのTx端子とラジオユニットのRx端子を、ArduinoのRx端子とラジオユニットのTx端子を繋げます。

 私はロータリーエンコーダーを1個使用して、プリセットした局を呼び出す機能のみをプログラミングしましたが、ラジオの実用上ではこれで十分な機能です。
 ロータリーエンコーダーはクリックリッとしたクリック感のあるタイプと、クリック感のないタイプの物がありますが、クリック感のあるものは1クリックの間に複数のパルスが出力されますので、プログラミングによって不要なパルスは無視するようにしておきます。
 私の使用したものは1クリックで4パルス出力されるようでした。出力を検知して回転方向を決定するときに、4個の検知出力のうち1個だけを拾い出しています。

参考までにArduinoのスケッチを記載します。
 なお、電源ON時に、OFF前に選局していた局を呼び出すために、変数の記憶が消えないEEPROMのアドレスを使用しています。EEPROMは書き込み回数に数万回とかの制限があるようですが、日常で普通に使っている分には気にすることはない制限だと思います。もし制限回数に達したら、書き込みアドレスを 変更す るだけで対処できるはずです。
 プリセット局最大数(スケッチ内の変数:maxchannel)は10局で使っていますが、switch  case文のところで自由に増減できます。増減した場合は int maxchannel=10 の設定数値も10から他の数値に変更しておきます。

 ロータリーエンコーダーの回転方向の判定は、出力値Aを1ビットシフトしてから出力値Bとの(OR)をとるビット演算で行っていますが、この方法はBackyさんから教えていただきました。たったの1行で回転方向の判定ができます。右回転なら十進数0,1,3,2の順で値が出力され、左回転なら 0,2,3,1の順 で値が出力されるので、ある数値の次に何が出てくるかを判定すれば回転方向が分かる訳です。
 
// DSP FM radio control program v3:
// FMラジオ基板のRX,TXポートと通信し、周波数を制御する:
// Arduino UNOを使用:
// EEPROMでスイッチOFF前のラジオ局を記録し、ON時に呼び出す :
// EEPROMの寿命は10万回? :

#include <EEPROM.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(12,11,5,4,3,2);

int na,nb;         // エンコーダー pinA,pinBの値:
int enc;           // エンコーダー判定flag 0,1,3,2:
int newEnc,oldEnc;
int cntEnc=0;     // エンコーダーチャタリング対策用カウンタ:
int maxEcnt=100;
int rotated=0;      // flag for encoder move 1ならばcntEncが加算される :
int channel;      // プリセットチャンネル :
int maxchannel=10; // チャンネル最大数 :

void setup(){
  Serial.begin(9600);   // serial1 for FM radio module :
  lcd.begin(16,2);      //16文字x2行のLCD使用 :
  lcd.clear();
   pinMode(7,INPUT_PULLUP);  // Encorder pinA:
   pinMode(8,INPUT_PULLUP);  // Encorder pinB:
  delay(1000);
  channel=EEPROM.read(0);
}

// ------周波数プリセット&局名表示関数--------------- :
void FreqSet(int ch){
 lcd.clear();
 switch (ch){
  case 1:  
    lcd.print("FMFukui JOLU-FM");
    lcd.setCursor(2,1);
    lcd.print("76.1 MHz 1Kw");
    Serial.write("AT+FREQ=761");
    break;
  case 2:
    lcd.print("Fukui Machikado");
    lcd.setCursor(2,1);
    lcd.print("77.3 MHz 20w");
    Serial.write("AT+FREQ=773");
    break;
  case 3:
    lcd.print("TannanFM");
    lcd.setCursor(2,1);
    lcd.print("79.1 MHz 20w");
    Serial.write("AT+FREQ=791");
    break;
  case 4:
    lcd.print("NHK-FM JOFG-FM");
    lcd.setCursor(2,1);
    lcd.print("83.4 MHz 1Kw");
    Serial.write("AT+FREQ=834");
    break;
  case 5:
    lcd.print("ZIP-FM JOQV-FM");
    lcd.setCursor(2,1);
    lcd.print("77.8 MHz 10Kw");
    Serial.write("AT+FREQ=778");
    break;
  case 6:
    lcd.print("FMAichi JOCU-FM");
    lcd.setCursor(2,1);
    lcd.print("80.7 MHz 10Kw");
    Serial.write("AT+FREQ=807");
    break;
  case 7:
    lcd.print("Mie-FM JONU-FM");
    lcd.setCursor(2,1);
    lcd.print("78.9 MHz 3Kw");
    Serial.write("AT+FREQ=789"); 
    break;
  case 8:
    lcd.print("Tsuruga-FM");
    lcd.setCursor(2,1);
    lcd.print("77.9 MHz 20w");
    Serial.write("AT+FREQ=779");  
    break;
  case 9:
    lcd.print("NHK-R1 JOFG");
    lcd.setCursor(2,1);
    lcd.print("86.8 MHz 100w");
    Serial.write("AT+FREQ=868");
    break;
  case 10:
    lcd.print("FBC JOPR");
    lcd.setCursor(2,1);
    lcd.print("94.6 MHz 1Kw");
    Serial.write("AT+FREQ=946");
    break;
 }
  delay(100);
}

// ------------------------------------------------ :
void loop() {

// pin7-8 ロータリーエンコーダー判定---------:
      na=digitalRead(7);
      nb=digitalRead(8);
      enc=(nb<<1) | na;     // make flag  0,1,3,2:
   if (enc!=newEnc){        // encoder moved!:
    rotated=1;              // moved flag :
    cntEnc=0;
    newEnc=enc;
   }
   if (cntEnc==maxEcnt){
     switch (oldEnc){
      case 0:
          break;
      case 1:
         break;
      case 2:           
         break;
      case 3:
         if (enc==1){
           channel--;
         }
         else if (enc==2){
           channel++;
         }
         delay(10);
         break;
     }
    if (channel==maxchannel+1){channel=1; }
      else if (channel==0) {channel=maxchannel; }

    FreqSet(channel);   // プリセット局名&周波数表示 :
       rotated=0;
       cntEnc=0;
       oldEnc=enc;
       newEnc=enc;
       EEPROM.write(0,channel);
   }
    else if(rotated==1){
      cntEnc++;
   }
}


回路図と前面パネルの様子です。
 概略図です。GRAND接続は、基本的な接続以外は回路表記せず省略してあります。
回路  panel

 ノイズフィルターはフェライトコアに1mm径ぐらいのエナメル線を10回~20回巻きつけたものです。効果のほどは未知数ですが、音を聞く限り電源ラインからのノイズ回り込みは無いようです。
 電源ラインにある100~200μFの電解コンデンサーは、耐圧に注意が必要です。25v以上の方が安全です。電源ON,OFF時のサージ電圧等を緩和するためにも、このコンデンサーは入れるべきです。
 
 全体として、据え置き型FMラジオとして便利に使えていますが、プログラム上ではスイッチON時の局の呼出し方が、ちょっとスマートで無いのが気になってはいます。
 スピーカーはやはりもう少し良いものを使った方が良かったかもしれません。その場合はアンプユニットも別に準備するのがベターです。音声出力はラジオユニットにあるイヤフォン端子から取り出せます。

 元々のFMラジオユニットにある2つのツマミは、選局と音量を操作するものですが、プッシュしてスケルチ機能などが操作できます。
 説明書が入っていないうえに、ちょっと分かりづらいので、AMAZONの商品ページでも質問が出ていました。覚えにくいのでラジオの前面パネルに操作項目を印刷しておきました。
  左ツマミの短押し --- 周波数シークUP     右ツマミの短押し --- 音声ミュート
                         右ツマミの長押し --- スケルチON/OFF
  左ツマミの長押し --- スケルチレベル---------->右ツマミを回してスケルチレベルの増減(値を決定)

  スケルチのレベル調整は左ツマミと右ツマミと両方を使って行う訳です。

 ホームページTOPに戻る

inserted by FC2 system