Cubie Boardというかわいいボードがある。
公式サイト: http://cubieboard.org/
主要諸元は以下のとおり
これが、$49。
わたくしは、
http://www.aliexpress.com/store/211096
で、
cubieboard 1GB ARM Cortex-A8 Allwinner A10、 しめて US $69.50
というものを買った。
(ついでに、"uSD Breakout"(後述)というものも、一緒に、一つ買った)
SATAケーブル, 電源のケーブルとアクリル板2枚で上下を守る簡易ケース的なもののセットである。
電源ケーブルは、USBコネクタ-> 丸いコネクタに変換するもの。
香港からの郵送にすると、*送料無料*、なので、挑戦した。
ほぼ1ヶ月弱 かかったが、無事に到着した。
日本で CubieBoardを扱う会社ができたようで、日本Amazonのマーケットで、買える。
瑞起
Amazon
これには、ケースと、"uSD Breakout"というのが付いている。
"uSD Breakout"というのは、micro SDカードの端子を、引っ張り出す治具である。
CubieBoardは、JTAG 端子が micro SDの端子が兼用になっていて、
JTAGを使用して、ROMを書き直すなどするためには、この"uSD Breakout"が必要である。
"uSD Breakout" と JTAG 端子 資料
Linuxのインストール
BerryBoot - bootloader / OS installer for Allwinner A10 devices
というページから、
Cubieboard (1 GB model)
berryboot-cubieboard-beta6.zip
というイメージをダウンロードする。
これは、展開しても非常に小さい。
micro SDカードは、私は、8GBytesのものを使用した。
micro SDカードは、SDHC Class4 という遅いものを使用すべし。
Class 10 のカードはうまく行かない。
micro SDHC Class 4のカードなら、複数のものでうまく行っている。
# gunzip < berryboot-cubieboard-beta6.zip |dd of=/dev/sdc bs=1mb conv=sync
などとして、micro SDカードに書き込む。
Cubie Boardに、Ethernet を接続し(LAN上に dhcpサーバが必要)、キーボード、マウス、HDMIディスプレイも接続する。
micro SDカードを、Cubie Boardに挿して、電源を入れると、
OSのインストーラが起動する。
ネットワーク接続が正しいと、インターネット経由で、インストールする OSの候補が表示されるので、選ぶ。
わたくしは、Linaro Ubuntu にした。
特に問題は出ないだろう。
Cubie Boardの CPUには、NEON(ARMの SIMD 機構)が載っている。
僕自身で触れる ARM で、NEON が載っているのは、これが初めてだ。
早速、試した。
残念ながら、Whetstoneは、かなり書き直さなければ NEON のコードが生成されない。
仕方がないので、とりあえず、簡単なプログラムを探した。
Neon Auto Vectorization Compiler directives and Example
で、極めて簡単な乗算ループの例(これは、整数だが、私は、float にしてみた)
と、
京都マイコンの koba さんの記事
で、積和演算ループの例
を見つけた。
それをコピペする。
0)
今回の kernel, gcc のバージョン
take@qb01% uname -a
Linux qb01 3.4.24-a10-aufs+ #33 PREEMPT Sun Feb 24 21:17:26 CET 20
13 armv7l armv7l armv7l GNU/Linux
take@qb01% gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/4.6/lto-wrapp
er
Target: arm-linux-gnueabihf
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.3-1ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --enable-multilib --disable-sjlj-exceptions --with-arch=armv7-a --with-float=hard --with-fpu=vfpv3-d16 --with-mode=thumb --disable-werror --enable-checking=release --build=arm-linux-gnueabihf --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf
Thread model: posix
gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
1)
gcc などをインストール。
% sudo bash
# apt-get install gcc make libclang-common-dev libcommoncpp2-dev
# apt-get install time
# apt-get install emacs
2)
gcc オプションには、
-mfpu=neon -funsafe-math-optimizations -mvectorize-with-neon-quad
を指定した。
--Makefile--
neon-test2: neon-test2.c Makefile
cc -mfpu=neon -funsafe-math-optimizations -mvectorize-with-neon-quad -O4 neon-test2.c -lm -o neon-test2
neon-test2-vfp: neon-test2.c Makefile
cc -mfpu=vfpv3 -O4 neon-test2.c -lm -o neon-test2-vfp
-- neon-test2.c --
#include <stdio.h>
#include <stdlib.h>
#define SIZE 1000000
#define LOOOP 1000
void
vmul(float* __restrict a, float* __restrict x, float* __restrict y)
{int i;
for(i = 0; i < SIZE; i++){
a[i] = x[i] * y[i];
}
}
void
vmla2(float* __restrict a, float* __restrict x, float* __restrict y, float* __restrict z)
{
int i;
for (i=0; i < SIZE; i++) {
a[i] = x[i] * y[i] + z[i];
}
}
float aa[SIZE], xx[SIZE], yy[SIZE], zz[SIZE];
main()
{int i;
for(i=0;i<SIZE; i++){
xx[i]=yy[i]=zz[i]=i;
}
for(i=0;i<LOOOP; i++){
vmul(aa,xx,yy);
}
for(i=0;i<LOOOP; i++){
vmla2(aa,xx,yy,zz);
}
#ifdef PRI
for(i=0;i<100; i++){
printf(" %f ", aa[i]);
}
#endif
}
--
neon-test2.s の一部 vmul のループ
.L5:
add r7, r3, sl
vldmia r3, {d16-d17}
adds r6, r6, #1
add r4, r3, r9
vld1.32 {q9}, [r7]
adds r3, r3, #16
vmul.f32 q8, q9, q8 ;;;;ここでNEONの SIMD乗算!
cmp r6, r8
vst1.32 {q8}, [r4]
bcc .L5
ldr r3, [sp, #4]
add r4, ip, fp
rsb r5, fp, r5
cmp r3, fp
beq .L1
.L4:
---
neon-test2.s の一部 vmla2 のループ
.L17:
add r6, r3, sl
add r5, r3, r9
vldmia r3, {d18-d19}
adds r4, r4, #1
vld1.32 {q10}, [r6]
add r2, r3, r8
adds r3, r3, #16
cmp r4, ip
vld1.32 {q8}, [r5]
vmla.f32 q8, q10, q9 ;;;ここで、SIMD 積和演算!
vst1.32 {q8}, [r2]
bcc .L17
ldr ip, [sp, #0]
ldr r3, [sp, #12]
add r2, r7, ip
rsb r0, ip, r0
cmp r3, ip
beq .L13
.L16:
--
ということで、NEON の SIMD 命令が出ている。
さて、このCPUは、VFPも積んでいるので、
gcc オプションに、
-mfpu=vfpv3
を指定すれば、VFPを使用することもできる。
同じソースで、NEON と VFP でコンパイルし、実行時間を測ってみた。
take@qb01% /usr/bin/time ./neon-test2
Command exited with non-zero status 64
22.23user 0.03system 0:22.55elapsed 98%CPU (0avgtext+0avgdata 63696maxresident)k
0inputs+0outputs (0major+4034minor)pagefaults 0swaps
take@qb01% /usr/bin/time ./neon-test2-vfp
Command exited with non-zero status 36
125.98user 0.01system 2:07.59elapsed 98%CPU (0avgtext+0avgdata 63696maxresident)k
0inputs+0outputs (0major+4034minor)pagefaults 0swaps
数回計測した。
NEON: 約 22.2 秒
VFP : 約126.0 秒
ということで、5倍以上も速くなっている。
メモリの読み書きも、NEON命令が効いているのであろうか…
SATA が付いているので、HDD を接続して試してみなければならない。
また、後日。
このCubie Boardは、なかなか良さそうなのだが、
SoC が、中国本土のものなので、
バックドアが付いていないとは限らない。
なので、気軽に人に勧める気にならないのが、玉に傷だなぁ。
Cubie Boardで遊ぶ。ARM NEON SIMDを試す
Raspberry Pi でOpenGL ES2
Raspberry Pi でOpenGL ES2 を試す
Raspiには、GPUが載っており、OpenGL がそれなりに速いらしい。
↓に、いいことが書いてあり、「OpenGL ES 2.0 programming guide」の例題をRaspiに移植したコードもある。
Using OpenGL ES 2.0 on the Raspberry Pi without X windows.
↓の感じで、「OpenGL ES 2.0 programming guide」の例題を取ってきて、展開
% wget --no-check-certificate https://github.com/benosteen/opengles-book-samples/tarball/master; tar -xvzf master
コンパイルは、
% cd opengles-book-samples-master/Raspi
% make
ただ、僕のRaspi では、そのままでは make が通らなかった。
Makefile の include 指定に、
-I$(SDKSTAGE)/opt/vc/include/interface/vmcs_host/linux
を加えた。
--- Makefileのdiff --
% diff Makefile.org Makefile
7c7
< INCDIR=-I./Common -I$(SDKSTAGE)/opt/vc/include -I$(SDKSTAGE)/opt/vc/include/interface/vcos/pthreads
---
> INCDIR=-I./Common -I$(SDKSTAGE)/opt/vc/include -I$(SDKSTAGE)/opt/vc/include/interface/vcos/pthreads -I$(SDKSTAGE)/opt/vc/include/interface/vmcs_host/linux
44a45
>
--------
コンパイルが終了すると、各ディレクトリの中に実行バイナリができる。
X Window無しで、画面に直書き。
当該の教科書を読んだことがないが、地味な例題ばっかりで、つまらなかった。
ソフトウェアでやるよりは、かなり速い印象はあり。
OpenGL ES2 のGPU版が、開発に使えることは分かったので、まぁ良し。
--
今回の、僕のRaspiのLinux (自分で make やり直したkernelです)
% uname -a
Linux nanami 3.6.11+ #2 PREEMPT Fri Jun 21 09:49:19 JST 2013 armv6l GNU/Linux
Raspberry Pi でOpenCV を試す
Raspberry Pi でOpenCV を試す
Raspi をロボットの中に入れたい人が多いらしい。
じゃ、画像の入力と、画像認識の初歩をやってみないと…
↓に、すでに行っている先哲がっ! そのまま、真似をさせて頂きます。
Raspberry Pi への OpenCV インストール.by いしわたむねお氏
顔認識もやりました。
これも先哲の成果を、ほぼそのままパクリさせて頂きました。
OpenCV本家の"cvHaarDetectObjects"の顔認識例
raspberrypi/OpenCVを使って顔認識しました by 竹本浩氏
カメラを接続する
あたくしは、手元にあった、安い Logitech の WebCam をつないでみた。
ロジクール Logicool QCAM-E2500 [USB接続 30万画素 Logicool Qcam E 2500](ヨドバシ)
-- 2013/JUL/06 追記--
Logicoolの 861200というWebカメラでも同様に使えた。
--
% lsusb
:
Bus 001 Device 010: ID 046d:089d Logitech, Inc. QuickCam E2500 series
-- dmesg --
[ 134.201702] usb 1-1.2.1: new full-speed USB device number 9 using dwc_otg
[ 134.304615] usb 1-1.2.1: New USB device found, idVendor=046d, idProduct=089d
[ 134.304645] usb 1-1.2.1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[ 134.387759] Linux media interface: v0.10
[ 134.419926] Linux video capture interface: v2.00
[ 134.430733] gspca_main: v2.14.0 registered
[ 134.443630] gspca_main: gspca_zc3xx-2.14.0 probing 046d:089d
[ 134.452089] input: gspca_zc3xx as /devices/platform/bcm2708_usb/usb1/1-1/1-1.2/1-1.2.1/input/input3
[ 134.467547] usbcore: registered new interface driver gspca_zc3xx
[ 134.623279] usbcore: registered new interface driver snd-usb-audio
--
てな感じで、めでたく認識されて使えた。
挿すだけで使えたので、正直、大変驚いた。
ちなみに、Logitechの このWeb カメラは、安価だが、近接撮影ができ、
紙や基板やLSIに書かれた文字などを、撮影することが可能。
電話会議中に、そういうものの画像を送ることができて、非常に便利。
(電話会議で、自分の顔を送るようなことはしない)
OpenCVのインストール
BSDな人間なので、ソースから make したいが、Linuxだから、目をつむって楽をするぜ。
% sudo bash
# apt-get install libopencv-dev
以上
OpenCV な 画像取り込み & 表示アプリケーション
上記の いしわたむねお氏の Raspberry Pi への OpenCV インストール.by いしわたむねお にある Cソースを、まるまるコピペすると、OKです。
-- あたくしが書いた Makefile (当該のソースファイルは、「cam-view.c」とする)--
CXX = g++
LDFLAGS = -lopencv_legacy -lopencv_highgui -lopencv_core -lopencv_ml -lopencv_video -lopencv_imgproc -lopencv_calib3d -lopencv_objdetect -L/usr/lib
CPPFLAGS = -g -I/usr/include/opencv -I/usr/include/opencv2
all: cam-view
---
% make
して、うまくできたら、
% startx
として、X Window Systemを起動しておいて、
% ./cam-view
とすれば、数秒して、窓が開き、カメラからの入力が窓に表示される。
このアプリケーションは、真面目な X Window アプリケーションである。
ssh -X で入ってると、元の機械に窓が出て使える。
(最初、適当に、ssh -X している状態で起動したら、手元に機械にカメラの画像が出て、非常に驚き&喜んだ)
うーん。とても簡単だった。
Webカメラを発掘する時間も含めて、20分ぐらいだった。
いしわた氏と、OpenCV(Intel)とそれをパッケージしてくれてる人たちに感謝。
たぶん、電源が弱いせいだと思うが…
盛大に、このアプリケーションでWeb カメラを動かしていると、
Raspiのシステムが不安定になる。(Ehter I/Fが使えなくなったり)
僕は、Webカメラは、電源付きUSB Hubにつないでいるのだが…
Raspi で、監視カメラや、画像認識付きロボットをつくるには、もうちょっと、電源まわりの強化が必要かも知れない。
顔認識を試した。 (2013/JUN/23 17:00 加筆)
上記のカメラ入力部と、↓を組み合わせる。
OpenCV本家の"cvHaarDetectObjects"の顔認識例
すると、竹本浩氏が作られた↓になる。
raspberrypi/OpenCVを使って顔認識しました by 竹本浩氏
ソースコード中に C99 文法的な記述があったので、普通の C89的に修正した。
#include "cv.h"
#include "highgui.h"
char* cascade = "/usr/share/opencv/haarcascades/haarcascade_frontalface_default.xml";
#define DISP_WIN "faceDetect"
CvSize minsiz ={0,0};
int
main( int argc, char** argv )
{
int i;
double w = 160;
double h = 120;
cvNamedWindow( DISP_WIN , CV_WINDOW_AUTOSIZE );
CvCapture* capture = NULL;
if (argc > 1){
capture = cvCreateFileCapture( argv[1] );
}else{
capture = cvCreateCameraCapture( 0 );
// (2)キャプチャサイズを設定する.
cvSetCaptureProperty (capture, CV_CAP_PROP_FRAME_WIDTH, w);
cvSetCaptureProperty (capture, CV_CAP_PROP_FRAME_HEIGHT, h);
}
IplImage* frame;
// 正面顔検出器の読み込み
CvHaarClassifierCascade* cvHCC = (CvHaarClassifierCascade*)cvLoad(cascade, NULL,NULL,NULL);
// 検出に必要なメモリストレージを用意する
CvMemStorage* cvMStr = cvCreateMemStorage(0);
// 検出情報を受け取るためのシーケンスを用意する
CvSeq* face;
while(1) {
frame = cvQueryFrame( capture );
if( !frame ) break;
// 画像中から検出対象の情報を取得する
face = cvHaarDetectObjects(frame, cvHCC, cvMStr,
1.2, 2, CV_HAAR_DO_CANNY_PRUNING,
minsiz, minsiz);
// 1.1, 3, 0, minsiz, minsiz);
for(i = 0; i < face->total; i++) {
// 検出情報から顔の位置情報を取得
CvRect* faceRect = (CvRect*)cvGetSeqElem(face, i);
// 取得した顔の位置情報に基づき、矩形描画を行う
cvRectangle(frame,
cvPoint(faceRect->x, faceRect->y),
cvPoint(faceRect->x + faceRect->width,
faceRect->y + faceRect->height),
CV_RGB(255, 0 ,0),
2, CV_AA, 0);
}
cvShowImage( DISP_WIN, frame );
char c = cvWaitKey(1);
if( c == 27 ) break;
}
// 用意したメモリストレージを解放
cvReleaseMemStorage(&cvMStr);
// カスケード識別器の解放
cvReleaseHaarClassifierCascade(&cvHCC);
cvReleaseCapture( &capture );
cvDestroyWindow( DISP_WIN );
}
-- Makefile --
CXX = g++
CPPFLAGS = -mfpu=vfpv3 -O4 -I/usr/include/opencv -I/usr/include/opencv2
LDFLAGS = -lopencv_legacy -lopencv_highgui -lopencv_core -lopencv_ml -lopencv_video -lopencv_imgproc -lopencv_calib3d -lopencv_objdetect -L/usr/lib
all: facedetect
% make
して、コンパイルが終了したら、
% ./facedetect
で、X サーバに窓がでて、認識結果が表示される。
はっきり言って、超遅い。この遅さはロボットには使えない。監視カメラならありえるか???
もうちょっと速くなるはずなので、パラメータを調整するべきであろう。
-- 2013/JUL/06 追記: 使えないほど遅い、ということもないようだ。用途による。
今回の、僕のRaspiのLinux (自分で make やり直したkernelです)
% uname -a
Linux nanami 3.6.11+ #2 PREEMPT Fri Jun 21 09:49:19 JST 2013 armv6l GNU/Linux
Raspberry Pi にHDMI->VGA変換器と、USBディスプレイをつなぐ
Raspberry Pi の表示ネタ
1.Raspberry Piに HDMI -> VGA変換器を接続する
2.Raspberry Piに USB Linkなディスプレイを接続する
1.Raspberry Piに HDMI -> VGA変換器を接続する
Raspberry Piには VGA 出力が無くて困る。
一般の会議室にあるプロジェクタに接続できないのだ。
そこで、 HDMI -> VGA変換器を購入して使用してみた。
安くていいものが、当然にありがたい。
Amazonで、レビューを見つつ、下記のものを購入し、快調。
ただし、まだ、手持の Benqのディスプレイで使っているだけ。
-- 2013/JUL/07 音についても、うまく出力された。
「HDMI to VGA adapter ブラック / HDMI信号をVGA出力信号に変換するアダプター
(音声出力あり)(HDMI延長アダプタ付き)
MEDIA ACTIVE
」
http://www.amazon.co.jp/gp/product/B008XU9M26/ref=oh_details_o00_s00_i00?ie=UTF8&psc=1
VGAディスプレイから情報が取得できない場合は、下記の設定を行う。
しかし、僕の場合、下記を行わなくとも、うまく映った。
下記を行うと、強制的に解像度を設定できている。
/boot/config.txt を編集し、
--
hdmi_ignore_edid=0xa5000080 #ディスプレイからのEDID参照しないようにする
hdmi_group=2 # 固定解像度を指定。この組み合わせは800x600
hdmi_mode=9
--
hdmi_group= と hdmi_mode= は、組で指定しなければならない。
解像度と、hdmi_group, hdmi_mode の関係は下の文書を見る
http://elinux.org/RPiconfig
このHDMI->VGA変換器で、OpenGL も omxplayer も動作する。
このどちらも、フレームバッファへ直書きで、結構厳しいものである。
X Windowも、普通に動作する。
いい買い物であったと思われる。
ちなみに、HDMI ディスプレイで、音を出すには、confix.txt に下記を書くとうまくいった。
# for Sound
hdmi_drive= 2
2.Raspberry Piに USB Linkなディスプレイを接続する
USB Linkなディスプレイは、コンパクトなものを以前から持っていた。
plus one(LCD-8000UD)
それをつないで成功した。
X Window Systemを Twin head (2 Display)で運用中。
右のUSB Display では、 fvwm -display :0.1 で、fvwmが動作中。
今回は、全面的に、下のページを真似した。ありがとうございます。> Anup Narkhede さん
Mimo USB Monitor and Raspberry Pi
Raspberry Pi の kernel 再コンパイルは、x86 によるクロスコンパイルがいいと思う。
やりかた
1) クロスコンパイル用のツールを得る。
x86マシンで、
x86# mkdir -p /opt/arm-tools/
x86# chown 自分のuid /opt/arm-tools
自分のユーザに戻り、
x86$ cd /opt/arm-tools
x86$ git clone https://github.com/raspberrypi/tools
とする。
僕の場合、
/opt/arm-tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
な、ツールが得られた。
2) kernelのソースを得る
kernel ソースを置きたいディレクトリに cd した後、下記を実行。
x86$ git clone --branch=rpi-3.6.11 --depth 1 git://github.com/bootc/linux.git
ちょっと時間が掛かる。
3) 動作中の Raspberry Pi の kernel config 情報が欲しい場合、
Linuxが動作中のRaspberry Piで、下記を実行
raspi$ zcat /proc/config.gz > raspi-kern-config
ここで、得られた raspi-kern-config は、クロス開発のx86 に送っておく。
4) kernel を config する
kernel ソースがあるディレクトリで、
x86$ make mrproper
※1 ここで、動作中の Raspi の raspi-kern-config を使用したければ、
x86$ cp raspi-kern-config .config
とする。
※2 ミニマルなconfig を使用したい時は、
x86$ cp arch/arm/configs/bcmrpi_cutdown_defconfig .config
とする。
そして、
x86$ ARCH=arm make menu-config
で、色々、好きにする。
USB Display を使うためには、
menu configのメニューを
‘Device Drivers’ > ‘Graphics Support’ > ‘Support for Framebuffer support’
と手繰り…
‘Displaylink USB Framebuffer support’ を‘M’にして、モジュールを使用可能にする。
5) kernel のコンパイル
環境変数 CCPREFIX に、ツールのプリフィックス
/opt/arm-tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
を設定する
bsh系の人
x86$ export CCPREFIX=/opt/arm-tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
csh系 の人
x86% setenv CCPREFIX /opt/arm-tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
kernelをコンパイルする。
x86$ ARCH=arm CROSS_COMPILE=${CCPREFIX} make
この時、コア数に合わせて、make -j 4 などとすると、4並列でmake を行える。
kernelは、 arch/arm/boot/zImage にできる。
6) モジュールをターゲット機に持っていく
ワーキング・ディレクトリを作る
x86$ mkdir -p ../newlinux/module
モジュールのコピー
x86$ MODULES_TEMP=../newlinux/modules
x86$ ARCH=arm CROSS_COMPILE=${CCPREFIX} INSTALL_MOD_PATH=${MODULES_TEMP} make modules_install
kernelもコピー
x86$ cp arch/arm/boot/zImage ../newlinux/
すべてを固める
x86$ cd ..; tar cvjf newlinux.tar.bz2 newlinux
ファイルをターゲットに転送
x86$ scp newlinux.tar.bz2 raspi:~/tmp/
7) Raspiでの作業
raspi$ cd ~/tmp
raspi$ tar xvjf newlinux.tar.bz2
raspi$ sudo bash
kernelを、/bootにコピー
raspi# cd newlinux
raspi# cp zImage /boot/kernel_new.img
/boot/config.txt を編集して、どこかに
kernel=kernel_new.img
という行を追加。
モジュールのコピー
raspi# cd modules/lib/modules
raspi# mv 3.6.11-cutdown+ /lib/modules/
8) 新しいkernelで起動する
raspi# sync
raspi# sync
raspi# sync
raspi# reboot
9) もしも、新しいカーネルが動作しなかったら
起動に使用している SD-Cardを x86 マシンに挿入。
SD-Cardの /boot は、FATファイルシステムであり、その中身はx86マシンで容易に操作できる。
config.txt を編集し、
kernel=kernel_new.img
という行を、
kernel=kernel.img
(動作していた kernelのファイル名)
として指定し直すと、Raspiは、元の正常なkernelで起動できるようになる。
10) kernelの確認
raspi$ uname -a
とやると、新しい kernel の名前や作成時刻が確認できる。
--
USB Display のドライバ・モジュールの入ったkernelで Linuxが起動したら、
USB にUSB Display を接続する。
Raspiは、電源が弱いので、USBディスプレイは、電源を持ったUSBハブに接続する。
僕の場合、
dmesgは、以下の感じ。
ここで、/dev/fb1 となっていることを知ることが大事。
[ 103.206171] udlfb: DisplayLink LCD-8000UD-DVI - serial #000000
[ 103.206207] udlfb: vid_17e9&pid_02b8&rev_0101 driver's dlfb_data struct at da829800
[ 103.206217] udlfb: console enable=1
[ 103.206224] udlfb: fb_defio enable=1
[ 103.206231] udlfb: shadow enable=1
[ 103.206524] udlfb: vendor descriptor length:22 data:22 5f 01 0020 05 00 01 03 04 02
[ 103.206541] udlfb: DL chip limited to 2080000 pixel modes
[ 103.209403] udlfb: allocated 4 65024 byte urbs
[ 103.214829] usbcore: registered new interface driver udlfb
[ 103.358073] udlfb: Unable to get valid EDID from device/display
[ 103.358108] udlfb: 640x350 @ 85 Hz valid mode
[ 103.358121] udlfb: 640x400 @ 85 Hz valid mode
:
[ 103.358430] udlfb: 1920x1440 beyond chip capabilities
[ 103.358442] udlfb: Reallocating framebuffer. Addresses will change!
[ 103.365371] udlfb: 800x600 @ 60 Hz valid mode
[ 103.365395] udlfb: set_par mode 800x600
[ 103.387384] udlfb: DisplayLink USB device /dev/fb1 attached. 800x600 resolution. Using 1880K framebuffer memory
$ lsusb -v
で、
:
Bus 001 Device 010: ID 17e9:403d DisplayLink
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x17e9 DisplayLink
idProduct 0x403d
bcdDevice 1.02
iManufacturer 1
iProduct 2
iSerial 3
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 91
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xc0
Self Powered
MaxPower 500mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 3
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 0
** UNRECOGNIZED: 1b 5f 01 00 19 05 00 01 03 00 04 04 01 00 03 d0 00 02 04 00 bd 1f 00 01 04 01 02
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 4
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x0a EP 10 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 0 No Subclass
bInterfaceProtocol 0 None
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.10
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 27
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x85 EP 5 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0010 1x 16 bytes
bInterval 4
と出た。
X Windowで使用できるようにする。
なまいきに ツインヘッド(ディスプレイ 2つ)として使用できる。
X windowを終了して、root 権限で、
/etc/X11/xorg.conf (無なければ新規作成) に、下記のように書く。
/dev/fb1 などのデバイス名は、必ずチェックすべし。
通常は、HDMIコンソールが /dev/fb0 で、USB ディスプレイは、/dev/fb1になる。
しかし、コンソール無しなどとしていると、USBディスプレイが、/dev/fb0になる。
# /etc/X11/xorg.conf
Section "ServerLayout"
Identifier "default"
Screen 0 "buitlin Screen" 0 0
Screen 1 "screenUsb" Rightof "buitlin Screen"
EndSection
Section "Device"
Identifier "builtin Video Device"
Driver "fbdev"
Option "fbdev" "/dev/fb0" #通常は、HDMIコンソールが fb0
EndSection
Section "Monitor"
Identifier "Monitor0"
EndSection
Section "Screen"
Identifier "buitlin Screen"
Monitor "Monitor0"
Device "builtin Video Device"
EndSection
# USB Link
Section "Device"
Identifier "uga"
driver "fbdev"
Option "fbdev" "/dev/fb1" # デバイス名を要チェック
Option "ShadowFB" "off"
EndSection
Section "Monitor"
Identifier "monitor1"
EndSection
Section "Screen"
Identifier "screenUsb"
Device "uga"
Monitor "monitor1"
EndSection
$ startx
として、X windowを起動すると、
HDMIコンソールが X Windowのディスプレイ 0、
USBディスプレイがディスプレイ 1となる。
そして、USBディスプレイは、右側となる。
USBディスプレイは、画面が黒くなるかも知れない。
とりあえず、USBディスプレイを使用するには、
$ gnome-text-editor --display :0.1
とする。
すると、USBディスプレイに画面が出る。
X Window 純正アプリケーションであれば、
-display :0.1
という引数が有効である。
伝統的、X Window 純正アプリケーションは、
$ sudo apt-get install x11-apps
で入る。
$ xterm -display :0.1
$ oclock -display :0.1
などとして、ディスプレイ 1 の画面を使用できる。
だが、Raspberry Pi(Raspbian) 標準のデスクトップ環境(ウインドウ・マネージャ)では、
ディスプレイ 1の窓に、キーフォーカスが移らず、キー入力ができず、かなり悲しい。
(この状態で、$ fvwm -display :0.1 とすると、
ディスプレイ1 でfvwm が動作し、キーフォーカスが正常になるが、
ディスプレイ0と1で異なるウインドウ・マネージャが動作し、
非常にマニアックな使用環境となる)
X Window全体のウインドウ・マネージャに twm か、fvwm を使用すると、ちゃんと
セカンド・ディスプレイの入力窓にもキーフォーカスが移る。
そのために、
~/.xinitrc
の *最終行* に、
exec twm
か
exec fvwm
と記述する。
twm, fvwmを終了すると、X Window System 全体が終了する。
twm, fvwmは、
$ sudo apt-get install twm fvwm
で、インストールされる。
USBディスプレイを、左に置きたいときは、
Screen 1 "screenUsb" Leftof "buitlin Screen"
とする。
USBディスプレイは、描画速度は遅いが、これはコンパクトなものなので、持ち運びができる。
--
NTSC 入力を持つディスプレイでコンパクトなものがあるので、それも候補としてはアリだが、
僕の手元に、NTSCのディスプレイが無いのだった。
Raspberry Pi に Xenomai(Linux実時間拡張)を入れる
Xenomaiは、Linuxの実時間拡張。
http://www.xenomai.org/
Xenomai を、Raspberry Pi に入れた。
Xenomaiは、Linux kernel(と、Makefile)に若干のパッチを当てる。
よって、Xenomaiが対応しているバージョンの kernel しか使えないのが、
やや残念。
現在の Raspbian は、kernel 3.6.11。
Xenomai 対応の最新は、kernel 3.5.7。
やや古いが、ま、ええやろ。
少し前、kernel 3.5.7 用のパッチは、3.5.7 kernelに当てると、少し失敗した。
しかし、今は、そのパッチに fix 版がでて、極めて簡単に動かせるようになった。
(私は、少し前に、色んなバージョンのxenomai+LinuxKernelでトライして、苦労した)
Linux+xenomai のソースツリーは、raspi と x86機の両方にあると、便利。
そして、それらのパスは、両マシンで、完全に一致させるべき。
(パスが、完全に一致していないと、数々の、非常に面倒くさいことが発生する)
以下は、kernel 3.5.7 を Xenomai 付きにして、raspberry Piで動かす方法
まず、普通に 通常kernelをmakeしてみる
kernel のコンパイルは、x86 マシンで、クロス・コンパイルする。
開発ツールをゲットする。
x86% git clone https://github.com/raspberrypi/tools
tools-master.zipというファイルが得られる。
それを、x86マシンの /opt/arm-tools/ に展開。
x86% sudo tcsh
x86# mkdir -p /opt/arm-tools/
x86# cd /opt/arm-tools/
x86# unzip /tmp/tools-master.zip
ツールの準備は以上
Linux kernelの取得
x86% mkdir -p raspi/src/linux-xenomai/
x86% cd raspi/src/linux-xenomai/
x86% wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.5.7.tar.bz2
x86% tar xvjf linux-3.5.7.tar.bz2
kernelを make するには、参考になる config ファイルがあった方が良い。
以下の、方法で、動作中のraspiから、configを得てみる。
ただし、kernelのバージョンが異なっているので、まったく適切なものが得られるとは限らない。
raspi% zcat /proc/config.gz > /tmp/raspi-kern-config
raspi% scp /tmp/raspi-kern-config x86:raspi/src/linux-xenomai/linux-3.5.7
x86% cd raspi/src/linux-xenomai/linux-3.5.7
x86% mv raspi-kern-config .config
次の様な shell script を、用意する。
-- raspi/src/linux-xenomai/make-menuconfig.sh
#! /bin/bash
# setup kernel-config
CCPREFIX=/opt/arm-tools/tools-master/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
ARCH=arm CROSS_COMPILE=${CCPREFIX} make menuconfig
--
-- raspi/src/linux-xenomai/make-do.sh
# make
date
CCPREFIX=/opt/arm-tools/tools-master/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
ARCH=arm CROSS_COMPILE=${CCPREFIX} make -j 4
date
--
上記の make -j 4 の数値は、並列に make を実行する指定である。
使用する x86機のコア数に応じて、適切に設定すると、make を早く終えることができる。
kernelのコンパイルの準備
x86% cd raspi/src/linux-xenomai/linux-3.5.7
x86% make mrproper
x86% sh ../make-menuconfig.sh
コンフィギュレーションをいじり、exit
x86% sh ../make-do.sh |& tee make-log
x86機の速さによるが、10分~30分程度で、make が終了するであろう。
makeが終了すると、
arch/arm/boot/ に
zImage
ができる
Raspberry Piに、新kernel, moduleなどを持っていく。
1)moduleを集める
shell変数 MODULES_TEMP に固めるディレクトリ(../newlinux/)を指定
x86% bash
x86$ mkdir -p ../newlinux
x86$ MODULES_TEMP= ../newlinux/modules
x86$ ARCH=arm CROSS_COMPILE=${CCPREFIX} INSTALL_MOD_PATH=${MODULES_TEMP} make modules_install
2)kernelもコピー
x86$ cp arch/arm/boot/zImage ../newlinux/
x86$ cd ..
x86$ tar cvJf newlinux.tar.xz newlinux
x86$ scp newlinux.tar.xz raspi:~/tmp/
Raspberry Piで kernel, module など配置
1) 新kernelを、/bootにコピー
raspi% cd ~/tmp
raspi% tar xvJf newlinux.tar.xz
raspi% cd newlinux
raspi% sudo bash
raspi# cp zImage /boot/kernel_new.img
raspiの /boot/config.txt を編集し、kernel=kernel_new.img
を追加。
(kernel= 指定がすでに存在していたら、そのエントリは、コメントにする)
2) moduleの配置
raspi# cd modules/lib/modules
raspi# mv 3.5.7 /lib/modules/
以上で、準備完了
新 kernel で再起動
raspi# sync;sync;sync
raspi# reboot
起動が終わったら、ログインして、uname を実行し、kernelを確かめる
raspi% uname -a
Linux raspi 3.5.7 #5 PREEMPT Fri Jul 26 11:45:30 JST 2013 armv6l GNU/Linux
Xenomai を入れる。
kernel 3.5.7 に対応するのは、 xenomai 2.6.2.1 である。
xenomai 2.6.2.1 と、Raspi用パッチを入手する。
x86% cd raspi/src/linux-xenomai/
x86% wget http://download.gna.org/xenomai/stable/xenomai-2.6.2.1.tar.bz2
x86% wget https://raw.github.com/TinHead/raspberry-xenomai-stuff/master/ipipe-core-3.5.7-raspberry-post-fixed.patch
x86% bash
x86$ tar xvjf xenomai-2.6.2.1.tar.bz2
x86$ xenomai-2.6.2.1/scripts/prepare-kernel.sh --verbose --arch=arm --adeos=xenomai-2.6.2.1/ksrc/arch/arm/patches/ipipe-core-3.5.7-arm-3.patch --linux=linux-3.5.7
x86$ cd linux-3.5.7
x86$ patch -p1 < ../ipipe-core-3.5.7-raspberry-post-fixed.patch
kernel のコンフィギュレーションをする。
x86$ sh ../make-menuconfig.sh
menuconfig で、
a)
"Kernel Features"で
"Interrupt pipeline" を生かす。
b)
"Kernel Features" -> "Preemption Model" で
"Preemptible Kernel (Low-Latency Desktop)" を選択
c)
"Real-time sub-system" で
"Xenomai" を生かす。
"Nucleus" を生かす。
d)
"Real-time sub-system" -> "Interfaces"で
"Native API"などを生かす。
menuconfig を終了する。
.config の内容を確認。
--
# CONFIG_NO_HZ
# CONFIG_CC_STACKPROTECTOR
# XENO_OPT_STATS
# CONFIG_CC_STACKPROTECTOR
--
上記 4つが、生かされていないことを確認する。
kernel をmake
x86$ sh ../make-do.sh |& tee make-xeno-log
kernelができたら、通常kernelの時と同様の手順で、実機に送り、
新kernel, moduleを配置する。
raspi の /boot/config.txt の kernel= に新kernelを設定する。
raspi を reboot する。
raspi が新kernelで起動したら、uname -a で、kernelのバージョンを確認する。
raspi% uname -a
Linux nana 3.5.7-xenomai-take #4 PREEMPT Thu Jul 25 04:19:28 JST 2013 armv6l GNU/Linux
(上記は、menuconfigで、"local version"の文字列に "-xenomai-take" を入れたもの)
そして、dmesgを確認する。
raspe% dmesg|less
下記のようなメッセージで、I-pipe が起動していることを確認する。
[ 0.000000] I-pipe, 250.000 MHz clocksource
[ 0.000000] Interrupt pipeline (release #3)
下記のようなメッセージで、Xenomai と Nucleus が起動していることを確認する。
[ 1.142057] I-pipe: head domain Xenomai registered.
[ 1.147008] Xenomai: hal/arm started.
[ 1.150845] Xenomai: scheduling class idle registered.
[ 1.156009] Xenomai: scheduling class rt registered.
[ 1.166183] Xenomai: real-time nucleus v2.6.2.1 (Day At The Beach) loaded.
上記が確認できれば、Xenomai は動作開始している。
Xenomaiのユーザランド・コマンドは Raspiで、セルフ・コンパイルする。
raspi上のソースツリーは、x86 のソースツリーとまったく同じパスに置くべし。
ソースツリーのコピー方法は色々あるが、
例えば、
x86$ cd raspi/src/
x86$ tar cjf - linux-xenomai | ssh raspi 'cd raspi/src/; tar xvjf -'
とやると、メディアが不要で、体も動かさなくてよい。
以下、Raspberry Piでの作業。
Xenomaiのユーザランド・コマンドを make & install
raspi$ cd raspi/src/linux-xenomai/xenomai-2.6.2.1/
raspi$ ./configure CFLAGS="-march=armv6" LDFLAGS="-march=armv6" --prefix=/opt/xenomai
raspi$ make
raspi$ sudo bash
raspi# make install
一般に、xenomai の管理は、root 権限で行う。
とりあえずのテストを行う。
ローダブル・モジュールを、読み込んでおく。
(当然ながら、menuconfigで選択したskin(API)のみしか、存在しない)
raspi# modprobe xeno_switchtest
raspi# modprobe xeno_posix
raspi# modprobe xeno_rtdm
raspi# modprobe xeno_native
テスト開始
raspi# /opt/xenomai/bin/latency -p 100 -T 60
== Sampling period: 100 us
== Test mode: periodic user-mode task
== All results in microseconds
warming up...
RTT| 00:00:01 (periodic user-mode task, 100 us period, priority 99)
RTH|----lat min|----lat avg|----lat max|-overrun|---msw|---lat best|--lat worst
RTD| -5.444| -4.004| 12.728| 0| 0| -5.444| 12.728
RTD| -5.480| -3.852| 13.728| 0| 0| -5.480| 13.728
RTD| -5.476| -3.936| 13.280| 0| 0| -5.480| 13.728
RTD| -5.440| -3.936| 13.960| 0| 0| -5.480| 13.960
RTD| -5.592| -3.956| 11.608| 0| 0| -5.592| 13.960
:
と動き出せば、大丈夫である。
raspi# /opt/xenomai/bin/xeno-test
xeno-test を実行するには、login shellが bsh系(/bin/sh, bash)であった方が楽。
csh系を login shell にしている人は、
raspi% bash
raspi$ SEHLL=/bin/bash
raspi$ sh /opt/xenomai/bin/xeno-test
という風にしなければならない。
(xenomaiの shell script は、面白すぎて、ちょっと腹が立つ)
xenomai-2.6.2.1/examples/
の中に、テストに使用できる、例がある。
それらも、実行してみると良いだろう。
examplesのmakeは…
raspi$ XENO=/opt/xenomai ARCH=arm make
などとしなければならない。
Raspberry Piで、OpenCV タンク(自走式)を作る
OpenCVタンク
Raspberry Piを脳みそに、自走する機械を作った。
人間の顔を認識し、その顔に狙いを付け、
その後、顔の大きさが適切になるまで、前進/後進を行う。
OpenCVが動作しているので、非常に、極めて簡単にできた。
ちなみに、これが、Raspiで、OpenCVを試した日記
できあがりは、こんな感じ。
搭載してあるものは
ロジック回路の電源は、外部からケーブルで、5V を供給している。
ロジック回路の電源も、モータと同じ電池から、取ってもいいのだが…
現在は、電池の消耗具合が不明なので、とりあえず、外部電源。
土台になっている、シャーシは、タミヤの楽しい工作シリーズ No.104のブルドーザ。
ちなみに、このセットのリモコンは、バネの力で、中立に戻ったりして、なかなかいい感じだ。
僕が子供の時の、タミヤ製 1/35 タイガーI型のリモコンよりかなりいいぞ。
近頃は、ロボットを動かすのに、ステッピング・モータや、サーボ・モータを使う人が多いようだ。
しかし、あたしは、DCモータでやりたかった。
DCモータには、ノイズキラー・コンデンサを付ける。模型小僧の基本である。
DCモータ・ドライバの基板は、Raspi用に丁度いいものがあった。
https://www.sparkfun.com/products/11561
Sparkfun Electronics社の その名も「RaspiRobot Board, KIT-11561」!
「Raspiロボット・ボード」とは、よう言うたっ!!! (厚かましいぞwww)
スイッチサイエンスの通販で、¥3,294円。
このボードは、
DCモータ・ドライバIC L293DNEと、7406(オープン・コレクタ高耐圧バッファ)を使用し、
Raspiの GPIO に7406やL293DNEを接続しているだけのシンプルで
オーソドックスな基板となっている。
諸元としては、
このロボット・ボードは、設計としては、電源として、6~10V程度を入力すると、レギュレータで電圧を降圧したのち、
Raspi本体にも電源供給をするようになっている。
しかし、本機のように、USBからの流れ出しが多いシステムでは、このボードのオマケの軟弱なレギュレータでは、
電流が足りない。
したがって、現在、僕は、3端子レギュレータは使用してない。
そして、モータ用の電源と、ロジックの電源を分けている。ロジック電源の方には、電解コンデンサを増量している。
どうも、Sparkfun社のボードは、電源回りの考えが変だ。
以前も、Arduino 用の USBホスト・シールド も、電源の取り回しで、細工をせざるを得なかった。
(この方のやりかたを、真似たのだった。)
電源以外は、まぁ、満足できるので、いいのだが。
このボードを Raspi に装着すると、通常の Raspi のケースには入らない。
というか、割と嫌な感じではみ出す。まぁ、いいんだけど…
本システムの構成は、下図のとおり。
Raspi単体で、顔認識して、どう動くかを考え、モータも制御する。
認識結果の表示のためだけに、WiFi で、PCと通信し、
X protocol over ssh で、認識結果を PC上の X サーバに表示する。
結果表示が不要であれば、WiFiもPCも不要で、完全に単独で走行する。
ソフトウェアは、
人間の顔を見つけたら、
顔の位置が、認識対象の視野の中央に来るように、
右へ旋回/左へ旋回を決める。
顔の位置がセンターであれば、認識された顔の大きさをみて、
ちょうどいいサイズになるまで、前進/後進を行う。
カメラ入力の処理、顔認識、認識結果の表示は、すべてOpenCVの
機能を使用している。
極めて、簡単なソースコードでできている。
モータの制御は、ロボット・ボードのサンプルとして与えられた
プログラムを適当に変更している。
Raspiの GPIO のIOポートを、MMAPでユーザ空間に貼り付け、
メモリアクセスと同様に、IOポートをアクセスしている。
-- folow2.c
/* follow2
*/
#include "cv.h"
#include "highgui.h"
/*char* cascade = "/usr/share/opencv/haarcascades/haarcascade_frontalface_default.xml";*/
char* cascade = "/usr/local/opencv/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml";
#define DISP_WIN "faceDetect"
void motor_drive(int cap_width,int last_face_x,int last_face_width);
extern void turn_right();
extern void turn_left();
extern void turn_stop();
extern void turn_stopNo();
extern void motor_gpio_init();
extern void go_forward();
extern void go_back();
CvSize minsiz ={0,0};
int last_face_x, last_face_width;
int cap_width=160;
int disp_and_sleepf=0;
int
main( int argc, char** argv )
{
int i;
double w = (double)cap_width;
double h = 120;
motor_gpio_init();
cvNamedWindow( DISP_WIN , CV_WINDOW_AUTOSIZE );
CvCapture* capture = NULL;
if (argc > 1){
disp_and_sleepf=1;
}else{
}
capture = cvCreateCameraCapture( 0 );
// (2)キャプチャサイズを設定する.
cvSetCaptureProperty (capture, CV_CAP_PROP_FRAME_WIDTH, w);
cvSetCaptureProperty (capture, CV_CAP_PROP_FRAME_HEIGHT, h);
IplImage* frame;
// 正面顔検出器の読み込み
CvHaarClassifierCascade* cvHCC = (CvHaarClassifierCascade*)cvLoad(cascade, NULL,NULL,NULL);
// 検出に必要なメモリストレージを用意する
CvMemStorage* cvMStr = cvCreateMemStorage(0);
// 検出情報を受け取るためのシーケンスを用意する
CvSeq* face;
while(1) {
frame = cvQueryFrame( capture );
if( !frame ) break;
// 画像中から検出対象の情報を取得する
face = cvHaarDetectObjects(frame, cvHCC, cvMStr,
1.2, 2, CV_HAAR_DO_CANNY_PRUNING,
minsiz, minsiz);
// 1.1, 3, 0, minsiz, minsiz);
//////cvHaarDetectObjects( //const CvArr* image,
for(i = 0; i < face->total; i++) {
// 検出情報から顔の位置情報を取得
CvRect* faceRect = (CvRect*)cvGetSeqElem(face, i);
// 取得した顔の位置情報に基づき、矩形描画を行う
cvRectangle(frame,
cvPoint(faceRect->x, faceRect->y),
cvPoint(faceRect->x + faceRect->width,
faceRect->y + faceRect->height),
CV_RGB(255, 0 ,0),
2, CV_AA, 0);
last_face_x=(int)faceRect->x;
last_face_width=(int)faceRect->width;
}
motor_drive(
(face->total <=0)? -1: cap_width,
last_face_x, last_face_width);
if(disp_and_sleepf){
cvShowImage( DISP_WIN, frame );
//char c = cvWaitKey(33);
char c = cvWaitKey(1);
if( c == 27 ) break;
}
}
// 用意したメモリストレージを解放
cvReleaseMemStorage(&cvMStr);
// カスケード識別器の解放
cvReleaseHaarClassifierCascade(&cvHCC);
cvReleaseCapture( &capture );
cvDestroyWindow( DISP_WIN );
}
#define HISTER 20
//#define HISTER 5
#define WANT_SIZE 40
#define SIZE_HISTER 5
//#define COUNT_SHIKII 30
#define COUNT_SHIKII 0
int turn_state =0;
int turn_count =0;
void
motor_drive(int cap_width,int last_face_x,int last_face_width)
{
int center = cap_width/2;
int face_x;
int new_state;
//test0();
face_x= last_face_x + (last_face_width/2);
printf(" size = %d \n", last_face_width);
/* centering */
if(cap_width <0){
/* stop (no face)*/
turn_state =0;
turn_stopNo();
return;
}else if(face_x < (center - HISTER)){
/* turn right (man view)*/
new_state =1;
turn_state =new_state;
turn_right();
return;
}else if(face_x > (center + HISTER)){
/* turn left (man view)*/
new_state =2;
turn_state =new_state;
turn_left();
return;
}
/* size */
if(last_face_width<(WANT_SIZE -SIZE_HISTER)){
go_forward();
return;
}
if(last_face_width>(WANT_SIZE +SIZE_HISTER)){
go_back();
return;
}
/* stop (man center & good size)*/
turn_state =0;
turn_stop();
return;
}
-- motor.c
//
// How to access GPIO registers from C-code on the Raspberry-Pi
// Example program
// 15-January-2012
// Dom and Gert
// Revised: 15-Feb-2013
// Access from ARM Running Linux
#define BCM2708_PERI_BASE 0x20000000
#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */
#include
#include
#include
#include
#include
#define PAGE_SIZE (4*1024)
#define BLOCK_SIZE (4*1024)
int mem_fd;
void *gpio_map;
// I/O access
volatile unsigned *gpio;
// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3))
#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
#define GPIO_SET *(gpio+7) // sets bits which are 1 ignores bits which are 0
#define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0
#define SET_OUT_MODE(g) { INP_GPIO(g); OUT_GPIO(g);}
void setup_io();
void turn_right();
void turn_left();
void turn_stop();
void motor_gpio_init();
void init_sign_led();
void led1(int);
void led2(int);
// Set GPIO pins 7-11 to output
//int main(int argc, char **argv)
void
motor_gpio_init()
{
int g;
// Set up gpi pointer for direct register access
setup_io();
// Switch GPIO 7..11 to output mode
/************************************************************************\
* You are about to change the GPIO settings of your computer. *
* Mess this up and it will stop working! *
* It might be a good idea to 'sync' before running this program *
* so at least you still have your code changes written to the SD-card! *
\************************************************************************/
// Set GPIO pins 7,8,21,22, 17,4,25 to output
SET_OUT_MODE(7); // LED1
SET_OUT_MODE(8); // LED2
SET_OUT_MODE(21); //OC output
SET_OUT_MODE(22);
SET_OUT_MODE(17); //Motor
SET_OUT_MODE(4);
SET_OUT_MODE(10);
SET_OUT_MODE(25);
GPIO_CLR = 1<<(17); // 1-2EN OFF
GPIO_CLR = 1<<(10); // 3-4EN OFF
GPIO_CLR = 1<<(4); // 1A OFF
GPIO_CLR = 1<<(25); // 3A OFF
init_sign_led();
return ;
}
void
init_sign_led()
{int i;
for(i=0;i<3;i++){
led1(1);led2(1);
sleep(1);
led1(0);led2(0);
sleep(1);
}
}
void
test0()
{
int g,rep;
GPIO_CLR = 1<<(10); // 3-4EN OFF
GPIO_SET = 1<<(17); // 1-2EN ON
GPIO_SET = 1<<7; //LED1
GPIO_SET = 1<<(4); // 1A ON
sleep(3);
GPIO_CLR = 1<<7; //LED1 OFF
GPIO_CLR = 1<<(4); // 1A OFF
sleep(3);
/*--*/
GPIO_CLR = 1<<(17); // 1-2EN OFF
GPIO_SET = 1<<(10); // 3-4EN ON
GPIO_SET = 1<<8; //LED2
GPIO_SET = 1<<(25); // 3A ON
sleep(3);
GPIO_CLR = 1<<8; //LED2 OFF
GPIO_CLR = 1<<(25); // 3A OFF
sleep(3);
}
void
test1()
{
int g,rep;
for(rep=0; rep<10; rep++) {
test0();
}
return ;
}
#define MOTOR_ON_TIME 30000
void
go_forward()
{
printf("forward()\n");
GPIO_SET = 1<<7; //LED1
GPIO_SET = 1<<8; //LED2
GPIO_CLR = 1<<(17); // 1-2EN OFF
GPIO_CLR = 1<<(10); // 3-4EN OFF
GPIO_CLR = 1<<(4); // 1A OFF
GPIO_CLR = 1<<(25); // 3A OFF
GPIO_SET = 1<<(17); // 1-2EN ON
GPIO_SET = 1<<(10); // 3-4EN ON
usleep(MOTOR_ON_TIME);
GPIO_CLR = 1<<(17); // 1-2EN OFF
GPIO_CLR = 1<<(10); // 3-4EN OFF
}
void
go_back()
{
printf("back()\n");
GPIO_SET = 1<<7; //LED1
GPIO_SET = 1<<8; //LED2
GPIO_CLR = 1<<(17); // 1-2EN OFF
GPIO_CLR = 1<<(10); // 3-4EN OFF
GPIO_SET = 1<<(4); // 1A ON
GPIO_SET = 1<<(25); // 3A ON
GPIO_SET = 1<<(17); // 1-2EN ON
GPIO_SET = 1<<(10); // 3-4EN ON
usleep(MOTOR_ON_TIME);
GPIO_CLR = 1<<(17); // 1-2EN OFF
GPIO_CLR = 1<<(10); // 3-4EN OFF
}
void
turn_right()
{
printf("turn_right()\n");
GPIO_SET = 1<<7; //LED1
GPIO_CLR = 1<<8; //LED2
GPIO_CLR = 1<<(17); // 1-2EN OFF
GPIO_CLR = 1<<(10); // 3-4EN OFF
GPIO_SET = 1<<(4); // 1A ON
GPIO_CLR = 1<<(25); // 3A OFF
GPIO_SET = 1<<(17); // 1-2EN ON
GPIO_SET = 1<<(10); // 3-4EN ON
usleep(MOTOR_ON_TIME);
GPIO_CLR = 1<<(17); // 1-2EN OFF
GPIO_CLR = 1<<(10); // 3-4EN OFF
}
void
turn_left()
{
printf("turn_left()\n");
GPIO_CLR = 1<<7; //LED1
GPIO_SET = 1<<8; //LED2
GPIO_CLR = 1<<(17); // 1-2EN OFF
GPIO_CLR = 1<<(10); // 3-4EN OFF
GPIO_CLR = 1<<(4); // 1A OFF
GPIO_SET = 1<<(25); // 3A ON
GPIO_SET = 1<<(17); // 1-2EN ON
GPIO_SET = 1<<(10); // 3-4EN ON
usleep(MOTOR_ON_TIME);
GPIO_CLR = 1<<(17); // 1-2EN OFF
GPIO_CLR = 1<<(10); // 3-4EN OFF
}
void
turn_stop()
{
printf("turn_stop()\n");
GPIO_SET = 1<<7; //LED1
GPIO_SET = 1<<8; //LED2
GPIO_CLR = 1<<(17); // 1-2EN OFF
GPIO_CLR = 1<<(10); // 3-4EN OFF
}
void
turn_stopNo()
{
printf("turn_stop()\n");
GPIO_CLR = 1<<7; //LED1
GPIO_CLR = 1<<8; //LED2
GPIO_CLR = 1<<(17); // 1-2EN OFF
GPIO_CLR = 1<<(10); // 3-4EN OFF
}
void
led1(int x)
{
if(x){
GPIO_SET = 1 <<7; //LED1
}else{
GPIO_CLR = 1 <<7; //LED1
}
}
void
led2(int x)
{
if(x){
GPIO_SET = 1 <<8; //LED2
}else{
GPIO_CLR = 1 <<8; //LED2
}
}
//
// Set up a memory regions to access GPIO
//
void setup_io()
{
/* open /dev/mem */
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
printf("can't open /dev/mem \n");
exit(-1);
}
/* mmap GPIO */
gpio_map = mmap(
NULL, //Any adddress in our space will do
BLOCK_SIZE, //Map length
PROT_READ|PROT_WRITE,// Enable reading & writting to mapped memory
MAP_SHARED, //Shared with other processes
mem_fd, //File to map
GPIO_BASE //Offset to GPIO peripheral
);
close(mem_fd); //No need to keep mem_fd open after mmap
if (gpio_map == MAP_FAILED) {
printf("mmap error %d\n", (int)gpio_map);//errno also set!
exit(-1);
}
// Always use volatile pointer!
gpio = (volatile unsigned *)gpio_map;
} // setup_io
-- Makefile
ALL= follow follow2
CXX = g++
# package openCV
LDFLAGS = -lopencv_legacy -lopencv_highgui -lopencv_core -lopencv_ml -lopencv_video -lopencv_imgproc -lopencv_calib3d -lopencv_objdetect -L/usr/lib
CPPFLAGS = -mfpu=vfpv3 -O4 -I/usr/include/opencv -I/usr/include/opencv2
##CPPFLAGS = -g -I/usr/include/opencv -I/usr/include/opencv2
all: $(ALL)
follow2 : follow2.o motor.o
$(CXX) -o $@ $< $(LDFLAGS) motor.o
follow2.o : follow2.c
$(CXX) -c $< $(CPPFLAGS)
follow : follow.o motor.o
$(CXX) -o $@ $< $(LDFLAGS) motor.o
follow.o : follow.c
$(CXX) -c $< $(CPPFLAGS)
motor.o : motor.c
$(CXX) -c $< $(CPPFLAGS)
clean:
rm -f $(ALL) *.o
110円のARM Cortex-M0(LPC1114)で遊ぶ
世間で 110円の ARM が騒がれていた。
この夏に、生まれて初めて、京都寺町のマルツに行って、なんだか変なテンションで 110円の ARM, LPC1114FN28 を買ってしまった。
でかい28ピン・パッケージが、UV-PROMとか 8228(8080用のバスドライバLSI)を思い出して、懐かしい。
安心できるね。(^^)
LPC1114FN28 の諸元は、
● ARM Cortex-M0搭載 低消費・高性能32-bitマイコン
● 50MHz クロックスピード (最大)
● Flash:32KB
● RAM:4KB
● RCオシレータ: 12MHz, 1%精度
ということで、Z80世代からすると、超絶に速い 1chip マイコン。
(PIC32 MIPSコアも楽しいが)
開発環境を全部Linux(IDEは一切無し)にして、
LEDチカチカ, UART が動いた。
ついでに、BASICインタープリタも動いた… (マルチスレッド版は、RAMの使い方を調整すべき)
(2013/SEP/07 追記: マルチスレッド Tiny BASICも動作した。とても安定している)
コンパイラは、
https://launchpad.net/gcc-arm-embedded/
から得た。
(他のコンパイラだと、ランタイム・ルーチンに、Cortex-M0用の除算ルーチンが入ってなかったりして困った)
LPC1114 への書き込みは、シリアル・ポートで行える。
pin15: RXD
pin16: TXD
となっている。(わたくしは、いつもどおり、 FT232の秋月基板 を接続した)
LPC1114 内臓ROMへの書き込みシーケンスの起動は、
pin24をGNDに落としながら、RESETする。
書き込みプログラムは、「lpc21isp」を使用。
http://sourceforge.net/projects/lpc21isp/
lpc21ispは、簡単に make できる。バイナリができたら、
# lpc21isp -hex 対象hexファイル /dev/ttyUSB0 115200 12000
てな感じで書き込める。
ROMへの書き込みが終わったら、RESETをする方が安心です。
UART 9600bps で、エコー(小文字 <-> 大文字 入れ替え加工) するプログラムを大公開。www
一文字受け取るたびに、LEDのON/OFFが反転します。
lpc1114-led2-take.tgz.130905b
スタック・ポインタは、例外ベクタの近所に初期値を書いておくと、自動的にロードされる。
LPC11xx_handlers.c と lpc1xxx/linkscript.ld の __stack_end を参照。
クロックは、LPC1114 内臓の発信器を使用。
電源もいつもの通り、 FT232の秋月基板 から 3.3V を頂いている。
RESETまわりには、チャタリング除去も、パワーオン・リセットも無い。書き込みと実験ができればいいのだ。
基板を小さく作ったので、在来線の電車の中でも書き込み&Goができて、とても楽しい (^^;
RAMが4KBなのは、アホなことをするには、なかなか厳しいが、USB I/Fとか入っていないので、まぁ、こんなものか…
でも、BASICインタープリタは動くので、整数電卓には使える。(そんなもの要らないwww)
LPC1114などで、再利用可能なコードを提供してくれている、素晴らしいサイト。
ライセンスは、BSD ! \(^^)/
microBuilder.eu
http://www.microbuilder.eu/Projects/LPC1114ReferenceDesign/LPC1114CodeBase.aspx
極小Lispマシン 作り :-P :-)
これは、Lisp Advent Calendar 2013 のDEC/05 です。
1981年だか82年だか、僕の居た大学のコンピュータクラブで、Lispを作るのが流行った。
5人ぐらいで、バラバラに オレオレLisp を作った。
Lispというものは、readerがもっとも難しいと思う。
昔風の eval は、すぐにできる気がする。
gcは、なかなかバグが取れない。C言語で書くと、Cのローカル変数や、Cのスタックに生きてるconsへのポインタが乗るが、そこはスキャンできなかったりするのが、主な原因だろう。
当時、あたくしは、BASICでLispを書いていた。
8bit機である。私は6809@1MHz の載ったBASIC Master Level3 を使っていた。
RAMは、8~48KBytes ぐらいの機械が普通だった。
BASIC master Level3は、30万円ぐらいして、5inch 片面フロッピ・ドライブとそのI/Fカードが35万円ぐらいした気がする…
さて、現在…
32bit MIPS core のPIC32が200円程度である。
PIC32MX220は、ROM:32K Bytes, RAM:8K Bytes を内蔵。
クロック周波数は40MHzで、1.56 DhrystoneMIPS。
ARM Cortex-M0 CoreのLPC1114が110円程度である。
LPC1114FN28 は、ROM:32K Bytes, RAM:4K Bytes
クロック周波数は50MHz(最大),内臓CR発信器で12MHzで使用。
32bit Coreで、40MHz って、なんぼほど速いねん!?!
RAMも4KB あれば、なんでも(?)できるぜっ。(そうか?)
そこで、極小 Lispマシンをつくろう、と思い立ったです。
BASIC インタープリタも動くんですけど、Lispインタープリタも動く。
(Flash ROMは、焼き直す)
Lisp処理系の名前「Lise:the Lisp Engine」というのは、冒頭の1981年頃の オレオレLispに付けた名前。
当時から リーゼ(liese)というシャンプー があり、その名前にインスパイアされ、Liseという女の子の名前にした。(爆笑)
まず、PIC32のマシン
PIC32の方は、液晶は Aitendo で買った 白黒の FSTN グラフィック液晶
FSTN液晶モジュール(128×64/SPI)[AD-12864-SPI]
これを、PIC32のGPIOにつないで、ソフトウェアでGPIOを制御し、SPI 的なタイミングで、コマンドを書き込む。
液晶のつなぎやすさのみを優先し、GPIOのピンを選択。
CPUチップの他には、コンデンサしか載っていない。可変抵抗は、LCDのバックライトの明るさ調整。
ネットに、8x5 ドットのフォントが落ちていたので、とりあえず、それを入れて、文字表示を行う。
(こういう液晶は、縦8ドットを1ワードとしてアクセスする。縦8ドットのフォントは、使いやすい。
当然、液晶を90°回転させた状態でマウントするなら、縦横は入れ替わるが…)
極小マシンに、キーボードは付けられないのでスイッチを何個にするか考える。
ゲームボーイ配列が面白いだろう、と、思って作ったが…
完成品を、@zick_minoh の後輩(僕の後輩でもある)の学生に見せたところ、
「だいぶ前に、zickさんが、ポケステで動かしてたのと同じですか?」と素直に言われて、驚いた。
そういえば、そんなのあったなぁ…
たぶん、以前に見た このポケステLispに、発想が引っ張られてしまったんだろうなぁ。
うーん、つまらない。
しかし、筐体を、100円ショップで売られている画鋲のケースにしたり、それにアロンアルファでスイッチを付けたり、結構、苦労しているのだ。
大体においては、ちびマシンは、入れ物が大事なのである。
だらだらした動画(無音)をあげました(2013/DEC/11)
zick君の ポケステLisp
ポケステでLispインタプリタ動かしてみた
ポケステでLispインタプリタ動かしてみた on ニコ動
ポケステは、RAMが2KBか、頑張ってるなぁ…
でも、zickは、入力補助が「コンプリーション」とか言ってるな。
こちらは、上ボタンを押すと、シンボルテーブルから、シンボルを取ってきて、入力候補にするぞ。
一回入力したシンボルは、シンボルテーブルにあるし、コンプリーションより楽なはず。
アプリケーションごとに、リセットすると、シンボルテーブルが肥大化せず、割と入力が楽。
ニュートラル状態から、下ボタン押下は、通常の1文字が候補に出る。
() '\177?+-*/0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~
という順序で候補文字が出る。
スイッチ入力と並行して、シリアル・ラインからの文字入力も受け付ける。
液晶に表示される8x5ドットの文字は、極小過ぎて、オジサンには極めて読みづらい。
なので、通常は、シリアルラインから入力して、楽しむ。(^^;
表示は、液晶とシリアルラインに同じものが出力される。
free cell(利用可能なcons cell)は、800個程度あり、まぁまぁ実用的。
液晶無しの回路図などは、 過去のブログで
ARM LPC1114 のマシンは、液晶はつないでいるが、入力はシリアルラインのみ。
液晶には、Lispプログラムから自由に表示できる。
筐体になるケースとか、入力方法を検討中。
ポケステLispの轍は踏むまい。www
こちらは、4KBしかメモリがないので、
free cell(使用可能なcons)は、39個。
これでは、デモ以外、何もできない。
まぁ、そういうもんだ。\(^^;/
この機械の液晶は、Aitendoで売られている下記
ノキア液晶5110(SPI)[M-LCD5110-PCB]
以前は、基板と液晶がバラになってて、500円ぐらいのものが売られており、僕はそれを買って使用。
液晶無しの回路図などは、 過去のブログで
今回の処理系は、生のポインタを使用しない。
メモリが少ないのに、32bitのポインタを使用すると非常に非効率である。
なので、consは、C言語の配列上に取る。
consのcar,cdrには、配列のオフセットを入れて表現。
オフセットは、unsigned short (16bit)。
tag を3bitにして、オフセット(ポインタ)の最上位3bitに入れている。
シンボルテーブルは、現在は、consとは別な領域に取っている。
fix num(小さな整数)が、13bitなので、符号付きで -4096~ +4095 しか表現できず、
すぐにオーバーフローして、やや辛い。
小規模組込用途で、使えるような、使えないような、ぎりぎりの線上。(^^;
appendできます
Lise>>(set! ap (lambda(x y) (cond ((eq? x nil) y)(#t (cons(car x)(ap(cdr x) y))))))
closure-40FC
Lise>>(ap '(a b) '(z x))
gc (a b z x )
Lise>>
クロージャなんぞも、一応ちゃんとつけてある。
Lise>>(set! aaa (let (z) (set! z 0) (lambda (x) (set! z (cons x z)))))
closure-421C
Lise>>(aaa 'asd)
gc (asd .0)
Lise>>(aaa 'asd)
(asd asd .0)
Lise>>(aaa 'asd)
(asd asd asd .0)
Lise>>(aaa 'asd)
(asd asd asd asd .0)
Lise>>(aaa 'asd)
(asd asd asd asd asd .0)
Lise>>(aaa 'asd)
(asd asd asd asd asd asd .0)
Lise>>(aaa 'asd)
gc (asd asd asd asd asd asd asd .0)
Lise>>z
NIL
Lise>>
最後に、z を見ているのは、グローバルな変数zに (asd asd asd asd asd asd asd .0)
が入っていないことを確認している。
ちなみに、Scheme風のシンボル名を使っているが、継続が無いので、ただの昔Lisp。
お粗末。
Robot言語インタープリタ
これは、 カーネル/VM Advent Calendar 2013 の DEC/21 です。
とりあえず、書きかけで公開 (^^;
いにしえ(1977年発表)の言語として Robot言語 というものがあり。
PCが普及しておらず、グラフィック機能が珍しいときに、出た言語。
しいて関数型と言えば関数型だが、変数が一つしかなく、極めて限定された言語。
リカーシブ・コールが前提。
なので、ループも、リカーシブに記述。
ループをリカーシブに書くということは、インタープリタは、テールリカーシブ・インタープリタであって欲しい。
Robot言語は、極めて単純な言語なので、実行系をテールリカーシブ・インタープリタとして実現するのは、容易である。
私が、大昔に、Mac用にCで書いたものがあるはずだが、ソースごと失った。
ケータイ用のJavaの出始め("KVM"と呼ばれた) に、KVM用に書いたソースは、いまだに公開中。
Krobot として公開中。
このソースは、素朴な仮想機械のインタープリタである。
と見せかけて、関数呼び出しの部分が、テールリカーシブ・インタープリタになっている。
そこだけ、解説をしたい…
… といいつつ、とりあえず、ここまでで公開。(^^;
すんません > 世界
オーディオ遊び(その1)
わたくしは、ラジオ小僧でありながら、子供のころからオーディオというものは触らないようにしてきた。
オーディオって、お金かかりそうだもん、というのが理由。
あれこれ聴くと、迷いが出そうなので、あれこれ聴いたことがない。
本当のお家(?)では、昔(1990年ごろ)に、買った、
「テクニクス」のTechnics SE-M100 デジタルストレートアンプ
を、今も使ってます。
この SE-M100 は、1990年ごろ、「テクニクス」のブランドが廃止になり「テクニクス」ブランドの製品が安売りされているときに、新品を3万円ぐらいで買った。
(後に、「テクニクス」ブランドが復活するとは、アレですな~)
SE-M100は、最終段のDACがそのまま出力になり、
それまでの前段はすべてデジタルという、変わった(?)アンプ。
色の付きようがない構成。
同時期に、 JBL Contol-One
を買って、SE-M100につないで、CDばっかり聴いてた。
このほど、安くてまぁまぁなスピーカを求めて、ネット徘徊したら、
なんと、24年位前に、なにげなく買った JBL Contol-One が、不朽の名機として、好評ではないか。
IT Media: 定番スピーカーはどう変わった? JBL「CONTROL ONE」を聴く
ということで、また、 JBL Contol-One を買ってしまった。
昔のモデルは、エンブレムのバッジがオレンジ色だったのが、
新型は、白になってる。
オーディオ遊び(その2)
オーディオに触れないようにしてきて、あれこれ聴いたことがないわたくし…
本当のお家(?)では、昔(1990年ごろ)に、買った
「テクニクス」のTechnics SE-M100 デジタルストレートアンプ に、
JBL Control One という構成
詳しくは、この日記にあり。
正月休みに、退屈過ぎ、東京の下宿にはまったくオーディオが無いのも寂しくなった。
(PCと安物のアンプ付きスピーカでネットラジオを聴いているだけだった。それでもまぁいいのだけど)
オーディオをなんとかしよう、と思い立つ。
そういえば、お友達の暇村さんが、楽しそうに、秋月のUSB DAC を作って、日経Linuxでも記事 を書いておられたなぁ。
暇村さんのUSB DAC 製作詳細
その流れで、OSSコンソーシアム 組込み部会 女子部で、秋月 USB-DAC製作会 もやったなぁ。(私は主催者の一員なのだが、残念ながら、日程が合わず、欠席)
秋月USB-DACは、ネット上でも評判いいんだなぁ、知らなかった…
というわけで、
秋月のUSB DAC キット は作った。
このキットは、
回路図 を見ると、
音のアナログ信号を通る所のコンデンサだけは、秋月の標準版でも、ちゃんといいコンデンサを使っている。
電源やらのコンデンサにこだわってもいいが、部品が余るのもアレなので、標準のままでいいや。
そして、ネット徘徊していると…
まともな測定器を使った人が、秋月USB-DACの出力にローパス・フィルタは入れた方がいいんじゃない と、書いているので、
そのページの最後にあった、ローパス・フィルタをそのまま作ってつないだ。
一応、ケースにも入れた。
わたしくは、金属ケースとかの加工は下手くそだし、やっぱり金属ケースは高い。
でも、シールドはしたいから、やっぱりオーディオのケースは金属ですね。
ちゃんと、ケースにアースしてます。電気の基本。
(マイコンなどは、ノイズ出しまくりOK なので、お菓子の紙の箱や、100円ショップのクリップのプラッチックの入れ物などでお気楽)
でも、アンプを作った方が楽しいんじゃね?
部品を買い集めたり、アナログ基板のことを考えるのは面倒なので、キットでいいや。
と思い、アンプ製作キットを求めて、ネット徘徊。
そこで一つ分かったことは…
完成品の中華アンプが数千円(2500円~3000円)程度で売られていて、
なんだか、それが結構いい音らしい。
(当たり前だけど)完成品なので、それなりにかっこいいケースに入ってるしな~
自分でアンプを作っても、ケースが高い。
本当のオーディオらしい高級感のあるケースは、1000円~数千円になってしまう。
スイッチとボリュームのつまみも、カッコいいのは、かなり高い。
これならば、ケースを買うつもりで、中華アンプを買ってもいいだろう、と思ってしまいました。
なので、キットで安直にアンプを作る、という夢は潰えた。
こうやって、アメリカ人も、日本製品にやられていったんだろうなぁ。
(そして、日本人は、現在、中国製品にやられつつ…)
中華アンプを調べるに…
Tripath社という半導体会社の TA2020 というチップを使ったものが、えらい安いのに、いい音が出るらしい。
Lepai社の LP2020Aというアンプが、2500円位(2014/JAN上旬 電源なし)だったので、購入を決断。
このLP2020A、トーン・コントロールという、1970年代の機能を搭載し、安い。
電源スイッチの安っぽさは、どうにかしろよ、と思うが、
フロントパネルは、工作の下手な私でも、全部作りなおせるだろう、などと、
ケースは部品取り用にも、考えつつ…
そもそも車載用らしいので、トーン・コントロールがついているらしい。
自動車というオーディオに向かない空間で、音をユーザが自分の好みに変える、というのは、健全ですな。
ただ、トーンコントロールをONにすると、音が濁るです。
トーン・コントロールのために、オペアンプが入って、そのオペアンプの色が入るんでしょね。
LP2020 参考回路図
Lepai LP2020をどこから買うか、とか、改造情報などを求めていると…
North Flat Japan というマニアックな会社が、LP2020を扱っており。
NFJ は、LP2020の別注版を作らせており、部品なども変えているらしい。
NFJのブログがおもしろい。
「ボリュームの軸がアースされてないことが発覚」とかは、ちょっと笑った。
Lepai社は、部品は安物だし、素人まるだし でおもしろい。
NFJ社の取り組みがいいので、Lepai LP2020は、
NFJ 社の LP2020 第7ロット というのを買った。
LP2020は、すぐに到着したので、 JBL Contol-One
に接続。
ちなみに、このJBL Contol-Oneは、今回、新たに買ったもの。
(スピーカの慣らし(エージング)もやりつつ聴いてみている)
1990年ごろ、なにげに買ったControl Oneが、不朽の名機になっていて驚いたですよ。 IT Media: 定番スピーカーはどう変わった? JBL「CONTROL ONE」を聴く
PCやら、Raspiやら、Cubox から、USB経由で
秋月USB-DAC(ローパスフィルタ入り)へ、その出力を
LP2020 + JBL Control One
私は、CDしか聴かなかったし、デジタル・ストレート・アンプしか聴いてないので、
偉そうに音を語る資格はないのですが…
(現在の音源は、大昔に iPod Shuffle に入れた音と、ネットラジオが主。CDが手元に無いのですなぁ)
デジタルらしい、色のついてない、
クリアでまっすぐした音だと思います。
低音から高温まで、まんべんなく出ている感じ。
(ある友人は、「低音が出てない」と言ってはりますが、私的には、ちょうどいいんじゃないかと…)
Raspberry Pi に、秋月USB-DAC, LP2020, JBL Control One。
iCatさんからお借りしている Cubox1 に、秋月USB-DAC, LP2020, JBL Control One。
PR: All Jeep Compass Fair
「舞妓はレディ」を観た
映画「舞妓はレディ」が、まわりの人に評判がいい。
なので、京都で「舞妓はレディ」を観てきた。
オードリーヘプバーンの「マイフェアレディ」のパクリ。
(あたしが割と好きな映画だ。オードリーヘプバーンが、歌が下手で口パクとかも楽しい)
日本でミュージカルとか、ようやるわ。
悪くはなかったが… 歌わなくても、ストーリー持つやろ。
とはいえ、私には、真ん中あたりが、もたつき感があり、寝るかと思たわ。
「京都で、雨は、だいたい盆地に降る?」というのが、「スペインでは、雨は主に平地に降る」のオマージュでよろしかったなぁ。
言語の映画ということで、ちゃんと京都弁をしゃべってるかチェックや。
(あたくしは、大阪生まれの尼崎育ちやっ。京都では呑んでるだけ)
岸辺一徳は、京都の旦那とかやらせても、いつも似合ってるなぁ。そもそも京都人らしいしな。
(沢田研二も京都人やで。と書いても、そのつながりである「ザ・ タイガース」が若い人には分からんやろwww)
29歳まで舞妓(本当は舞妓は18歳まで)をやってるという役の田畑智子は、祇園の料亭の娘らしい。ドラマ「ファーストクラス」でも、怖くて上手い関西弁喋ってたし。
竹中直人は、芝居は上手いが、京都弁は残念。なんでもかんでも竹中直人を使うのは、いかがなものだろう。
言語学の先生で、どの地方の言葉でも操るという長谷川博己だが、全然、喋れてなかったで。
そこの学生で、京都のお茶屋の息子という濱田岳は、酷かった。京都弁をしゃべれる役者を使うべきやろ。
その他の脇を固めてる人は、ちゃんとした花街らしい言葉をしゃべってた。なかなかやるなー
ヒロインは、最後はちゃんと京都花街弁を喋ってた。
本物の舞妓ちゃんも、ほぼ地方出身者なので、練習すれば、普通、喋れるようになるのだろう。
「下八軒」という「上七軒」をもじった場所が舞台だが、
街のイメージは、祇園東。
ちなみに、上七軒の方が格は高いそうだが、西陣が不景気なので…
あたくしは、とても若いときに、上七軒のビアガーデンの只券を西陣の旦那からもらって、行ったきり。
舞台の街は、セットだが、「祇園東」のこのあたり をイメージして作ったと思われ。
祇園東の白川の橋のあたり。
東側に橋。西側に、小さいお堂がある。東から橋を渡ってきたら、よろしいよ。
南側の橋の辺りが、風情がある。
節分の祇園は、「おばけの日」で、コスプレするのは本当。
祇園のクラブのホステスも多少コスプレする。
(紋付で正装してはる芸子はんも居はる)
だいぶ前の節分の日に、錦の超絶に安い立ち飲み(ただし客筋はとても良い)で有名な「松川酒店」に、
友人の社長と呑みに行ったら…
芸子はんを ぎょうさん連れた旦那が呑みに来てはった。旦那は、「裸の大将」のカッコしてた。よう似合てはった(2月やのに)。
ちなみに、江戸の芸者さんと、銀座のホステスは、節分は、紋付で正装するのみらしい。
OpenEL 対応 MultiThread BASIC
OpenEL というものがあり…
OpenELの概要
OpenELの概要 2
OpenELというのは、 JASA((社)組込みシステム技術協会) などが絶賛 推進中の規格で、
ロボット用ハードウェアの下まわりを抽象化するレイヤ。
ROSやRTミドルウェアの下位の層を抽象化して、ミドルウェアやアプリケーションの移植性を高める。
あたくしは、JASAの役員などを拝命しており、OpenELのユーザとしてぼちぼちと遊んでいる。
あたくしは、かねてより、 Multi ThreadなBASICインタープリタを作っている。
これは、裸のマイコンに入れて、対話的にI/Oを叩いたり、
マルチ・スレッドで、多数のI/Oを制御するプログラムを簡単に書けるようにするプログラミング言語である。
この MultiThread BASICに、DCモータ制御のプリミティブを追加した。
そのプリミティブは、OpenEL の DCモータ・コンポーネントを介し、DCモータの制御を行う。
OpenELのDCモータの初期化などは、暗黙のうちにBASIC処理系がやってしまう。
よって、追加したのは、
oeltrq ポート,トルク値
だけである。
内部では、OpenELの
elMotorSetTorque_I32(ポート, トルク値 );
を呼び出している。
トルク値が 0~33で逆転、34~66で停止、67~100で正転。
模型用のDCモータは単純な制御しかできませんから。(電圧を変えるとか、パルスで制御とかもできるでしょうが)
BASICインタープリタはC言語で書いてあり、移植性は高い。
DCモータ制御もOpenELを通している。
よって、OpenELをサポートしたプラットフォームならば、
すぐにMultiThread BASICを移植し、BASICからDCモータを制御することが可能である。
せっかくなので、応用例として、
フォトダイオードで、黒い線を読み取って、走る
ライントレーサを作った。
土台は、タミヤの、壁づたいに走るネズミ。
オリジナルは、メカのタッチセンサで、右に走るか、左に走るかを決める。
上記を、光センサとマイコン(BASIC+OpenEL)で作り直して、
黒い線を中心に左右に振りながら、進むようにする。簡単。
あたくしは、1970年代前半の小学校の時に、NHK教育TVの「みんなの科学」でライントレーサをみて、
「マイキット150」の CDS とリレーで、作った。
まだ、マイクロ・プロセッサもなければ、デジタルIC TTL 74シリーズも、アマチュアにはほとんど知られていない頃の話だ。
「マイキット150」は、部品取りになった側面もあるが、楽しいオモチャだった。
あたくしは、「電子ブロック」よりも、圧倒的に「マイキット」派である。
「マイキット150」の太陽電池は、今でも大切に取ってある。
ライントレーサは、極めて簡易な装置なので、BASICのプログラムも簡単である。
-- ライントレーサのBASICソース
5 'PIC32 OpenEL Motor ADC
6 'oeltrq 0,50:oeltrq 1,50
10 do
20 if &@<40 oeltrq 0,1:oeltrq 1,50:goto 50
30 oeltrq 0,50:oeltrq 1,1:goto 50
50 while 1
-- EOF
上記中の "&@"は、フォト・ダイオードを接続したADコンバータからの入力を読み込む引数なし関数である。
MultiThreadBASIC+OpenELが動いているチップは、
PIC32MX250 (MIPSコア@50MHz、ROM128KB, RAM32KB)
秋月で360円
である。
PIC32MX220 (MIPSコア@40MHz、ROM32KB, RAM8KB)
秋月で250円
は、残念ながらROMが足りないので、
マルチ・スレッドではない普通のTiny BASICにOpenELをつないで動かしている。
ライントレーサは、このPIC32MX220のシングル・スレッドBASICでも動く。
回路図(2014/OCT/11追記)
Lispアドベントカレンダー 2014/DEC/22
が、ネタ、まだ。無し…
すんません。
Raspi2 Floating Performance
Raspberry Pi 2を動かした
Dhrystone など、整数性能は、クロック比程度の性能向上。
Raspi1は、ARM11@700MHz で、Raspi2 は、ARM Cortex-A7@1000MHz。
ARM11は、なかなかいい機械だったので、Cortex-A7と比べてもあまり見劣りしない。
浮動小数点演算 性能が気になる。
組込みCPUなので、期待をしてはいけないが…
Raspi1 の FPU は、ARMの VFP で、ショート・ベクトルとか言っているが、
どないもこないも、遅いしろものであった…
Raspi2 のFPUは、また別物。
Raspbian 標準の gcc (gcc 4.6.3) に
CFLAGS = -O4 -mfp=3 -march=armv7-a -mfpu=vfpv3-d16
で、linpack を make。
システムクロックは、1000MHz と 標準の700MHz で計測。
--- 1000MHz ---
take@raspi2% ./linpackc_sp
Enter array size (q to quit) [200]:
Memory required: 158K.
LINPACK benchmark, Single precision.
Machine precision: 6 digits.
Array size 200 X 200.
Average rolled and unrolled performance:
Reps Time(s) DGEFA DGESL OVERHEAD KFLOPS
----------------------------------------------------
64 0.58 86.21% 10.34% 3.45% 156952.375
128 1.16 91.38% 0.00% 8.62% 165836.516
256 2.32 88.79% 1.72% 9.48% 167415.844
512 4.62 89.18% 3.46% 7.36% 164286.562
1024 9.27 87.59% 3.02% 9.39% 167415.984
2048 18.54 88.03% 2.10% 9.87% 168317.594
Enter array size (q to quit) [200]:
Memory required: 158K.
LINPACK benchmark, Single precision.
Machine precision: 6 digits.
Array size 200 X 200.
Average rolled and unrolled performance:
Reps Time(s) DGEFA DGESL OVERHEAD KFLOPS
----------------------------------------------------
64 0.58 89.66% 0.00% 10.34% 169025.500
128 1.16 83.62% 0.00% 16.38% 181223.141
256 2.32 87.50% 4.74% 7.76% 164286.656
512 4.63 89.20% 2.16% 8.64% 166228.547
1024 9.27 88.57% 2.48% 8.95% 166622.547
2048 18.54 88.24% 3.13% 8.63% 166032.109
Enter array size (q to quit) [200]:
take@raspi2% ./linpackc_dp
Enter array size (q to quit) [200]:
Memory required: 315K.
LINPACK benchmark, Double precision.
Machine precision: 15 digits.
Array size 200 X 200.
Average rolled and unrolled performance:
Reps Time(s) DGEFA DGESL OVERHEAD KFLOPS
----------------------------------------------------
64 0.78 87.18% 5.13% 7.69% 122074.074
128 1.54 89.61% 4.55% 5.84% 121232.184
256 3.09 91.59% 2.59% 5.83% 120815.578
512 6.19 90.79% 2.75% 6.46% 121441.566
1024 12.36 91.10% 2.91% 5.99% 121023.523
Enter array size (q to quit) [200]:
Memory required: 315K.
LINPACK benchmark, Double precision.
Machine precision: 15 digits.
Array size 200 X 200.
Average rolled and unrolled performance:
Reps Time(s) DGEFA DGESL OVERHEAD KFLOPS
----------------------------------------------------
64 0.77 90.91% 2.60% 6.49% 122074.074
128 1.55 91.61% 2.58% 5.81% 120401.826
256 3.10 90.97% 2.58% 6.45% 121232.184
512 6.20 90.97% 3.06% 5.97% 120608.348
1024 12.40 91.05% 2.66% 6.29% 121023.523
Enter array size (q to quit) [200]:
--- 700MHz ---
take@raspi2% ./linpackc_sp
Enter array size (q to quit) [200]:
Memory required: 158K.
LINPACK benchmark, Single precision.
Machine precision: 6 digits.
Array size 200 X 200.
Average rolled and unrolled performance:
Reps Time(s) DGEFA DGESL OVERHEAD KFLOPS
----------------------------------------------------
64 0.64 90.63% 1.56% 7.81% 148971.734
128 1.29 88.37% 2.33% 9.30% 150245.031
256 2.57 87.94% 2.72% 9.34% 150889.688
512 5.14 88.13% 3.11% 8.75% 149924.641
1024 10.28 88.42% 2.63% 8.95% 150245.156
Enter array size (q to quit) [200]:
Memory required: 158K.
LINPACK benchmark, Single precision.
Machine precision: 6 digits.
Array size 200 X 200.
Average rolled and unrolled performance:
Reps Time(s) DGEFA DGESL OVERHEAD KFLOPS
----------------------------------------------------
64 0.65 89.23% 4.62% 6.15% 144087.297
128 1.30 89.23% 1.54% 9.23% 148971.484
256 2.59 88.03% 2.70% 9.27% 149605.656
512 5.19 91.71% 2.12% 6.17% 144383.328
1024 10.37 90.26% 2.12% 7.62% 146794.453
Enter array size (q to quit) [200]:
take@raspi2% ./linpackc_dp
Enter array size (q to quit) [200]:
Memory required: 315K.
LINPACK benchmark, Double precision.
Machine precision: 15 digits.
Array size 200 X 200.
Average rolled and unrolled performance:
Reps Time(s) DGEFA DGESL OVERHEAD KFLOPS
----------------------------------------------------
64 0.86 93.02% 2.33% 4.65% 107186.992
128 1.72 92.44% 2.33% 5.23% 107844.581
256 3.45 91.01% 2.90% 6.09% 108510.288
512 6.87 90.83% 3.20% 5.97% 108846.233
1024 13.75 92.95% 1.38% 5.67% 108426.626
Enter array size (q to quit) [200]:
Memory required: 315K.
LINPACK benchmark, Double precision.
Machine precision: 15 digits.
Array size 200 X 200.
Average rolled and unrolled performance:
Reps Time(s) DGEFA DGESL OVERHEAD KFLOPS
----------------------------------------------------
64 0.86 93.02% 0.00% 6.98% 109866.667
128 1.74 91.38% 1.72% 6.90% 108510.288
256 3.47 89.63% 4.03% 6.34% 108176.410
512 6.95 90.65% 3.02% 6.33% 108010.241
1024 13.90 90.86% 2.66% 6.47% 108176.410
Enter array size (q to quit) [200]:
コア1つで、この性能なら、組込みCPUとしては、まぁ速い。
4コアなので、OpenMP とかで並列に動けば、まぁまぁいいかも知れない。
だが、キャッシュの食い合いとか、内部のバンド幅のせいで、性能が出ないかも知れない。
OpenMP版Linpack も動かしたが、Flops 値が、今は出せていない。
上記で使用したコンパイラ
take@raspi2% gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/4.6/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: ../src/configure -v --with-pkgversion='Debian 4.6.3-14+rpi1' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --disable-sjlj-exceptions --with-arch=armv6 --with-fpu=vfp --with-float=hard --enable-checking=release --build=arm-linux-gnueabihf --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf
Thread model: posix
gcc version 4.6.3 (Debian 4.6.3-14+rpi1)
2015/FEB/27 追記
kkojimaさんのコメントにより…
gcc-4.8 に
CFLAGS = -O4 -march=armv7-a -mfpu=vfpv3-d16
で、linpack を makeし計測。
システムクロックは、1000MHzで計測。
単精度はそこはかとなく遅い気がする(700MHzでは、はっきりと遅い)。
が、倍精度は、速いようだ。
これがコンパイラの力か…
でも、単精度が遅くなったら、アカンやん…うーん
--- 1000MHz ---
take@raspi2% ./linpackc_sp
Enter array size (q to quit) [200]:
Memory required: 158K.
LINPACK benchmark, Single precision.
Machine precision: 6 digits.
Array size 200 X 200.
Average rolled and unrolled performance:
Reps Time(s) DGEFA DGESL OVERHEAD KFLOPS
----------------------------------------------------
64 0.57 87.72% 0.00% 12.28% 175786.672
128 1.15 88.70% 2.61% 8.70% 167415.891
256 2.31 88.31% 4.33% 7.36% 164286.578
512 4.60 88.91% 2.39% 8.70% 167415.844
1024 9.20 88.70% 2.83% 8.48% 167018.266
2048 18.41 88.21% 2.82% 8.96% 167815.422
Enter array size (q to quit) [200]:
Memory required: 158K.
LINPACK benchmark, Single precision.
Machine precision: 6 digits.
Array size 200 X 200.
Average rolled and unrolled performance:
Reps Time(s) DGEFA DGESL OVERHEAD KFLOPS
----------------------------------------------------
64 0.58 84.48% 6.90% 8.62% 165835.672
128 1.16 87.07% 3.45% 9.48% 167416.609
256 2.32 88.79% 3.45% 7.76% 164287.234
512 4.65 89.25% 2.80% 7.96% 164287.094
1024 9.28 88.04% 3.02% 8.94% 166425.469
2048 18.57 88.21% 3.02% 8.78% 166031.844
Enter array size (q to quit) [200]:
Memory required: 158K.
LINPACK benchmark, Single precision.
Machine precision: 6 digits.
Array size 200 X 200.
Average rolled and unrolled performance:
Reps Time(s) DGEFA DGESL OVERHEAD KFLOPS
----------------------------------------------------
64 0.58 87.93% 3.45% 8.62% 165839.250
128 1.17 86.33% 2.56% 11.11% 169024.250
256 2.32 87.50% 3.45% 9.05% 166623.000
512 4.64 88.58% 2.80% 8.62% 165836.562
1024 9.29 89.13% 1.94% 8.93% 166228.250
2048 18.57 88.37% 2.85% 8.78% 166032.328
Enter array size (q to quit) [200]: q
take@raspi2% ./linpackc_dp
Enter array size (q to quit) [200]:
Memory required: 315K.
LINPACK benchmark, Double precision.
Machine precision: 15 digits.
Array size 200 X 200.
Average rolled and unrolled performance:
Reps Time(s) DGEFA DGESL OVERHEAD KFLOPS
----------------------------------------------------
64 0.73 91.78% 1.37% 6.85% 129254.902
128 1.46 90.41% 2.05% 7.53% 130212.346
256 2.92 89.04% 2.40% 8.56% 131675.406
512 5.84 90.07% 2.91% 7.02% 129492.940
1024 11.68 89.81% 2.65% 7.53% 130212.346
Enter array size (q to quit) [200]:
Memory required: 315K.
LINPACK benchmark, Double precision.
Machine precision: 15 digits.
Array size 200 X 200.
Average rolled and unrolled performance:
Reps Time(s) DGEFA DGESL OVERHEAD KFLOPS
----------------------------------------------------
64 0.73 89.04% 4.11% 6.85% 129254.902
128 1.46 90.41% 2.74% 6.85% 129254.902
256 2.92 89.73% 3.42% 6.85% 129254.902
512 5.84 89.90% 2.74% 7.36% 129971.657
1024 11.68 89.64% 3.00% 7.36% 129971.657
Enter array size (q to quit) [200]:
Memory required: 315K.
LINPACK benchmark, Double precision.
Machine precision: 15 digits.
Array size 200 X 200.
Average rolled and unrolled performance:
Reps Time(s) DGEFA DGESL OVERHEAD KFLOPS
----------------------------------------------------
64 0.74 89.19% 4.05% 6.76% 127381.643
128 1.47 91.84% 0.68% 7.48% 129254.902
256 2.94 89.12% 3.40% 7.48% 129254.902
512 5.89 90.15% 2.55% 7.30% 128781.441
1024 11.78 89.81% 2.63% 7.56% 129136.211
Enter array size (q to quit) [200]:
Memory required: 315K.
LINPACK benchmark, Double precision.
Machine precision: 15 digits.
Array size 200 X 200.
Average rolled and unrolled performance:
Reps Time(s) DGEFA DGESL OVERHEAD KFLOPS
----------------------------------------------------
64 0.74 90.54% 1.35% 8.11% 129254.902
128 1.47 88.44% 4.08% 7.48% 129254.902
256 2.94 88.44% 3.74% 7.82% 129731.857
512 5.89 89.64% 2.89% 7.47% 129017.737
1024 11.77 89.97% 2.63% 7.39% 129017.737
Enter array size (q to quit) [200]: q
take@raspi2% gcc-4.8 -v
Using built-in specs.
COLLECT_GCC=gcc-4.8
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/4.8/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: ../src/configure -v --with-pkgversion='Raspbian 4.8.2-21~rpi3rpi1' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --disable-libitm --disable-libquadmath --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-armhf/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-armhf --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-armhf --with-arch-directory=arm --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-sjlj-exceptions --with-arch=armv6 --with-fpu=vfp --with-float=hard --enable-checking=release --build=arm-linux-gnueabihf --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf
Thread model: posix
gcc version 4.8.2 (Raspbian 4.8.2-21~rpi3rpi1)
PR: 今年もやってきた!選ばれし傑作100選発表!
Aitendo FSTN液晶 COG128X64-18P7565
Aitendo に行くと、特売品を買ってしまう。
今日は、液晶漏れ(?)だかの、FSTN液晶[COG128X64-18P7565]を100円で買ってしまった。
(今回は、LCDにコネクタ基板がついている シリアルFSTN液晶モジュール(128x64/SPI) [18P7565-2P] 100円を買った)
そもそも、先日に、Aitendoの下記のWebページで、簡単に動きそうなことを読んでいたものだった、だがしかし…
びんぼうでいいの with LCD [U3RLCD18P7565]
シリアルFSTN液晶モジュール(128x64/SPI) [18P7565-2P]
FSTN液晶モジュール(128x64) [COG128X64-18P7565]
下の写真は、苦労の末、動いているもの
しかし、この びんぼうでいいの(Arduino) と接続する情報が、えらい酷いもので…
安定の、Aitendo クオリティ。100円で、長時間、楽しめる(^^;
当該ページに、ある結線のうち、一つは、VSS(GND)ではなく、オープン(N.C)にしておくべきものであった。(下図)
今回、N.Cにしたものは、なにか、意味のある線かも知れないが、調べる気もしなく、得体が知れないので、もう、N.Cでいいや。
コントラストと、しきい値抵抗を、適切に設定すると、結構キレイに映る。
その情報は、下記。
------ ST7565.cpp.patch
*** ST7565.cpp.org 2015-02-28 17:42:20.000000000 +0900
--- ST7565.cpp 2015-03-01 01:27:20.000000000 +0900
***************
*** 421,427 ****
_delay_ms(10);
// set lcd operating voltage (regulator resistor, ref voltage resistor)
! st7565_command(CMD_SET_RESISTOR_RATIO | 0x6);
// initial display line
// set page address
--- 425,432 ----
_delay_ms(10);
// set lcd operating voltage (regulator resistor, ref voltage resistor)
! // st7565_command(CMD_SET_RESISTOR_RATIO | 0x6);
! st7565_command(CMD_SET_RESISTOR_RATIO | 0x2); /*take@takeoka.net*/
// initial display line
// set page address
***************
-----------examples/st7565lcd/st7565lcd.pde.patch
*** examples/st7565lcd/st7565lcd.pde.org 2013-03-11 20:49:20.000000000 +0
900
--- examples/st7565lcd/st7565lcd.ino 2015-03-01 01:30:00.000000000 +0900
***************
***************
*** 27,37 ****
Serial.print(freeRam());
// turn on backlight
! pinMode(BACKLIGHT_LED, OUTPUT);
! digitalWrite(BACKLIGHT_LED, HIGH);
// initialize and set the contrast to 0x18
! glcd.begin(0x18);
glcd.display(); // show splashscreen
delay(2000);
--- 29,43 ----
Serial.print(freeRam());
// turn on backlight
! // pinMode(BACKLIGHT_LED, OUTPUT);
! // digitalWrite(BACKLIGHT_LED, HIGH);
// initialize and set the contrast to 0x18
! // glcd.begin(0x18);
! glcd.begin(0x10); /*contrast ,
! and check st7565_command(CMD_SET_RESISTOR_RATIO | 0x2);
! take@takeoka.net*/
! glcd.st7565_command(CMD_SET_RESISTOR_RATIO | 0x2);/*take@takeoka.net*/
glcd.display(); // show splashscreen
delay(2000);
Raspi2 Floating Performance with OpenMP
Raspi2 の浮動小数点演算性能 OpenMP 使用編
先日、Raspi2 の1 コアの浮動小数点演算性能を Linpack で測った 。
OpenMP を使用する Linpack がある。
古いのかも知れないが、 http://people.inf.ethz.ch/arbenz/book/Chapter4/ から、
http://people.inf.ethz.ch/arbenz/book/Chapter4/ompsgefa.tar を得た。
CBLASやBLASのルーチンが必要なので、上記ページからリンクのある、CBLASなどをゲットして、
適当にmake した。
gcc, gfortranは、4.8.2 を使用した。
gcc, gfortran のオプションは下記
CFLAGS = -O4 -fopenmp -march=armv7-a -mfpu=vfpv3-d16
FFLAGS = -O4 -fopenmp -march=armv7-a -mfpu=vfpv3-d16
Raspbian 標準の gcc,gfortran 4.6.3も計測したが、今回は、単精度に関わらず、4.8.2 に負けていた。
(結果の表の、末尾に gcc,gfortran 4.6.3 omp_tread=4 の結果を掲げてある)
Raspi2 は 4 coreである。
OMP thread を1 ~ 4 まで変えて、計測してみた。
システム・クロックは1000MHz
計測結果は、Google表計算で
https://docs.google.com/spreadsheets/d/1HV3aaqAxxXxustCJjhZsqLiypWJ_kZGGwEeE2aybEh0/edit?usp=sharing
結局、
OpenMP で 4 thread だと、1threadの 2.13倍ぐらい。
Raspi2は、1 core Linpack で 166 MFlops 程度だったので…
4thread (4 core) 時は、
166 MFlops × 2.13 = 352.76 MFlops ぐらいの
実効性能であろうか。
XBee の再初期化
XBee をだいぶ前に、入手して、少し遊んでいた。
だが、End Device APIだか、End Device AnalogIOだったか、ADC を読み込んで、自動的に送出する ファームウェア を焼いたら、ちっとも通信できなくなった… orz
そして、ファームウェアの更新(元に戻す)も、できなくなった…
急に思い立って、真面目にググって見つけたのが…
「Bootloader to force XBee reflash」
http://www.digi.com/wiki/developer/index.php/Bootloader_to_force_XBee_reflash
これでうまく、ファームウェアを焼き直せた。
僕の XBee は、XB24-Z7CIT-007
要するに…
DTR (9ピン), DIN(3ピン) を GND に落として、reset する。
僕の場合、それで、Bootloader が起動した。
シリアル端末を、115200bps, 8bit, non-parity で、つないでおけば、boot loaderの起動メッセージが見えて、判る。
その後、X-CTU を起動して、強制的にファームウェア更新を行えば、良し。
「Bootloader to force XBee reflash」の内容、正確には…
DTR (9ピン), DIN(3ピン) を GND に落として、reset する。
シリアル端末を、115200bps, 8bit, non-parity で、つないで、
"B", 「CR」
を打ち込むと、boot loader が起動すると、書いてある。
ま、とりあえず、ATコマンドで遊べるように戻ったので、めでたい。