Raspberry Pi 日記 (part2)

長嶋 洋一


2013年7月9日(火)

梅雨前線が消滅して全国的に梅雨明けし、いきなり真夏日続きで熱中症続出のニュースが飛び交う火曜日である。 1限の「サウンドデザイン」では最終課題に2回生がいろいろと食い付いてきていて、前期末の最終課題合評が楽しみになってきた。 4-5限の「企画立案演習」はクラス内プレゼンであり、来週の3クラス合同・成果発表会に向けて、こちらも大詰めである。

その合間の2-3限で、昨日の続きに取りかかった。 まず、「test7.c」をコマンドラインの数値オプションを与えられるようにして、RAMdisk内のtest.txtを読み出しに行く頻度を変更できるようにした上で、以下のように改訂したMaxパッチで、LED[0]の値を0から255までインクリメントしつつ、64個のPWMデータを全て周期的にOSCメッセージとして連続的に送るようにした。

このMaxパッチで実験したところ、連続送出のインターバルを20msecまで下げても(毎秒50メッセージ)動作したが、19msecにすると表示の変化がストップしたので、最小値を20msecとした。 その上で、LED[0]がじわじわと明るくなりつつ、さらに画面内の「Random」ボタンを連打でクリックして、Raspberry Pi側の対応を調べた。 そして、LEDのチラつきがもっとも少ない「良好なゾーン」として、以下の改訂「test7.c」のRAMdisk内のtest.txtを読み出しに行く頻度パラメータについて、オプション無しの場合の初期値を200、と設定した。 これより小さくても(2とかでも)大きくても(10000とかでも)動作するが、大きく違えてみると反応速度とかチラつきが気になってくる。

改訂版 test7.c (RAMdiskアクセス頻度 設定可能)

#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[134];
int PWM_data[64];

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 );
}

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);
	}
}

void data_file_read(){
	int i, j;
	if ((fp = fopen("/media/ramdisk/test.txt", "rb")) == NULL) {
		for(i=0; i<64; i++){
			PWM_data[i] = 0;
		}
	}
	else{
		for(i=0; i<132; i++){
			s[i] = fgetc(fp);
		}
		s[132] = 0;	
		fclose(fp);
		for (j=0; j<8; j++) {
			for (i=0; i<8; i++) {
				PWM_data[8*j+i]  = 16*asc_2_int(s[2*(8*j+i)+2])  + asc_2_int(s[2*(8*j+i)+3]);
			}
		}
	}
}

int main(int argc, char *argv[])
{
	int i, j, bit_data, put_data;
	int interval = 0;
	int current_value = 0;
	int RADdisk_access = 200;

	if (!bcm2835_init()){
		printf("GPIO is not found.\n");
		return 1;
	}
	if(argc > 1){
		RADdisk_access = atoi(argv[1]);
	}
	for (i=0; i<15; i++){
		bcm2835_gpio_fsel(assign[i], BCM2835_GPIO_FSEL_OUTP);
	}
	while(1){
		if(++interval > RADdisk_access){
			interval = 0;
			data_file_read();
		}
		if (++current_value > 255){
			current_value = 0;
		}
		for (j=0; j<8; j++) {
			put_data = 0;
			for (i=0; i<8; i++) {
				if(PWM_data[8*j+i] < current_value){
					bit_data = 0;
				}
				else{
					bit_data = 1;
				}
				put_data = put_data + (bit_data<
これで、Raspberry Pi+SUACboardのシステム側のツールは完成、と見て、「test7.c」を「gcc test7.c -l bcm2835」でコンパイルした「a.out」を「disp_go」にリネームし、「test.py」を「OSC_2_RAMdisk.py」とリネームした。 RAMディスクの設定から含めると、この環境での起動準備は、以下のようになった。 ターミナルを1画面にしたいのであれば、以下のように、起動の最後に「&」を付けてバックグラウンド実行、とすればよい。 ここまでをRaspberry Piの起動時処理として登録してもいいのだが、それほどの手間でもないので、Raspberry Pi62号機にだけ「disp_go」と「OSC_2_RAMdisk.py」を置いておき、必要に応じて呼び出すこととした。 そして3限のうちに、改訂したMaxパッチ UDP_test_03.maxpat によって、以下のように色々なモードで、多数のLEDを同時にPWM制御する、というデモを実現することが出来た。 あまりにRaspberry Piが高速なためか、GPIOポートの出力電圧が一部の74HCロジックのスレショルドレベルと拮抗して正しく伝わらずにチラつくところもあるが、これはLinuxのバックグラウンド処理の不定期な間欠処理とも関係しているようで、まぁ「気にしない」というところである(^_^;)。

YouTube

ここまで来たところで、ちょうどこのHTMLのファイルサイズが「part1」と同じ238KBとなった。 ちょうど区切りなので、ここまでを「part2」として、日ごとのHTMLにも分割することにした。 Sketching2013でのお披露目に向けて、まだまだ続くところは「part3」としよう。(^_^)


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