Raspberry Pi 日記 (part2)

長嶋 洋一


2013年6月26日(水)

さて水曜日である。 講義の無いこの日は、放課後のアカペラまでがっつり進める日である。 昨日の帰り際に、「昨日走ったソフトが何故か今日走らない」という情けないメイルをふーみんに出していたが、今朝読んだ返信は以下であり、まさにもっともであった(^_^;)。 ちゃんとふーみんはピン番号の新旧についても記述していたが、僕が読み落としていた。 今日はまず、ヘンな省略をしないところから再開し、紹介された情報をチェックしていこう。
http://netlog.jpn.org/r271-635/2013/01/raspberry_pi_gpio_test.html
あたりをみて,
http://www.open.com.au/mikem/bcm2835/
のライブラリを使った方が楽ではないかと・・・.

# *_close()を省略しても大丈夫,という記述はちょっと信じられません.

ちなみにRevisionによるピンアサインの差異は私の本でも
見分け方とともに説明してあります.
CQのRaspberry Pi本の第5章の「デバイスドライバを使う」のところに書かれていた「省略可能」という記述を並べると以下のようになる。 OSが別途に管理してくれているので、まぁ、動くよ、という事なのだが、ここは基本に戻って、しっかりと形式を整えることにしよう。 ・・・ということで、Raspberry Piを立ち上げ、VNCだとコピペが出来ないのでsshでRaspberry Piに入り、まずは昨日の現象を確認した。 リセット直後のRaspberry Piで再現確認しておく事は意味があるだろう。 まず、再掲になるが、拡張7ビットに対してコマンドラインから表示を指令したシェルスクリプトの test1.c をrcpすると、以下のようにこれは自動的に実行可能と表示され、sudoで実行してLEDが順に点灯した。
Last login: Wed Jun 26 06:43:50 on console
nagasm-Mac-mini:~ nagasm$ ssh pi@172.16.65.61
pi@172.16.65.61's password: 
Linux raspberrypi 3.6.11+ #456 PREEMPT Mon May 20 17:42:15 BST 2013 armv6l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sat Jun 22 13:45:45 2013

pi@raspberrypi ~ $ ls
Desktop         blink1-tool    null        python_games    pyusb-1.0.0a3  twilight.png
RPi.GPIO-0.1.0  blink_autorun  ocr_pi.png  pyusb-1.0.0-a1  testrun

pi@raspberrypi ~ $ rcp nagasm@172.16.65.31:Desktop/test1.c .
Password:
test1.c                                                        100% 1700     1.7KB/s   00:00    

pi@raspberrypi ~ $ ls -l
合計 1068
drwxr-xr-x 2 pi   pi    4096  6月 18 23:18 Desktop
drwxr-xr-x 7 pi   pi    4096  6月 18 04:31 RPi.GPIO-0.1.0
-rwsr-xr-x 1 root pi 1020394 11月 28  2012 blink1-tool
-rwxr-xr-x 1 pi   pi    5170  6月 22 06:19 blink_autorun
-rw-r--r-- 1 pi   pi       0  6月 22 14:10 null
-rw-r--r-- 1 pi   pi    5781  2月  3 05:07 ocr_pi.png
drwxrwxr-x 2 pi   pi    4096  7月 20  2012 python_games
drwxr-xr-x 6 pi   pi    4096 12月 29  2010 pyusb-1.0.0-a1
drwxr-xr-x 5 pi   pi    4096  6月 18 23:09 pyusb-1.0.0a3
-rwxr-xr-x 1 pi   pi    1700  6月 22 14:11 test1.c
-rwxr-xr-x 1 pi   pi    6289  6月 22 12:02 testrun
-rw-r--r-- 1 pi   pi   20123  5月 31 11:45 twilight.png

pi@raspberrypi ~ $ sudo ./test1.c
pi@raspberrypi ~ $ 
次に、汎用8ビットと拡張7ビットに対して、C言語のシステムコールとしてシェルコマンドを並べた test2.c をrcpすると、以下のようにこれは実行できないCソースコードと表示され、ccでコンパイルして、sudoで「a.out」を実行すると、全てのLEDが順に点灯した。 ここまでは昨日も一昨日も問題なかったところである。
pi@raspberrypi ~ $ rcp nagasm@172.16.65.31:Desktop/test2.c .
Password:
test2.c                                                        100% 5427     5.3KB/s   00:00    

pi@raspberrypi ~ $ ls -l
合計 1076
drwxr-xr-x 2 pi   pi    4096  6月 18 23:18 Desktop
drwxr-xr-x 7 pi   pi    4096  6月 18 04:31 RPi.GPIO-0.1.0
-rwsr-xr-x 1 root pi 1020394 11月 28  2012 blink1-tool
-rwxr-xr-x 1 pi   pi    5170  6月 22 06:19 blink_autorun
-rw-r--r-- 1 pi   pi       0  6月 22 14:14 null
-rw-r--r-- 1 pi   pi    5781  2月  3 05:07 ocr_pi.png
drwxrwxr-x 2 pi   pi    4096  7月 20  2012 python_games
drwxr-xr-x 6 pi   pi    4096 12月 29  2010 pyusb-1.0.0-a1
drwxr-xr-x 5 pi   pi    4096  6月 18 23:09 pyusb-1.0.0a3
-rwxr-xr-x 1 pi   pi    1700  6月 22 14:11 test1.c
-rw-r--r-- 1 pi   pi    5427  6月 22 14:15 test2.c
-rwxr-xr-x 1 pi   pi    6289  6月 22 12:02 testrun
-rw-r--r-- 1 pi   pi   20123  5月 31 11:45 twilight.png

pi@raspberrypi ~ $ cc test2.c
pi@raspberrypi ~ $ sudo ./a.out
pi@raspberrypi ~ $ 
次に、ふーみんの指摘を真摯に受け止めて(^_^;)、exportに帯するunexportも、openに対するcloseも、ちゃんと全て完備させ(当たり前の)、さらにエラー処理もサンプルの通りに戻したCプログラムとして修正した test3.c をrcpしてccでコンパイルしてsudoで「a.out」を実行すると、以下のように「GPIO 7 direction open error」と出た。 なるほど、printfを入れたエラー処理は入れておくものだった(^_^;)。
pi@raspberrypi ~ $ rcp nagasm@172.16.65.31:Desktop/test3.c .
Password:
test3.c                                                        100%  824     0.8KB/s   00:00    

pi@raspberrypi ~ $ ls -l
合計 1092
drwxr-xr-x 2 pi   pi    4096  6月 18 23:18 Desktop
drwxr-xr-x 7 pi   pi    4096  6月 18 04:31 RPi.GPIO-0.1.0
-rwxr-xr-x 1 pi   pi    9355  6月 22 14:15 a.out
-rwsr-xr-x 1 root pi 1020394 11月 28  2012 blink1-tool
-rwxr-xr-x 1 pi   pi    5170  6月 22 06:19 blink_autorun
-rw-r--r-- 1 pi   pi       0  6月 22 14:25 null
-rw-r--r-- 1 pi   pi    5781  2月  3 05:07 ocr_pi.png
drwxrwxr-x 2 pi   pi    4096  7月 20  2012 python_games
drwxr-xr-x 6 pi   pi    4096 12月 29  2010 pyusb-1.0.0-a1
drwxr-xr-x 5 pi   pi    4096  6月 18 23:09 pyusb-1.0.0a3
-rwxr-xr-x 1 pi   pi    1700  6月 22 14:11 test1.c
-rw-r--r-- 1 pi   pi    5427  6月 22 14:15 test2.c
-rw-r--r-- 1 pi   pi     824  6月 22 14:26 test3.c
-rwxr-xr-x 1 pi   pi    6289  6月 22 12:02 testrun
-rw-r--r-- 1 pi   pi   20123  5月 31 11:45 twilight.png

pi@raspberrypi ~ $ cc test3.c
pi@raspberrypi ~ $ sudo ./a.out
GPIO 7 direction open error

pi@raspberrypi ~ $ 
エラーが出ればそこを攻める、というのがデバッグの常道である。 そして今ではインターネットという強力な助っ人がいる。 エラーの「GPIO direction open error」というタームでyahoo.comから検索すると、 こんなページ が出て来て、そこには以下のようなプログラム(ただしunexportしていない(^_^;))があった。
public void sync () {
    int fd = -1;
    fd = open("/sys/class/gpio/export", O_WRONLY);
    if (fd < 0) {
        GLib.stdout.printf("Error sync export\n");
        return;
    }
    write(fd, "31", 3);
    close(fd);
    fd = open("/sys/class/gpio/gpio31/direction", O_WRONLY);
    if (fd < 0) {
        GLib.stdout.printf("Error sync direction\n");
        return;
    }
    write(fd, "out", 4);
    close(fd);
    fd = open("/sys/class/gpio/gpio31/value", O_WRONLY);
    if (fd < 0) {
        GLib.stdout.printf("Error sync value\n");
        return;
    }
    write(fd, "0", 2);
    write(fd, "1", 2);
    Thread.usleep (1000); /* 1ms */
    write(fd, "0", 2);
    close(fd);
}
違いとしては、ポートのopenに、CQ本では「O_WRONLY」と「O_RDWR」とが混在しているが、こちらでは全て「O_WRONLY」というのがまず、目についた。 そこで試しに、 test3.c の中の「O_RDWR」を全て「O_RDWR」に置換しただけの test4.c をrcpしてccでコンパイルしてsudoで「a.out」を実行すると、ちゃんと拡張ポートの1ビット(GPIO7)が点滅した。 これはつまり、解決ということかな(^_^)。 そこで、一昨日の最後に走っていたが昨日は駄目だった、15ビットのLEDを7ビットと8ビットと交互にまとめて点滅させる、というC言語プログラムを、ここまでの修正を反映させて以下のような「test5.c」として、rcpしてccでコンパイルしてsudoで「a.out」を実行すると、ちゃんと走った。
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

int main()
{
	int fd[15];
	int assign[15] = {17,18,27,22,23,24,25,4,2,3,10,9,11,8,7};
	char s[64];
	int i, j, ff;

	for (i=0; i<15; i++) {
		ff = open("/sys/class/gpio/export", O_WRONLY);
		if (ff < 0) {
			printf("GPIO export open error\n");
			exit(1);
		}
		write(ff, assign[i], 2);
		close(ff);
	}

	for (i=0; i<15; i++) {
		sprintf(s,"/sys/class/gpio/gpio%d/direction", assign[i]);
		ff = open(s, O_WRONLY);
		if (ff < 0) {
			printf("GPIO %d direction open error\n",assign[i]);
			exit(1);
		}
		write(ff, "out", 2);
		close(ff);
	}

	for (i=0; i<15; i++) {
		sprintf(s,"/sys/class/gpio/gpio%d/value", assign[i]);
		fd[i] = open(s, O_WRONLY);
		if (ff < 0) {
			printf("GPIO %d value open error\n",assign[i]);
			exit(1);
		}
	}

	for (j=0; j<7; j++) {
		for (i=0; i<8; i++) {
			write(fd[i],"0",2);
		}
		for (i=8; i<15; i++) {
			write(fd[i],"1",2);
		}
		sleep(1);
		for (i=0; i<8; i++) {
 			write(fd[i],"1",2);
		}
		for (i=8; i<15; i++) {
			write(fd[i],"0",2);
		}
		sleep(1);
	}

	for (i=0; i<15; i++) {
		close(fd[i]);
	}

	for (i=0; i<15; i++) {
		ff = open("/sys/class/gpio/unexport", O_WRONLY);
		if (ff < 0) {
			printf("GPIO unexport open error\n");
			exit(1);
		}
		write(ff, assign[i], 2);
		close(ff);
	}
}
・・・ところが、ここからまた、昨日の悪夢の再現のような現象が起きた(^_^;)。 現象としては、 test1.c のスクリプト実行と、 test2.c のコンパイル結果の実行は、必ず問題なくできるが、 C言語で叩く、というタイプについては、またまた「GPIO 7 direction open error」とか「GPIO 17 direction open error」、つまりdirectionの設定のいちばん最初のところでエラーとなる現象が起きるが、まれに test1.c のスクリプト実行、あるいは test2.c のコンパイル結果の実行によって、状態が正常に戻るのか、問題なく実行できることも「まれに」ある、という状況だった。 「まれに」というのが、100%よりもずっと厄介なのである。(^_^;)

ここでさすがにふーみんメイルのように、 このページ と、実質的にはその元ネタである このページ に行くしかない、と観念して(^_^;)、調べてみることにした。

 # download the latest version of the library, say bcm2835-1.xx.tar.gz, then:
tar zxvf bcm2835-1.xx.tar.gz
cd bcm2835-1.xx
./configure
make
sudo make check
sudo make install
上のように簡単に書かれていた このページ の手順に従い、最新の「bcm2835-1.25.tar.gz」をダウンロードして、Raspberry Piにrcpして、tarから実行すると、実際には以下のように表示された。
pi@raspberrypi ~ $ rcp nagasm@172.16.65.31:Desktop/bcm2835-1.25.tar.gz .
Password:
bcm2835-1.25.tar.gz                                            100%  225KB 225.5KB/s   00:00    

pi@raspberrypi ~ $ tar zxvf bcm2835-1.25.tar.gz
bcm2835-1.25/
bcm2835-1.25/config.sub
bcm2835-1.25/ChangeLog
bcm2835-1.25/doc/
bcm2835-1.25/doc/Makefile.am
bcm2835-1.25/doc/Makefile.in
bcm2835-1.25/doc/Doxyfile.in
bcm2835-1.25/aclocal.m4
bcm2835-1.25/README
bcm2835-1.25/src/
bcm2835-1.25/src/bcm2835.h
bcm2835-1.25/src/Makefile.am
bcm2835-1.25/src/bcm2835.c
bcm2835-1.25/src/test.c
bcm2835-1.25/src/Makefile.in
bcm2835-1.25/INSTALL
bcm2835-1.25/depcomp
bcm2835-1.25/config.h.in
bcm2835-1.25/config.guess
bcm2835-1.25/configure.in
bcm2835-1.25/NEWS
bcm2835-1.25/COPYING
bcm2835-1.25/Makefile.am
bcm2835-1.25/ltmain.sh
bcm2835-1.25/configure
bcm2835-1.25/missing
bcm2835-1.25/install-sh
bcm2835-1.25/Makefile.in
bcm2835-1.25/AUTHORS
bcm2835-1.25/examples/
bcm2835-1.25/examples/blink/
bcm2835-1.25/examples/blink/blink.c
bcm2835-1.25/examples/input/
bcm2835-1.25/examples/input/input.c
bcm2835-1.25/examples/spin/
bcm2835-1.25/examples/spin/spin.c
bcm2835-1.25/examples/event/
bcm2835-1.25/examples/event/event.c
bcm2835-1.25/examples/spi/
bcm2835-1.25/examples/spi/spi.c

pi@raspberrypi ~ $ cd bcm2835-1.25

pi@raspberrypi ~/bcm2835-1.25 $ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... no
checking for mawk... mawk
checking whether make sets $(MAKE)... yes
checking for style of include used by make... GNU
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking dependency style of gcc... gcc3
checking for clock_gettime in -lrt... yes
checking for doxygen... no
configure: WARNING: Doxygen not found - continuing without Doxygen support
checking for ranlib... ranlib
checking for gcc... (cached) gcc
checking whether we are using the GNU C compiler... (cached) yes
checking whether gcc accepts -g... (cached) yes
checking for gcc option to accept ISO C89... (cached) none needed
checking dependency style of gcc... (cached) gcc3
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating src/Makefile
config.status: creating doc/Makefile
config.status: creating config.h
config.status: executing depfiles commands
pi@raspberrypi ~/bcm2835-1.25 $ make
make  all-recursive
make[1]: ディレクトリ `/home/pi/bcm2835-1.25' に入ります
Making all in src
make[2]: ディレクトリ `/home/pi/bcm2835-1.25/src' に入ります
gcc -DHAVE_CONFIG_H -I. -I..     -g -O2 -MT bcm2835.o -MD -MP -MF .deps/bcm2835.Tpo -c -o bcm2835.o bcm2835.c
mv -f .deps/bcm2835.Tpo .deps/bcm2835.Po
rm -f libbcm2835.a
ar cru libbcm2835.a bcm2835.o 
ranlib libbcm2835.a
make[2]: ディレクトリ `/home/pi/bcm2835-1.25/src' から出ます
Making all in doc
make[2]: ディレクトリ `/home/pi/bcm2835-1.25/doc' に入ります
make[2]: `all' に対して行うべき事はありません.
make[2]: ディレクトリ `/home/pi/bcm2835-1.25/doc' から出ます
make[2]: ディレクトリ `/home/pi/bcm2835-1.25' に入ります
make[2]: ディレクトリ `/home/pi/bcm2835-1.25' から出ます
make[1]: ディレクトリ `/home/pi/bcm2835-1.25' から出ます

pi@raspberrypi ~/bcm2835-1.25 $ sudo make check
Making check in src
make[1]: ディレクトリ `/home/pi/bcm2835-1.25/src' に入ります
make  test
make[2]: ディレクトリ `/home/pi/bcm2835-1.25/src' に入ります
gcc -DHAVE_CONFIG_H -I. -I..     -g -O2 -MT test.o -MD -MP -MF .deps/test.Tpo -c -o test.o test.c
mv -f .deps/test.Tpo .deps/test.Po
gcc  -g -O2   -o test test.o ./libbcm2835.a -lrt 
make[2]: ディレクトリ `/home/pi/bcm2835-1.25/src' から出ます
make  check-TESTS
make[2]: ディレクトリ `/home/pi/bcm2835-1.25/src' に入ります
PASS: test
=============
1 test passed
=============
make[2]: ディレクトリ `/home/pi/bcm2835-1.25/src' から出ます
make[1]: ディレクトリ `/home/pi/bcm2835-1.25/src' から出ます
Making check in doc
make[1]: ディレクトリ `/home/pi/bcm2835-1.25/doc' に入ります
make[1]: `check' に対して行うべき事はありません.
make[1]: ディレクトリ `/home/pi/bcm2835-1.25/doc' から出ます
make[1]: ディレクトリ `/home/pi/bcm2835-1.25' に入ります
make[1]: ディレクトリ `/home/pi/bcm2835-1.25' から出ます

pi@raspberrypi ~/bcm2835-1.25 $ sudo make install
Making install in src
make[1]: ディレクトリ `/home/pi/bcm2835-1.25/src' に入ります
make[2]: ディレクトリ `/home/pi/bcm2835-1.25/src' に入ります
 /bin/mkdir -p '/usr/local/lib'
 /usr/bin/install -c -m 644  libbcm2835.a '/usr/local/lib'
 ( cd '/usr/local/lib' && ranlib libbcm2835.a )
 /bin/mkdir -p '/usr/local/include'
 /usr/bin/install -c -m 644 bcm2835.h '/usr/local/include'
make[2]: ディレクトリ `/home/pi/bcm2835-1.25/src' から出ます
make[1]: ディレクトリ `/home/pi/bcm2835-1.25/src' から出ます
Making install in doc
make[1]: ディレクトリ `/home/pi/bcm2835-1.25/doc' に入ります
make[2]: ディレクトリ `/home/pi/bcm2835-1.25/doc' に入ります
make[2]: `install-exec-am' に対して行うべき事はありません.
make[2]: `install-data-am' に対して行うべき事はありません.
make[2]: ディレクトリ `/home/pi/bcm2835-1.25/doc' から出ます
make[1]: ディレクトリ `/home/pi/bcm2835-1.25/doc' から出ます
make[1]: ディレクトリ `/home/pi/bcm2835-1.25' に入ります
make[2]: ディレクトリ `/home/pi/bcm2835-1.25' に入ります
make[2]: `install-exec-am' に対して行うべき事はありません.
make[2]: `install-data-am' に対して行うべき事はありません.
make[2]: ディレクトリ `/home/pi/bcm2835-1.25' から出ます
make[1]: ディレクトリ `/home/pi/bcm2835-1.25' から出ます

pi@raspberrypi ~/bcm2835-1.25 $ 
そして、実質的には このページ でなく、 このページ の方に全て必要な情報がある、と判明したので、とりあえず Examples のページの先頭にあった、以下の「blink.c」をRaspberry Piにrcpして、このプログラムの冒頭にあった「gcc -o blink blink.c -l bcm2835」というオプションでコンパイルして、「sudo ./blink」してみると、ちゃんと先頭のLEDが0.5秒間隔で点滅した(^_^)。
// Example program for bcm2835 library
// Blinks a pin on an off every 0.5 secs
//
// After installing bcm2835, you can build this with something like:
// gcc -o blink blink.c -l bcm2835
// sudo ./blink

#include <bcm2835.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);

	while (1)
	{
		// Turn it on
		bcm2835_gpio_write(PIN, HIGH);
		// wait a bit
		bcm2835_delay(500);
		// turn it off
		bcm2835_gpio_write(PIN, LOW);
		// wait a bit
		bcm2835_delay(500);
	}
	bcm2835_close();
	return 0;
}
これはかなり簡単である(^_^)。 このページ には、他にも「event.c」「input.c」「spi.c」「spin.c」など、シンプルな低水準プログラムが並んでいる。 ヘッダファイル も参考になる。 まさにここ数日、こういう低水準のライブラリが欲しかったのである(^_^)。 ここで昼休みになったところに、以下のふーみんメイルが届き、ちょうど欲しかった資料として BCM2835のマニュアルRaspberry Pi(バージョン1)の回路図Raspberry Pi(バージョン2)の回路図 とがゲットできた。 欲しかったデータを以心伝心で送ってくれるあたり、さすがの師匠である。(^_^)
ちょっと今すぐには長嶋さんのwebを詳細にチェックしている
時間がないのですが、Rev.1 とRev.2のschematic、bcm2835の
データシートを送ります。

elinux.orgによれば、ブート時にAlt0にいくのはUARTのTX/RXのみ、
のはずですが、SPIやI2Cのモジュールを有効にしていれば
単純なGPIOではなくそれぞれのfunctionに切り替わっている
可能性もあります。

長嶋さんの作業手順をちゃんと読んでいないので蓋然性の指摘に
留まりますが、ライブラリを呼び出しているようなプログラムが動いた
ときにbasic functionに切り替わっていてたまたま動いた、とかも
あるかもしれません。この辺は調べてみないとわかりませんが・・・
初期状態に何かありそうだ、というのは予想がついていたが、これに限るものでもなさそうである。 現象としては、出来たり駄目だったり、ときに戻ったり(^_^;)、という怪しいものだった。 まぁ、このCQ本のライブラリは、ちょっと放置プレイである。 PythonのBlink(1)に続いて、そういうのが増えてきた。 昼食をはさんで再開する前に、以下のように、新しいライブラリの解凍からインストールまで、作業していたRaspberry Pi61号機だけでなく、さらにターミナルを開いて62号機・63号機にも、コマンドのコピペで済むので作業しておいた。 まだ62号機・63号機のGPIOには何も繋がっていないが、これからそれぞれに別のブツを繋いでいく計画である。(^_^)

さて、こうなると、新しく知った低水準のGPIOアクセスを、C言語のプログラムとしてきちんと整理する、というのが第一目標である。 まずは既に動いている「blink.c」を、15ビット個別制御バージョンまで拡張である。 「blink.c」の冒頭にあるピン定義の「#define PIN RPI_GPIO_P1_11」であるが、これは ヘッダファイル の中に、Raspberry Piバージョン2の定義として「RPI_GPIO_P1_11 = 17」というのがあったので、11ピンを指定するにはGPIOポート番号の「17」を使えばいい、と判った。 つまり、先に作ったCプログラムの定数配列「int assign[15] = {17,18,27,22,23,24,25,4,2,3,10,9,11,8,7};」が使えるのでは、と期待できる。 そして、数分ほどで、以下のようなプログラムを作って、Raspberry Piにrcpして、「gcc -o blink blink.c -l bcm2835」でコンパイルして、「sudo ./blink」すると、何度でも確実に、15ビットのLEDが全て点滅する、と確認できた。(^_^)

#include <bcm2835.h>

int main()
{
	int i, j;
	int assign[15] = {17,18,27,22,23,24,25,4,2,3,10,9,11,8,7};

	if (!bcm2835_init())
		return 1;

	for (i=0; i<15; i++) {
		bcm2835_gpio_fsel(assign[i], BCM2835_GPIO_FSEL_OUTP);
	}

	for (j=0; j<7; j++) {
		for (i=0; i<8; i++) {
			bcm2835_gpio_write(assign[i], HIGH);
		}
		for (i=8; i<15; i++) {
			bcm2835_gpio_write(assign[i], LOW);
		}
		bcm2835_delay(500);
		for (i=0; i<8; i++) {
 			bcm2835_gpio_write(assign[i], LOW);
		}
		for (i=8; i<15; i++) {
			bcm2835_gpio_write(assign[i], HIGH);
		}
		bcm2835_delay(500);
	}

	bcm2835_close();
	return 0;
}
こうなればC言語の世界なので、いちいちネットで「ビット排他的論理和」「ビット論理積」「ビットシフト」などの記号を調べて思い出したものの、以下のように無限ループでLEDを点灯させる改訂版の「blink.c」はすぐに出来た。 8ビットのGPIO汎用ポートを1msecのインターバルごとに2進数で0から255までカウントアップして、ゼロに戻るとGPIO拡張ポートが1だけカウントアップし、これが7ビットの拡張ポートで0から127まで回ると一周である。

YouTube
#include <bcm2835.h>

int assign[15] = {17,18,27,22,23,24,25,4,2,3,10,9,11,8,7};

void GPIO_out(int data, int mode){
	int i;
	mode = mode & 1;	// mode=0 : active high / mode=1 : active low
	data = data & 255;
	for (i=0; i<8; i++) {
		bcm2835_gpio_write( assign[i], ( ( (data >>i) & 1) ^ mode ) );
	}
}

void EXT_out(int data, int mode){
	int i;
	mode = mode & 1;	// mode=0 : active high / mode=1 : active low
	data = data & 127;
	for (i=0; i<7; i++) {
		bcm2835_gpio_write( assign[i+8], ( ( (data >>i) & 1) ^ mode ) );
	}
}

int main()
{
	int i, j;

	if (!bcm2835_init())
		return 1;
	for (i=0; i<15; i++)
		bcm2835_gpio_fsel(assign[i], BCM2835_GPIO_FSEL_OUTP);

	EXT_out(0, 1);
	GPIO_out(0, 1);

	while(1){
		for (j=0; j<128; j++) {
			EXT_out(j, 1);
			for (i=0; i<256; i++) {
				GPIO_out(i, 1);
				bcm2835_delay(1); // 1msec interval
			}
		}
	}

	EXT_out(0, 1);
	GPIO_out(0, 1);

	bcm2835_close();
}
これを61号機では、「LED_blink」とリネームして、「sudo nano .profile」からの追加によって、Blink(1)の自動点滅と合わせて起動時に呼ばれるようにセットすることにした。 また、Raspberry PiをHALTせずにリブートするのは「sudo reboot」というのも知った。 なかなか進んだところで、今日はここまでである。(^_^)

「Raspberry Pi日記」トップに戻る