はじめまして。
RL78/G10 10ピン製品を使用する場合、PWMを使用しながら圧電ブザーに任意の音階を出力することは可能でしょうか。
ハードウェアマニュアルを確認しながら試行錯誤していますが、PWMと音階波形を同時に出力するには16ピン製品の必要なのではと考えています。
お手数をおかけしますが、ご教示いただけますと幸いです。
また、プッシュスイッチを押すと
1.圧電ブザーで音階演奏
2.LEDがPWM制御で徐々に点灯し、数秒間保持したのちに消灯
といった動作を実現したいと考えています。(音階演奏以外は出来ています。)
現在は、コード生成R_PCLBUZ0を使用して1.22kHz,0.61kHz(おそらく)のブザーで代替していますが、
可能であれば音階演奏したいです。
IDE:e2 studio(CC-RL)
マイコン等:R5F10Y16ASP使用 RL78マイコンモジュール(秋月電子, 10ピン製品)
E2 Lite
コード生成
端子割り当て:初期設定(PCLBUZ0 - P02, TI01/TO01 - P04, INTP1 - P00)
クロック設定:VDD2.0~5.5V, クロック5MHz
タイマアレイ:PWM, 周期1ms, 初期Duty0%, 初期出力値0, 出力レベルアクティブハイ
ブザー出力:使用する, 出力クロックfMAIN/2^12
接続部品
ピン06(P00):抵抗 - VDD, プッシュスイッチ - GND
ピン08(P02):抵抗 - 圧電ブザー - GND
ピン10(P04):抵抗 - LED - GND
* File Name : r_cg_tau_user.c /*********************************************************************************************************************** Global variables and functions ***********************************************************************************************************************/ /* Start user code for global. Do not edit comment generated here */ static unsigned long _systime=0; unsigned long getsystime(void) { return _systime; } /* End user code. Do not edit comment generated here */ /*********************************************************************************************************************** * Function Name: r_tau0_channel0_interrupt * Description : This function INTTM00 interrupt service routine. * Arguments : None * Return Value : None ***********************************************************************************************************************/ static void __near r_tau0_channel0_interrupt(void) { /* Start user code. Do not edit comment generated here */ _systime++; //1msを前提とした場合 /* End user code. Do not edit comment generated here */ } * File Name : r_cg_main.c /*********************************************************************************************************************** Global variables and functions ***********************************************************************************************************************/ /* Start user code for global. Do not edit comment generated here */ unsigned short tdr_value = 0x0000; // 初期値 0 (16進数) unsigned short tdr_max = 0x1388; // 最大値 5000 (16進数) unsigned short step = 0x0001; // 増加量 1 (16進数) unsigned long start_time; // 現在の時間を取得 unsigned long last_update; // 最後に更新した時間を記録 void delay_ms(unsigned long ms) //getsystime() を利用して一定時間待つ関数 { start_time = getsystime(); // 現在のシステム時刻を取得 while ((getsystime() - start_time) < ms); // 指定したmsだけループで待つ } void play_note(unsigned char cks, unsigned int duration) //圧電ブザーの関数 { CKS0 = cks; // PCLBUZ0 の周波数設定 R_PCLBUZ0_Start(); // ブザーON delay_ms(duration); // 指定時間待つ R_PCLBUZ0_Stop(); // ブザーOFF delay_ms(50); // 音の間隔 } void play_melody(void) { play_note(_06_PCLBUZ_OUTCLK_fMAIN6, 200); // 1.22kHz play_note(_07_PCLBUZ_OUTCLK_fMAIN7, 200); // 0.61kHz play_note(_06_PCLBUZ_OUTCLK_fMAIN6, 200); // 1.22kHz play_note(_07_PCLBUZ_OUTCLK_fMAIN7, 200); // 0.61kHzz play_note(_06_PCLBUZ_OUTCLK_fMAIN6, 200); // 1.22kHz play_note(_07_PCLBUZ_OUTCLK_fMAIN7, 200); // 0.61kHz play_note(_06_PCLBUZ_OUTCLK_fMAIN6, 400); // 1.22kHz(長め) } /* End user code. Do not edit comment generated here */ static void R_MAIN_UserInit(void); /*********************************************************************************************************************** * Function Name: main * Description : This function implements main function. * Arguments : None * Return Value : None ***********************************************************************************************************************/ void main(void) { R_MAIN_UserInit(); /* Start user code. Do not edit comment generated here */ R_TAU0_Channel0_Start(); // PWM開始 while (1U) { if (P0_bit.no0 == 0) // スイッチが押されたら(Low) { delay_ms(10); // 10ms待つ チャタリング対策 play_melody(); // メロディー演奏 //delay_ms(2000); // 2秒待つ start_time = getsystime(); // 現在の時間を取得 last_update = start_time; // 最後に更新した時間を記録 tdr_value = 0x0000; // 初期値 0 (16進数) while (getsystime() - start_time < 1500) { if (getsystime() - last_update >= 1) // **1ms 経過ごとに** { last_update = getsystime(); // 時間を更新 tdr_value += step; // Duty 比を増加 if (tdr_value > tdr_max) tdr_value = tdr_max; TDR01H = (unsigned char)(tdr_value >> 8); TDR01L = (unsigned char)(tdr_value & 0xFF); } } start_time = getsystime(); // 現在の時間を取得 while (getsystime() - start_time < 3000) { TDR01H = (unsigned char)(tdr_max >> 8); TDR01L = (unsigned char)(tdr_max & 0xFF); } start_time = getsystime(); // 現在の時間を取得 while (getsystime() - start_time < 2000) { TDR01H = (unsigned char)(0x0000 >> 8); TDR01L = (unsigned char)(0x0000 & 0xFF); } } } /* End user code. Do not edit comment generated here */ }
チョコです。
10pinのRL78/G10ではTAUには2chしかありません。これをPWMで使うとあとは12bitインタバルタイマしかないので、音階用には使えないですね。
1KHz周期のPWMの分解能がどの程度かによりますが、分解能がそれほど必要でなければインターバルタイマ+ソフトでのPWMも考えられます。分解能が必要なら、10pinでは難しいですね。16pinを使うのが簡単ですね。
以上
LEDの明るさ制御は、アバウトで良い気がしますので、PWM→ブザー、12bitインターバルタイマをLED制御に使うのはどうでしょうか、と思ったのですが、(コード生成の画面を見ると)10pinには12bitインターバルタイマが無いですね…
じゃあですが、PWMの出力をLEDとブザーの両方につないで、
PWM周波数→ブザーの音階
PWMデューティ→LEDの明るさ
にしてしまう
(ブザーの音階の方は、聞いた感じはあまりデューティに依存しない。LEDの明るさは、PWM周波数に依存しない。)
というのは、(かなりイカサマチックですが)どうでしょうか。
最後にLEDを点灯させるタイミングでブザーが鳴った状態とするのであれば、デューティ=100%には設定出来ませんが(99%とかにする)。
>10pinには12bitインターバルタイマが無いですね…
そうですね、ありませんね。12bitインターバルタイマのクロックは15kHzで±15%なので、音程には使えないので気にもしていませんでした。
>最後にLEDを点灯させるタイミングでブザーが鳴った状態とするのであれば、デューティ=100%には設定出来ませんが(99%とかにする)。
明るさでは100%と99%は人の目では区別できないでしょう。以前、RL78/G10(10pin)で12個のLEDを制御したときには明るさは20マイクロ×32段階で制御していました。
一応それでも、ゆっくり明るさが変化しました。
ブザーは電圧を加えると音が鳴る物です。スピーカとは違います。
圧電スピーカも周波数範囲は狭い。
普通の発振器を使って予備試験をしたらどうですか。
LEDは(今のまま)TO01につなぐ、ブザー(例えば)P02につなぐ(今と変わらないがP02は汎用出力)。
TAUの周期終わりで割り込みを設定し
r_tau0_channel0_interrupt()
内で、
P0_bit.no2 = ~P0_bit.no2;
の様なコードを入れると、
ブザーは、LEDの半分の周波数でデューティ50%で駆動出来ます。
・LEDとブザーを別々のポートにつなげられる
・ブザーは常にデューティ50%(LEDのデューティに引きずられない)
というやり方もあるかと思いました。(LEDの駆動周波数は、音階に引きずられる)
>ブザーは電圧を加えると音が鳴る物です。スピーカとは違います
おそらく圧電スピーカを圧電ブザーと呼んでいるのではないかと思います。
(自励式の)圧電ブザーは1.22kHzではドライブできないのではないかと思います。
また、ポートのハイ出力ではドライブ電流が不足してまともにドライブできないでしょうね。
チョコさん、tfさん、リカルドさん
たくさんの回答、誠にありがとうございます。
16ピン製品が簡単そうなことが分かりましたので、注文します。
届くまでの間、tfさんに提案頂いた2つ目の案を試してみます。
(TDR00H,TDR00Lの値を変更し、PWM周期を調整する認識です。
PWM周波数(Hz) = 5MHz/(TDR00の値+1) )
マニュアル ハードウェア編P192(PDF207ページ)
https://www.renesas.com/ja/document/mah/rl78g10-users-manual-hardware?r=1054271
ブザー名記載していませんでしたが、TDKの圧電ブザーPS12の薄物を使用しています。
各社で圧電ブザーの定義が違うと勝手に考えていました。
https://product.tdk.com/ja/products/sw_piezo/sw_piezo/piezo-buzzer/index.html
⇒TDKは圧電ブザーのみ
https://www.murata.com/ja-jp/products/sound/library/basic/soundtype
⇒村田は圧電ブザー、サウンダを分類
沢山のアドバイス誠にありがとうございます。
(投稿したところ反映されていないため、再投稿しました。重複されていましたら申し訳ございません。)
16ピン製品が簡単そうですので、注文しました。
届くまでtfさんの2つ目の提案を試してみます。
TD00H,TD00Lの値により、PWM周期を調整する認識です。
周波数(Hz) = 5MHz/(TDR00の値 + 1 )
ハードウェア編 p.192(PDF 207ページ)
記載していませんでしたが圧電ブザーはTDK製のPS12を使用しており、
各社で圧電ブザーの呼び方が違っていると考えていました。
⇒圧電ブザーの表記
⇒圧電ブザー、サウンダmスピーカーを分類
>記載していませんでしたが圧電ブザーはTDK製のPS12を使用しており
これは、リカルドさんがコメントしているように出せる音の高さは固定で、音階は出せません。音階を出すなら、圧電スピーカにすべきです。→TDKのカタログをよく見たら「発振回路なし」なので使えそうですね。
ちなみに、圧電スピーカの周波数特性はなだらかではなく、かなり凸凹しており、440Hz辺りでは音の大きさは結構小さく3KHz辺りはかなり大きくかつ凸凹がひどかったような記憶があります。
以前、RL78/G11で音階を出したときには、3.3Vの電源電圧では音が小さすぎたので、2本の信号に逆相を出力してやっと使えるレベルになったことがありました。
Udonさま
・周期の変更
DI();TDR00H = new_period_h_val;TDR00L = new_period_l_val;EI();
・デューティの変更
DI();TDR01H = new_duty_h_val;TDR01L = new_duty_l_val;EI();
new_period_h_val は、新しい周期の上位8ビットnew_period_l_valは、新しい周期の下位8ビット
上記の様な感じで、周期とデューティを変更出来ると思います。
(現在の値を読み出す時は、順番が逆でL側を読んでからH側を読む)
デューティを100%(LED点灯)にする場合は、TDR01H=TDR01L=0xFFにすれば点灯状態も作れると思います(アクティブハイの場合)。(周期終わりの割り込みでブザーを駆動する場合は、デューティ100%もOK)