engineer01の日記

電子工作、ソフトウェア、資格、DIY、日常のことなど

/*パンくずリスト階層化*/

アイリスオーヤマ照明リモコンの自作(2) プログラム作成&動作確認

前回リモコン信号の解析を行ったため、そのとおりに作るだけ。

engineer01.hatenablog.com

まず、「何のマイコンを使うか?」だが、結論から言うとRL78のR5F10Y47ASPを使うことにした。

akizukidenshi.com

理由としては、手持ちのマイコンの中で最も動作電圧が低く(2.0V)、電池駆動に適していたため。本当はPICが一番使い慣れているので、それが良かったんだけどね。最低でも2.3Vのやつしか持っていなかった。

プログラム

全て説明すると大変なので、主要な部分だけ書くことにする。

リモコン信号は38kHzパルス信号のON/OFFなので、内蔵ペリフェラルのタイマ・アレイ・ユニットを使用して、

・パルス信号の生成(チャネル0&1でPWM)

・パルス信号のON時間計測(チャネル2)

・パルス信号のOFF時間計測(チャネル3)

を行うことにした。これだけでは何のことか分からないので、図で表すとこんな感じ。

つまり、、

  1. チャネル0&1と、チャネル2をスタート。
  2. チャネル2のカウント完了割り込みで、チャネル0&1と、チャネル2をストップ。チャネル3をスタート。
  3. チャネル3のカウント完了割り込みで、チャネル3をストップ。

の一連の流れで1bitのデータを送信することになる。

基本的にレジスタ設定はCS+のコード生成機能を使用して行った。

 

クロック設定画面。

 

割り込み設定画面。割り込みは、全灯ボタン・消灯ボタンを押したときにスタンバイ状態から通常動作に復帰するために使用している。

 

タイマ・アレイ・ユニットの設定画面はこんな感じ。チャネル2とチャネル3のインターバル時間についてはプログラム上で可変するので適当な値。

 

で、コード生成されたタイマ・アレイ・ユニットの割り込みサービスルーチンには、以下のようにタイマのスタート/ストップやフラグを立てる処理を追加。

r_cg_tau_user.c

  1. /***********************************************************************************************************************
  2. Includes
  3. ***********************************************************************************************************************/
  4. #include "r_cg_macrodriver.h"
  5. #include "r_cg_tau.h"
  6. /* Start user code for include. Do not edit comment generated here */
  7. /* End user code. Do not edit comment generated here */
  8. #include "r_cg_userdefine.h"
  9.  
  10. /***********************************************************************************************************************
  11. Pragma directive
  12. ***********************************************************************************************************************/
  13. #pragma interrupt r_tau0_channel2_interrupt(vect=INTTM02)
  14. #pragma interrupt r_tau0_channel3_interrupt(vect=INTTM03)
  15. /* Start user code for pragma. Do not edit comment generated here */
  16. /* End user code. Do not edit comment generated here */
  17.  
  18. /***********************************************************************************************************************
  19. Global variables and functions
  20. ***********************************************************************************************************************/
  21. /* Start user code for global. Do not edit comment generated here */
  22. /* End user code. Do not edit comment generated here */
  23.  
  24. /***********************************************************************************************************************
  25. * Function Name: r_tau0_channel2_interrupt
  26. * Description : This function INTTM02 interrupt service routine.
  27. * Arguments : None
  28. * Return Value : None
  29. ***********************************************************************************************************************/
  30. static void __near r_tau0_channel2_interrupt(void)
  31. {
  32.     /* Start user code. Do not edit comment generated here */
  33.     R_TAU0_Channel0_Stop();//38kHz発振停止
  34.     TO0=0;//TO01の出力をLにする
  35.     R_TAU0_Channel2_Stop();
  36.     
  37.     R_TAU0_Channel3_Start();//OFF時間の計測開始
  38.     /* End user code. Do not edit comment generated here */
  39. }
  40. /***********************************************************************************************************************
  41. * Function Name: r_tau0_channel3_interrupt
  42. * Description : This function INTTM03 interrupt service routine.
  43. * Arguments : None
  44. * Return Value : None
  45. ***********************************************************************************************************************/
  46. static void __near r_tau0_channel3_interrupt(void)
  47. {
  48.     /* Start user code. Do not edit comment generated here */
  49.     PPMTime_flg=1;//フラグを立てる
  50.     R_TAU0_Channel3_Stop();
  51.     /* End user code. Do not edit comment generated here */
  52. }
  53.  
  54. /* Start user code for adding. Do not edit comment generated here */
  55. /* End user code. Do not edit comment generated here */

 

リモコンの処理関数はこんな感じ。

nec_remocon.c

  1. /***********************************************************************************************************************
  2. Includes
  3. ***********************************************************************************************************************/
  4. #include "nec_remocon.h"
  5. static void sendWave(uint16_t onTime_us, uint16_t offTime_us);
  6.  
  7. const uint16_t _1T_CLK=2810;
  8. const uint16_t _1T_OFF_CLK=2810-240;
  9. const uint16_t _3T_CLK=8430-240;
  10. const uint16_t _8T_CLK=22480-240;
  11. const uint16_t _16T_CLK=44960-240;
  12.  
  13. void sendDataByte(uint8_t val){
  14.     uint8_t data_bit=0;
  15.     uint8_t cnt=0;
  16.     for(cnt=0;cnt<8;cnt++){
  17.         data_bit=val & 0x01;
  18.         if (data_bit){
  19.             sendWave(_1T_CLK,_3T_CLK);
  20.         }else{
  21.             sendWave(_1T_CLK,_1T_OFF_CLK);
  22.         }
  23.         val=val>>1;    
  24.     }
  25. }
  26.  
  27. void sendLeader(void){
  28.     sendWave(_16T_CLK,_8T_CLK);
  29. }
  30.  
  31. void sendStopbit(void){
  32.     sendWave(_1T_CLK,_1T_OFF_CLK);
  33. }
  34.  
  35. static void sendWave(uint16_t onTime_clkcount, uint16_t offTime_clkcount){
  36.     //38kHzの発振のON時間をセット
  37.     TDR02H=(onTime_clkcount & 0xff00)>>8;
  38.     TDR02L=(onTime_clkcount & 0xff);
  39.  
  40.     //OFF時間をセット
  41.     TDR03H=(offTime_clkcount & 0xff00)>>8;
  42.     TDR03L=offTime_clkcount & 0xff;    
  43.  
  44.     PPMTime_flg=0;
  45.     R_TAU0_Channel0_Start();//38kHz発振開始
  46.     R_TAU0_Channel2_Start();//発振のON時間の計測開始
  47.  
  48.     while(PPMTime_flg==0);//フラグが1になるまで待つ
  49. }

クロック周波数が5MHzなので、インターバルタイマーで1T(=562us)をカウントする場合、設定値は562*10^(-6)*5*10^6=2810となる。ちなみに、定数で-240しているものがあるが、これはクロック周波数が5MHzと遅く、オーバーヘッドを無視できないため、調整のために入れている。20MHz駆動とかなら多分不要。

 

メインの処理はこんな感じ。

r_cg_main.c

  1. /***********************************************************************************************************************
  2. Includes
  3. ***********************************************************************************************************************/
  4. #include "r_cg_macrodriver.h"
  5. #include "r_cg_cgc.h"
  6. #include "r_cg_port.h"
  7. #include "r_cg_tau.h"
  8. #include "r_cg_it.h"
  9. #include "r_cg_intp.h"
  10. /* Start user code for include. Do not edit comment generated here */
  11. #include "nec_remocon.h"
  12. /* End user code. Do not edit comment generated here */
  13. #include "r_cg_userdefine.h"
  14.  
  15. /***********************************************************************************************************************
  16. Pragma directive
  17. ***********************************************************************************************************************/
  18. /* Start user code for pragma. Do not edit comment generated here */
  19. /* End user code. Do not edit comment generated here */
  20.  
  21. /***********************************************************************************************************************
  22. Global variables and functions
  23. ***********************************************************************************************************************/
  24. /* Start user code for global. Do not edit comment generated here */
  25. volatile uint8_t PPMTime_flg=0;
  26. volatile uint8_t timer_200msec_flg=0;
  27.  
  28. /* End user code. Do not edit comment generated here */
  29.  
  30. static void R_MAIN_UserInit(void);
  31. /***********************************************************************************************************************
  32. * Function Name: main
  33. * Description : This function implements main function.
  34. * Arguments : None
  35. * Return Value : None
  36. ***********************************************************************************************************************/
  37. void main(void)
  38. {
  39.     R_MAIN_UserInit();
  40.     /* Start user code. Do not edit comment generated here */
  41.     R_IT_Start();//200msインターバルタイマをスタート
  42.     R_INTC1_Start();//INT割り込み有効
  43.     R_INTC3_Start();//INT割り込み有効
  44.  
  45.     while (1U){
  46.     LED1=~LED1;//デバッグ
  47.     R_IT_Stop();
  48.     if (TURN_ON_BTN==0){//全灯ボタンを押したとき
  49.         sendLeader();
  50.         sendDataByte(0x51);
  51.         sendDataByte(0x76);
  52.         sendDataByte(0x10);
  53.         sendDataByte(0x00);
  54.         sendDataByte(0x01);
  55.         sendDataByte(0x00);
  56.         sendDataByte(0x6C);
  57.         sendStopbit();
  58.         timer_200msec_flg=0;
  59.  
  60.     }else if (TURN_OFF_BTN==0){//消灯ボタンを押したとき
  61.         sendLeader();
  62.         sendDataByte(0x51);
  63.         sendDataByte(0x76);
  64.         sendDataByte(0x10);
  65.         sendDataByte(0x00);
  66.         sendDataByte(0x02);
  67.         sendDataByte(0x00);
  68.         sendDataByte(0x6F);
  69.         sendStopbit();
  70.         timer_200msec_flg=0;
  71.  
  72.         
  73.     }else{//ボタンが押されていないとき
  74.         timer_200msec_flg=0;
  75.         LED1=0;
  76.         STOP();//STOPモードに入る
  77.         
  78.     }
  79.     R_IT_Start();
  80.     while(timer_200msec_flg==0);
  81.     }
  82.     /* End user code. Do not edit comment generated here */
  83. }
  84. /***********************************************************************************************************************
  85. * Function Name: R_MAIN_UserInit
  86. * Description : This function adds user code before implementing main function.
  87. * Arguments : None
  88. * Return Value : None
  89. ***********************************************************************************************************************/
  90. static void R_MAIN_UserInit(void)
  91. {
  92.     /* Start user code. Do not edit comment generated here */
  93.     EI();
  94.     /* End user code. Do not edit comment generated here */
  95. }
  96.  
  97. /* Start user code for adding. Do not edit comment generated here */
  98. /* End user code. Do not edit comment generated here */

200ms毎に消灯ボタン・全灯ボタンの状態を取得し、何も押されていない場合はスタンバイ状態(STOPモード)に入って電池の消耗を抑えるようにしている。

 

今回はソースコードを一部しか載せていないが、全ソースコードGitHubで公開したいね。GitHubは使ったことが無いので、まずは使い方を覚えるところからだけど・・。

動作確認

ブレッドボードで回路を組んで問題なく、全灯/消灯できることを確認した。ぶっちゃけこんな画像を載せても何のこっちゃって感じだが・・。清書した回路図を次回は作りたいね。

 

/*パンくずリスト階層化*/