記事内に広告が含まれています

M5Stack対応DSPラジオモジュール 2nd editionの製作

M5STACK

はじめに


2023年に開催されたM5Stack Japan Creativity Contest へのエントリー作品としてM5Stack向けのラジオモジュールを製作しましたが、その時は、プロトタイプ製作を主目的としてのDSPラジオICの動作確認の意味合いが強く、最低限必要な回路で基板設計をしていた為、ハードウェア部分で満足できていない点がありました。そこで1年と数ヶ月ぶりに改めていくつかの改良を盛り込んだモジュールをリメイクしてみました。

M5Radio module designed by massa

2nd edition モジュールのハードウェアの機能

・モジュールの外観は写真の通りです。

外観図

・MBUSコネクタ:M5STACKとの接続に使用します。外観図の左上が1番端子です。
・イヤホン用ジャック:イヤホンを使用する場合はここに接続します。イヤホンはFMアンテナにもなります。
・音量調整用ボリューム:ダイヤル式になっており上下に回転させて音量を変更します。プログラミング次第で周波数変更用としても使用可能です。
・FMアンテナ用ジャック:FMアンテナの接続専用ジャックです。イヤホンアンテナより高感度なFMアンテナが別途準備できればこのジャックに接続することができます。

・AMアンテナ接続用スルーホール:ICのAM信号入力端子と接続されているスルーホールです。ここに、端子台(ターミナル)やピンヘッダなどを実装後(あるいはスルーホールに直接)AMアンテナを接続するとAM信号を受信することができます。

・スピーカ接続用端子:ICの音声出力からアンプを介して出力されているスルーホールです。小型のスピーカを直接接続すればモジュール内にスピーカを配置できます。端子を実装してモジュール外部にスピーカを接続するアレンジも可能です。

それでは前回の試作機 “M5Radio Module 1st edition” からのハードウェア面での改造点を簡単に説明します。

前回試作機からの主な改造点

外部スピーカー駆動用のアンプを実装

音声出力をイヤホンジャックからのみではなく、パッシブスピーカーからも出力できるように、アンプICをモジュール基板に実装し、出力端子としてスルーホールを設けました。
スピーカー駆動用のアンプ回路設計については、今回採用したオーディオアンプNS4150Bのデータシートに記載されている参考回路図に倣えば大きな問題は発生しないと思います。

audioアンプ周辺回路図

当記事の冒頭の写真のようにスルーホールに直接スピーカーの配線をはんだ付しても良いですし、コネクタやピンヘッダあるいはピンソケットなどを実装してスピーカーを着脱可能にしても良いでしょう。

Audio アンプ周辺の基板パターン図

オーディオ信号出力先の切替および内蔵アンプのON/OFF

オーディオ出力用イヤホンジャックにPJ307A(J1)を使用しており、イヤホンの挿抜で音声信号の接続先切替とSPDTスイッチの接続先切替を行うことができます。つまりこの機能を利用することで音声出力先をイヤホンジャックまたはアンプICのいずれかに選択することができ、かつ内蔵アンプICのON/OFFコントロールも行うことができます。
ここで内蔵アンプ使用時には、Leftチャンネルから音声信号を取り出す回路設計としているので、ソフトウェアにてKT0913のオーディオ出力がモノラルになるようにレジスタ設定をすることが良いと思います。

オーディオジャックの接続説明


なお、参考までに裏技的な設計ですが、チップジャンパーの実装箇所を変更しオーディオ信号の流れを変更することでM5Stack本体のG25端子に接続されている内部スピーカーを利用することも可能です。

外部FMアンテナ接続用コネクタを実装

上記1.に記載した通り、オーディオ出力端子にイヤホンを接続すると外部スピーカーからは音声が出力されない設計としているため、外部スピーカーを使用する場合には、イヤホンジャックに接続しているイヤホンをFMアンテナとして使用することはできません。そこで、外部スピーカーの使用時にアンテナを接続するためのアンテナ接続専用のΦ3.5mmジャック(J4)を実装しています。

外部アンテナ接続用コネクタ周辺回路図


なお回路図からわかるようにイヤホンをオーディオ出力端子に接続した状態で、外部アンテナ用ジャック(J4)にアンテナを接続して使用することも可能です。
外部アンテナ用ジャック(J4)に接続するアンテナとして、簡易的にはイヤホンを使用しても良いですね。

チャンネル選局用と音量調整用の可変抵抗器を統合

前回の1st edition Moduleでは周波数調整用と音量調整用にそれぞれ独立して可変抵抗器を使用していましたが、2nd editonでは可変抵抗器には音量調整またはチャンネル選局のいずれか一方の機能を割り当て、もう一方の機能はM5Stack本体の”A”,”B”,”C”ボタンに割り当てることにして一つの2連可変抵抗器を使用することにしました。
各自の好みによりますが、操作のし易さからすると可変抵抗器には音量調整の機能を、ボタンに周波数選局の機能を割り当てるのが良いように思います。

PCBA(部品実装)の製作について

半田付けが得意であっても、小さな面実装部品の点数が多いと時間と集中力が必要なり製作の重荷となってくるため、基板製造と合わせてPCBAを基板製造業者さんへ依頼しました。

ただし、今回依頼した部品実装業者が標準的に取り扱っている部品ライブラリにはKT0913は含まれておらず、実装依頼できないためこのICは自分ではんだ付けをしました。
(業者に部品支給をすればPCBAでの実装が可能と思いますが、送料や手番を考えると自身で手はんだ付けするほうがベターと考えました。)
今回は、普通に手はんだ付するだけでは面白くないので、クリームはんだと簡易リフロー装置というのかリワーク装置というべきなのか、MHP50(Miniware製)を使用しての部品実装を試してみました。

この装置は、電源ON後、設定した温度まで上昇し保温することになりますが、リフローモードというものがあり温度プロファイルに従った温度制御も可能となっています。
クリームはんだを塗布しICをフットプリントに仮置きした基板を装置に載せ温めて観察していると、じわじわとクリームはんだが溶けた後、フットプリントから少しずれて搭載していたICにセルフアライメントが働き、ICの実装位置がフットプリントにあうように自己補正されて、きれいに実装されていく様子がよくわかりました。
こういうアイテムがあると、作業が捗りますし、製作物もきれいに仕上がるので電子工作がアップグレードして楽しくなりますね。
続いて、挿入部品のオーディオジャックとM-BUSコネクタを手はんだ付けすれば完成です。
実は、はんだ付け用の小型ディップ層も所有しているのですが、挿入部品の半田付け作業でまだ使ったことがありません。試作台数が多くなれば使ってみようと思いますので、使用感はまた報告させて頂きます。

基板取り付け用のフレームについて

プロトペグモジュール13.2 を利用する場合

M5Stack本体と合体させるために、基板をフレームに取り付ける必要がありますが、13.2プロトペグモジュールは側面の加工がある程度可能な構造となっているため、オーディオジャック等が干渉する部分のフレームを切抜くことで基板を取り付けることができます

フレームの加工例として各側面の写真を貼付します。
なお、写真ではAMアンテナ接続用コネクタとしてターミナルブロック(緑色の部品)を実装しています。

イヤホン用ジャック部分の加工

イヤホンジャック側

アンテナ用ジャック部分の加工

アンテナジャック側

ボリューム部分の加工

ボリューム側

オリジナルフレームを使用する場合

市販されている13.2プロトペグモジュールのフレームを加工して利用することが簡単でお勧めですが、もう少しかっこよくするためにラジオモジュール専用フレームを3DCADで設計してみました。
筐体外部に飛び出すジャックと可変抵抗器のダイヤル部分のみをくり抜いており、汎用品のプロトペグモジュールのフレームと比べるとすっきりとした感じに仕上げることができたと思います。

Frame for M5Radio module designed by massa

ソフトウェアの設計

M5Stack Creative Contest 用に作成したプログラムをベースにいくつかの機能を実装してみました。
拙作なスケッチですがご参考までに一部分をご紹介します。

①M5Stack本体のボタン”B”に選局周波数のアップ、”C”に選局周波数のダウンを割り当てる

if (M5.BtnB.wasPressed() && dial == 0 && AM_FM == "FM"){
  REGISTER_ADDRESS = TUNE;
  I2CreadMULTIbyte();  // レジスタ値を読み込む関数を呼び出す
  data = (data + 0x0002) | 0B1000000000000000; // + 100KHz step
  if ( (data & 0B0000111111111111)  > 1882){  // >94.1MHz
    data = 0B1000010111110000; // 76MHz 1520 = 5F0
  }
  I2CsendMULTIbyte();  // レジスタ値を書き込む関数を呼び出す
}

if (M5.BtnB.wasPressed() && dial == 0 && AM_FM == "AM"){
  REGISTER_ADDRESS = AMCHAN;
  I2CreadMULTIbyte();  // レジスタ値を読み込む関数を呼び出す
  data = (data + 0x0001) | 0B1000000000000000; // + 1kHz step
  if ( (data & 0B0000011111111111)  > 1621){ // >1621KHz
    data = 0B0000001000001110 ; // 526KHz = 20E 
  }
  I2CsendMULTIbyte();  // レジスタ値を書き込む関数を呼び出す
}

if (M5.BtnC.wasPressed() && dial == 0 && AM_FM == "FM"){
  REGISTER_ADDRESS = TUNE;
  I2CreadMULTIbyte();  // レジスタ値を読み込む関数を呼び出す
  data = (data - 0x0002) | 0B1000000000000000; // - 100KHz step
  if ( (data & 0B0000111111111111) <1520) {  // <76MHz
    data = 0B1000011101011010; // 94.1MHz  1882
  }
  I2CsendMULTIbyte();  // レジスタ値を書き込む関数を呼び出す
}

if (M5.BtnC.wasPressed() && dial == 0 && AM_FM == "AM"){
  REGISTER_ADDRESS = AMCHAN;
  I2CreadMULTIbyte();  // レジスタ値を読み込む関数を呼び出す
  data = (data - 0x0001) | 0B1000000000000000; // - 1kHz
  if ( (data & 0B0000011111111111)  < 526){  // <526KHz
    data = 0B0000011001010101 ; // 1621KHz = 655 
  }
  I2CsendMULTIbyte();  // レジスタ値を書き込む関数を呼び出す
}

②イヤホンの未接続(M5StackのG16がHigh電圧)を検出してKT0913のオーディオ信号をモノラル出力に設定する

  REGISTER_ADDRESS = DSPCFGA;
  I2CreadMULTIbyte();
  mono = data & 0B1000000000000000 >> 15; // MONOのみを抽出してmonoに代入

if (digitalRead(G17) == LOW) {// when use earphone
    data = data & 0B0111111111111111; // set MONO = stereo(bit15=0)
    I2CsendMULTIbyte();
  }

else if (digitalRead(G17) == HIGH) {// when use speaker
    data = data | 0B1000000000000000; // set MONO = force mono(bit15=1)
    I2CsendMULTIbyte();
  }

③電源OFF前の受信チャンネルを記憶させて次回電源ON時に受信チャンネルを呼び出すようにする

#include <EEPROM.h>
uint16_t prefmfreq , preamfreq; //EEPROMに保存する周波数
・・・
・・・
void setup() {
  EEPROM.begin(24); // 例えば24byte分の保存領域を確保する
  eeprom_read(); //EEPROMから変数読み出す関数を呼び出す 
・・・
・・・
void eeprom_write(){ //EEPROMに変数を保存する関数
  EEPROM.put(0,prefmfreq);
  EEPROM.put(4,preamfreq);
・・・
・・・
  EEPROM.commit();
}

void eeprom_read(){ //EEPROMから変数を読み出す関数
  EEPROM.get(0,prefmfreq);
  EEPROM.get(4,preamfreq);
・・・
・・・
  EEPROM.commit();
}

④受信信号の品質を数値で参照できるようにRSSI,SNRの画面表示する

REGISTER_ADDRESS = STATUSA;
I2CreadMULTIbyte();
uint16_t statusa = data;
uint16_t fmrssi = (statusa & 0B000000011111000) >> 3; // FM RSSI bitのみを抽出して3ビット右へシフトしてRSSIの数字をfmrssiに代入
int16_t FMRSSI = -100+fmrssi*3;
M5.Display.printf("RSSI: %4d\n", FMRSSI);  // RSSIを画面に表示

REGISTER_ADDRESS = STATUSC;
I2CreadMULTIbyte();
uint16_t statusc = data;
uint16_t snr = (statusc & 0B0001111111000000) >> 6; // SNR bitのみを抽出して6ビット右へシフトしてSNRの数字をfmrssiに代入
M5.Display.printf("SNR: %d\n", snr);  // SNRを画面に表示

簡単ですが紹介動画はこちらになります。

おわりに

個人の電子工作であっても、基本的なアイデアを1st editionとしてまず形にして(rapid prototyping) 動作させることで改良点を洗い出し、2nd editonの詳細設計に盛り込むことが比較的安価にそして短期間で可能となっているこの令和の時代、本当に素晴らしく感心させられています。
なお、ラジオモジュール2nd editionはBOOTHにて頒布していますのでよろしければ下記のバナーからご覧ください。

コメント

タイトルとURLをコピーしました