2016年2月20日土曜日

Raspberry Pi 2 Model B + NOOBS Lite 1.7

Raspberry Pi 2 Model B に NOOBS Lite 1.7 をインストールしてみた。

ここを見ながら、SD メモリをフォーマットして、NOOBS Lite 1.7 を解凍してできたファイルをドラッグアンドドロップして起動する。

OS の選択と、言語とキーボードの選択をする。HHK US 配列を使っているので、US の英語にしておく。

インストールが終わって再起動すると GUI の画面が立ち上がるようになっている。
ユーザーのパスワード設定の画面がなくなった?
デフォで pi の raspberry になっている。

画面の縁が黒いので、再起動する時にシフトキーを押したままにして設定画面を表示して、縁を出ないようにする。
Edit Config をクリックして、一番下の disable_overscna の設定を =0 ではなく =1 にする。
ここは次の raspi-config でも設定できる。

いろいろ設定をする raspi-config がどこかに行ってしまったので、
$ sudo raspi-config する。
GUI からでも設定できるメニューが追加されていた。便利。
wifi も簡単につながるし、便利になった。



デフォで、ssh が使えるので、パスワードの変更と TimeZone、GUI で起動する必要はないので text で起動するように設定する。ここはお好みで。
TimeZone は Asia/Tokyo にする。

GUI で起動した時と text の時のメモリ使用状況の違い。
ひとつめが GUI、ふたつめが text 。
used の 190168 と 74512 を比べると、半分以下になっている。
pi@raspberrypi:~ $ free
             total       used       free     shared    buffers     cached
Mem:        948140     190168     757972       6924      15008      98852
-/+ buffers/cache:      76308     871832

Swap:       102396          0     102396

pi@raspberrypi:~ $ free
             total       used       free     shared    buffers     cached
Mem:        948140      74512     873628       6384       7256      36428
-/+ buffers/cache:      30828     917312
Swap:       102396          0     102396
pi@raspberrypi:~ $ 

2014年2月21日金曜日

Raspberry Pi + OpenCV 日経Linux の顔認識が動かない

日経Linux の 2013/8 や「電子工作入門」に掲載されている「専用カメラモジュールを活用“美女Linux”を顔認識」をやってみた。
その結果は、動かなかった。
まず、この記事で使用している「まなみん」だか「てるみん」という女性の顔写真が入手できない。しかたがないので、IMDb で適当な番組を検索して、その出演者の顔写真をダウンロードして使用した。
3/4 くらいは認識できなかった。
Wil Wheaton、Patrick Stewart、Naveen Andrews、Michael Emerson、Matthew Fox、LeVar Burton、Ken Leung、Josh Holloway、Jorge Garcia、Jonathan Frakes、Grace Park、Brent Spiner、Mayim Bialik、Simon Helberg、Johnny Galecki、Kunal Nayyar は認識できる顔写真だった。さらに探して20枚でやってみた。
で、実行すると・・・。
pi@raspberrypi /opt/vc/camcv $ ./camcv face.cfg 1 5000
start
(init) People initialized
(OK) csv=face.cfg
(init) 10 pictures read to train
(init) 10 pictures of Pierre (0) read to train
(init) 0 pictures of Natacha (1) read to train
(init) 0 pictures of Mona Lisa (2) read to train
(init) 0 pictures of Lisa (3) read to train
(OK) read CSV ok
(init) taille images ok
(init) start train images
(init) train images : ok
(init) Load modele : ok
Xlib:  extension "RANDR" missing on display ":1.0".
mmal: main: Failed to create preview component
mmal: Failed to run camera app. Please check for firmware updates

2668812741 seconds for 0 frames : FPS = 0.000000
pi@raspberrypi /opt/vc/camcv $ 

「mmal: main: Failed to create preview component」と言われてしまう。
このメッセージの出所を調べると、camcv_vid1.cpp の 764 行めあたりにあるこれ「else if (!raspipreview_create(&state.preview_parameters))」が、エラーの条件を判断しているところであることがわかった。
次に、「raspipreview_create()」が何を返しているかを調べてみた。
RaspiPreview.h で宣言されていて、MMAL_STATUS_T を返している。
それは、mmal_types.h に定義されている enum の値であった。
見ると、「MMAL_SUCCESS = 0」となっているではないか。
さきほどの「else if (!raspipreview_create()」は0でなければエラーとしている。
でも0なら MMAL_SUCCESS ということで、エラーの無い状態です。
逆なんです。というわけで 764 行めを次のように変更した。
else if (raspipreview_create(&state.preview_parameters) != MMAL_SUCCESS)
0でエラー、ではなく、0でなければエラー、にした。
これで一応なんとか動いているが、しばらくするとやっぱりエラーがでる。
pi@raspberrypi / $ /opt/vc/camcv/camcv /opt/vc/camcv/face.cfg 1 5000
start
(init) People initialized
(OK) csv=/opt/vc/camcv/face.cfg
(init) 10 pictures read to train
(init) 10 pictures of Pierre (0) read to train
(init) 0 pictures of Natacha (1) read to train
(init) 0 pictures of Mona Lisa (2) read to train
(init) 0 pictures of Lisa (3) read to train
(OK) read CSV ok
(init) taille images ok
(init) start train images
(init) train images : ok
(init) Load modele : ok
Xlib:  extension "RANDR" missing on display ":1.0".
mmal: Failed to run camera app. Please check for firmware updates

65 seconds for 208 frames : FPS = 3.200000
pi@raspberrypi / $ 

これって、そうしているようです。
同じソースファイル camcv_vid1.cpp の 233 行めにこれがありました。
state->timeout = 65000; // capture time : here 65 s
65秒で止まるようにしてありました。でも「Please check for firmware updates」は無いと思います。

2014年1月24日金曜日

SDメモリの丸ごとバックアップ

SDメモリを丸ごとバックアップする方法について書いておく。
こうして作成したバックアップファイルをリストアする方法についても書いておく。

まず、バックアップ。(disk3の場合。これの確認は $ df -h)
$ sudo diskutil unmount /dev/disk3s1
$ sudo diskutil unmount /dev/disk3s5
$ sudo dd if=/dev/disk3 of=~/Desktop/RaspberryPi_20130620.img bs=8m
$ sudo diskutil eject /dev/rdisk3

あるいは?
$ sudo diskutil unmount /dev/disk3s1
$ sudo diskutil unmount /dev/disk3s5
$ sudo dd if=/dev/rdisk3 of=~/Desktop/RaspberryPi_20130620.img bs=8m
$ sudo diskutil eject /dev/rdisk3

次にリストアする。(disk4の場合)
$ sudo diskutil unmount /dev/disk4s1
$ sudo dd bs=8m if=~/Desktop/RaspberryPi_20130620.img of=/dev/rdisk4
$ sudo diskutil eject /dev/rdisk4

bs=8m にしているけれど、てきとうです。

2014年1月8日水曜日

OpenCV で、C のソースを Python にする

OpenCV の C のソースを Python に変換するときのメモ。
C にしておくと、ソースとオブジェクトの二つのファイルの管理が必要となったり、ライブラリの置く場所など、いろいろめんどう。
というわけで、Python にしてしまおうという計画。

言語文法上で注意するのはこれくらい?
  1. C の文は「;」で終了するが、Python にはない。
  2. C の変数宣言では型が必要だが、Python は変数名だけ。
  3. C では「&」をつけて、その変数のポインタを求めたりするが、Python では不要。
  4. True/False や Not の表記
  5. nil や NULL や None の表記
  6. Python のインデント。
「import cv」とすると、メソッド名などに「cv.」をつけることになる。
しかし、cv. の後のメソッド名には「cv」がつかない。
ただし、定数名の頭についている「CV」はそのまま残る。
こんな感じ。

C:
frame = cvQueryFrame(capture);
cvSmooth(frame, frame, CV_GAUSSIAN, 3, 3);

Python:
frame = cv.QueryFrame(capture)
cv.Smooth(frame, frame, cv.CV_GAUSSIAN, 3, 3)

C の cvQueryFrame は Python では cv.QueryFrame となる。
ただし定数は、C で CV_GAUSSIAN、Python で cv.CV_GAUSSIAN となる。

厄介なのがマクロ(?)。Python にはない。ふつーにタプルで表現したりする。

C:
const int w = frame->width;
const int h = frame->height;
imgR = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
cvCircle(frame, cvPoint(gX, gY), 80, CV_RGB(0,0,255), 6, 8, 0);

Python:
the_size = cv.GetSize(frame)
imgR = cv.CreateImage(the_size, cv.IPL_DEPTH_8U, 1)
cv.Circle(frame, (gX, gY), 80, (0, 0, 255), 6, 8, 0)

そのほか、調べないとわからないもの。

C:
cvMoments(imgResult, &moments, 0);
double m00 = cvGetSpatialMoment(&moments, 0, 0);

Python:
moments = cv.Moments(cv.GetMat(imgResult, 1), 0)
m00 = cv.GetSpatialMoment(moments, 0, 0)


サンプルとして、次のページにあった赤い色のエリアを抽出し、重心を求めるソースの C 版と Python 版を示す。
http://d.hatena.ne.jp/shokai/20090203/1233609981
http://opencv-srf.blogspot.ro/2010/09/object-detection-using-color-seperation.html

これは Mac (10.9.1 Mavericks) と Raspberry Pi で動作確認した。

C:
#include <opencv/cv.h>
#include <opencv/highgui.h>

// This function threshold the HSV image and create a binary image
IplImage* GetThresholdedImage(IplImage* imgHSV) {
    IplImage* imgResult = cvCreateImage(cvGetSize(imgHSV), IPL_DEPTH_8U, 1);
    cvInRangeS(imgHSV, cvScalar(150, 160, 60), cvScalar(200, 256, 256), imgResult);
    return imgResult;
}

int main() {
    CvCapture* capture = NULL;
    IplImage *frame = NULL;
    IplImage *imgR = NULL, *imgG = NULL, *imgB = NULL;
    IplImage *imgThreshold_R = NULL, *imgThreshold_G = NULL, *imgThreshold_B = NULL;
    IplImage *imgTmp = NULL;
    IplImage *imgHSV = NULL;
    IplImage *imgResult = NULL;
    CvMoments moments;
    
    capture = cvCaptureFromCAM(0);
    if (!capture) {
        printf("Capture failure\n");
        return -1;
    }
    
    cvNamedWindow("Video");
    cvNamedWindow("Results");
    
    
    // iterate through each frames of the video
    while (true) {
        
        frame = cvQueryFrame(capture);
        if (!frame) {
            break;
        }
        
        frame = cvCloneImage(frame);
        cvSmooth(frame, frame, CV_GAUSSIAN, 3, 3); // smooth the original image using Gaussian kernel
                
        if (1) {
            const int w = frame->width;
            const int h = frame->height;
            
            imgR = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
            imgG = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
            imgB = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
            imgThreshold_R = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
            imgThreshold_G = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
            imgThreshold_B = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
            imgResult = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
            imgTmp = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);

            cvSplit(frame, imgB, imgG, imgR, NULL); // BGRを分解
            
            // 赤の要素が100以上で、緑と青より1.5倍以上あるピクセルを抽出
            cvThreshold(imgR, imgThreshold_R, 100, 255, CV_THRESH_BINARY);
            cvDiv(imgR, imgG, imgTmp, 10); // 10倍
            cvThreshold(imgTmp, imgThreshold_G, 15, 255, CV_THRESH_BINARY);
            cvDiv(imgR, imgB, imgTmp, 10);
            cvThreshold(imgTmp, imgThreshold_B, 15, 255, CV_THRESH_BINARY);
            cvAnd(imgThreshold_G, imgThreshold_B, imgTmp, NULL);
            cvAnd(imgTmp, imgThreshold_R, imgResult, NULL);
            
            cvMoments(imgResult, &moments, 0);
            double m00 = cvGetSpatialMoment(&moments, 0, 0);
            double m10 = cvGetSpatialMoment(&moments, 1, 0);
            double m01 = cvGetSpatialMoment(&moments, 0, 1);
            int gX = m10 / m00;
            int gY = m01 / m00;
            cvCircle(frame, cvPoint(gX, gY), 80, CV_RGB(0,0,255), 6, 8, 0);
        } else {
            imgHSV = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 3);
            cvCvtColor(frame, imgHSV, CV_BGR2HSV); // Change the color format from BGR to HSV
            imgResult = GetThresholdedImage(imgHSV);
            cvSmooth(imgResult, imgResult, CV_GAUSSIAN, 3, 3); // smooth the binary image using Gaussian kernel
        }
        cvShowImage("Results", imgResult);
        cvShowImage("Video", frame);
        
        
        // Clean up used images
        cvReleaseImage(&imgHSV);
        cvReleaseImage(&imgResult);
        cvReleaseImage(&frame);
        
        // Wait 50mS
        int c = cvWaitKey(10);
        // If 'ESC' is pressed, break the loop
        if ((char)c == 0x1b ) {
            break;
        }
    }
    
    cvDestroyAllWindows() ;
    cvReleaseCapture(&capture);
    
    return 0;
}

Python:
#!/usr/bin/env python
# coding: UTF-8
"""
DetectingRedObjects.py

"""
import cv

def GetThresholdedImage(imgHSV):
    imgResult = cv.CreateImage(cv.GetSize(imgHSV), cv.IPL_DEPTH_8U, 1)
    cv.InRangeS(imgHSV, cv.Scalar(150, 160, 60), cv.Scalar(200, 256, 256), imgResult)
    return imgResult

def main():
    capture = None
    frame = None
    imgR = imgG = imgB = None
    imgThreshold_R = imgThreshold_G = imgThreshold_B = None
    imgTmp = imgHSV = imgResult = None
    moments = None
    
    capture = cv.CaptureFromCAM(0)
    if (not capture):
        print("Capture failure")
        return -1
    
    cv.NamedWindow("Video")
    cv.NamedWindow("Results")
    
    
    # iterate through each frames of the video
    while (True):
        frame = cv.QueryFrame(capture)
        if (not frame):
            break;
        
        frame = cv.CloneImage(frame)
        cv.Smooth(frame, frame, cv.CV_GAUSSIAN, 3, 3) # smooth the original image using Gaussian kernel
        
        if (True):
            # 赤色領域を検出(3) 重心も計算
            # http://d.hatena.ne.jp/shokai/20090203/1233609981
            the_size = cv.GetSize(frame)
            # w = frame.width
            # h = frame.height
            
            imgR = cv.CreateImage(the_size, cv.IPL_DEPTH_8U, 1)
            imgG = cv.CreateImage(the_size, cv.IPL_DEPTH_8U, 1)
            imgB = cv.CreateImage(the_size, cv.IPL_DEPTH_8U, 1)
            imgThreshold_R = cv.CreateImage(the_size, cv.IPL_DEPTH_8U, 1)
            imgThreshold_G = cv.CreateImage(the_size, cv.IPL_DEPTH_8U, 1)
            imgThreshold_B = cv.CreateImage(the_size, cv.IPL_DEPTH_8U, 1)
            imgResult = cv.CreateImage(the_size, cv.IPL_DEPTH_8U, 1)
            imgTmp = cv.CreateImage(the_size, cv.IPL_DEPTH_8U, 1)
            
            cv.Split(frame, imgB, imgG, imgR, None) # BGRを分解
            
            # 赤の要素が100以上で、緑と青より1.5倍以上あるピクセルを抽出
            cv.Threshold(imgR, imgThreshold_R, 100, 255, cv.CV_THRESH_BINARY)
            cv.Div(imgR, imgG, imgTmp, 10) # 10倍
            cv.Threshold(imgTmp, imgThreshold_G, 15, 255, cv.CV_THRESH_BINARY)
            cv.Div(imgR, imgB, imgTmp, 10)
            cv.Threshold(imgTmp, imgThreshold_B, 15, 255, cv.CV_THRESH_BINARY)
            cv.And(imgThreshold_G, imgThreshold_B, imgTmp, None)
            cv.And(imgTmp, imgThreshold_R, imgResult, None)
            
            # cv.Moments(imgResult, moments, 0)
            moments = cv.Moments(cv.GetMat(imgResult, 1), 0)
            m00 = cv.GetSpatialMoment(moments, 0, 0)
            m10 = cv.GetSpatialMoment(moments, 1, 0)
            m01 = cv.GetSpatialMoment(moments, 0, 1)
            if (m00 != 0):
                gX = int(m10 // m00)
                gY = int(m01 // m00)
                # cvCircle(frame, cvPoint(gX, gY), 80, CV_RGB(0,0,255), 6, 8, 0);
                cv.Circle(frame, (gX, gY), 80, (0, 0, 255), 6, 8, 0)
        else:
            # Color Detection & Object Tracking
            # http://opencv-srf.blogspot.ro/2010/09/object-detection-using-color-seperation.html
            imgHSV = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_8U, 3)
            cv.CvtColor(frame, imgHSV, cv.CV_BGR2HSV) # Change the color format from BGR to HSV
            imgResult = GetThresholdedImage(imgHSV)
            cv.Smooth(imgResult, imgResult, cv.CV_GAUSSIAN, 3, 3) # smooth the binary image using Gaussian kernel

        cv.ShowImage("Results", imgResult)
        cv.ShowImage("Video", frame)
        
        
        # Clean up used images
        # cv.ReleaseImage(imgHSV)
        # cv.ReleaseImage(imgResult)
        # cv.ReleaseImage(frame)
        
        # Wait 50mS
        c = cv.WaitKey(10)
        # If 'ESC' is pressed, break the loop
        if (c == 0x1b):
            break

    cv.DestroyAllWindows()
    # cv.ReleaseCapture(capture)
    return 0


if __name__ == '__main__':
    main()

2013年12月13日金曜日

Raspberry Pi (その前に Mac で)+ OpenCV + OpenNI + Xtion Pro Live

まず、Mac でいろいろやってみる。
OpenCV は MacPorts で opencv @2.4.7_1+openni+python27 をインストールする。
OpenNI も MacPorts で一応入れたものの・・・openni @1.5.7.10_0
OpenNI-MacOSX-x64-2.2 をダウンロード。
「OpenNI-MacOSX-x64-2.2/Samples/Bin」にあるサンプルは動作している。

次に、Samples のソースをいじる前に、make できることを確認する。
make すると deprecated のエラーがでてしまう。
Makefile を修正してコンパイルオプションに「-Wno-deprecated」を追加する。
例を示す。
<<修正前>>
CFLAGS += -Wall -D_CLOSEST_POINT
<<修正後>>
CFLAGS += -Wall -D_CLOSEST_POINT -Wno-deprecated



ClosestPointViewer を make するには、MWClosestPoint を先に make しておかなければならない。
MWClosetPointApp を make するときも、先に MWClosestPoint を make しておかなければならない。

まず、MWClosestPoint/Bin は削除してから、MWClosestPoint を make する。

次に、ClosestPointViewer/Bin/ にある Intermediate と x64-Release の二つのディレクトリは空にする。
MWClosestPoint/Bin/x64-Release/libMWClosestPoint.dylib を、先ほど空にした ClosestPointViewer/Bin/x64-Release/ にコピーする。
コピーコマンドはこれ。
$ cp MWClosestPoint/Bin/x64-Release/libMWClosestPoint.dylib ClosestPointViewer/Bin/x64-Release/
そして、ClosestPointViewer を make する。

同様に、MWClosestPointApp/Bin/ にある Intermediate と x64-Release の二つのディレクトリは空にする。
MWClosestPoint/Bin/x64-Release/libMWClosestPoint.dylib を、先ほど空にした MWClosestPointApp/Bin/x64-Release/ にコピーする。
コピーコマンドはこれ。
$ cp MWClosestPoint/Bin/x64-Release/libMWClosestPoint.dylib MWClosestPointApp/Bin/x64-Release/
MWClosetPointApp を make する。

make できることが確認できたので、ソースをいろいろいじってみることにする。

2013年12月5日木曜日

Raspberry Pi + ビュートローバー ARM VS-WRC103LV (Mac に LPCXpresso をインストール)

ビュートローバー ARM VS-WRC103LV のソフトを作る話のメモ。
Mac に LPCXpresso をインストールし、C でソフトを作る。
NXP のダウンロードサイトから LPCXpresso をダウンロードしてインストールする。
アクティベーションがちょっと面倒。

2014.04.03 時点では、lpcxpresso_7.1.1_125.pkg がダウンロードされる。
これを開くとインストーラーが動き出す。アプリケーションフォルダに「lpcxpresso_7.1.1_125」という名前のフォルダがつくられるが、どれがアプリの本体なのかわからない。
「Open lpcxpresso」というファイルがあるけれど、どこかのファイルへのエイリアスになっている。調べると・・・「Open lpcxpresso -> lpcxpresso/lpcxpresso.app/Contents/MacOS/lpcxpresso」と、なっている。
lpcxpresso フォルダの中をみると「lpcxpresso」という名前のアプリケーションがある。これだね。これをダブルクリックすると立ち上がる。Dock のオプションで「Dock に追加」をしておくと、今後は Dock から起動できる。

で、この lpcxpresso_7.1.1_125.pkg は、USB 関係で使われる SciInit() で問題が発生する。帰ってこない。ここで止まってしまう。
これでは使い物にならないので、7.1.1 から 7.0.0 に戻した。

2014.05.23 現在、バージョン 7.2.0_153 が公開されていて、これは SciInit() の問題はない。7.1.1 は使えないが、 7.2.0_153 は使える。
ほかにも問題が改善されている。原因不明だが、ビュートローバーのセンサーの値を返すように修正し、その後、リビジョンを返す関数を追加した。しかし、そのリビジョンはなぜかセンサーの値になっていた。この問題は 7.0.0 で発生していたが、7.2.0 では正しくリビジョンを返すようになった。かなりいい加減な C の処理系らしい。

サンプルでついてくる VS-WRC103LV_Sample_LED_20110118_1104.zip を解凍してビルド。
その後、VS-WRC103LV に書き込む。Debug フォルダに作成された「VS-WRC103LV_Sample_LEDなんたらかんたら.bin」をマウントした VS-WRC103LV にコピーするのだが、実行すると動かない。
ファインダからコピーすると不可視ファイルをいくつかつくるので、それが邪魔をしてうまくいかないと思われる。ちなみに Ubuntu Desktop でも試してみるが同様にうまくいかない。Mac でビルドした bin ファイルを Windows でコピーすると動くので、LPCXpresso は正しく動いているようだ。
Mac のターミナルでコピーすると正常に動いたので、そのときの手順をメモしておく。

  1. VS-WRC103LV を Mac に接続する
    VS-WRC103LV のボタンを押したまま Mac に接続し、マウントされたらボタンを話す。このとき、VS-WRC103LV の電源は OFF にしておく。
    マウントした VS-WRC103LV をファインダで開かないで、そっとしておく。

  2. ターミナルから次のコマンドで、古い farmware.bin を削除する
    $ rm /Volumes/CRP\ DISABLD/firmware.bin

  3. 新しい bin ファイルをコピーする
    「New_VS-WRC103LV_Firmware.bin」をコピーしている例。
    $ cp New_VS-WRC103LV_Firmware.bin /Volumes/CRP\ DISABLD/

  4. VS-WRC103LV のマウントを解除し、イジェクトする
    イジェクトする前に df コマンドで、Filesystem 名の確認を行う。
    ここでは「/dev/disk1」になっている。
    $ df -h
    Filesystem Size Used  Avail Capacity iused ifree %iused Mounted on
    /dev/disk1 32Ki 7.0Ki  25Ki    22%      16     0  100%  /Volumes/CRP DISABLD

    df コマンドで調べた Filesystem 名で VS-WRC103LV をイジェクトする。
    $ sudo diskutil eject /dev/disk1

  5. VS-WRC103LV を Mac から取り外す

付属している前進・後退のソフトをちょっと修正して LED を点滅させている例。
#include "lpc13xx.h"
#include "gpio.h"
#include "vs-wrc103.h"
#include "ixbus.h"

int main(void) {
    int ii;
    const unsigned short MainCycle = 60;
    Init(MainCycle);
    LED(3);
    while (getSW() != 1) {
        // ボタンが押されるまで待つ
        Wait(50);
        LED(0);
        Wait(50);
        LED(3);
    }
    LED(0);
    while (getSW() == 1) {
        ; // ボタンが離されるまで待つ
    }

    while (1) {
        // 前進
        Mtr_Run_lv(10000, -10000, 0, 0, 0, 0);
        LED(3);
        Wait(1000);
        // 停止
        Mtr_Run_lv(0, 0, 0, 0, 0, 0);
        LED(0);
        Wait(1000);
        // 後進
        Mtr_Run_lv(-10000, 10000, 0, 0, 0, 0);
        for (ii = 0; ii < 10; ii++) {
            LED(1);
            Wait(50);
            LED(2);
            Wait(50);
        }
        // 停止
        Mtr_Run_lv(0, 0, 0, 0, 0, 0);
        LED(0);
        Wait(1000);
    }
    return 0;
}

=== そのほか
LPCXpresso を起動した状態で、何もしていないのにエラーがでている。
これは気にしなくてもいい?
Description Resource Path Location Type
make: *** [src/main.o] Error 1     C/C++ Problem


Linux では注意!
ソースの中では「lpc13xx.h」となっているが、実際は「LPC13xx.h」と、大文字も使っているファイルがいくつかある。Mac/Win ではファイル名の大文字と小文字を区別しないので問題は起きない。でも Linux では大文字と小文字を区別するので、ファイルが見つからないというエラーが発生する。ファイル名を直すか、ソースを直す処置が必要。


LPCXpresso は Eclipse 
Eclipse のプラグインがそのまま使える。
MercurialEclipse をインストールして使っている。



LPCXpresso の設定変更のメモ:
タブはスペースにしたい。
General -> Editors -> Text Editors の Insert spaces for tabs にチェック。
C/C++ -> Code Style -> Formatter で、新しい profile を作成する。
その中で、Indentation を Spaces only にする。

Code Style の設定は、Source メニューの Format の時に使われる。

2013年11月2日土曜日

Raspberry Pi + I2C LCD module

Raspberry Pi に I2C で秋月電子の LCD ディスプレイをつないでみる。
そのときの記録。

使用した LCD ディスプレイは「I2C接続小型LCDモジュールピッチ変換キット」。
これは、「I2C接続小型LCDモジュール 8x2行」と「I2C接続小型LCDモジュール用ピッチ変換基板」をセットにしたもの。LCDモジュールだけではブレッドボードに取り付けるのが大変なので、ピッチ変換基板も必要となる。

I2C の準備はこちら「Raspberry Pi + I2C」を参照。

Python でソフトを作る。
ソースはこれ。日付と時刻を表示する。

#!/usr/bin/env python
# coding: UTF-8

'''
$ sudo apt-get install python-smbus
$ sudo apt-get install i2c-tools

comment out this line in /etc/modprobe.d/raspi-blacklist.conf
blacklist i2c-bcm2708

add the following lines to /etc/modules  
 i2c-dev 
 i2c-bcm2708
and then reboot.

search all addr.
$ sudo i2cdetect -y 1
'''

import smbus
import RPi.GPIO as GPIO
import time
import math
import datetime

class st7032i:
    def __init__(self, addr = 0x3e, ch = 1, contrast = 0x20):
        self.addr = addr
        self.ch = ch
        self.bus = smbus.SMBus(ch)
        self.contrast = contrast
        self.reset()
        
    def reset(self):
        contrast_h = 0x70 | (self.contrast & 0x0f)
        contrast_l = 0x54 | ((self.contrast >> 4) & 0x03)
        self.bus.write_i2c_block_data(self.addr, 0, [0x38, 0x39, 0x14, contrast_h, contrast_l, 0x6c])

        time.sleep(0.25)
        self.bus.write_i2c_block_data(self.addr, 0, [0x0c, 0x01, 0x06])
        time.sleep(0.05)
        
    def clear(self):
        self.bus.write_i2c_block_data(self.addr, 0, [0x01])
        
    def mov_to(self, row = 0, col = 0):
        self.bus.write_i2c_block_data(self.addr, 0, [0x80 + 0x40 * row + col])
        
    def put_str(self, the_str):
        self.bus.write_i2c_block_data(self.addr, 0x40, map(ord, the_str))
        
if __name__ == '__main__':
  try:
    my_lcd = st7032i(0x3e, 1)
    while True:
        time_str = datetime.datetime.now().strftime("%H:%m:%S")
        date_str = datetime.datetime.now().strftime("%y/%m/%d")
        my_lcd.clear()
        my_lcd.mov_to(0, 0)
        my_lcd.put_str(date_str)
        my_lcd.mov_to(1, 0)
        my_lcd.put_str(time_str)
        print date_str + ' ' + time_str
        time.sleep(1)
  except:
    print "Error accessing default I2C bus"


回路は、LCD モジュールに I2C の信号と電源(3.3V)を供給するだけ。