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」であった。
- sudo mkdir -p /media/ramdisk
- sudo mount -t tmpfs -o size=1K tmpfs /media/ramdisk
- 上の2行で、RAMdiskの作られるディレクトリの作成とマウントは完了
- 下の1行で、終了時のアンマウントができる
- sudo umount /media/ramdisk
- このRAMdisk領域へのファイル書き込み例は以下
- fp = fopen("/media/ramdisk/test.txt", "w");
- fputs(s, fp);
- このRAMdisk領域からのファイル読み込み例は以下
- fp = fopen("/media/ramdisk/test.txt", "rb");
- s[i] = fgetc(fp);
そこでまず、 RAMdiskにtest.txtを書き込むプログラム、 を改訂した以下の「test4.c」を作ってRaspberry Piにrcpして「cc」でコンパイルして実行を確認し、RAMdiskにMaxで実験した適当な64バイトの16進数データの並んだファイルを置いた。(一部、表示のため改行を挿入)
これで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」に入れて実験することで、この動作を確認した。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 ~ $これでようやく、最後の接続の部分に到達した。 つまり、「Maxから送られる64個の16進数(00-FF)データに対応したPWM値をパックしたOSCメッセージ」を受信して、これを刻々とRAMdiskにある「test.txt」に書き出す、というPythonプログラム★を作れば、最終的には以下の流れとなるわけである。#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<これが動いたら、ビット単位の点滅だった「disp_go」を、いよいよPWM制御の時分割プログラムに成長させる、という事になる。 一気にやらずに外堀から埋めてきたので、「PythonでOSC受信」までは既に出来ていて、いよいよ最後に残ったのは「Pythonでファイル書き出し」という一点だけになった。
- (最初に)RAMdiskを設定、マウントしておく
- MaxからOSCメッセージとして64個の16進数(00-FF)データに対応したPWM値を送信
- これをPythonプログラム★がOSC受信してRAMdisk内のtest.txtに書き出す
- これをバックグラウンドで走る「disp_go」がビットごとに表示(PWM値が127以上だと点灯)
そこで「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」はこれを点灯させるのである。
明らかに、この「test.py」の、それも追加した「f=・・・」の部分のバグということである。 しかしここで時間切れとなり、また明日以降に継続となった。 かなりいいセンまで進んでいるので、なんとか頑張って、Sketchingまでに作り上げたいところである。#!/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()
「Raspberry Pi日記」トップに戻る