2021.8.31 OT-01の回路設計

前回のブログでは、超音波楽器のブロック図まで設計しました。

さっそく回路設計に入ります。

下記が前回設計したブロック図です。

要するに、各モジュールをいかにしてマイコンに接続するかが大事になります。

まず、使用するマイコンのピン配置を確認します。

ATmega328PUのピン配置
ATmega328PUの各通信端子

SRF-02の接続

SRF-02はI2Cという形式で通信します。

I2Cの接続方法はとても簡単です。今回は超音波センサを2台並列でつなげられるようにします。

I2Cの通信は、センサ(Slave)とマイコン(Master)にそれぞれあるVcc,GNDの電源端子、同期クロックのSCL、信号線のSDAの4つの端子同士をつなぎます。

並列でつないでいても、それぞれのセンサにはアドレスが振り分けられているため、問題ありません。

YMF-825の接続

YMF-825はSPIで通信します。

SPIの通信は、音源IC(Slave)とマイコン(Master)にそれぞれあるVcc,GNDの電源端子、同期クロックのSCKと接続対象のSlaveを選択するSS(Slave Select)、MasterからSlaveに信号を送るMOSI(Master Out Slave In)とSlaveからMasterに信号を送るMISO(Master In Slave Out)があり、合計6本の線で構成されます。

Software Writer

ソフト書込みは前回のブログでも紹介しました。

ソフト書込みはUARTで通信しますので、変換器のTXD(送信)を,ATmega328のRXD(受信)に、変換器のRXD(受信)をATmega328のTXD(送信)に接続します。あとは、TTL変換器の+5VとGNDを、ATmega328にも供給します。そして、変換器からリセットの信号を送れるように、RTSとATmega328のResetを、0.1uFのコンデンサを経由して接続します。

Speaker Driver

YMF-825の使い方次第ではメモリーが足りなくなります。そういうときのために、単純な電子音であれば出せる、スピーカーのドライバ回路を用意しました。

以前のブログにもまとめています。

さいごにこれらの回路を統合した回路図を書きました。

次回は、KiCadで基板設計をします。

2021.8.28 GIXIEケースオーディオの設計

今回から新企画になります。

以前、謎の木の箱を分解しました。

前回のブログでは、このケースを分解して、正体をさぐる内容でした。結果として、時計だったんでしたが、時計は以前も作ったし、ギクシー管を6個もそろえるのはお金がかかりすぎるので諦めました。

そこで、せっかくこのおしゃれなケースがあるんだから、せめて何かに応用できないかと思考錯誤しました。

とくにこのケースは、直径34mmの丸い穴が6個も開いている点です。

これには、スピーカーとVUメータ―がぴったりでした。

そこで、スピーカー4つ、VUメータ2つのオーディオアンプスピーカーを作ろうと思います。

スピーカーの選定

今回は、サイズも小型なので、音質はあまり求めず、デザイン優先で作ることにしました。

スピーカーは、同じ直径34mmのものを選びました。

Amazon 小口径アルミコーン!フルレンジスピーカーユニット1.5インチ(34mm)3Ω/MAX8W

価格;590円

  • ユニット1個単位での販売です
  • 1.5インチフルレンジスピーカー
  • 15mmボイスコイル
  • アルミコーン
  • ネオジウムマグネット仕様(防磁仕様)

インピーダンスが3Ωしかないのがすこし気になりますが、おおむね大丈夫だと思います。

 

VUメータ―

VUメータ―は、最近は手に入るのかなと心配しましたが、Amazonを探すと、海外の安いものがありました。

Amazon VUパネル レベルメーター 6V〜12V 500μA 高精度 バックライト付 2個

価格;1990円

  • 材質:プラスチック、電子部品
  • ヘッダDC抵抗:630オーム
  • バックライトフィラメント電圧:DC / AC 6V〜12V
  • フィラメントによるバックライト付き500μAVUメーター
  • それはオーディオレコーダー機器で広く使われています

二個セットで1990円。結構お手頃です。

 

ブロック図

下記にブロック図を示します。

スピーカー単体のインピーダンスが低いため、一個のアンプからスピーカーを並列で接続するのは厳しいと思います。そのため、それぞれにアンプをつけなければなりません。

アンプの手前に、二連の可変抵抗を置き、これをボリュームとして使います。

音声入力から、アンプと分岐させて、VUメータのドライバを並列で繋ぎます。

また、DCジャックで任意の電圧を入れられるようにして、レギュレターの回路を入れ、各回路に供給します。

Block Diagram

次回は、これを回路図に起こします。

2021.8.26 KTF5002を分解してみた

今回から新企画です。

市販の製品を分解して、そこに秘められた技術を学びます。

今回は、AM/FMラジオチューナー、KENWOOD製のKTF5002を分解します。

これは、近所のハードオフで1500円で販売されていました。

ジャンク品だったのですがかなり状態がよく、FMラジオ、AMラジオ共に音も問題なく鳴っています。

FMラジオが受信できる

AMラジオが受信できる

まずは、このラジオについて調べてみました。

調べると、発売はなんと1997年ごろ。僕の年齢の一つ下です。

価格は25000円とお手頃価格です。

取扱説明書のpdfも上がっていたので下記にリンクを貼ります。

KTF-5002の取扱説明書

下記に仕様を示します。

 

FMラジオの受信周波数範囲は76MHz~90MHz。当時のFMラジオでは十分な帯域です。90MHz以上はアナログテレビの音声信号の帯域でした。現在は、この空いた帯域がAMラジオの補完放送(WideFM)になっています。

全高調波歪率は0.5% オーディオ機器としてはまずまずかなと思います。

個人的に驚いたのは、FMラジオのSN比が70dBであること。当時としてはかなり高い性能ではないかと思います。

また、AMのSN比は40dB。やはりFMよりノイズが多くなってしまうのがAMラジオです。

 

フロントパネル

Auto(自動選局)やスリープ、時間予約などの設定ができるみたいです。

パッと見ボリュームだと思いましたが、これは選局です。ぐるぐる回すことはできず、傾かせるだけです。

後ろはこんな感じ。FMのアンテナ端子、AMのアンテナ端子、オーディオ出力、コンセント、検波出力があります。FMのアンテナ端子はテレビのアンテナ線と同じものです。

それではカバーを外して中身を見てみましょう。

なるほど。複雑かと思いましたが中身は基板一枚に収まっていました。

さらに基板を取り出します。

ざっくりと、回路の名称を示します。

FMのフロントエンド、FMのマルチプレクサ、AMステレオの復調回路、PLL回路、電源回路等、多くの回路から成り立っています。今後のブログにて、これらの回路を一つづつ説明していきます。

今日は、分解したばかりですので、基板全体に着目します。

まず、基板の素材は、紙フェノール基板です。安価で耐久性はあまりありませんが、置き型のオーディオ機器ではこれで十分です。基板は片面一層構造で、部品は片方の面にしかついていません。そのため、線と線の交差のため、ジャンパ線が多く使われています。また、表面実装部品は、裏面についているマイコン(ぶ厚い、、)だけで、あとはすべてディスクリート部品です。部品の足が基板の裏で曲げられているところから、この部品はすべて人の手で手挿入されています。そして、人の手でカットしているのがわかります。

また、はんだづけに一切のムラがないことから、はんだ槽に基板をあてがう、フロー式ではんだ付けをしていることがわかります。マイコンだけは後付けでクリームはんだのリフローかもしれません。

正直これは、今の時代から見ると、かなり人件費がかかっているなと思います。

これを、25000円ぽっきりで売っているのはすごいと思います。

また、電源回路も注目です。

オーディオ関連の機器がやたら重いのは、電源回路にスイッチング方式を使わないからです。スイッチング方式の電源は、たとえば携帯の充電器やパソコンの充電アダプタなどです。このラジオも、スイッチングを使えば回路は軽くなりますが、スイッチングはノイズを多く発生させるため、とくにラジオの電源に使えばSN比は一気に下がります。そのため、大きなトランスを置き、昔ながらの電源回路で作るしかありません。

また、表示はVFDという表示方式です。よく、スーパーのレジで青白い文字で「ゴウケイ2350エン」って出てるアレです。今では液晶表示(電卓などの)や、LEDが多いですが、これは真空管の技術を応用した昔ながらの表示です。

これも、今後のブログで詳しく書けたらなと思います。

最後に、スイッチ類の裏側です。かなりシンプルでした。

今日は、ざっくり分解したレポートでした。今後は、下記の計画で、この製品をより詳しく分析していこうと思います。次回は、9/2にそもそもAMラジオ、FMラジオの受信原理について解説します。PLL、MPXの話も触れようと思います。

現在の連載; 「FM/AMステレオチューナーKTF-5002の分解調査」

更新日      題名          
8/26KTF5002を分解してみた(仕様、解体手順、基板構成、機構について)
9/2AM/FMラジオの受信原理(AM・FMとは、主に使われる受信方式について、PLL・MPXとは)
9/9KTF5002で使用されているICについて調べた
9/16FMフロントエンド回路、FM-IF回路、AM-RF回路 について
9/23PLL回路の原理
9/30FM-AM DET回路について
10/7FM-MPX回路について
10/14Audio AMP回路について
10/21電源回路について
10/28VFD表示回路について

 

2021.8.24 超音波楽器OT-01の構想と設計

今回から新企画です。

新しい、楽器を作ってみたいと思います。

今回のブログはその構想からブロック図の設計までをやりたいと思います。

作りたい楽器のイメージ

イメージは右図のように、超音波センサを上向きで配置します。

センサの上に手をかざして、演奏をします。かざす手の高さで音階が決まるシンプルなものです。

ブロック図

次にブロック図です。

メインとなるマイコンは、Arduinoで簡単にプログラムできる利便性から、ATmega328を使います。

超音波センサにはSRF-02を使用しました。最大2台のセンサをつなげられるようにします。超音波センサとマイコンの間は、I2C通信によって情報伝達を行います。

また、様々な音色を作れるYAMAHAの音源ICを使ったモジュールYMF-825を接続します。

これは、SPI通信にて情報交換をします。

あとは、音を出すタイミングを手動で入れられるジョイスティック。

そして、マイコンのメモリーオーバーなどで、YMF-825と超音波センサを同時に動かせないときのために、

スピーカーを直で駆動できる回路も備えます。

また、マイコンを単体で動かすので、ソフトの書込み端子を用意しなければなりません。まだ開発段階なので、RAM値を読み込めるように、UART通信により、パソコンのUSBと接続できるようにします。

次に、各ブロックを詳細に見ていきましょう。

マイコン

使用するマイコンについて、秋月電子の販売ページに簡単にまとまってたので下記に示します。

ATmega328 (秋月電子HPより引用)
ATmega328 (秋月電子HPより引用)

ATmega168のメモリ倍増版です。ブートローダと呼ばれるプログラムを書き込んだものは、Arduinoに搭載されるなど電子工作においてポピュラーなマイコンの一つです。

■主な仕様
・シリーズ:ATMEGA
・電源電圧:1.8~5.5V
・コア:megaAVR
・コアサイズ:8bit
・クロック:20MHz
・プログラムメモリ:32kB
・EEPROM:1kB
・RAM:2kB
・GPIO:23pin
・ADC:6Ch
・UART/USART:1Ch
・I2C:1Ch
・SPI:1Ch
・タイマ:3Ch
・オシレータ:内蔵/外付
・パッケージ:DIP28

**秋月電子HPより引用**

汎用性は、かなり高く、メモリー容量もまずまずです。

 

超音波センサ(SRF-02)

まず、SRF-02の通信には二つのモードがあり、I2CとUARTがありますが、今回はI2Cに焦点を当てて説明します。

まずは、SRF-02の主な特徴です。

詳しくは以前のブログを参考にしてください。

◆主な仕様
・使用マイコン:16F687-I/ML
・測定範囲:16cm~6m.
・電源:5V(消費電流4mA Typ.)
・使用周波数:40KHz.
・アナログゲイン:64段階の自動ゲインコントロール
・接続モード:モード1=I2C、モード2=シリアルバス
・全自動調整機能:電源投入後キャリブレーション不要
・測距タイミング:エコー時間計測、ホストによるタスクコントロール
・測定単位:μS(マイクロ秒)、ミリ、インチ
・サイズ:24mmx20mmx17mm
・入出力端子:5ピン
・重量:4.6グラム

音源IC(YMF-825)

ヤマハのFM音源チップYMF825(SD-1)を搭載した音源ボードについて以前のブログに掲載してますので参考にしてください。ヤマハ独自のFMシンセサイザを搭載し、数種類のパラメータ指定により豊かなサウンドを再生することが可能です。

ArduinoやRaspberry Pi等のマイコンボードから、SPIを通して直接YMF825のレジスタを制御することで発音させます。スピーカーアンプも搭載しているので、アンプ回路を別途外部に用意する必要がありません。

※3.5 mmのヘッドホンジャックを搭載していますが、iPhone用などの4極CTIA採用のイヤホンはお使いいただけません(OMTPのものはお使いいただけます)。**Switch science様の販売ページより**

**Switch science様より画像引用**

仕様

  • 4オペレータのFM音源
  • 最大16音同時に発音可能
  • FMの基本波形29種類内蔵、アルゴリズム8種類
  • SPIによるシリアルインタフェース
  • スピーカアンプ内蔵
  • 3バンドイコライザ内蔵
  • 16 bitモノラルD/Aコンバータ内蔵
  • 動作電圧:5 V
  • 3.3 Vでも改造することで利用可能

スピーカードライバー回路

スピーカーの駆動回路について以前のブログでまとめてますので参考にしてください。

この回路は、電子音を鳴らすことに特化させているので、この回路で普通の音楽を流すことには向かないとおもいます。

回路はいたってシンプルです。Arduinoからはデジタル出力の矩形波が出力される。このデジタル信号がトランジスタQ1のベースに入力される。ベースに電流を流すと、コレクタエミッタ間がONとなち、スピーカーに電流が流れる。デジタル信号のHIGH/LOWの周期によって、すぴーかーに電流を流す、流さないが変化する。したがって、デジタル信号の周波数の電子音がスピーカーから発せられる。

R1の抵抗は、デジタル信号の電流が、ベースには高すぎるので、抵抗R1を挟んで電流を小さくしている。

また、R2の抵抗も、スピーカーに流れる直流電流が大きすぎるため、R2の抵抗を挟み電流を小さくしている。

また、D1のダイオードは、スピーカーのコイルを矩形波でON/OFFしてしまうと、スピーカーの電圧が一気に跳ね上がってしまうため、電圧が跳ね上がらないようび、スピーカーのコイルにたまった電流を逃がす回生ダイオードを積んでいる。

ソフト書込み

ソフト書込みに関しても以前のブログを参考にしています。

UARTの通信ですので、変換器のTXD(送信)を,ATmega328のRXD(受信)に、変換器のRXD(受信)をATmega328のTXD(送信)に接続します。あとは、TTL変換器の+5VとGNDを、ATmega328にも供給します。

そして、変換器からリセットの信号を送れるように、RTSとATmega328のResetを、0.1uFのコンデンサを経由して接続します。

あとは、ATmega328のクロックとして、16MHzの水晶発振子を接続します。


今日はここまで。次回は回路設計に入ります。

2021.8.21 Wiiリモコンを分解した

今回は、wiiリモコンを分解しました。

一時は大人気だったwiiですが、みなさん覚えているでしょうか。

今や、ハードオフで300円で投げ売りされています。

せっかくなので、分解してみることにしました。

さっそく、開封します。

なるほど、まあこんなもんだろうな。

やはり、wiiといえばリモコンの傾きや振ったり、高さや水平移動を検知していました。さて、そのセンサはどこにあるでしょうか。

くわしく見ていきます。

本体上面の裏側にはスピーカーがついていました。

なるほど、ボタン周りはすごくシンプルです。導電体をはりつけたシリコーンのボタンを基板の接点にあてることで、ボタンの役割を果たします。

あとは、振動モーターと、前にCMOSカメラがついていました。なるほど、水平移動などはこのカメラで見ていたのでしょうか。

真ん中にあった十字のボタンは、導電体が4つ。。?と思っていましたが、一つでした。

また、接点が4つです。どの、接点同士を繋げるかで、十字の方向を決めているようです。

ジョイコンをつなげるコネクターは金メッキでした。

また、電源の入力には、ルビコン製の電解コンデンサが入っています。

基板の裏面には、ジョイスティックと通信するためのDTMFレシーバIC(BU8872)や、Wii本体と無線で通信するためIC、BLOADCOM製のBCM2042が搭載されています。また、BCM2042の四隅に、三角のパットがありました。

おそらくこれは、ノイズ試験がうまくいかなかったときに、ここに金属のカバーをつけるためのパットでしょう。

ノイズ耐性がよかったので未実装になっているのでしょう。

また、表面にはEEPROMのようなものがありました。これは、データを保管するメモリのようなものです。最低限の動作を記憶しています。

また、表面の上側に加速度センサーがありました。これでwiiリモコンの傾きを検知しています。

また、近いうちに、これらのICチップを調べて、ブログにできたらと思います。

2021.8.19 謎の箱を分解した

先日、近所のハードオフに行って、よくわからない箱と、wiiリモコンを分解用に衝動買いしました。

 

今回は、この謎の木の箱の正体を確認します。

もし、中身がなにかわからなくても、このケースはいろいろ使い道があるだろうなと思いました。

まず、上に6か所、なにかを置くスペースがあります。

そして、横には3つのボタンがありました。

 

なにかを置く場所は、二つの磁石と、その真ん中に端子が3つありました。

二つ仮説が考えられ、一つは、この二つの磁石が、それぞれ電源の+、ーになっており、真ん中の3本は信号線(3本だとSPI通信)の可能性があります。

もう一つの仮説は、磁石に電圧はかかっておらず、3本の端子のうち二つは、電源の+とー、残り1本が信号線です。データが多くなければ(7セグメント等)、サーボモータのような制御でも問題ないのかなと思います。

裏面は、DCジャックがあるのみです。

電圧は書かれておらず、怖いのでまだ電圧は掛けません。DCジャックは秋月で販売されてる2.1φのものなので、とても親近感がわきます。

それではさっそく中を開けてみましょう。

!!!!!!!!!

中はとてもシンプルでした。まず、真ん中にマイコンが一つ、クリスタル,そしてコイン電池が入っています。

基板を詳しく見てみましょう。

まず、基板から見るに、これは時計です。

表示系をコントロールするマイコンチップはATmega8A、クロックに16MHzの一般的な水晶発振子を使用しています。また、その横にあるチップがRTC(リアルタイムクロック)だと思います。

これは、時間を常に正確に刻みつづけ、現在時刻のデータをマイコンに送り続ける素子です。電源を抜いても、最省電力で時間を刻み続けられるために、コイン電池を積んでいます。コイン電池の電圧は3V、それに対し、電源から供給される電圧は5Vであるため、電源の電圧がコイン電池に流れ込まないよう、また、コイン電池の電圧がマイコン等にながれこまないために、ダイオードが二つ付いています。

また、未実装の部品もありました。まず、マイコンのとなりにある6ピンの端子は、プログラム書き込み端子です。これは、ArduinoのISP端子とつなぐことで簡単にプログラムを書き換えることができます。

また、未実装部品も気になります。とくに、JDY-16と書かれた未実装端子は気になります。これはBluetooth通信のモジュールです。おそらく、スマホなどと接続して時計をあんなことやこんなことにするためのものでしょう。オプションによってはあるんですかねえ。わかりませんが。

基板にGIXIECLOCKと書かれていたので調べました。

思ったよりすごいものを手に入れたみたいです。

やはり時計でした。

下記にリンクを貼ります。

AZUREST(アズレスト)✖️Gixie Clock (ギクシークロック )

これらはのケースは、すごく使えそうなので、なにか考えます。

とても面白かったです。

2021.8.17 Arduino 関数について

本日のTOPIC

今回は、ArduinoのVoid関数についてです。

Arduinoの関数とは、プログラムを機能ごとに分割し、特定の仕事をこなすモジュールを作成するといったことが簡単にできます。このモジュールの単位のことを関数(function)と呼びます。

関数には大きく分けて二種類あり、戻り値を返すタイプと返さないタイプに分かれます。

戻り値を返さない関数

まず、戻り値を返さないタイプのプログラムを下記に示します。

void 関数名(void) {
  
  //処理内容//

}

      関数名();      

戻り値を返さない関数というのは、関数に何かの作業だけをさせ、その作業結果をスケッチ内で特に利用しない場合に利用します。関数に対して、作業をさせるために情報を渡す(引数と言う)場合もあります。

関数の考え方は、あらかじめ省略したい処理を、一つの関数(数式?)としてひとまとまりにして作っておけば、メインのプログラムの流れに関数の名前を入れるだけで、その処理を一通りこなしてくれるため、プログラムの見た目がシンプルになり、わかりやすくなります。

下図が、プログラムの例です。

void setup() {
  // put your setup code here, to run once:
pinMode(13,OUTPUT);
pinMode(A1,INPUT);
}
void LED_ON_OFF(void) {
   digitalWrite(13,HIGH);
   delay(500);
   digitalWrite(13,LOW);
   delay(500);
   digitalWrite(13,HIGH);
   delay(500);
   digitalWrite(13,LOW);
   delay(500);
}
void loop() {
  // put your main code here, to run repeatedly:
    int a;
    a=digitalRead(A1);
    if(A==1){
    LED_ON_OFF();      
    }else{
    }
}

これを要約した図を下記に示します。

戻り値を返さないプログラム例

上の方に void LED_ON_OFF(void){ 処理 } でLEDをON/OFFするプログラムを関数化し、プログラムの途中に関数名を一言いれるだけで、関数を実行できる。

戻り値を返す関数

次に、戻り値を返すタイプのプログラムです。

戻り値があるタイプとしては、たとえば関数に計算式を入れておき、メインのプログラムから計算したいパラメータを関数に送り、関数で計算して、計算結果を戻り値として返すものです。

下記に例を示しますと、速度の計算を関数にしたいとします。

戻り値を返すタイプのプログラムの定義を示します。

int 関数名(int 変数1,int 変数2,・・・){

     実行する処理

  return 戻り値の変数;
}

  関数名(変数1,変数2・・・);

なお、intはdoubleでも構いません。また、送り値の変数はいくつあっても大丈夫です。

メインプログラムから、距離と時間のパラメータを関数に送ります。それを関数内で計算して、計算結果(速度)を戻り値として戻すわけです。

次に、プログラム例を示します。

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
}
int sokudo(int d, int s) {
   int a;
   a=d/s;
   return a;
}
void loop() {
  // put your main code here, to run repeatedly:
    int d;
    d=105;
    s=100;

    x=sokudo(d,s);
    
    Serial.println(x);
}

 

sokudoという名前の関数を整数型(int)で定義して、()内に送り値の距離dと時間sをintで記載し、計算結果をaに代入、これをreturn a;で戻り値として返します。

以上が、関数のおおまかな内容です。

今日は、ここまで。

2021.8.18 今後の目標

柊工房の今後やりたいことをまとめました。

Maker Fair Tokyoに出展したい

現在は、コロナの影響でなかなか展示会には足を運べませんが、来年以降2022年度のMaker Fairや、Nico Tech, Creema, minne様の展示会に出展したいと考えています。

現在、Creemaで販売している時計や試験管立てに加え、超音波の楽器などを展示し、今後の活動につながる人脈を形成する狙いです。

そのためにも、超音波楽器をはじめとした新たな楽器、おもしろ工作のラインナップをもっと充実させる必要があります。

柊工房のホームページを電子工作の総合情報サイトにする

私の理念は、いままで電子工作に触れる機会がない、難しそう、ダサそう、といった思い込みを払拭し、より多くの方々に電子工作を始めていただきたい。そのお手伝いができたらと考えています。そのためにも、このHPの情報量をより増やし、電子工作に関して検索すれば、大体このサイトにあたる。といった総合情報サイトを目指します。

そのためにも、今は情報量を増やすときです。日本語版を毎週火、木、土。英語版を水、金、日のほぼ毎日投稿を徹底し、情報量拡大につとめます。

ある程度、情報が増えたら、それらをまとめ、辞書のようにお使いいただける、より分かりやすいHPを目指します。

 

本を出版したい

ブログの情報がある程度そろいましたら、内容別に本を出版したいと考えています。といっても、出版社を通さずに、同人誌のような形での出版となると思います。また、Kindleなどの電子書籍でも直接出版することができるため、それらも活用したいと考えています。

YouTube配信をする

できる範囲で、Youtubeに首を突っ込みます。といっても、HPの作成でだいぶ忙しいはずなので、あくまでブログの補助教材としてYouTubeに動画をアップする形になるかと思います。

また、新しい楽器ができたら、さまざまな曲をカバーした演奏動画を出したいと思います。

2021.8.14 YMF-825を使いこなす2

前回のつづきです。

今回は、YMF-825のサンプルスケッチを用いて、様々な音を鳴らします。

サンプルスケッチは、GitHubに上がっていました。

下記を参考にしてください。

YMF-825サンプルスケッチ

このサンプルスケッチをArduinoNanoに書き込みます。

GitHubのフォルダーを開くと、下記のようなファイルが入っています。

この中の、sample1のプログラムを今回はいじります。

sample1のプログラムはこんな感じです。

/*
 Conditions only for Arduino UNO
   RST_N- Pin9   
   SS   - Pin10
   MOSI - Pin11
   MISO - Pin12
   SCK  - Pin13
 */
#include <SPI.h>
//0 :5V 1:3.3V
#define OUTPUT_power 0

// only for Arduino UNO
void set_ss_pin(int val) {
    if(val ==HIGH) PORTB |= (4);
    else PORTB &= ~(4);
}

// only for Arduino UNO
void set_rst_pin(int val) {
    if(val ==HIGH) PORTB |= (2);
    else PORTB &= ~(2);
}

void if_write(char addr,unsigned char* data,char num){
  char i;
  char snd;
    set_ss_pin(LOW);
    SPI.transfer(addr);
    for(i=0;i<num;i++){
      SPI.transfer(data[i]);    
    }
    set_ss_pin(HIGH);  
}

void if_s_write(char addr,unsigned char data){
  if_write(addr,&data,1);
}

unsigned char if_s_read(char addr){
  
    unsigned char rcv;
    
    set_ss_pin(LOW);    
    SPI.transfer(0x80|addr);
    rcv = SPI.transfer(0x00);
    set_ss_pin(HIGH);  
    return rcv;  
}

void init_825(void) {
   set_rst_pin(LOW);
   delay(1);
   set_rst_pin(HIGH);
   if_s_write( 0x1D, OUTPUT_power );
   if_s_write( 0x02, 0x0E );
   delay(1);
   if_s_write( 0x00, 0x01 );//CLKEN
   if_s_write( 0x01, 0x00 ); //AKRST
   if_s_write( 0x1A, 0xA3 );
   delay(1);
   if_s_write( 0x1A, 0x00 );
   delay(30);
   if_s_write( 0x02, 0x04 );//AP1,AP3
   delay(1);
   if_s_write( 0x02, 0x00 );
   //add
   if_s_write( 0x19, 0xF0 );//MASTER VOL
   if_s_write( 0x1B, 0x3F );//interpolation
   if_s_write( 0x14, 0x00 );//interpolation
   if_s_write( 0x03, 0x01 );//Analog Gain
   
   if_s_write( 0x08, 0xF6 );
   delay(21);
   if_s_write( 0x08, 0x00 );
   if_s_write( 0x09, 0xF8 );
   if_s_write( 0x0A, 0x00 );
   
   if_s_write( 0x17, 0x40 );//MS_S
   if_s_write( 0x18, 0x00 );
}

void set_tone(void){
  unsigned char tone_data[35] ={
    0x81,//header
    //T_ADR 0
    0x01,0x85,
    0x00,0x7F,0xF4,0xBB,0x00,0x10,0x40,
    0x00,0xAF,0xA0,0x0E,0x03,0x10,0x40,
    0x00,0x2F,0xF3,0x9B,0x00,0x20,0x41,
    0x00,0xAF,0xA0,0x0E,0x01,0x10,0x40,
    0x80,0x03,0x81,0x80,
  };
  
   if_s_write( 0x08, 0xF6 );
   delay(1);
   if_s_write( 0x08, 0x00 );
  
   if_write( 0x07, &tone_data[0], 35 );//write to FIFO
}

void set_ch(void){
   if_s_write( 0x0F, 0x30 );// keyon = 0
   if_s_write( 0x10, 0x71 );// chvol
   if_s_write( 0x11, 0x00 );// XVB
   if_s_write( 0x12, 0x08 );// FRAC
   if_s_write( 0x13, 0x00 );// FRAC  
}

void keyon(unsigned char fnumh, unsigned char fnuml){
   if_s_write( 0x0B, 0x00 );//voice num
   if_s_write( 0x0C, 0x54 );//vovol
   if_s_write( 0x0D, fnumh );//fnum
   if_s_write( 0x0E, fnuml );//fnum
   if_s_write( 0x0F, 0x40 );//keyon = 1  
}

void keyoff(void){
   if_s_write( 0x0F, 0x00 );//keyon = 0
}

void setup() {
  // put your setup code here, to run once:
  pinMode(9,OUTPUT);
  pinMode(10,OUTPUT);
  set_ss_pin(HIGH);
 
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV8);
  SPI.setDataMode(SPI_MODE0);
  SPI.begin();

  init_825();
  set_tone();
  set_ch();
}

void loop() {
  // put your main code here, to run repeatedly:
  keyon(0x14,0x65);
  delay(500);
  keyoff();
  delay(200);
  keyon(0x1c,0x11);
  delay(500);
  keyoff();
  delay(200);
  keyon(0x1c,0x42);
  delay(500);
  keyoff();
  delay(200);
  keyon(0x1c,0x5d);
  delay(500);
  keyoff();
  delay(200);
  keyon(0x24,0x17);
  delay(500);
  keyoff();
  delay(200);
}

正直、よくわからなかったので早速書込んでみました。

なおスピーカーは、YMF-825のSPに直接繋ぎます。

実際の動作が下記の動画になります。

ド、レ、ミ、フぁ、ソまでをずっと繰り返しているようです。

どうやら、このプログラムの一番下の、void loop内の処理で音階を演奏しているみたいですね。



void loop() {
  // put your main code here, to run repeatedly:
  keyon(0x14,0x65);    //ド
  delay(500);
  keyoff();
  delay(200);
  keyon(0x1c,0x11);    //レ
  delay(500);
  keyoff();
  delay(200);
  keyon(0x1c,0x42);       //ミ
  delay(500);
  keyoff();
  delay(200);
  keyon(0x1c,0x5d);    //ファ
  delay(500);
  keyoff();
  delay(200);
  keyon(0x24,0x17);        //ソ
  delay(500);
  keyoff();
  delay(200);
}

この、keyonの中の16進数の数時(0x14,0x65)が音階を決めているようです。でも、数字に連続性もないし、10進数に変換しても、周波数ではなさそう。

いろいろ調べてみたところ、しくみはよくわかりませんでしたが、EguchiKazuyuki様のQiitaのブログにて、ここに書き込む音階のデータが示されていました。これもデータが必ずしも正確とは限らないそうなので、参照はあくまで自己責任でおねがいします。

YMF825の音階パラメータについてhttps://qiita.com/KazuyukiEguchi/items/8e7192a0114250f8898f

なので、音階は取り合えずここから参照すれば使えそうです。(大変感謝申し上げます)

次に、音色です。

設定次第で、様々な音を出せるようで、ピアノ、ギターなど自由に作れます。

サンプルコード内の、void set_toneの中の、tonedata[35]の配列の数字で決めています。



void set_tone(void){
  unsigned char tone_data[35] ={
    0x81,//header
    //T_ADR 0
    0x01,0x85,
    0x00,0x7F,0xF4,0xBB,0x00,0x10,0x40,
    0x00,0xAF,0xA0,0x0E,0x03,0x10,0x40,
    0x00,0x2F,0xF3,0x9B,0x00,0x20,0x41,
    0x00,0xAF,0xA0,0x0E,0x01,0x10,0x40,
    0x80,0x03,0x81,0x80,
  };
  
   if_s_write( 0x08, 0xF6 );
   delay(1);
   if_s_write( 0x08, 0x00 );
  
   if_write( 0x07, &tone_data[0], 35 );//write to FIFO
}

この配列を変えることで音色を変更できそうです。

音色のサンプルスケッチは、Himagine様のブログを参考にさせていただきました。

ヤマハ提供サンプル(2)https://sites.google.com/site/himagine201206/home/arduino/ymf825/030

下記に転載させていただきます。感謝申し上げます。

変換済 tonedata.txt

/*
// GrandPiano
0x01,0x43,      // modify BO:0 -> BO:1
0x00,0x67,0xFF,0x9D,0x00,0x10,0x40,
0x21,0x33,0xE2,0xA3,0x00,0x50,0x00,
0x10,0x41,0xD3,0x88,0x01,0x10,0x00,
0x21,0x62,0xD4,0x02,0x01,0x10,0x00,
*/

/*
// E.Piano
0x01,0x45,      // modify BO:0 -> BO:1
0x51,0xC4,0xFB,0x8C,0x44,0x70,0x95,
0x10,0x82,0xFF,0x12,0x45,0x10,0x00,
0x11,0xB0,0xF1,0x49,0x44,0x10,0x02,
0x11,0x72,0xFF,0x10,0x41,0x10,0x00,
*/

/*
// TenorSax
0x01,0x45,      // modify BO:0 -> BO:1
0x01,0x03,0x70,0x16,0x44,0x10,0x0B,
0x00,0x92,0x70,0x3C,0x43,0x10,0x40,
0x01,0x03,0x70,0x22,0x44,0x10,0x4B,
*/

/*
// PickBass
0x02,0x43,      // modify BO:0 -> BO:2
0x21,0x37,0xF1,0x4E,0x44,0x10,0x05,
0x41,0x6B,0xC7,0x54,0x44,0x70,0x00,
0x21,0x69,0xF2,0x5E,0x44,0x20,0x00,
*/

/*
// TnklBell
0x01,0x45,      // modify BO:0 -> BO:1
0x30,0x46,0xF5,0x41,0x44,0xE0,0x03,
0x70,0x66,0xCE,0x2E,0x44,0x20,0x00,
0x20,0x26,0xC5,0x78,0x44,0x77,0x08,
0x40,0x55,0xFD,0x04,0x54,0x60,0x00,
*/

/*
// NewAgePd
0x01,0x45,      // modify BO:0 -> BO:1
0x31,0x3F,0xF0,0x98,0x44,0x70,0x0D,
0x40,0x47,0xF0,0x2E,0x44,0x50,0x00,
0x00,0x11,0x60,0x62,0x03,0x17,0x0E,
0x00,0x51,0x81,0x02,0x03,0x10,0x00,
*/

/*
// RimShot
0x00,0x45,
0x59,0x50,0xF0,0x14,0x44,0xC0,0x17,
0x79,0x77,0xF7,0x00,0x44,0xB0,0x00,
0x68,0x6A,0xF8,0x00,0x44,0xC0,0x00,
0x78,0x77,0xF7,0x00,0x44,0x70,0x10,
*/

/*
// Castanet
0x01,0x45,      // modify BO:0 -> BO:1
0x58,0x97,0xFF,0x08,0x44,0x70,0x0E,
0x59,0xF8,0xAF,0x00,0x44,0x50,0x30,
0x68,0x55,0xF0,0x9C,0x44,0x20,0x28,
0x98,0x9A,0xCA,0x50,0x44,0x50,0x00,
*/

ここには、GrandPiano  E.Piano  TenorSax  PickBass  TnklBell  NewAgePd  RimShot  Castanetの八種類の音源があり、これをコピペすることで音色を変えれそうです。

今日は、ここまで。

2021.8.12 YMF-825を使いこなす1

本日の内容

超音波の楽器を作るにあたり、出力する音は、いろんな音が出せる方が良いと思うようになりました。

YMF-825の特徴

ヤマハのFM音源チップYMF825(SD-1)を搭載した音源ボードです。ヤマハ独自のFMシンセサイザを搭載し、数種類のパラメータ指定により豊かなサウンドを再生することが可能です。

ArduinoやRaspberry Pi等のマイコンボードから、SPIを通して直接YMF825のレジスタを制御することで発音させます。スピーカーアンプも搭載しているので、アンプ回路を別途外部に用意する必要がありません。

※3.5 mmのヘッドホンジャックを搭載していますが、iPhone用などの4極CTIA採用のイヤホンはお使いいただけません(OMTPのものはお使いいただけます)。**Switch science様の販売ページより**

仕様

  • 4オペレータのFM音源
  • 最大16音同時に発音可能
  • FMの基本波形29種類内蔵、アルゴリズム8種類
  • SPIによるシリアルインタフェース
  • スピーカアンプ内蔵
  • 3バンドイコライザ内蔵
  • 16 bitモノラルD/Aコンバータ内蔵
  • 動作電圧:5 V
  • 3.3 Vでも改造することで利用可能
**Switch science様より画像引用**

サンプルスケッチがGitHubに上がっていますので参考にしました。

・サンプルスケッチ

どんな波形も生み出せる

サンプルスケッチには、簡単なマニュアルも入っています。

YMF825が生み出せる波形

基本的な、正弦波、三角波、のこぎり波、矩形波、半波整流みたいな波、など様々です。

 

7種類の帰還が掛けれる

エフェクターや、シンセサイザーでおなじみの帰還も、7種類から選ぶことができます。

まだ、くわしく分かってないので今後、紹介させていただければと思います。

SPI通信とは

シリアル・ペリフェラル・インタフェース(Serial Peripheral Interface, SPI)は、コンピュータ内部で使われるデバイス同士を接続する方法であり、比較的低速なデータ転送を行うデバイスに利用される。

SPIは省ピンで接続できるバスとして、モトローラ(現在はNXPセミコンダクターズ)が提唱した規格であり、

信号線は4本で構成され、一つのデバイスを接続する場合はSSを固定することで3本で接続できる。

SCK
Serial Clock

MISO
Master In Slave Out

MOSI
Master Out Slave In

SS
Slave Select

SPI通信の接続(*Wikipediaより引用)

 

 

簡単な動作回路例

次に、接続図です。

YMF-825との接続

YMF-825とArduinoNanoをSPIの形式で通信するだけですので、相互の、電源ライン(+5V,GND)とSPIの端子(SCK,MISO,MOSI,SS,Reset)を接続します。

 

今日はここまで

2021.8.10 ATmega328にプログラムを書込む

本日のトピック

以前のブログで、ATmega328のブートローダを書き込みました。

今回は、この続きとして、ATmega328にArduinoと同様にプロブラムを書き込みます。

まず、プログラムを書き込むのに、PCと接続する必要がありますよね。ですが、ATmega328にはUSBがありません。

さてはまた純正のArduinoを用意するかと思いますが、もっと安いもので代用が出来ます。

それが、USB-シリアル変換器です。

USB-TTL変換器

FTDI社FT232RQを使ったUSBシリアル変換モジュールです.
・WindowsXP~10まで幅広いドライバーが有り対応しています。
・DIPスイッチで5V/3.3Vの信号レベルの変更が可能です。

端子は、+5V、GND、CTS、TXD、RXD 、RTSの六端子です。

TXD,RXDということは、そうですUARTの通信になります。

 

ATmega328との接続

次に、ATmega328との接続方法です。

UARTの通信ですので、変換器のTXD(送信)を,ATmega328のRXD(受信)に、変換器のRXD(受信)をATmega328のTXD(送信)に接続します。あとは、TTL変換器の+5VとGNDを、ATmega328にも供給します。

そして、変換器からリセットの信号を送れるように、RTSとATmega328のResetを、0.1uFのコンデンサを経由して接続します。

あとは、ATmega328のクロックとして、16MHzの水晶発振子を接続します。

Arduino IDEの設定

TTL変換器をUSBに接続すれば、あとは普通のArduinoと同様に書き込むことが出来ます。

ただ、ここで書き込めるのは、ブートローダを書込み済のマイコンに限ります。

ブートローダの書込み方法は下記に示しますので参考にしてください。

・ブートローダ書込み方法

さて、Arduinoと同様に書けるとは言ったものの、ATmega328でも、ATmega328P-PUと、ATmega328Uでは少し、設定が違います。

ATmega328P-PUの書込み設定

ATmega328P-PUは、少し割高ですが、純正品のArduino UNOと同じチップを使っているので、「ツール」を開いた設定画面では、ボード「Arduino Uno」を選び、あとはTTL変換器を繋いでいるCOMポートを選択すれば、これで書き込めてしまいます。

Arduino IDEを開きプログラミング
ATmega328P-PUの設定

ATmega328 U(ATmega328PU)

Arduinoに初期から入っているボードマネージャーでは、ATmega328は書き込めません。

「ツール」→「ボード」→「ボードマネージャー」を開き、MiniCoreと検索し、インストール。

ボードマネージャーを起動
MiniCoreをインストール

Arduinoを再起動して、「ツール」→ボード→「MiniCore」→「ATmega328」を選択します。

ボードはATmega328を選択

あとは、左上の書込みボタンで書き込めます。

学校のチャイムが鳴るLED時計の製作

先日、とあるアウトレットモールのガチャガチャコーナーで見つけた、学校のチャイムが鳴るキーホルダー。

衝動的につい回してしまいました。

詳しくはこちらに載ってました。

・カプセルトイ 学校のチャイム

[オタク向けカプセルトイ情報局]【5月再販】学校のチャイム

**カプセルトイ情報局様HPより画像引用**

だれもが青春時代に聞いていた、あの学校のチャイムを聞くことができるなつかしのカプセルトイです。

今回はこれをいろいろ改造し、以前電子工作マガジンで製作した、自作のLED時計と組み合わせ、家庭で本物のチャイムとして運用できるようにします。

組み合わせる自作LED時計

電子工作マガジン2021年春号 電波新聞社HPより画像引用

以前、電子工作マガジン2021年春号に掲載させていただいた、RTC搭載LED時計に組み合わせます。

詳しい作り方は、ぜひ電子工作マガジン春号をお買い求めください。

・amazon 販売ページ

[Amazon 電子工作マガジン2021年春号]

・電波新聞社HP

[電波新聞社 電子工作マガジン2021年春号]

この時計はArduinoを使用しているため、今回はArduinoのプログラムを少し変えて、時計にプログラムした時間に、チャイムを鳴らす機能を付けます。

学校のチャイムを分解

まずは、学校のチャイムを分解します。さて、どんな仕組みになっているでしょうか。

裏面にネジ穴が4つ開いていたので、まずは精密ドライバーで開封。

中は、こんな感じです。

思ったよりシンプルな構造になっています。

さすがは、300円のカプセルトイ。かなり簡素な設計でコストを抑えています。

中は、回路基板、スピーカー、電池BOX、磁石、だけしかありません。

基板にはほんとに何も載っていません。

写真右側にある黒い部品が、ICチップです。

これはおそらく小メモリのマイコンチップで、学校のチャイムが録音されており、それを再生するだけのシンプルなプログラムが組まれていると思います。

型番は、204HWCZ04と表記されていますがGoogleで検索してもなにもでてこないため、おそらくは中国の半導体メーカーにソフトウェアを特注で作らせているため、客先固有の型番が刻印されているのだと思います。

真ん中の黒い部品がタクトスイッチです。これは、プラスチックケースのボタンの丁度真下に来るように配置されており、ボタンを押すことでチャイムが作動します。

 

基板を展開したのが左図です。

写真左側の電池ボックスから電源を真ん中の回路基板に流します。左側の緑色の部品がスピーカーです。スピーカーの性能は、8Ω0.25Wの低電力向けの格安スピーカーです。おそらく原価は20円程度でしょう。

 

電池は、LR44が二つです。

なので、電源電圧は3Vで動作していることがわかります。

次に、基板を調べて、回路図に起こしました。

バッテリーは3Vで供給。電源に付いているコンデンサCは、パスコンと呼ばれ、電源ラインに乗っかってしまうノイズを除去し、マイコンの誤動作を防ぎます。

今回少し驚いたのが、スイッチがNPN型(押すとGNDに接続)ではなく、PNP型である点です。これは、改造に少し手間がかかりそうです。

また、スピーカーの出力が、片チャンネルではなく、スピーカーの両方の端子がICに直結していることです。

これは、おそらくBTL方式と呼ばれるスピーカーの駆動方式を採用していると思います。詳しくは、今度書こうと思いますが、低い電源電圧でもなるべく大きな音を出したいときによく使われます。この回路も、電源電圧が3Vと非常に低いため、苦肉の策でBTLが使われていると考えます。

 

学校のチャイムの改造

さて、ここからが本題です。

このチャイムを改造します。

やりたいことは、LED時計のArduinoからのデジタル出力で、チャイムを駆動させることです。

今回ややこしいのは、まず学校のチャイムのスイッチがPNP型であること。

そして、LED時計の電源電圧は、USBからの供給で5Vであり、学校のチャイムの電源電圧3Vと違っている点です。

つまり、LED時計のデジタル出力のHIGH電圧が5Vなのに対し、学校のチャイムのHIGH入力は最大3Vであるため、レベルシフトが必要な点です。

まずは、設計した回路図を示します。

今回は、トランジスタを二つ用いて改造します。

まず、チャイムを鳴らすためには、スイッチの両端を電気的にショートさせる必要があります。

そのために、PNPのトランジスタ(2SA1015)を使いました。トランジスタのベース電圧を2V以下にすることで、エミッターコレクタ間がショートし、ボタンを押したのと同様の状態になります。

また、ベース電圧を2V以下(0V)にするため、下側にNPNのトランジスタを入れます。

このNPNトランジスタをArduinoのデジタル出力によってON/OFFします。ArduinoのHIGH出力は5Vです。

そのため、間に1kΩの抵抗を挟みました。

 

学校のチャイムを加工する

まず、ケーブルを通す穴をあけます。

ケーブルを通す穴をあける
ケーブルを通す
トランジスタのリードを曲げる

その後、トランジスタのりードを曲げ、回路図通りに空中配線していきます。

PNPトランジスタを配線
NPN側も配線
LED時計のケーブルをつなぐ箇所
LED時計のプログラムを変更

下記が、変更後のプログラムです。

詳細は割愛します。

#include <DS3232RTC.h>//ライブラリーをインクルード
void setup() {
DDRD = DDRD | B11111100;      //D7 6 5 4 3 2 1 0 の入出力設定(1で出力 0で入力)
DDRB = DDRB | B00111111;      //D * * 13 12 11 10 9 8の入出力設定(1で出力 0で入力)
DDRC = DDRC | B00000000;      //A* * 5 4 3 2 1 0の入出力設定(1で出力 0で入力)
pinMode(A0,INPUT_PULLUP);
pinMode(A1,INPUT_PULLUP);     //SW1タクトスイッチの入力設定(内部プルアップ)
pinMode(A3,OUTPUT); //Alartピンの出力設定
}
boolean Number_Array[10][7]={    //Number_Array[数字の数][セグ数]
{1,0,0,0,0,0,0},//0 {g,f,a,b,e,d,c}で入力。1がOFF,0がON(アノードコモンのため) 
{1,1,1,0,1,1,0},//1
{0,1,0,0,0,0,1},//2
{0,1,0,0,1,0,0},//3
{0,0,1,0,1,1,0},//4
{0,0,0,1,1,0,0},//5
{0,0,0,1,0,0,0},//6
{1,0,0,0,1,1,0},//7
{0,0,0,0,0,0,0},//8
{0,0,0,0,1,0,0} //9
};

//チャイムを慣らす時刻の設定(1日最大10回)
int alart[10]={
  600,
  610,
  700,
  9999,
  1900,
  2130,
  2200,
  9999,
  9999,
  825
};



//LED表示関数を定義
void Number(int x){
  int z[]={10,11,12,13,9,8,7};      //{g,f,a,b,e,d,c}で入力
  for (int seg=0; seg<=6; seg++){
    digitalWrite(z[seg],-Number_Array[x][seg]);
  }
}
void loop(){  
  PORTD |= 0b11111100;      //D7 6 5 4 3 2をHIGH(一旦非表示にする)
  PORTB |= 0b00111111;      //D * * 13 12 11 10 9 8をHIGH(一旦非表示にする)
  int com[]={6,5,3,2};      //COMポートを設定{comA,comB,comC,comD}
  int y[]={0,0,0,0};        //各桁に表示する数字の変数を宣言{時,時,分,分}
  int altime = 0;           //アラート時間であることを判定する時間の変数
  int al;
  
  
  tmElements_t tm;
  RTC.read(tm);
  y[0]= tm.Hour/10;           
  y[1]= tm.Hour%10;
  y[2]= tm.Minute/10;
  y[3]= tm.Minute%10;
  int dots = tm.Second%2;
  digitalWrite(4,dots);
  for(int i=0;i<=3;i++){        //ダイナミック点灯のループ
     digitalWrite(com[i],LOW);   //表示する桁を開ける
     int x=y[i];                 //その桁で表示する数字をxに代入
     Number(x);                  //xの数字を表示する
     delay(3);
     digitalWrite(com[i],HIGH);  //表示した桁を閉じる    
  }
  if(digitalRead(A0)==LOW){
      delay(250);
      if(digitalRead(A0)==LOW){
        setTime(tm.Hour+1, tm.Minute ,0,0,0,0);//時、分、秒、日、月、年の順で入力
        RTC.set(now());//初期設定時間の書き込み
      }
  }
  if(digitalRead(A1)==LOW){
      delay(250);
      if(digitalRead(A1)==LOW){
        setTime(tm.Hour, tm.Minute+1 ,0,0,0,0);//初期設定 時、分、秒、日、月、年の順で入力
        RTC.set(now());//初期設定時間の書き込み
      }
  }
//チャイムを鳴らす判定をするPG

  altime = 1000*y[0]+100*y[1]+10*y[2]+y[3];       //現在時刻を4桁の数字にしている

  
  for(int j=0; j <= 10; j++){
      if(altime==alart[j]){
        digitalWrite(A3,HIGH);
        delay(60000);
      }else{
         digitalWrite(A3,LOW);
      }
      
  } 
}
プログラムを書き込んで完成

実際の動作がこちらです。

2021.8.7 SRF-02の使い方

本日のトピック

今回は、超音波センサSRF-02のコマンドについて調べました。

まず、SRF-02の通信には二つのモードがあり、I2CとUARTがありますが、今回はI2Cに焦点を当てて説明します。

まずは、SRF-02の主な特徴です。

◆主な仕様
・使用マイコン:16F687-I/ML
・測定範囲:16cm~6m.
・電源:5V(消費電流4mA Typ.)
・使用周波数:40KHz.
・アナログゲイン:64段階の自動ゲインコントロール
・接続モード:モード1=I2C、モード2=シリアルバス
・全自動調整機能:電源投入後キャリブレーション不要
・測距タイミング:エコー時間計測、ホストによるタスクコントロール
・測定単位:μS(マイクロ秒)、ミリ、インチ
・サイズ:24mmx20mmx17mm
・入出力端子:5ピン
・重量:4.6グラム

SRF-02の主なコマンド

次に、SRF-02で使用される主なコマンドです。

コマンドの通信方法は、ArduinoのWireライブラリを使って通信します。詳細は、以前のブログを参照してください。

I2Cでの通信方法

SRF02をI2Cモードで使用するには、モードピンをオープンにします。

I2Cの通信では、最大16個まで並列で接続できます。並列でつなぐので、それぞれのSlave(超音波センサ)にアドレスを振り分けます。
SRF02の出荷時のアドレスは0xE0です。アドレスはユーザによって変更することができ、最大16個(E0、E2、E4、E6、E8、EA、EC、EE、F0、F2、F4、F6、F8、FA、FC、FE)のアドレスが使用できます。

 

レジスタ

SRF-02には6種類のレジスタがあります。

ロケーション 読む書く
0 ソフトウェアリビジョンコマンドレジスタ
1未使用(0x80を読み取ります)該当なし 
2測定値 上位バイト該当なし
3測定値 下位バイト該当なし
4オートチューン最小-上位バイト該当なし
5オートチューン最小-下位バイト該当なし
レジスタ

 

6個あるレジスタのうち、Masterから書き込むことができるのは、0番のレジスタのみです。

すべて、0番のレジスタに数値を入れることでSRF-02の様々な設定ができます。

0番から読み出す場合は、ソフトウェアリビジョンを返されます。1番は使用していない空きピンです。

2,3番のレジスタが、測定した数値を返すレジスタです。測定値は最大2byteの容量で返します。レジスタ1個は1byteですので、レジスタが二つ(2,3)必要なわけです。この測定値は、設定の状態によって、インチ、センチ、マイクロ秒などで返します。

4、5番のレジスタは、16ビットの符号なし最小範囲です。これは、ソナーが測定できるおおよその最も近い範囲です。

つまり最初0番で指定をしたら、あとは2,3番のレジスタで測定値を参照すればよいということです。

 

SRF-02のコマンド

下記が、SRF-02の0番に指定するコマンドです。

  2進数    16進数  動作
800x50Real Ranging Mode – Result in inches
810x51Real Ranging Mode – Result in centimeters
820x52Real Ranging Mode – Result in micro-seconds
860x56Fake Ranging Mode – Result in inches
870x57Fake Ranging Mode – Result in centimeters
880x58Fake Ranging Mode – Result in micro-seconds
920x5CTransmit an 8 cycle 40khz burst – no ranging takes place
960x60Force Autotune Restart – same as power-up. You can ignore this command.
1600xA01st in sequence to change I2C address
1650xA53rd in sequence to change I2C address
1700xAA2nd in sequence to change I2C address
コマンド

必要に応じて、上記のコマンドを1番のコマンドレジスタに書き込み、必要な時間待機して結果を読み取ります。エコーバッファは、各レンジングの開始時にクリアされます。レンジングは最大66m秒持続します。この後、測定値を2,3番のレジスタから読み取ります。

SRF-02の命令方法

MasterからSRF-02に命令する場合、どのようにしたらよいでしょうか。

下記が、参考に、測定値をcmにするプログラムです。

Wire.beginTransmission(226); //通信先のアドレス
  Wire.write(0x00);    //レジスタを選ぶ
  Wire.write(0xA0);  //コマンドを選ぶ
  Wire.endTransmission();

順番としては、まず Wire.beginTransmission(226); で、Slaveのアドレス(226)を指定。

次に送信するものは、接続するレジスタになります。なにか設定などをする場合は、

0番のレジスタにアクセスするため、Wire.write(0x00);で0を送ります。

次に、送るものが設定するコマンドです。

例えば、測定値をcmで返す設定をする場合は、コマンド0x51を送ればよいので、

Wire.write(0x51);となります。

設定はこれで終了なので、 Wire.endTransmission(); で今回の通信を終わります。

コマンドの内容にもよりますが、基本は、レジスタを指定→そのレジスタのコマンドを送る、の流れです。

 

SRF-02の測定値を読み出すプログラム

次に、SRF-02から測定値を読み出す方法です。

      Wire.beginTransmission(0xE0); // transmit to device #112
      Wire.write(byte(0x02));      // sets register pointer to echo #1 register (0x02)
      Wire.endTransmission();      // stop transmitting

     
      Wire.requestFrom(0xE0, 2);    // request 2 bytes from slave device #112
    
      if (2 <= Wire.available())   // if two bytes were received
      {
        reading = Wire.read();  // receive high byte (overwrites previous reading)
        reading = reading << 8;    // shift high byte to be high 8 bits
        reading |= Wire.read(); // receive low byte as lower 8 bits
        Serial.print(reading);   // print the reading
        Serial.println("cm");
      }

まず、SRF-02から数値を読み出す場合、2番目のレジスタ0x02にアクセスします。それが、3行目までのプログラムです。

次に、SRF-02からデータを受信する準備をします。それが、 Wire.requestFrom(0xE0, 2); です。

これは、アドレスE0のSlaveから、2byteのデータを受け取りますという意味です。

あとは Wire.read();で、データを受け取ることが出来ます。しかし、2byteあるため、そのまま受け取ると下位ビットが上書きされます。そのため、まず、上位8ビットのデータを受け取り( reading = Wire.read(); )、readingのビットを (reading = reading << 8; )8bit高い位にシフトさせてから、次に飛んでくる数値(下位ビット)を ( reading = Wire.read(); ) で受信します。

Slaveで分割されたデータは、上位ビットから書き込まれる

そのまま下位ビットを書き込むと上書きされてしまう

そこで、最初に書き込まれた上位ビットを8ビット上にシフト

そのあとで下位ビットを書き込めばすべて正しく送れる

 

 

SRF-02のアドレス指定

次に、SRF-02のアドレス指定手順です。方法は簡単で、上記コマンドの0xA0, 0xAA, 0xA5,を順番に送り、最後に新しいアドレスを送ることで、アドレスを指定するモードになります。例えば、もともとのアドレスE0から新しいアドレスF4に帰る場合は下記のプログラムを動かします。とてもシンプルですよね。

  Wire.beginTransmission(0xE0);
  Wire.write(0x00);
  Wire.write(0xA0);               //A0を書き込む
  Wire.endTransmission();

  Wire.beginTransmission(0xE0);
  Wire.write(0x00);
  Wire.write(0xAA);               //AAを書き込む
  Wire.endTransmission();

  Wire.beginTransmission(0xE0);
  Wire.write(0x00);
  Wire.write(0xA5);               //A5を書き込む
  Wire.endTransmission();

  Wire.beginTransmission(0xE0);
  Wire.write(0x00);
  Wire.write(0xF4);               //新しいアドレスF4を書き込む
  Wire.endTransmission();

今日は、ここまで。

 

2021.8.7 ひいらぎ

2021.8.3 ATmega328にブートローダを書き込む

本日のトピック

今回は、市販のAVRマイコンのATmega328を、Arduinoとして使うための処理をします。

ATmega328とは、Arduinoに搭載されているマイコンチップです。

Arduinoは、定価で買うと大体3000円程度。基板も大きいので実装には不向きです。

そこで、ATmega328を単体でArduinoとして使うようにします。

ATmega328は、通販サイトで結構売られています。

ただ、最近は半導体不足によりATmega328の表面実装や、ATmega328P-PUなどは手に入りにくい状況です。

今のところ、まだ在庫はありそうです。

RSコンポーネンツで一つ323円です。つまり、Arduinoの10分の1の価格で小サイズのArduinoが使えるわけです。

RSコンポーネンツ ATmega328-PU 通販ページ

今回は、このICにArduinoとして使うためのブートローダを書き込みます。

そもそも、ブートローダとは何でしょうか。

 

ブートローダとは

ブートとは、コンピュータなどでOSなどの基本ソフトウェアを起動することを意味する俗語。ブートローダとは、このときに、OS本体や「OSをロードするためのソフトウェア」をメモリに読み込むための小さなソフトウェアを言います。このプログラムは、ATmegaマイコンを動かす上の基礎てきなソフトです。初期設定みたいなものなので、一度書き込んでしまえば、ずっと使えますし、ソフトも何回も書き換えれます。

 

ブートローダを書き込む準備

ブートローダを書き込むためには、純正品のArduinoを用意してください。ATmega328とSPI方式で通信する必要があり、そのために純正のArduinoが必要になります。

純正のArduinoは基本的になんでも構いません。私は、ブレットボードに刺せるArduino Nanoを使いました。

Arduino Nano
ATmega328PU

 Arduino NanoとATmega328PUの配線図は下図の通りです。

要するに、ArduinoNanoとATmega328でSPI通信を行いたいため、お互いのMISO、MOSI、SCKと+5V、GNDを接続します。あとは、ArduinoNanoが指定するタイミングで、328のResetをかけるため、NanoのD10と328のResetを接続し、6.8kΩの抵抗でプルアップしています。

あとは、ATmega328もクロック無しでは動かないので、16MHzの水晶発振子と定番のコンデンサ22pFを入れています。

ブートローダを書き込む接続図

実際にブレッドボードで配線しました。

ブレッドボードで配線

ArduinoIDEの設定

次に、Arduinoの書込みソフトの設定をします。

まず、書き込むICが ATmega328P-PUと、ATmega328PU(部品表記;ATMEGA328 U)では、ブートローダの書込み方が違います。これは、ATmel社がMicroChip社に変わってから、廉価版として発売されたATmega328PUは、書き込むバリアントが違うためです。

 

ATmega328P-PUのブートローダを書き込む

まず、ArduinoIDEを起動します。Arduinoのソフトのインストールは下記のリンクから行ってください。

ArduinoIDEのダウンロード

ArduinoIDEが起動したら、「ファイル」→「スケッチ例」→「11.ArduinoISP」→「ArduinoISP」を開きます。

Arduino IDEを起動
Arduino ISPを起動

まず、ArduinoNanoにArduinoISPのソフトを書き込みます。これで、ArduinoNanoを書き込み機として使えます。

その後、「ツール」を押して、ポート「Arduino Uno」、シリアルポート「ArduinoNanoを接続してるCOMポート」、書込装置「Arduino as ISP」を選択し、一番下の「ブートローダを書き込む」を押して、ブートローダを書き込むことが出来ます。

ArduinoNanoにArduinoISPのソフトを書き込む
ブートローダを書き込む

 

ATmega328PUにブートローダを書き込む

上記で、ArduinoISPをArduinoNanoにISPのソフトを書き込むところまでは同じです。

Arduinoに初期から入っているボードマネージャーでは、ATmega328は書き込めません。

「ツール」→「ボード」→「ボードマネージャー」を開き、MiniCoreと検索し、インストール。

ボードマネージャーを起動
MiniCoreをインストール

Arduinoを再起動して、「ツール」→ボード→「MiniCore」→「ATmega328」を選択します。

ボードはATmega328を選択
シリアルポート、書き込み装置を選択

あとは、「ブートローダを書き込む」を押すと書き込まれます。

これでブートローダの書き込みが完了します。

 

今日はここまでです。