2013年12月23日月曜日

Raspberry Pi (8) IO制御 5

IO制御 5 (モールス信号でIPアドレス表示)


最初に

前回の続きで、ACT_LEDでIPアドレスを表示したいと思います。
1個のLEDで表示するので、モールス信号での表現となります。
うまく行けば、Rpi本体だけで自分のIPアドレスを表示できるはずなのですが...

さて、ACT_LED(GPIO16)をWiringPiライブラリで制御しようと思いましたが、アドレスが設定されていないようです。
今回は、より低レベルの操作が可能なbcm2835.hライブラリを使う事とします。WiringPiよりハード寄りのライブラリなので、面倒ですが細かい制御が出来そうです。


bcm2835.hのインストール

以下のスクリプトを実行して、bcm2835.hをインストールします。

sudo wget http://www.airspayce.com/mikem/bcm2835/bcm2835-1.34.tar.gz
tar zxvf bcm2835-1.34.tar.gz
sudo tar zxvf bcm2835-1.34.tar.gz
cd bcm2835-1.34/
sudo ./configure
sudo make
sudo make install

プログラム

  1. bcm2835の初期化
  2. /sys/class/leds/led0/trigger の書き換え
    1. CからUNIXのコマンドを発行する時は、system()を使います。   
    2. このプログラムではこの値を元に戻していないので、実験が終わったら手動で戻しておいてください。
  3. IPアドレスの取得
  4. 一文字づつモールス表示   
    1. ACT LEDはLowで点灯なので注意
    2. トンは100ms、ツーは800ms、休みを400msでやってみました。

// Raspberry Pi でIPアドレス表示 // eth0のアドレスをモールス符号でACTランプに表示させる // 2013.12.23 ImageWriter // Compile: gcc ipaddr2.c -o ipaddr2 -l bcm2835 // USAGE: sudo ./ipaddr2 // // ACT_LED = GPIO-16 , Active-Low // ACT_LED is SD-Card acsess lamp in default. // For disable ACT_LED,
"echo none >/sys/class/leds/led0/trigger" // Then,eneble ACT_LED,
"echo mmc0 > /sys/class/leds/led0/trigger" #include < stdio.h > #include < string.h > #include < unistd.h > #include < sys/types.h > #include < sys/socket.h > #include < arpa/inet.h > #include < netdb.h > #include < errno.h > #include < linux/if.h > #include < sys/ioctl.h > #include < bcm2835.h >
// bcm2835.h from
http://www.airspayce.com/mikem/bcm2835/index.html #define out_LED 16 // ACT_LED active-low // モールス符号 char M0[]= "-----"; char M1[]= ".----"; char M2[]= "..---"; char M3[]= "...--"; char M4[]= "....-"; char M5[]= "....."; char M6[]= "-...."; char M7[]= "--..."; char M8[]= "---.."; char M9[]= "----."; char Mdot[]= ".-.-.-"; const char* GetMyIpAddr(const char* device_name); /** * 自マシンのIPアドレスを取得します。 * @param デバイス名(e.g. "eth0") * @return 「数値とドット」記法のアドレス */ const char* GetMyIpAddr(const char* device_name) { //指定したデバイス名のIPアドレスを取得します。 int s = socket(AF_INET, SOCK_STREAM, 0); struct ifreq ifr; ifr.ifr_addr.sa_family = AF_INET; strcpy(ifr.ifr_name, device_name); ioctl(s, SIOCGIFADDR, &ifr); close(s); struct sockaddr_in addr; memcpy( &addr, &ifr.ifr_ifru.
ifru_addr, sizeof(struct sockaddr_in) ); return inet_ntoa(addr.sin_addr); } // ACT_LED disable void ACT_LED_mode(int mo){ if(mo==0){ // Contorole by my program system("echo none >/sys/class/leds/led0/trigger"); } else { // Contorole by system system("echo mmc0 > /sys/class/leds/led0/trigger"); } } // 出力初期設定 void out_init(void){ bcm2835_gpio_fsel(out_LED,
BCM2835_GPIO_FSEL_OUTP); bcm2835_gpio_write(out_LED, HIGH);
// ACT_LED is active low } // モールス発生 void morse_encode(char *pc){ int i,a; //loop,morse-length a=strlen(pc); //morse-length for(i=0;i < =a-1;i++){ if(pc[i]=='.'){ printf("%c\n",'.'); bcm2835_gpio_write(out_LED, LOW);
// ton! bcm2835_delay(100); } else { printf("%c\n",'-'); bcm2835_gpio_write(out_LED, LOW);
// tuuu! bcm2835_delay(800); } bcm2835_gpio_write(out_LED, HIGH); bcm2835_delay(400); // char break } bcm2835_delay(1000);
// word break printf("\n"); } // モールス変換 void morse_decode(char c){ int i,a; //ループカウンタ char *pc; //モールス符号のポインタ switch(c){ case '0': pc = M0; //符号のポインタを渡す。 morse_encode(pc); //モールス発生。 break; case '1': pc = M1; morse_encode(pc); break; case '2': pc = M2; morse_encode(pc); break; case '3': pc = M3; morse_encode(pc); break; case '4': pc = M4; morse_encode(pc); break; case '5': pc = M5; morse_encode(pc); break; case '6': pc = M6; morse_encode(pc); break; case '7': pc = M7; morse_encode(pc); break; case '8': pc = M8; morse_encode(pc); break; case '9': pc = M9; morse_encode(pc); break; case '.': pc = Mdot; morse_encode(pc); break; default: break; } } int main(){ bcm2835_init() ; // bcm2835_init out_init(); // GPIO-16 output mode ACT_LED_mode(0); const char* r = GetMyIpAddr("eth0");
// Get IP-ADDRES const int a = strlen(r); // ADDRESS length for(;;){ int i; // Loop for(i = 0; i < = a; i++) { // Loop in ADRS length printf ("%c:",r[i]); morse_decode(r[i]); // morse-sending } printf("\n"); bcm2835_gpio_write(out_LED, HIGH); // 消灯 bcm2835_delay(4000); // Wait next line. } return 0; }

無事、モールス信号でIPアドレスが表示されました。
でも、私は電話級アマ免許しかもっておらずCW通信もした事がないので、このスピードでも読み取れません。(^^;)
作ってはみたけれど、私にとってはちょっと実用的じゃありませんでした。
点滅の回数で数字を表した方が良かったかもW。