Raspberry PiとGR SAKURAでキャラクターLCD (2)
Raspberry Pi側からGR SAKURAに対して、自分のIPアドレスを文字列としてUARTに流すのですが、出荷時の設定だとUARTはシリアルターミナルのログイン用になっており、通信に使用できないとのことで、起動設定を変更しました。
変更内容は下記サイトの内容そのままです。
Raspberry Pi でシリアル通信 Chick Lab
書いてあるとおりに、以下の2ファイルを変更しました。
/boot/cmdline.txt
/etc/inittab
また、シリアル通信を一から書くと意外と面倒ですので、WiringPiというライブラリーを入れます。
公式サイト:Raspberry Pi | Wiring | Gordons Projects
インストールは上記のサイトの以下のページの通りにすすめます。
Raspberry Pi | Wiring | Download & Install | Gordons Projects
(うちは最初のgit-coreのインストールでエラーが出たので、updateとupgradeを行いましたが、けっこう時間がかかりました…)
WiringPiをインストールすると、serialXXXXという名前のついた関数を使って簡単にシリアル通信ができるようになります。
以下がRaspberry Pi側のプログラムです。
/* ipuart.c */ #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <netinet/in.h> #include <net/if.h> #include <arpa/inet.h> #include <wiringSerial.h> /* WiringPi */ int main( int ac, char *av[] ) { int fd, sfd; struct ifreq ifr; char ipstr[256]; /* get my IP addr */ fd = socket(AF_INET, SOCK_DGRAM, 0); ifr.ifr_addr.sa_family = AF_INET; strncpy(ifr.ifr_name, "eth0", IFNAMSIZ-1); ioctl(fd, SIOCGIFADDR, &ifr ); close(fd); memset( ipstr, '\0', sizeof(ipstr)); strcpy(ipstr, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr)); // printf("%s\n", ipstr); /* UART */ sfd = serialOpen( "/dev/ttyAMA0", 38400 ); if( sfd == -1 ){ printf( "serial cannot open.\n" ); return 1; } serialPuts( sfd, ipstr ); delay(1000); serialClose( sfd ); return 0; }
(前半でソケットを使ってマジメにIPアドレスを取得していますが、実はこの処理は不要なことが後で判明…)
ビルドすると実行ファイルができるので適当なディレクトリに置きます。うちは、/usr/local/binに置いてみました。
あとは、起動時に実行するようにしたいので、/etc/rc.localの末尾に実行ファイル名を書いておきます。以下は記述例です。
/usr/local/bin/ipuart
(上でIP取得が不要と書いた理由ですが、rc.localの中で自分のIPアドレスが$_IPという変数に記録されていますので、引数に指定した文字列をそのままUARTに流すようなプログラムを作れば$_IPを引数にするだけでよくなります。結果、自作プログラムの中でIPを取得する必要は無くなります…。)
ただ、GR SAKURAを持ち出したり、20x4という大きめのLCDを使っていたりと、我ながらIP表示するだけのことにずいぶんおおげさになってしまったなあと思いまして、結局、今は3.3VでI2Cインタフェースの小さい16x2 LCDを直接Raspberry Piにつないでおります。まあ、勉強にはなりましたので後悔はしてません。多分…。