RL78/G10 10ピン製品 PWM使用時の圧電ブザー音階出力について

はじめまして。

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 */
}

Parents
  • ブザーは電圧を加えると音が鳴る物です。スピーカとは違います。

    圧電スピーカも周波数範囲は狭い。

    普通の発振器を使って予備試験をしたらどうですか。

  • チョコです。

    >ブザーは電圧を加えると音が鳴る物です。スピーカとは違います

    おそらく圧電スピーカを圧電ブザーと呼んでいるのではないかと思います。

    (自励式の)圧電ブザーは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

    ⇒村田は圧電ブザー、サウンダを分類

  • チョコさん、tfさん、リカルドさん

    沢山のアドバイス誠にありがとうございます。

    (投稿したところ反映されていないため、再投稿しました。重複されていましたら申し訳ございません。)

    16ピン製品が簡単そうですので、注文しました。

    届くまでtfさんの2つ目の提案を試してみます。

    TD00H,TD00Lの値により、PWM周期を調整する認識です。

    周波数(Hz) = 5MHz/(TDR00の値 + 1 )

    ハードウェア編 p.192(PDF 207ページ)

    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

    ⇒圧電ブザーの表記

    https://www.murata.com/ja-jp/products/sound/library/basic/soundtype

    ⇒圧電ブザー、サウンダ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)

  • trさん ありがとうございます!!
    無事音階を実装できました。
    (実用上問題ないため無視していますが、delay関数を周期1ms前提で作成しているため、ブザー時に想定したms単位からずれています。)

    制限のあるなかで機能追加できることに感動しています。

    また、TDR読み込みも勉強になりました。


    チョコさん
    今回はプラモデルのようなものへの組み込みを予定しており、小さい圧電スピーカーを選びました。
    自分の子供へのおもちゃですので、音圧の周波数依存性は多少目をつぶろうと思います。

    2本の信号に逆相を出力は、回路例にも記載されていました。
    色々なテクニックがあるのですね。
    https://www.murata.com/ja-jp/products/sound/library/basic/circuit

    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;
    volatile unsigned char buzzer_enable = 0; // 0:OFF, 1:ON
    
    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を前提とした場合
    
    	if (buzzer_enable)  // ブザーが ON のときだけ P02 をトグル
    	    {
    	        P0_bit.no2 = ~P0_bit.no2;
    	    }
        /* End user code. Do not edit comment generated here */
    }
    
    
    
    File Name    : r_cg_tau.h
    /***********************************************************************************************************************
    Global functions
    ***********************************************************************************************************************/
    void R_TAU0_Create(void);
    void R_TAU0_Channel0_Start(void);
    void R_TAU0_Channel0_Stop(void);
    
    /* Start user code for function. Do not edit comment generated here */
    unsigned long getsystime(void);
    extern volatile unsigned char buzzer_enable; // 外部参照用
    /* End user code. Do not edit comment generated here */
    #endif
    
    
    
    File Name    : r_cg_main.c
    
    /***********************************************************************************************************************
    Includes
    ***********************************************************************************************************************/
    #include "r_cg_macrodriver.h"
    #include "r_cg_cgc.h"
    #include "r_cg_port.h"
    #include "r_cg_tau.h"
    /* Start user code for include. Do not edit comment generated here */
    /* End user code. Do not edit comment generated here */
    #include "r_cg_userdefine.h"
    
    /***********************************************************************************************************************
    Pragma directive
    ***********************************************************************************************************************/
    /* Start user code for pragma. Do not edit comment generated here */
    /* End user code. Do not edit comment generated here */
    
    /***********************************************************************************************************************
    Global variables and functions
    ***********************************************************************************************************************/
    /* Start user code for global. Do not edit comment generated here */
    #define D5_PERIOD  8512  // D5 (587.3Hz) TDR00の値(10進数)
    #define E5_PERIOD  7583  // E5 (659.3Hz) TDR00の値(10進数)
    #define D6_PERIOD  4256  // D6 (1174.7Hz) TDR00の値(10進数)
    #define E6_PERIOD  3791  // E6 (1318.5Hz) TDR00の値(10進数)
    
    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 set_buzzer_period(unsigned short new_period) // ブザー用の周期設定関数
    {
        DI();
        TDR00H = (unsigned char)(new_period >> 8);
        TDR00L = (unsigned char)(new_period & 0xFF);
        EI();
    }
    
    void play_note(unsigned short period, unsigned short duration_ms)
    {
        set_buzzer_period(period);  // 周期設定
        buzzer_enable = 1;          // ブザーON
        start_time = getsystime();
    
        while ((getsystime() - start_time) < duration_ms);  // 指定時間待機
    
        buzzer_enable = 0;  // ブザーOFF
        P0_bit.no2 = 0;     // P02をLOWにして無音にする
        delay_ms(50);      // 音の間隔
    }
    
    /* 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待つ チャタリング対策
    
        		//R_PCLBUZ0_Start(); //圧電ブザーON
                //play_melody();    // メロディー演奏
                //delay_ms(2000);   // 2秒待つ
    
        		play_note(E5_PERIOD, 50);  // ミ (E5)
        		play_note(D5_PERIOD, 50);  // レ (D5)
        		play_note(E5_PERIOD, 50);  // ミ (E5)
        		play_note(D5_PERIOD, 50);  // レ (D5)
        		play_note(E5_PERIOD, 50);  // ミ (E5)
        		play_note(D5_PERIOD, 50);  // レ (D5)
        		play_note(E5_PERIOD, 50);  // ミ (E5)
        		play_note(D5_PERIOD, 50);  // レ (D5)
        		play_note(E5_PERIOD, 50);  // ミ (E5)
        		play_note(D5_PERIOD, 100);  // レ (D5)
    
        		//初期値1ms周期へ戻す 4999
    			TDR00H = (unsigned char)(4999 >> 8);
    			TDR00L = (unsigned char)(4999 & 0xFF);
    
    			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);
    			}
    
    			//R_PCLBUZ0_Stop();//圧電ブザーOFF
    			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 */
    }
    

  • チョコです。

    >自分の子供へのおもちゃですので

    いいですね。おもちゃへの組み込みですか。

    10年前になりますが、おなじく10pinのRL78/G10で12個のLEDをいろんなパターンで点滅させました。CR2032のボタン電池で1週間近く動いていました。

    この写真で、LEDの間で微かに光っているのはビーズでデコられているところです。

    回路とプログラムをかふぇルネにアップしていたのですが、今ではなくなってしまいました。

    これを他の人が作ったという話は聞きませんでしたが、私は10枚程度作って、知り合いに配りました。手持ちの1枚は、今でも動いていますよ。

    女子には受けたのではないかと思っています。

    以上

Reply
  • チョコです。

    >自分の子供へのおもちゃですので

    いいですね。おもちゃへの組み込みですか。

    10年前になりますが、おなじく10pinのRL78/G10で12個のLEDをいろんなパターンで点滅させました。CR2032のボタン電池で1週間近く動いていました。

    この写真で、LEDの間で微かに光っているのはビーズでデコられているところです。

    回路とプログラムをかふぇルネにアップしていたのですが、今ではなくなってしまいました。

    これを他の人が作ったという話は聞きませんでしたが、私は10枚程度作って、知り合いに配りました。手持ちの1枚は、今でも動いていますよ。

    女子には受けたのではないかと思っています。

    以上

Children
No Data