ラベル RaspberryPi の投稿を表示しています。 すべての投稿を表示
ラベル RaspberryPi の投稿を表示しています。 すべての投稿を表示

2014年3月7日金曜日

Linuxのシリアルポート

Raspberry PiでFT232を使えれば便利だと思ったので、試しています

とりあえず
      1 #include <sys/types.h>
      2 #include <sys/stat.h>
      3 #include <fcntl.h>
      4 #include <termios.h>
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <string.h>
      8 #include <unistd.h>
      9
     10 #define BAUDRATE (115200)
     11 #define MODEMDEVICE "/dev/ttyUSB0"
     12
     13 int main(void) {
     14     int fd;
     15     struct termios oldtio, newtio;
     16     char buf[255];
     17
     18     sprintf(buf, "stty -F %s speed %d\n", MODEMDEVICE, BAUDRATE);
     19     system(buf);
     20
     21     fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY);
     22     if (fd < 0) { perror(MODEMDEVICE); return(-1); }
     23
     24     tcgetattr(fd, &oldtio);
     25
     26     bzero(&newtio, sizeof(newtio));
     27     newtio.c_cflag = CRTSCTS | CS8 | CLOCAL | CREAD;
     28     newtio.c_iflag = IGNPAR;
     29     newtio.c_oflag = 0;
     30     newtio.c_lflag = 0;
     31     newtio.c_cc[VTIME] = 0;
     32     newtio.c_cc[VMIN]  = 0;
     33
     34     tcflush(fd, TCIOFLUSH);
     35     tcsetattr(fd, TCSANOW, &newtio);
     36
     37
     38     strcpy(buf, "hello world " __DATE__ " " __TIME__ " " __FILE__ "\n");
     39     write(fd, buf, strlen(buf));
     40
     41     int size = 0;
     42     int ret;
     43     memset(buf, 0, sizeof(buf));
     44
     45     while (size < 10) {
     46         ret = read(fd, buf + size, 10 - size);
     47         if (ret < 0) { break; }
     48         size += ret;
     49     }
     50
     51     printf("%d:%s\n", size, buf);
     52
     53     tcflush(fd, TCIOFLUSH);
     54     tcsetattr(fd, TCSANOW, &oldtio);
     55     close(fd);
     56
     57     return(0);
     58 }
という感じのコードになっています

tcsetattrでビットレートの設定ができなかったため、system関数でstty関数を叩いて変更しています

そしてwriteで出力後、readで10文字を入力して終了
という感じの動作となるはずです

しかし実際には
1)起動
2)入力待ち
3)10文字入力する
4)入力された文字列を表示
5)送信先に文字列が表示される
6)終了
という感じで、文字列の送信がうまく出来ていません

動作としてはバッファリングされている感じですが、そもそもopenはじめwriteなどの低レベル処理ではバッファリングはされていないはずで、結局どこが原因かわかっていません
とりあえずwriteした直後にmemsetでバッファを0埋めしているので、少なくともwrite関数から出た時点でどこかのバッファなりに転送しているはずです
なので問題が有るとすればwrite関数の中か、writeよりも低レベルな場所ということになります

「送信したいのに送信されてない」という問題さえなんとかなれば、いろいろ使い道が出てくるのですが。。

27行目、c_cflagに設定しているCTRSCTSを消したら希望通りの動作をするようになりました
やっぱ説明はちゃんとしたのを読む必要がありますね!!!

ということで、ファイルディスクリプタを引数にしたUARTアクセス用のライブラリを作れば結構便利に扱えそうです

例えば秋月のXBeeアダプタはFT232を使っているので、簡単にRasPiからXBee経由で他のマイコンと通信ができるようになります


まとめ

情報はちゃんと調べよう

Raspberry Piにジョイスティックを

最近はSTM32F1ネタばっかりでしたが
ちょっと違うネタも扱おうと思います

調べ物をしていて「どうやらLinuxでジョイスティックを使うのは簡単のようだ」ということで
じゃぁやってみよう という自然な流れでLinuxからジョイスティックを読んでみました

仮想のUbuntuを起動するのは面倒というこれまた自然な流れでRasPi上で試しています

ソースコードは
http://d.hatena.ne.jp/aki-yam/20130729/1375097014
を参考にしました

使用したジョイスティックは箱○の有線コントローラです

RasPiのUSBポートに突き刺したらドライバとかも必要なく簡単に認識してくれました

上記ブログのコードを動かしてみたところ
Joystick: Microsoft X-Box 360 pad
axis    : 8
buttons : 11
として認識され、操作も出力されています

8軸11スイッチのコントローラで
軸0:左スティック左右(左が- 右が+)
軸1:左スティック上下(上が- 下が+)
軸2:左トリガ(開放状態が- 引いた状態で+)
軸3:右スティック左右
軸4:右スティック上下
軸5:右トリガ
軸6:Pad左右(左が- 右が+)
軸7:Pad上下(上が- 下が+)

ボタン0:A
ボタン1:B
ボタン2:X
ボタン3:Y
ボタン4:LB
ボタン5:RB
ボタン6:Back
ボタン7:Start
ボタン9:Xboxロゴ
ボタン10:左スティック
ボタン11:右スティック

という感じの配置です
ジョイスティックの値は符号付き16bitで、Padは0か-32768か32767の3種類しかありません

Padは上下が-であれば上 +であれば下
左右が-であれば左 +であれば右
で、斜めは両方のANDで検出できます(上下が-で左右が+なら右上 など)

また、トリガについてですが これは左右で1軸ずつ用意されているようです
以前にC#のDirectX.DirectInputで遊んだ時は左右のトリガで1軸でした(左を引くと- 右を引くと+ 両方引くと0 みたいな)
この実装の場合 例えば飛行機のゲームを作る場合、トリガをラダーに割り当て、両方のトリガを引くとブレーキ みたいな動作ができません
しかし左右のトリガで2軸だとこのような実装ができるので便利です


ということで、RasPiで箱○コントローラを読むことができるようになったので
足が生えて歩きまわるようなロボットの制御とかに使えそうです
RasPiにXBeeを接続すればロボットを遠隔で制御できるようになります
また操作対象にもRasPiを搭載し、無線LANの11n等でリンクすれば、対象のカメラで写した画像をこちら側に表示したりもできそうです(もっとも、そこまで行くと両方共ノートPCとかを使ったほうが便利ですが。。。)

2013年12月28日土曜日

RasPi+OpenCV+WebCamera

Raspberry PiにUSBカメラを接続してOpenCVで撮影してみました


とりあえずこんな感じになっています

流れとしては
10行目)カメラを探す
12行目)ポインタアドレスを表示(デバッグ用 0位外であれば正常という判断)
14行目)ヌルポインタ(カメラが見つからない)以外であれば処理
15-16行目)デフォルトの画面解像度を獲得
20行目)画像をキャプチャ
21行目)画像を保存
23行目)保存した画像をsystem関数を使いscpで画面の有るマシンに転送
25-26行目)構造体を解放
だと思います(てきとーにそれらしい関数を引っ張ってきてるだけなので微妙

僕の環境はRasPiに画面が無いので、scpで他のマシンに飛ばしていますが
RasPiに画面が接続されているなら23行目及び4行目は削除しても問題ありません


コンパイルは
$ gcc hoge.c `pkg-config --cflags --libs opencv`
で通ります
めちゃくちゃ時間かかりますが。。


当初はRasPi用カメラモジュールを使おうかと思って、可視光のモジュールも購入済みですが
raspistillが地味に面倒なのでOpenCVを使ってしまいました
あとOpenCVだといろいろ参考になりそうな情報が多い というのも理由です


今のところカメラモジュールを使って何かをつくろうというネタは2個ほどありますが、優先度はかなり低いので気分転換に進める 程度になりそうです
その前にOpenCV本も1冊買っておかないと(ネット情報だと頭にはいらない性格)(本を買っても読まない性格だけど)


いろいろやりたいことはありますが、優先度が低かったり、恐ろしく面倒だったり、高コストだったり、それらのフルコンボだったりでいまいちやる気が出てこない今日このごろです

2013年12月12日木曜日

OpenCVでキャプチャ

基本的なコードは前回のエントリ参照

画像を獲得するには
IplImage *img = cvQueryFrame(capture);
で画像のポインタを受け取る

保存するには
cvSaveImage("img.png", img, 0);
とする
Webのサンプルを見るとcvSaveImageの引数は2個なんだけど
これはC++で使う前提で、Cだと最後まで引数を指定する必要がある

ファイルのフォーマットはファイル名の拡張子で識別される
bmpとかpngとか、たいていは対応してそう


ノイズとか解像度はカメラによって異なるので、綺麗な画像が欲しければちゃんとしたカメラを探したりとかする必要がある
あとカメラによって解像度が違う とかの可能性もあるので、ちゃんと動くプログラムを作るならその辺りも作りこむ必要がある
(それが嫌でRasPi用のカメラを買ってみたりしたのだけど)

一旦IplImageになってしまえば顔検出とか色々できるので、煮るなり焼くなり好きにできる

RasPiでWebカメラ

今回はラズパイ用カメラじゃないです

前回の続き OpenCVを使ったプログラムのコンパイル方法
$ gcc main.c `pkg-config --libs opencv`
でa.outが作成される
ちょっと時間がかかるんで頻繁にコンパイルしてエラー吐かせる とかはむりぽ

テストコード
      1 #include <opencv/cv.h>
      2 #include <opencv/highgui.h>
      3 #include <ctype.h>
      4 #include <stdio.h>
      5
      6 int main(int argc, char **argv) {
      7     const int cCameraNum = 0;
      8     CvCapture *capture = 0;
      9
     10     capture = cvCreateCameraCapture(cCameraNum);
     11
     12     printf("capt  :%d\n", (int)capture);
     13     printf("width :%d\n", (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH));
     14     printf("height:%d\n", (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT));
     15
     16     cvReleaseCapture(&capture);
     17
     18     return(0);
     19 }
     20
Webカメラが接続されていればcaptureのポインタと、現在設定されているカメラの解像度が出力される
OpenCVがカメラを検出できなければポインタにはnullが入り、解像度も0になる
ちなみにこのカメラにRasPi用カメラはカウントされない
手持ちのUSBカメラは認識された

画像の獲得とかはこれからやる

ちなみにWebカメラのドライバとかは不要 接続するだけで使える
USBホント便利

2013年12月11日水曜日

RasPiのカメラ

RasPiのカラーカメラを買ってみた
RSで買うものが色々あったのでついでに という感じ
このエントリは備忘録と言うより愚痴に近い

カメラの接続はいたって簡単
カメラから伸びてるFFCをRasPiのコネクタに接続するだけ
ちなみにRasPiには全く同じコネクタが2つ乗っている
カメラで使うのはLANコネクタとかUSBコネクタの側にある方
向きを間違えないように接続
→確かFFCの電極がHDMIコネクタ側に来るように
後は電源を入れてraspi-configからカメラを有効にする
これだけで準備完了
撮影したい場合はraspistillコマンドを使う
最低限必須なオプションは-oでファイル名を指定する これがないと保存されない
その他コマンドは http://www.mztn.org/rpi/rpi23.html にまとまっていて見やすい

raspi-configもraspistillもSSHからできる
なのでRasPiには電源のUSBとLANコネクタを接続するだけで撮影が可能
ただ撮影した画像の確認ができないので、何らかの方法でファイルを転送する必要がある
転送にはscpコマンドが便利(ちょっと面倒だけど


で、あと色々やりたいなとおもってOpenCVを入れた
sudo apt-get install libopencv-dev
で入る(はず)
ヘッダファイルは/usr/include/opencvとか/usr/include/opencv2とかになる
なのでプログラムで読み込むヘッダファイルは<cv.h>ではなく<opencv/cv.h>とかになる
highgui.hも同様

ただ、ネットに転がってるサンプルは画面が接続されていることが前提のコードばっかりで、SSHから試すとかができない
この辺りはもうちょっと調べて見る必要がある

最近のRAMが8GBでCPUが2.5GHzで みたいなマシンばっかり使ってるのでRasPiのワンテンポ遅れたGUIはどうもストレスがたまる。。。(データがたっぷり詰まったiPhone とかも操作の反映が遅くてつらい)


やりたいこととしてはRasPi単体で動作する、画像解析装置 みたいな感じ
15fpsくらいはほしいけど、解像度はそれほど必要ないのでRasPiでも可能なはず

とりあえず今回はこんなところで
今年中にもーちょっと進めたいなぁ

2013年10月3日木曜日

Raspberry Piでシリアル通信

Raspberry PiのUSBポートにFT232を接続し、シリアル通信を試してみました

例によってViのキャプチャで申し訳ないです

とりあえずググって出てきたページのコードをほぼそのまま使っていますが
一応通信出来ました

ポート名はcpPortNameに設定され、これは各自の環境で調べてください
例えば ls /dev/tty* コマンドをFT232を接続する前と後に実行し、増えた項目がそのポートのはずです(dmesgでもいいですが)

設定は基本的に初期設定から変更していません
このあたりは追々調べていきます

とりあえずgccでビルドして実行します

正常に通信できれば相手には上のように表示されるはずです


Linuxは最近のパッケージにはFT232のドライバが標準で付属していて、インストールの手間もなくサクッと扱えます これはRasbpianでも同じで、簡単にシリアルポートにアクセスできるようです

USB-TTL UARTの変換にはFT232シリーズがデファクトスタンダードとなっており、秋月のXBeeアダプタストリナのXBeeアダプタはこのICが使用されているため、RaspBiのシリアルポートを消費することなくXBeeを接続することもできるようになります
他にもFT232+レベル変換ICを使えば本来のRS232通信も可能となります

2013年9月28日土曜日

RasPiのピンヘッダ

Raspberry Piの大きなピンヘッダには色々なポートが出力されていますが、基本的には電源とGPIOです
GPIOは例のごとく複数の機能を持ったものがあり、どこに何を繋ぐかが問題になります

僕の例を書いておくと
GPIO25にLEDを吊り下げで接続
GPIO24にタクトスイッチをプルアップ(アクティブL)で接続
GPIO14および15のUARTをピンヘッダに接続
4ピン及び6ピンに電源を接続
という感じになっています
UARTを使うのはSSHで接続できない場合のためで、あまり使うことはありません

電源は通常microUSBコネクタで供給しますが
1) USBポート経由の給電はあまり評判がよろしくない(長時間の安定性がよくないらしい)
2) USB出力の高容量な電源の手持ちが少ない
というような理由により通常のDCジャックから供給しています
ただし電源の逆接や異常な電圧が供給された際の保護がないのでそのあたりは要注意です


他に余ってるポートはSPIやI2Cくらいで、あまり複雑なことはできない、もしくは非常に複雑になってしまいます
例えば、とある応用ページではパラレル接続のモジュールを使うためにシリパラ変換ICを複数個カスケード接続して実現しています
このような規模になってくると、せめて外部に小さなARMマイコンを1個置いてソフトウェアで処理する等の方がはるかにスッキリと実現できますが、そうするとRasPiを使う必要性も薄れるために難しいところではあります

RasPiで実現できる範囲はUSB接続ができるものや、Ethernetを使ったIO それ以外ではRasPi専用に設計されたモジュールくらいが限界のようです

僕の感想としては「帯に短し襷に長し」という感じで
より低レベルなIOが必要なら普通のマイコンで実現したほうが楽だし、データ処理をさせたいなら一般的なPCのほうがはるかに使いやすいです
RasPiの最適な用途はちょっとしたEthernetアクセスのサーバー あたりでしょうか
この場合もあまり高負荷なことはできないはずなので 非常に微妙なところではあります

RasPiをFT232の母艦に

RasPiのUSBポートにFT232を接続してみました
FT232は言わずと知れたシリアル変換ICで、LinuxなどはOSに標準でドライバが入っていたりします
Raspbianでも同じように、ドライバをいれる必要なく接続できました

screenコマンドがなかったため、apt-get install screenで入れてやりましたが、それ以外は特に何も必要ありません
もちろんSSHからscreenを叩いて送受信することもできます

ただ、欠点というかなんというか、僕の環境ではscreenを終了することができませんでした
もちろんsshを終了すれば接続は切れるのですが、デバイスが解放されているわけではないので、次に使うにはrebootが必要になります

ただその辺りを解決できれば ピンヘッダに出ているシリアルポート以外に、USB接続でシリアルポートを使うこともできるはずです


参考
http://tomono.eleho.net/2011/02/28/646/