Raspberry Pi 日記 (part2)

長嶋 洋一


2013年7月7日(日)

日曜日の朝から「サンフランシスコ空港でアシアナ機が着陸失敗」というニュースが届いたが、11日後にそのサンフランシスコ空港に僕のフライト(ANA)も着陸する。 Sketching2013の主宰者Mike Kuniavskyからは、全体の詳細なスケジュールとともに直前連絡のメイルも届いた。 午後にアカペラ合宿の行先検討会議で学生2人が研究室に来る予定があるが、午前中はRaspberry Piタイムだ、と思っていたところ、某将棋杯の解説が山崎7段ということで、七夕のキャスティング「矢内・山崎漫才」をチェックしないと・・・と予定が大幅に変わった(^_^;)。

それでも、朝から頑張って、将棋ネット中継の開始までに、かつて 未踏プロジェクト で作ったMaxパッチに、昨日ぶつかっていた壁を突破するネタがあったのを思い出して、無事に以下のようなパッチを作った。 これで、OSC経由でRaspberry Piに64個のLEDのPWMデータを64個の16進データ(00-FF)をまとめた文字列として与えられる。 そして、午前中は「矢内・山崎漫才」を囃し立てる某掲示板のスレを2本同時に眺めつつ、最後はグタグダとなった将棋とともに過ごした。

午後にはアカペラの代表2人と、この夏休みの「合宿」の行き先を検討して浜北森林公園と決定した。 そして作業再開、まず午前に完成させた、「幅64ポイント、値0-255」のテーブルデータをOSCでポート7003に送る、という UDP_test_01.maxpat を呼び出し、さらに昨日作った、このOSCメッセージを受けて表示する、という Pythonプログラム を呼び出し、Raspberry Pi62号機で以下のようにOSC受信を確認した。

そして次に、「2013年7月1日(月)」にやったRAMディスクの実験のところをなぞって、以下のような手順でRaspberry PiにRAMdiskを設定した。 これはスクリプト化してRaspberry Piの起動時に呼び出すようにする事も、あれこれうまく行ったら検討しよう。

ここで、手元に実験途中で残してきたC言語プログラムを確認すると、 RAMdiskに50000回、test.txtを書き込むプログラムRAMdisk内のtest.txtを15ビットのGPIOポートのLEDに表示するRaspberry Pi61号機で動くプログラムSUACboardの64個のLEDを個別ON/OFF表示するRaspberry Pi62号機で動くプログラム、 の3本である。 コンパイルは3本目の場合であれば「gcc test3.c -l bcm2835」で、実行は「sudo ./a.out」であった。

そこでまず、 RAMdiskにtest.txtを書き込むプログラム、 を改訂した以下の「test4.c」を作ってRaspberry Piにrcpして「cc」でコンパイルして実行を確認し、RAMdiskにMaxで実験した適当な64バイトの16進数データの並んだファイルを置いた。(一部、表示のため改行を挿入)

Last login: Sun Jul  7 07:40:52 on console
nagasm-Mac-mini:~ nagasm$ ssh pi@172.16.65.62
pi@172.16.65.62'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: Mon Jun 24 02:18:54 2013

pi@raspberrypi ~ $ ls
Desktop         SimpleOSC     blink1-tool    ocr_pi.png    pyusb-1.0.0-a1  twilight.png
GPIO_clear      a.out         blink_autorun  pyOSC         pyusb-1.0.0a3
RPi.GPIO-0.1.0  bcm2835-1.25  null           python_games  test.py

pi@raspberrypi ~ $ rcp nagasm@172.16.65.31:Desktop/test4.c .
Password:
test4.c                                                   100%  451     0.4KB/s   00:00    

pi@raspberrypi ~ $ cat test4.c
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	FILE *fp;
	char ss[3];
	char s[130] = "1E3246586A6A868B919494938B857E62605C5D5E60626A6E758C93949597989A9
				C9D9E9D9B9A99928A84817A787773757B7DADC0CACBCDD6DEE4E5EAECF0F4F5";
	s[128] = '\n';	
	s[129] = 0;
	if ((fp = fopen("/media/ramdisk/test.txt", "w")) == NULL) {
		printf("file open error!!\n");
		exit(EXIT_FAILURE);
	}
	fputs(s, fp);
	fclose(fp);
	printf("Write access done.\n");
	return 0;
}

pi@raspberrypi ~ $ cc test4.c
pi@raspberrypi ~ $ ./a.out
Write access done.

pi@raspberrypi ~ $ ls -l /media/ramdisk
合計 4
-rw-r--r-- 1 pi pi 129  6月 24 04:06 test.txt

pi@raspberrypi ~ $ cat /media/ramdisk/test.txt
1E3246586A6A868B919494938B857E62605C5D5E60626A6E758C93949597989A9
C9D9E9D9B9A99928A84817A787773757B7DADC0CACBCDD6DEE4E5EAECF0F4F5

pi@raspberrypi ~ $ 
これでRAMdiskにサンプルとなるテキストファイルが出来たので、次に、 RAMdisk内のtest.txtの呼び出しSUACboardの64個のLEDを点灯 の2本を合体させて改編し、「RAMdisk内のtest.txtを読み出し、64個の16進数(00-FF)データが128以上なら該当のLEDが点灯、128未満なら消灯する」という、以下のプログラム「test5.c」を作った。 これをコンパイルした結果の「a.out」を「disp_go」とリネームして、「sudo ./disp_go &」としてバックグラウンドで無限ループで走らせておくと、常にRAMdiskにあるtest.txtを読み出し、64個の16進数(00-FF)データに対応してLEDをONまたはOFFさせている。 その状態で、Maxのパッチから色々なPWMデータの16進文字列を作って「test4.c」に入れて実験することで、この動作を確認した。
#include <stdio.h>
#include <stdlib.h>
#include <bcm2835.>

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

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 Select_out(int data){
	int i;
	data = data & 7;
	for (i=0; i<3; i++) {
		bcm2835_gpio_write( assign[i+10], ( (data >>i) & 1)  );
	}
	bcm2835_gpio_write( assign[13], 0 );
	bcm2835_gpio_write( assign[13], 1 );
}

void data_file_read(){
	int i;
	if ((fp = fopen("/media/ramdisk/test.txt", "rb")) == NULL) {
		printf("\nread error!!\n");
	}
	else{
		for(i=0; i<129; i++){
			s[i] = fgetc(fp);
		}
		s[129] = 0;	
		fclose(fp);
	}
}

int asc_2_int(char s){
	char c;
	if ('0' <= s && s <= '9')
		return(s - '0');
	else if ('a' <= (c = tolower(s)) && c <= 'f')
		return(c - 'a' + 10);
}

int main(void)
{
	int i, j, get_data, bit_data, put_data;

	if (!bcm2835_init()){
		printf("GPIO is not found.\n");
		return 1;
	}
	for (i=0; i<15; i++){
		bcm2835_gpio_fsel(assign[i], BCM2835_GPIO_FSEL_OUTP);
	}
	while(1){
		data_file_read();
		for (j=0; j<8; j++) {
			put_data = 0;
			for (i=0; i<8; i++) {
				get_data =16*asc_2_int(s[2*(8*j+i)]);
				get_data = get_data + asc_2_int(s[2*(8*j+i)+1]);
				if(get_data<128)
					bit_data = 0;
				else
					bit_data = 1;
				put_data = put_data + (bit_data<
これでようやく、最後の接続の部分に到達した。 つまり、「Maxから送られる64個の16進数(00-FF)データに対応したPWM値をパックしたOSCメッセージ」を受信して、これを刻々とRAMdiskにある「test.txt」に書き出す、というPythonプログラム★を作れば、最終的には以下の流れとなるわけである。 これが動いたら、ビット単位の点滅だった「disp_go」を、いよいよPWM制御の時分割プログラムに成長させる、という事になる。 一気にやらずに外堀から埋めてきたので、「PythonでOSC受信」までは既に出来ていて、いよいよ最後に残ったのは「Pythonでファイル書き出し」という一点だけになった。

そこで「Python file write」などと検索して、コレかな・・・というサンプルを発見し、以下のように改訂した「test.py」を作って、Raspberry Piにrcpして「sudo python ./test.py」で走らせてみると、MaxからのOSCメッセージは受け取るものの、バックグラウンドで走っている「disp_go」は、全LEDを点灯させた(^_^;)。 調べてみると、以下の「test.py」は、どうもopenの際に既存の「test.txt」を消して、そして新しいファイルの書き出しに成功していないらしく、「cat /media/ramdisk/test.txt」の結果が空白、つまりファイルが消えていた(^_^;)。 Maxのパッチで、異なるPWMデータの16進文字列を作って「test4.c」に入れて実験した「go_1」や「go_2」を走らせると、ちゃんとRAMdisk内のtest.txtが復活して、バックグラウンドの「disp_go」はこれを点灯させるのである。

#!/usr/bin/env python

from simpleOSC import initOSCClient, initOSCServer, setOSCHandler, sendOSCMsg, closeOSC, \
     createOSCBundle, sendOSCBundle, startOSCServer
import time, threading, OSC

def pi_62_test(addr, tags, data, source):
    print "%s" % data
    f = open('/media/ramdisk/test.txt', 'w')
    f.write( data )
    f.close()

initOSCServer(ip='172.16.65.62', port=7003, mode=0)   
setOSCHandler('/pi_62', pi_62_test)
startOSCServer()

send_address = '172.16.65.31', 7001
c = OSC.OSCClient()
c.connect( send_address )
msg = OSC.OSCMessage()
msg.setAddress("/pi_62")
msg.append( "Raspberry Pi 62 OK (^_^)")
c.send(msg)

try:
    while 1:
        time.sleep(3) 
except KeyboardInterrupt:
    print "closing all OSC connections... and exit"
    closeOSC()
明らかに、この「test.py」の、それも追加した「f=・・・」の部分のバグということである。 しかしここで時間切れとなり、また明日以降に継続となった。 かなりいいセンまで進んでいるので、なんとか頑張って、Sketchingまでに作り上げたいところである。

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