*[[RapberryPi-赤外線リモコン]] [#h5fa06ad]
>
>以前製作したWindowsXP用の赤外線リモコンのRaspberryPiへの引越しです。~
最近、プリンターポートありのPCが少なくなっているので、どうするか検討していましたが、RaspberryPiを最近さわりはじめたので、こちらに引越しさせることにしました。~
時間精度や、制御方法などの基本を調査し、Windws版のTCPサーバ機能を実現する予定です。
<
**基本方針 [#t5f36206]
-キャプチャは単純に、IOポートのポーリングを検討します。重要な点は、時間精度です。
-送信はPWM機能を検討します。これにより38KHzの発信器を不要とします。
-ハードウェアはWindows版より大幅に削減します。基本IR-ReceiverrとIR-LED、コンデンサ、抵抗で構成します。

**調査 [#dddd20c6]
***時間精度の確認 [#bf6cc5af]
>
>単純にLEDチカチカのTPを125usで制御してみます。125us(8K)はWindows版リモコンのサンプリング周期です。
 #include <bcm2835.h>
 #include <stdio.h>
 // Blinks on RPi Plug P1 pin 11 (which is GPIO pin 17)
 #define PIN RPI_GPIO_P1_11
 int main(int argc, char **argv)
 {
     if (!bcm2835_init())
       return 1;
     // Set the pin to be an output
     bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_OUTP);
     // Blink
     while (1)
     {
         // Turn it on
         bcm2835_gpio_write(PIN, HIGH);
         // wait a bit
         bcm2835_delayMicroseconds( 125LL );
         // turn it off
         bcm2835_gpio_write(PIN, LOW);
         // wait a bit
         bcm2835_delayMicroseconds( 125LL );
     }
     bcm2835_close();
     return 0;
 }
 
<
>
>実行した結果がこれです。
#ref(125usx2-period.jpg,zoom)
<
>
>250usに対して誤差は500ns以下ですので、シリアル通信として、レシーブマージンは十分に確保できます。
<
***RaspberryPiのPWM機能の確認 [#l20e4fb9]
>

-まずはじめに

>
>RaspberryPiのPWM機能については、使用したことがないため、改めて確認しました。~
まずは、bcm2835ライブラリですがPWM関係は
 void 	bcm2835_pwm_set_clock (uint32_t divisor)
 void 	bcm2835_pwm_set_mode (uint8_t channel, uint8_t markspace, uint8_t enabled)
 void 	bcm2835_pwm_set_range (uint8_t channel, uint32_t range)
 void 	bcm2835_pwm_set_data (uint8_t channel, uint32_t data)
<
>
>があります。つまり
+ライブラリ初期化(bcm2835_init())
+ピンの機能設定(bcm2835_gpio_fsel())
+PWMクロック設定( bcm2835_pwm_set_clock())
+PWMモード設定(bcm2835_pwm_set_mode())
+PWMレンジ設定(bcm2835_pwm_set_range())
+PWMスタート/ストップ設定(bcm2835_pwm_set_data())
>


>でよさそうです。
<
-クロック

>
>クロックソースは 19.2MHzが使用されるようで、最終的にここで指定した分周比が出力のクロックとなります。~
ただし分周の指定は以下の中からしか選べないようです。
 typedef enum
 {
 BCM2835_PWM_CLOCK_DIVIDER_2048  = 2048,    
 BCM2835_PWM_CLOCK_DIVIDER_1024  = 1024,    
 BCM2835_PWM_CLOCK_DIVIDER_512   = 512,     
 BCM2835_PWM_CLOCK_DIVIDER_256   = 256,     
 BCM2835_PWM_CLOCK_DIVIDER_128   = 128,     
 BCM2835_PWM_CLOCK_DIVIDER_64    = 64,      
 BCM2835_PWM_CLOCK_DIVIDER_32    = 32,      
 BCM2835_PWM_CLOCK_DIVIDER_16    = 16,      
 BCM2835_PWM_CLOCK_DIVIDER_8     = 8,       
 BCM2835_PWM_CLOCK_DIVIDER_4     = 4,       
 BCM2835_PWM_CLOCK_DIVIDER_2     = 2,       
 BCM2835_PWM_CLOCK_DIVIDER_1     = 1        
 } bcm2835PWMClockDivider;
<
-モード

>
>モードは2つあり、
+バランスモード:RANGEパルス数に対して全体としてDATAパルス数になるようにクロックパルスの組み合わせを発生させる。
+マークスペースモード:DATAクロック数の幅の間HIGHを出力して、RANGE-DATAクロック数の間LOWを出力する。

>今回の用途では、Duty=50%の波形としたいので。マークスペースモードを選択します。


-レンジの設定

>
>では、どのようにこの2つを設定するかですが、38KHzにするためには
>>
>>19200 / 76 = 252.63157894736842105263157894737
<<
>これでON/OFFを繰り返せば言い訳ですが、実際には、256がもっとも近い値になります
>>
>>19200 / 256 = 75 KHz (37.5KHz)
<<
>が設定可能となります。受光器のフィルタは上記の誤差では影響はないものと考えます。~
次にRANGEとDATAですが、ON/OFFが一回ですので~
    Range = 2~
    Data = 1~
でよいはずです
<
-早速確認

>
 #include <bcm2835.h>
 #include <stdio.h>
 #include <termios.h>
 #include <unistd.h>
 #include <fcntl.h>
 // PWM output on RPi Plug P1 pin 12 (which is GPIO pin 18)
 // in alt fun 5.
 // Note that this is the _only_ PWM pin available on the RPi IO headers
 #define PIN RPI_GPIO_P1_12
 // and it is controlled by PWM channel 0
 #define PWM_CHANNEL 0
 // This controls the max range of the PWM signal
 #define RANGE 2
 int kbhit(void)
 {
     struct termios oldt, newt;
     int ch;
     int oldf;
     tcgetattr(STDIN_FILENO, &oldt);
     newt = oldt;
     newt.c_lflag &= ~(ICANON | ECHO);
     tcsetattr(STDIN_FILENO, TCSANOW, &newt);
     oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
     fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
     ch = getchar();
     tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
     fcntl(STDIN_FILENO, F_SETFL, oldf);
     if (ch != EOF) {
         ungetc(ch, stdin);
         return 1;
     }
     return 0;
 }
 int main(int argc, char **argv)
 {
     if (!bcm2835_init())
         return 1;
     // Set the output pin to Alt Fun 5, to allow PWM channel 0 to be output there
     bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_ALT5);
     // Clock divider is set to 256.
     bcm2835_pwm_set_clock(BCM2835_PWM_CLOCK_DIVIDER_256);
     // set Mark-Space mode and enable
     bcm2835_pwm_set_mode(PWM_CHANNEL, 1, 1);
     bcm2835_pwm_set_range(PWM_CHANNEL, RANGE);
     bcm2835_pwm_set_data(PWM_CHANNEL, 1);
     while(!kbhit())
     {
         bcm2835_delay(50);
         bcm2835_pwm_set_mode(PWM_CHANNEL, 1, 1);
         bcm2835_delay(50);
         bcm2835_pwm_set_mode(PWM_CHANNEL, 1, 0);
     }
     bcm2835_close();
     return 0;
 }
 
<
-結果
#ref(37-5khz.jpg)

>
>問題ありません。
<

つづく。

お疲れ様でした。

トップ   編集 編集(GUI) 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS