齢寿天任せ

写真付きで日記や趣味を書くならgooブログ

Bluetoothを使ってESP32のRTC(時計)を設定する

2024-07-07 13:44:32 | 電子工作
DSPラジオのコントローラ(MCU)に時計機能を持たせるととても便利である。
ESP32にはWiFi機能があり、NTPを参照すれば現在時刻を得て、ESP32のRTC(時計)を設定することができる。この方法には2つ難点がある。WiFiのアクセスポイントが必要な点と、SSDとパスワードをプログラムに記述する点である。
他に何か方法はないかと思案して、ESP32のBluetoothは利用できないか調べて見た。最初、Bluetoothを使って、スマホの時刻を参照できないものかと考えた。BluetoothにはGATTという規格があり、その中に「Current time」サービスがあることに気が付いた。ESP32からスマホに問い合わせれば時刻が分かりそうである。しかしながら、スマホの「Current time」サービスは常時動作しているものではなく、このサービスを起動した上で、スマホ側から通知(notify)してもらわないといけないらしい(iPhone対応のライブラリを見つけたが、iPhoneが無い上に、コンパイルがエラーになったので評価できず)。その様な便利なスマホのアプリはないかと検索してみたが見つからなかった。
次に、ESP32側で「Current time」サービスを動作させて、外部から時刻を設定することはできないかを検討することにした。GATTのサービスを動作させる方法や外部から値を書き込む方法については、ネット上に先達の参考資料(ツールとして「nRF Connect for Mobile(スマホアプリ)」の使い方も含む)等があり、目途がついた。
一方、外部からBluetoothを使ってESP32にアクセスするには、スマホ(Android)のプログラムを作成する必要があるが、これについては、数年前に経験があるものの、開発環境とスキルの再構築には時間がかかりそうなので、諦めた。他に何かないか調べてみると、「Web Bluetooth」という技術があり、例えばPCのブラウザからBluetoothを使ってESP32にアクセスすることができそうである。
さらに手っ取り早い方法として、Googleのサイトにサンプルがあり、Chromeを使って試すことができる。ただし、PCにはBluetooth機能(内蔵)かBluetoothのUSBドングルが必要である。またはスマホのChromeからでも試すことができる。
ESP32上に「Current time」サービスを動作させるためのスケッチ(ArduinoIDE2.0で作成)はGitHubに登録してある。また「Web Bluetooth」を利用して、PCのブラウザからBluetooth経由で、このESP32にアクセスして現在時刻を設定するHTMLも登録してある。スマホ(Android)のChromeでの動作も確認した。なお、上のスケッチには「Lチカ」を行うコードも含めてある。今後、DSPラジオの制御にも使えそうである。写真は実験の様子。


プリント基板の設計コンテストに応募してみた

2024-05-22 18:06:52 | 電子工作
前回のプリント基板制作では、リカバリしたものの、凡ミスがあった。このブログを見たPCBWAYの担当者さんから「再挑戦しませんか。支援しますよ」という連絡があり、私もリベンジしたいと思っていたので、お誘いに応じることにした。
修正は、部品の配置を見直して、抵抗を2本を追加するだけなので難しくない。ただし、チェックは念入りに行った。
注文のためにPCBWAYのサイトを見たところ、”KiCad Open Source Design Contest”の募集(4/2-6/2)を行っているのに気が付いた。
PCBWAYでは、ユーザーによるPCB(プリント基板)設計の成果を共有するための”共有プロジェクト”を実施している。
”共有プロジェクト”では、定期的にコンテストを実施していて、丁度、今が募集期間になっている。入賞者には賞金が授与されるとあったが、こちらは参加賞の”Pi Pico”を狙うことにした。大急ぎで、再注文し、PCB上での動作を確認して応募すれば間に合うと考えた。
PCBの注文時に、PCBWAYの担当者さんに連絡したところ、なんと費用の全額をアカウントに入金してくれた(感謝です)。
修正版のPCBは、注文から7日目に到着、PCBが設計通りであることを確認後、早速、部品の実装にとりかかる。その翌日、動作にも問題がないことを確認できたので、ひとまず安堵。いよいよ、コンテストへの応募に着手である。
コンテストには、応募サイトから以下の物を登録する必要がある。
  • 簡潔な説明文(英語、140字以内)
  • ガーバーデータ(基板の設計データ、KiCadで出力)
  • 説明文(英語、簡単なエディタがある)
  • 実物の写真
  • 回路図(KiCadにて作成済)
  • プログラム(GitHubに登録されていたライブラリのサンプルを改修)
  • 部品表(KiCadで作成)
  • 使用した設計ツール(KiCad、Arduino IDE)
プログラムについては、ライブラリのサンプルがArduino pro mini対応であった物を、Pi Pico対応に改修し、若干の機能追加した物をGitHubに登録した。
既に、”共有プロジェクト”に公開されているので、応募の審査はパスしたようである。
なお、今回の成果は、埃避けのアクリルケースに収容し、受信性能の確認中である。


プリント基板の制作 SI4732&Pi Pico編

2024-04-24 16:06:13 | 電子工作
【末尾に追記あり】
プリント基板制作の第2弾である。以前、Arduino Pro MiniとSI4732の組み合わせで製作した物をRaspberry Pi Picoとの組み合わせで再製作する。
以前の物は、ブレッドボード上に製作し、評価した後、放置してあった。受信感度(AM)がそれ程でもなく、音が出力不足(スピーカー使用時)で歪む(特にFM)ため常用する気にならなかったからである。
SI4732とPi Picoの組み合わせでの動作確認 (スケッチ、接続情報はこちらを参照)は済んでいるので、感度と音の問題をどう解決するかが課題である。
感度向上については、トランジスタ(S9018)による高周波増幅を1段追加することにした。ブレッドボード上で評価したところ、中波での効果が認められた。
音の出力と歪みについては、オペアンプによる増幅回路を追加することにした。音が歪む原因については、SI4732のデジタル信号処理から高周波成分が漏れるためであるとの記述(真偽は不明)があったので、ローパスフィルタ付属の回路構成を採用することした。
オペアンプはNJM4580(低雑音仕様、旧新日本無線)を選択した。回路はローパスフィルタ付非反転増幅回路と呼ばれるタイプである。増幅率は計算上、5.7(回路図より、”1+R1/R13=1+39/8.2”)である。電源は5Vの端子から、仮想電源経由で±2.5Vを得ている。
ローパスフィルタはブレッドボード上でのCR(コンデンサと抵抗)定数評価においては、まあまあの結果(体感で歪みが低減)が得られた。
決定した回路図を以下に示す。なお増幅回路の入力部にCRによるローパスフィルタを追加している。CR定数はオペアンプ部も含めて、カットオフ周波数が18KHzから20KHz(大雑把です)程度になるように選択している。
汎用目的のため、Pi Picoのモジュールの両サイドにピンヘッダーを設置し、Pi Picoの各入出力ピンに接続できるようにしている。

プリント基板の設計では、いくつか注意点がある。
まず、回路図の配線において、ピンヘッダーのフットプリントは2列のものを用いたが、Pi Picoのモジュールに直結するとピンの順番が正しく対応しなくなり、番号付けが狂った”NET”の情報ができてしまう。そのためピンの番号順をフットプリントエディタで修正したフットプリントを作成した。
また、ピンに外からの配線(SI4732からの配線)を接続する場合は、直結すると”NET”の情報が生成されず、”NETなし”になってしまう。そのままプリント基板の配線を行うと、最後のDRC(デザインルールチェック)において、「配線がパッドに近すぎます」というエラーになる。面倒でも、ピンヘッダーを少し離して、1本ずつ配線を描き、配線の接続点を明確にしておく必要がある。
同じく”NET”に関する問題で、電源はPi Picoの3V3とVSYSに接続するが、外部からの”電源”として”3V3”と”5V”を定義しておかないと”NET”の情報が正しく生成されない。
上のように対応しても、2列のピンヘッダーの外側のピンには”NET”の情報が生成されないので、PCBエディタにおいてピンのプロパティに”NET”の名称を追記する必要がある。
まともなNETリストができるまでは、回路図エディタとPCBエディタの間を何度も行き来する必要がある。
PCBエディタにNETリストをロードして部品の配置を決めた時点で、基板のサイズを確認すると74mmx108mm程度であった。念のため、PCBWAYのサイトで見積もりを行うと29$であった。一辺が100mmを超えると急に高くなるようである(29$は妥当だと思うが…)。
部品の配置を見直し、長さを10mm短縮した。74mmx98mmで見積もると無事、5$である。
部品が増え、基板が大きくなるとPCB上の配線作業は、かなり難しい「パズル」と化す。何度もやり直しになり、DRCがOKになるまで、10日を要した。
PCBの発注は、今回もPCBWAYであったが、8日後に到着した(途中、中国の祝日が1日あり)。
PCBは回路図通りの出来上がりであったが、実は評価後のブレッドボードから回路図を起こした時に、抵抗が2本抜け落ちている(回路図の丸で囲んだ個所)のに気づかず、「空中配線」でリカバリしている(基板がゴミにならずに済んだ、汗)。なお、今は円安であるし、送料も高いので修正版の再発注は諦めた。
基板に部品を実装して評価した。まず、音量はスピーカーを鳴らすのに十分であった。FMの音質は歪みが、かなり軽減しており、低音のノイズは残っているが、音量を上げれば気にならない程度で、聴き続けても問題ないと感じた。改善策は成功したようである。
ただ、Pi Picoはピン数が多く、基板が大きいため扱いづらい。特に今回はピンヘッダーを設置したので、ハンダ付けの個所が100ヶ所を越え、製作途中、いささか閉口した。
【追記】
百均のホビーコーナーで、この基板が収まるサイズのアクリルケースを見つけた。ケースに収めるため、配線の取り回しを変更したところ低周波で発信するようになった。対策として、オペアンプの増幅率を下げることした。上の回路図の丸印の抵抗2本を8.2KΩから15KΩに変更(増幅率は"1+39/15=3.6")した。無事ケースに収容し、問題なく使用出来ている。



SI4732(DSPラジオ)とPi Picoの組み合わせを検証した

2024-03-26 15:08:02 | 電子工作
Raspberry Pi Picoを入手したので、以前、”Arduino Pro Mini 3.3V”との組み合わせで製作したSI4732FP(オールウェーブ対応のDSPラジオIC、以下SI4732)を引っ張り出して検証してみた。Pi PicoはArduino IDE(2.0)環境での開発が可能である。開発環境の設定などはこちらを参考にすると良い。
Pi PicoはGPIOピンが多いので、多くのボタン(タクトスイッチ)が必要であるSI4732を制御するには都合が良い。ただし、Pi Picoの基板は長いので、5x7のブレッドボードは2枚必要になる。
スケッチは、PU2CLRさんのサイト(Github)の”SI47XX_02_ALL_IN_ONE_OLED.ino”がベースである。このスケッチは、”Pro Mini 3.3V”を想定しているが、以下に述べる変更を行えば、そのまま流用可能であることを確認した。
SI4732とディスプレイ(OLED 128x64 SSD1306)は、I2Cで接続するが、今回の環境ではPi Picoの既定のSDA、SCLは、GPIO4とGPIO5だったので、上記のスケッチのピンのアサインと衝突する。
Pi PicoのI2C対応のピンは複数グループあり、スケッチで指定することができる。ここでは、GPIO20とGPIO21を利用した。
”pinMode”の指定のコードの直後に以下のコードを追加した。
 Wire.setSDA(20);
 Wire.setSCL(21);
リセットのピンは、配線の都合上、GPIO22とした。
 #define RESET_PIN 22
その他のGPIOピンは”Pro Mini 3.3V”と同じピンアサインでOKである。
なお、プルアップの抵抗は無くても動作した。
ロータリーエンコーダーは、出払っていたので、動作不良になったマウスを分解して、マウスホイール取り出し流用した。マウスホイールの”ボリューム(?)”にある3つの端子のうち、GNDを判別してGNDに接続し、残りをGPIO2とGPIO3に接続する(ハンダ付けが必要)。
ピン(GPIO)の割り当ては以下の通り。
 Encoder 1 2
 Encoder 2 3
 Mode Switch (AM/LSB/USB) 4
 BANDWIDTH switch 5
 Volume Up 6
 Volume Down 7
 Next Band (Up) 8
 Previous Band (Down) 9
 Step switch 10
 AGC Switch 11
 BFO Switch 14
 SDA 20
 SCL 21
動作は確認できたが、以前の記事にも書いた様に、音質は良くなく、音声出力も不足なのは同じである。今後、これらをなんとかしてみたいと思う。


プリント基板の制作を発注してみた(その2)

2024-02-04 21:15:43 | 電子工作

前回までに、プリント基板上の部品の配置が決まると、プリントパターンの配線のステップに進むことができる。プリント基板は複数の層で構成されているが、各層の役割を理解しておく必要がある。基板のベース(ガラスエポキシ樹脂)の次の層は配線層(銅箔の部分、裏表の2層)で、これらの層に対してプリントパターンの配線を行う。銅箔層の上はレジスト層(緑や紫で色付け)で、レジスト層の上にはシルク印刷(部品名の表示など)の層がある。レジスト層については、ハンダ付けする部分にマスク(レジストしない)を定義する必要があるが、フットプリントを適切に選択すれば属性として定義されているので心配ない。

配線の基本方針として、配線層の表面はVCCや信号線、裏面はGNDの配線とすることにした。パターンの配線は、KiCaDの「PCBレイアウトエディタ」で行う。この作業は、各層ごとに表示・非表示を切り替えて行う。表面側の配線は以下のようになった。

裏面側の配線は以下の通り。

VCC、信号線が表面側に通せない場合は裏面を使う。また、同じ面で配線が交差するケースは、「ビア」(白い四角の印)を経由させて、一方を裏側に配線する。

配線パターン以外の銅箔部分は、「べた」(表裏ともGNDとした)にするが、この描画はPCBレイアウトエディタが自動で処理してくれる。「べた」の表裏は、GNDのスルーホールのところで接続しているが、念のためGNDから遠い場所は「ビア」で接続した。パターンの設計は、KiCaDのパターンチェックツールを実施して完了である。最後にピンヘッダーの信号名など、シルク印刷の文字を追加した。

プリント基板の設計情報は、「ガーバー(Gerber)データ」として出力する。ここまで、PCBWAYからお誘いを受けてから8日経過。

PCBWAYのサイトから発注手続きを行う(このサイトが参考になる)。プリント基板の仕様を入力し、注文カートに「ガーバー(Gerber)データ」をZIP化したファイルをアップロードする。配送情報の指定では、送料が高い($13)と感じたが、日本の場合は、「OCS」が推奨とのことなので選択する(今回、国内の配送は、佐川急便に連絡された)。この後、審査にパスすれば発注可能になる。今回は、プロモーションなので、PCBWAYの担当者に連絡を入れたところ、アカウントに費用が振り込まれた。金額は、「OCS」の配送料+見積もり額($5)ピッタリだったので、結局、0円で制作できたことになる。なお、発注してから3時間後に、審査をパスして製造手配したというメールが来た。

この後、発送まで2日、通関、関空経由での配送に7日かかり(関西の大雪で配送遅れあり)、無事入着した。梱包は丁寧で、プリント基板の出来上がりも綺麗である。

早速、部品を実装してみた。ユニバーサル基板では、配線にほぼ1日かかったが、約1時間で完了した。なお、R1からR4は無くても動作する。Y1(Xtal)は、RD5807の変換基板側に実装しているので差し替えるだけである。

ユニバーサル基板をプリント基板に交換して、動作確認。

今回の、配線図とガーバー(Gerber)データは、こちら(Github)に登録した。また、PCBWAYのプロジェクトに登録したので、同じ基板の発注が可能である。

 

 

 


プリント基板の制作を発注してみた(その1)

2024-01-29 19:47:02 | 電子工作

電子工作では、一般にブレッドボード上で試作評価してみて、結果が良ければ、ユニバーサル基板を使って実用版を製作する。ユニバーサル基板は配線の手間がかかって大変なのは承知であるが、多くは一品物なので、わざわざプリント基板を制作することはない。それにプリント基板の制作を発注には万円単位で費用がかると思っていた。

今回は、PCBWAYさんからお誘いがあったので、プリント基板の制作に挑戦してみることにした。費用についてはプロモーションなので補助があるとのことである。一応、ホームページで見積もりしてみた。5cmx7cmのサイズで2層の物は、なんと5$という結果になった。おまけに初めて登録(発注)する場合は5$のクーポンが貰える(結局、タダ?)。

プリント基板の制作は、全く初めて(昔、「エッチング」で製作したことはある)なので、まず、ツールと手順を調べてみた。大まかにいうと、KiCaDというツール(無料で使える)で、配線図を作成し、プリント基板のパターンを設計、それをガーバー(gerber)データにして発注先に渡せば(アップロードする)良いということが分かった。この手順については、こちらに懇切丁寧な記事がある。

現在、KiCaDの最新はV7であるが、より安定しているV6をダウンロードして使い始めた。しかし、前記の記事はV5対応なので、色々と変わっている上に、たまに固まってしまうのであきらめて、V5に変更した。最初に行うのは配線図の作成である。色々パーツ(コンデンサ、抵抗、IC、ピンヘッダーなど)が用意してありそれを並べて、それらの間を配線するという作業であるが、KiCaDは結構クセのあるツールで、作図の操作を会得するまで2日を要した。コツは、どんな部品が用意されているか事前に調べておくこと。作業が早く済む。部品の選択を誤り、やり直しが何度か生じた。

今回は、以前のブログの記事である「週間スケジュール可能なDSPラジオ」をプリント基板化することにした。配線図は以下のようになった。特徴は、I2Cで接続するOLED表示装置とSPIで接続する丸形カラーLCDの両方に対応することである。

KiCadでは、配線図を作成する時に各パーツのプロパティに対して「フットプリント」を定義する。「フットプリント」は、プリント基板上でパーツの実サイズと穴(足)の位置を示している。パーツをプリント基板に取り付ける時に、ピッタリ合わなければいけないので極めて重要である。例えば、U2のXIAO_ESP32C3はメーカーがKiCad用の「フットプリント」を提供している。ただし、KiCad V6用で、今回のV5には取り込めなかった。その際、新規に「フットプリント」を作成するには「フットプリントエディタ」を使用する。今回はサイズとピンの数が同じICの「フットプリント」を流用した。U1のRDA5807については、変換基板を利用するので、サイズ、ピンの数とも合致するDIP ICの「フットプリント」を流用した。

配線図と「フットプリント」が揃ったところで、「ネットリスト」の生成を行う。この「ネットリスト」を「PCBレイアウトエディタ」に取り込むと、「蜘蛛の巣に取り込まれた獲物」の様な「部品が配線によって搦めとられた塊」が現れる。それをほぐすと以下のようになる。

「PCBレイアウトエディタ」上でパーツの配置を決め、プリントパターンを作成する。上のパーツを繋いでいる白い線(配線)は、プリントパータンが出来上がるにつれて消えていく。最終的に、配置は以下のようになった。

左上の赤い十字は基準点((50,50)に設定)である。次のステップは、いよいよプリントパターンの設計である(その2に続く)。

 

 


週間スケジュールが可能なRDA5807 FM DSPラジオに丸形LCDを取り付けてみた

2023-12-28 12:14:23 | 電子工作

試作を行い、丸形カラーLCDを調査していたが、だいぶ使い方が分かってきたので、以前製作した「週間スケジュールが可能なRDA5807 FM DSPラジオ」の表示装置を、丸形カラーLCDに取り換えたものを新たに製作した。時計とFMラジオの表示を合体して、表示画面は結局以下のようになった。ケースは手元にあった筒形の物を利用した。作成したスケッチはGithubに登録してある。

コントローラ(MCU:Seed Studio XIAO ESP32C3)からの制御インターフェースは、I2CとSPIを利用するので、ESP32C3の入出力ピン数ではギリギリで、操作のボタンスイッチを設ける余裕はない。したがって、操作は全てWiFi経由で行う。

この丸形LCDは、240x240ピクセルなので、表示位置は、x:ヨコ位置、y:タテ位置とすると、左上隅は(0,0)、中心は(120,120)、右下隅は(239,239)となる。なお、実際に表示できる円からはみ出た部分は表示されない。丸形LCDにおいては、円の外周に沿って表示を行う必要があるが、その表示位置を求めるためには三角関数を利用する必要がある。

例えば、半径rの円の外周位置(x,y)を求めるには、以下の図に示した計算を行えばよいことになる。角度θの起点は時計の秒針では、15秒の位置になる。例として、半径r=108の時、20秒(4時)の位置は、x=108*cos30°+120≒94+120=214、y=108*sin30°+120=54+120=174というふうに求められる。

腕時計によくある秒単位の印を表示したい場合は、半径r1の円の内側に半径r2の円を想定し、同じ角度θの位置、(x1,y1)と(x2,y2)を求め、2の点を指定して直線を描けば良い。そうすれば、中心からの放射状の直線の一部として描かれる。

高校の数学の教科書みたいになってしまった。


1.28インチ丸形LCDディスプレイ(GC9A01)とESP32でデジタル時計を試作した

2023-11-24 13:47:06 | 電子工作

1.28インチの丸形LCDディスプレイ(カラー、ドライバはGC9A01)が500円位で購入できるようになったので表示装置として利用できないか調べてみることにした。インターネットで調べてみると、レポートはあまり多くない。その中で、このディスプレイの特徴を生かしたデジタル時計の製作例があったので、それを参考に試作してみた。

製作例では、RTC(リアルタイムクロック)モジュールが必須になっているが、RTCモジュールの持ち合わせは無い。以前、Seeed StudioのXIAO ESP32C3を利用して時計を作ったので、RTCの替わりにNTPから時刻を得るのはどうかということで取り組んでみた。

ディスプレイのドライバGC9A01対応のライブラリは幾つかあるが、ここでは「TFT_eSPI」を利用した。ライブラリにはサンプル例が色々あるので動作確認のために幾つか試してみると良い。このサイトが参考になる。確認には「Boing Ball」がお勧めである。

TFT_eSPIは事前に、使用するドライバとMCUに対応するための変更が必要である。ライブラリをインストールした後、「..\Arduino\libraries\TFT_eSPI」の「User_Setup.h」を編集する。

  1. 「Section 1. Call up the right driver file and any options for it」の個所に、ディスプレイ対応のドライバの定義があるので、「#define ILI9341_DRIVER」の行をコメント化し、「#define GC9A01_DRIVER」の行を「非」コメント化する。
  2. 「Section 2. Define the pins that are used to interface with the display here」の個所に、各MCUごとSPIに対するピンの定義があるのでそれを変更する。まず、ESP8266のピン定義をコメント化する。

// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ######

// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation  ##### comment out to line 176
//#define TFT_MISO  PIN_D6  // Automatically assigned with ESP8266 if not defined
//#define TFT_MOSI  PIN_D7  // Automatically assigned with ESP8266 if not defined
//#define TFT_SCLK  PIN_D5  // Automatically assigned with ESP8266 if not defined

//#define TFT_CS    PIN_D8  // Chip select control pin D8
//#define TFT_DC    PIN_D3  // Data Command control pin
//#define TFT_RST   PIN_D4  // Reset pin (could connect to NodeMCU RST, see next line)
//#define TFT_RST  -1     // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V

次に、XIAO_ESP32C3に対するピン定義を追加する。


// For the XIAO_ESP32C3 module use these #define lines   with GC9A01 display ####
#define TFT_MOSI 10  // SDA
#define TFT_SCLK 8   // SCL
#define TFT_CS   3   // Chip select control pin
#define TFT_DC   5   // Data Command control pin
#define TFT_RST  4   // Reset pin (could connect to Arduino RESET pin)

なお、使用しないピン(BLK)は定義していない。接続の様子を以下に示す。

大元のスケッチは、こちら(Github)にあるが、説明は何もない。2ファイルあり、「fonts.h」はそのまま利用し、「watchESP.ino」を改修した。なお、オープンソースのライセンスが明確ではないため、Githubに載せたり、全体を紹介するのは控えることにする。

改修内容を紹介すると、「setup」においては、RTCに関係するコードと意味不明のコードをコメント化し、Wifiに接続後、NTPを参照して、XIAO_ESP32C3の時刻に設定するコードを追加している。

ここで紹介していない部分(特にwifisyncjst())は、XIAO_ESP32C3による時計の記事(上方にリンクあり)を参照するとよい。WifiのSSIDとPASSWORDは、実際にアクセスする無線LANを設定する。


void setup() {
    Serial.begin(115200);
    Serial.println("");
    delay(10);

    //if (! rtc.begin()) {
    //  Serial.println("Couldn't find RTC");
    //}
    //pinMode(2,OUTPUT);
    //pinMode(0,INPUT_PULLUP);
    //pinMode(35,INPUT_PULLUP);
    //pinMode(13,INPUT_PULLUP);

    //digitalWrite(2,0);

    //ledcSetup(pwmLedChannelTFT, pwmFreq, pwmResolution);
    //ledcAttachPin(5, pwmLedChannelTFT);
    //ledcWrite(pwmLedChannelTFT, 200);
    WiFi.mode(WIFI_STA);
    wifiMulti.addAP(ssid.c_str(), password.c_str());  
    wifiMulti.run();   // It may be connected to strong one

    while (true) {
      if(WiFi.status() == WL_CONNECTED){ break; }  // WiFi connect OK then next step
      Serial.println("WiFi Err");
      WiFi.disconnect(true);
      delay(5000);
      wifiMulti.run();
      delay(1000*60);  // Wait for Wifi ready
    }
    wifisyncjst(); // refer time and day
    WiFi.disconnect(true);  // Connection is no longer needed

    //tft.init();  ####
    tft.begin();  // initialize
    //tft.setRotation(0);
     
    //tft.setSwapBytes(true);  ####
    tft.fillScreen(TFT_WHITE); //#### BLACK
    delay(100);
        
    //img.setSwapBytes(true);
    img.setColorDepth(8);      // Create an 8bpp Sprite of 240x240 pixels
    img.createSprite(240, 240);
    img.fillSprite(TFT_BLACK); // Fill the Sprite with black
    img.setTextColor(TFT_GREEN);        // Green text
    img.setTextDatum(4);
   :
   :
}

「loop」では、XIAO_ESP32C3から時刻を得たのち、もとの「DateTime now」変数に設定するコードを追加している。

又、そのままだと何故か、曜日が1日ずれるためXIAO_ESP32C3の時刻から得た曜日を使っている。


void loop() {  
  rAngle=rAngle-2;
  //DateTime now = rtc.now();   ####
  time_t t = time(NULL);
  tm = localtime(&t);
  d_year = tm->tm_year;
  d_mon  = tm->tm_mon+1;
  d_mday = tm->tm_mday;
  d_hour = tm->tm_hour;
  d_min  = tm->tm_min;
  d_sec  = tm->tm_sec;
  d_wday = tm->tm_wday;

  //DateTime now = DateTime(1110000 + sec1);
  DateTime now = DateTime(d_year, d_mon, d_mday, d_hour, d_min,  d_sec);
  angle=now.second()*6; 
:
:
 //img.drawString(days[now.dayOfTheWeek()],circle,120,2);
 img.drawString(days[d_wday],circle,120,2);
:
:
}

 

とりあえず、手元にあったお菓子の容器に入れてみた。外側の秒表示が回転する。外側の赤い丸印は反時計回りに回転する(ただの飾りだと思われる)。ついでに、紹介しておくと、「volos projects」で検索すると、この種の色々なガジェットがyoutubeで見られる。


週間スケジュールが可能なRDA5807 FM DSPラジオ

2023-10-26 15:02:00 | 電子工作

色々なDSPラジオを製作してきたが、普段、聴く上で面倒なのはラジオ局の選択である。ボリュームで行うのは論外で、プリセット(ボタン)で行うのは許容範囲内であるが、番組の時刻になった時に、ボタンを押すのを忘れ聞き逃すことがある。常々、時刻になったら自動で番組を選択してくれる機能があればと思っていた。そのようなラジオはないので、自分で作ることにした。

求める機能は以下の通りである。

  • 時刻機能(時刻設定は自動)を持つ。
  • 番組の時刻になったら(電源をONして⇒目覚まし機能)該当のラジオ局を自動で選局する(スケジュール機能)。
  • 指定の音量で再生する。
  • 番組が終了したら、電源をOFFする(Sleep機能)。
  • スケジュールの設定は、PCやスマホからブラウザ経由でできる。
  • 最低限の操作(音量調節、選局、電源ON/OFF)はブラウザ経由でできる。

以上の機能は、RDA5807FP(FM DSPラジオ)とSeeed Studio XIAO ESP32C3(WiFi機能あり)を組み合わせることで可能となる。RDA5807FPは、安価であるが性能的には十分である。ワイドFMに対応し、聴きやすい音質で、ステレオをサポートする。XIAO ESP32C3は、サイズが500円硬貨位で、全体をコンパクトにできる。また、Arduino IDEでのプログラミングがサポートされている。RDA5807FPとXIAO ESP32C3は、I2Cで接続する。RDA5807FPは、小口径のスピーカーなら十分駆動できるので、アンプは不要である。全体の、消費電力は微少(0.3W程度)で、24時間電源ONでも大丈夫である。今回、作成したスケッチ(プログラム)と製作に関する情報はGithubに登録してある。

スケジュールは、曜日ごとに週間で設定する。ラジオの番組は、平日、土、日で異なり、毎週ほぼ同じなので、週間スケジュールで十分である。聴きたい番組について、「開始時刻、ラジオ局、番組の長さ(分)、音量、番組終了後に電源OFF(RDA5807FPのみ)するか否か」を設定する。以下に示すのは、ブラウザに表示された週間スケジュールの設定画面である。中央の表に各曜日ごとのスケジュールが表示されている。各エントリの指定項目は上記の通りである。ラジオ局については、”Station List:”の数字を設定する。

スケジュールを変更する方法は、まず各曜日のラジオボタンをクリックする。選択した曜日の設定が上部の入力領域にコピーされるので、それを編集後、”Submit”ボタンをクリックする、これで変更内容が保存される。

上の設定画面の下部”Control Functions”にあるボタンは、それぞれ、音量調節、選局、電源(RD5807FPのみ)をON/OFFするためのものである。

製作したDSPラジオの外観を以下に示す。

手前がXIAO ESP32C3、奥がRDA5807FP。部品数は少ない。口径10センチのスピーカーをRDA5807FPに直接接続している。アンテナは70センチ程のリード線を接続すれば十分受信できる。

OLEDの表示内容を以下に示す。

日付、曜日、時刻、音量、電源(1:ON,0:OFF)、受信周波数の順。

数か月間利用しているが、朝、電源ONした後はノータッチで自動選局してくれるので、大変便利である。

 


ESP32でWiFiとBluetooth(A2DP)は同時に使えるか

2023-09-17 15:20:22 | 電子工作

以前、ESP32によるインターネットラジオを製作したが、これはDACをI2Sで接続し、スピーカーから音を出す物だった。ESP32はWiFiとBluetoothを搭載しているので、それらを同時に使えば、ESP32でインターネットラジオを受信し、それをA2DPでBluetoothスピーカーに送って音を出すことができるはずである(スマホで普通にやってること)。事例がないかを調べて見た。

GithubにESP32を色々な方式のプレイヤーにするコードの実装例があった。その中に、SDカードモジュールを使い、A2DPで接続したBluetoothスピーカーから音を出すプレイヤーと、インターネットラジオを受信し、I2Sで接続したDACから音を出すプレイヤーの例を見つけた。これらを組み合わせれば、所期の目的を達成できそうだと思った。

しかしながら、結論からいうと、WiFiとA2DPを同時に動作させることはできなかった。A2DPを接続するとWiFiが繋がらない。WiFiを接続するとA2DPの接続でリセットエラーになる等、(このケースでは)同時には動作しなかった。

以下は試行錯誤の報告である。実装コード(ライブラリ)は洗練されていて、各種のプレーヤーが簡単に実装できるようになっており、最初の2例は動作を確認したので参考になると思う。

インターネットラジオを受信し、I2Sで接続したDACから音を出すプレイヤー

以下にスケッチを示す。上記の実装例からは、ボリューム(音量)や接続先のURLを変更するコードは省略している。ライブラリは、pschatzmannさんのライブラリを、ZIP形式でダウンロードし、ArduinoIDEのライブラリ管理からインストールする。「*wifi」と「*password」の部分は、利用しているWiFiのものを指定する。DACはUDA1334かPCM5102のモジュールが使える。ESP32との接続方法は、上記のリンク先に記載されている。

なお、ArduinoIDEは1.8.9。ボードマネージャからインストールするESP32ライブラリはEspressif Systemsの2.0.10である(古いとコンパイルエラーになる)。

下記のスケッチ中の、「AudioPlayer player(source, i2s, decoder)」の組み合わせを変えることで、色々なプレーヤーを実装できる。


#include "AudioTools.h"
#include "AudioCodecs/CodecMP3Helix.h"

const char *urls[] = {
  "http://stream.srg-ssr.ch/m/rsj/mp3_128"
};
const char *wifi = "your_ssid";
const char *password = "your_password";

URLStream urlStream(wifi, password);
AudioSourceURL source(urlStream, urls, "audio/mp3");
I2SStream i2s;
MP3DecoderHelix decoder;
AudioPlayer player(source, i2s, decoder);

void setup() {
  Serial.begin(115200);
  AudioLogger::instance().begin(Serial, AudioLogger::Info);

  // setup output
  auto cfg = i2s.defaultConfig(TX_MODE);
  i2s.begin(cfg);

  // setup player
  player.begin();
}

void loop() {
  player.copy();
}

 

A2DPで接続したBluetoothスピーカーから音を出すプレイヤー

以下にスケッチと実験セットを示す。SDカードモジュール(写真ではタテになっている基板。Amazonから200円程度で入手できる)の接続方法は、上記の実装例に記載されている。mp3の楽曲をSDカードにコピーしてセットしておく。複数の曲をコピーした場合は一通り演奏後に停止する(その後は一旦電源を落とさないと「ファイル無」のエラーになる)。スケッチ中の「cfg.name」に、Bluetoothスピーカーのデバイス名を設定する。

なお、SDカードモジュールが手元に無い場合は、ESP32のSPIFFS領域にMP3のファイルを予めコピーしておく方法(プラグインの設定が必要。なお、このプラグインはArduinoIDEのVer2.x.xでは使用できないので注意)で実験できる(実装例はこちら、コピーするデータあり)。


#include "AudioTools.h"
#include "AudioLibs/AudioA2DP.h"
#include "AudioLibs/AudioSourceSDFAT.h"
#include "AudioCodecs/CodecMP3Helix.h"

const char *startFilePath="/";
const char* ext="mp3";
AudioSourceSDFAT source(startFilePath, ext); // , PIN_AUDIO_KIT_SD_CARD_CS);
A2DPStream out;
MP3DecoderHelix decoder;
AudioPlayer player(source, out, decoder);

void setup() {
  Serial.begin(115200);
  AudioLogger::instance().begin(Serial, AudioLogger::Warning);
  // setup output - We send the test signal via A2DP - so we conect to a Bluetooth Speaker
  auto cfg = out.defaultConfig(TX_MODE);
  cfg.name = "bbbbbbbbbb";  // set the device here. Otherwise the next available device is used for output
  cfg.auto_reconnect = true;  // if this is use we just quickly connect to the last device ignoring cfg.name
  out.begin(cfg);

  // setup player
  player.setVolume(0.7);
  player.begin();

}

void loop() {
  player.copy();
}

 

インターネットラジオを受信し、A2DPで接続したBluetoothスピーカーから音を出すプレイヤー(動作せず)

目的のプレイヤーである。実装例にはないが、上の2つを組み合わせれば(入力:インターネットラジオ、出力:Bluetoothスピーカー)実現できるはずである。実装例からの類推で作成したスケッチは以下の通り。

実行したところ、「E (17464) wifi_init_default: netstack cb reg failed with 257」というようなエラーとrebootを繰り返し、動作はしなかった。なお、以下のスケッチをコンパイルすると、プログラムサイズが1.7MBになるので、ArduinoIDEからPartition Schemeのサイズを「No OTA 2MB APP/ 2MB SPIFFS」に変更した。

 


#include "AudioTools.h"
#include "AudioLibs/AudioA2DP.h"
#include "AudioCodecs/CodecMP3Helix.h"
const char *urls[] = {
  "http://cast1.torontocast.com:2170/stream"
};
const char *wifi = "your_ssid";
const char *password = "your_password";

URLStream urlStream(wifi, password);
AudioSourceURL source(urlStream, urls, "audio/mp3");

A2DPStream out;
MP3DecoderHelix decoder;
AudioPlayer player(source, out, decoder);

void setup() {
  Serial.begin(115200);
  AudioLogger::instance().begin(Serial, AudioLogger::Warning);
  // setup output - We send the test signal via A2DP - so we conect to a Bluetooth Speaker
  auto cfg = out.defaultConfig(TX_MODE);
  cfg.name = "bbbbbbbbbb";  // set the device here. Otherwise the next available device is used for output
  cfg.auto_reconnect = true;  // if this is use we just quickly connect to the last device ignoring cfg.name
  out.begin(cfg);

  // setup player
  player.setVolume(0.9);
  player.begin();
}

void loop() {
  player.copy();
}