BBBでシリアル通信
概要
BeagleBoneBlack(BBB)のシリアルポートUART4(P9 11:RXD,13:TXD)を使えるようにする。
背景
ある探査ロボットのモータ制御をRS485で行う必要があり、RS232でしゃべれるBBBを利用した。
その際に、手始めに、BBBでシリアル制御を行ったのでその備忘録。
この後、pythonからシリアル制御を行ったのでそれも近日中に記載予定。
RS232C<-->RS485コンバータの製作についても記載するかも。
手順
設定
以下の設定を行いreboot。UART4の部分は設定を行いたいものに読み替え。
$ diff -u /boot/uboot/uEnv.txt~ /boot/uboot/uEnv.txt --- /boot/uboot/uEnv.txt~ 2014-05-15 23:58:50.000000000 +0000 +++ /boot/uboot/uEnv.txt 2014-06-20 01:28:44.000000000 +0000 @@ -17,7 +17,7 @@ ##BeagleBone Black: ##Disable HDMI/eMMC #optargs=capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN,BB-BONE-EMMC-2G - +optargs=quiet drm.debug=7 capemgr.enable_partno=BB-UART4 console=ttyO0,115200n8 mmcroot=UUID=526efd31-8f31-4dc6-8b5d-ac3a2b3736e2 ro
reboot後、/dev/ttyO4が見えるようになる。ちなみに、ttyO0は、オンボードのデバッグ用シリアルピン。
シリアル通信の設定を行う。
$ sudo stty -F /dev/ttyO4 raw $ sudo stty -F /dev/ttyO4 9600
P9 11,13をシリアルで別の端末に接続。写真のような感じで。
端子同士の配線は以下。
動作確認
TeraTermなどでシリアルを9600bpsで開いた状態で、BBBから以下を実行。
$ sudo su - # echo "Hello,nihohi" >/dev/ttyO4
無事表示されました。
BBB側も、ttO4をcatして、TeraTerm側からも文字を送ると受信にも成功。
# cat /dev/ttyO4 moge^C hello,nihohi!
※2014/09/28追記。
もし2つのデバイスを有効化する場合(例えばttyO2とttyO4)、前述の/boot/uboot/uEnv.txtで、以下のようにカンマ区切りでデバイスを設定すればOK。
capemgr.enable_partno=BB-UART2,BB-UART4
今後の更新予定/備忘
- (自分向け。見たときに思い出せるように)
決意/方針
- ドタバタしてていろいろ放置気味だったので、完璧に仕上がらなくても一部でも知見を共有できるように徐々に更新して行こう...。
- 「あっ、と気付いたこと」、「心に引っ掛かったこと」、「これ知ってると便利なのに」、や、「面白い/愉快と感じたこと」を中心に。
- 無理に分野に分けるより、上記分類でタグ付けた方が自分の中ではわかりやすいかも。
- あと、これらの一見異なるものがすべてリンクしているというのも表明できると面白いかも。
ソフトウェア技術ネタ
今後ぼちぼちアップして行こう
実験ネタ
- .11ac距離計測
- 月面探査ローバー開発の話
- 鉱山跡探訪
- 砂鉄が良く取れるところ
- 自宅製鉄実験
社会ネタ? 生活ネタ? 考え方?
シリアル通信(RS232C/422A/485)の特徴まとめ
概要
背景
- BBBでモータードライバとシリアル通信する際にRS232Cだけでなく、RS485も使うことになったので、シリアル通信の整理と、サンプルコード、その際に利用したコンバータの情報などを整理しておきたいと思ったため。
環境
// 書く
RS232C/422A/485の特徴
- RS485はRS422Aの上位互換があるらしい。(RS485が改良版)
規格 | 最大伝送速度 | 最大ケーブル長 | 接続形式 |
---|---|---|---|
RS232C | 20kbps | 15m | 1:1 |
RS422A | 10Mbps | 1200m | 1:N (Nmax:10) |
RS485 | 10Mbps | 1200m | N:N (Nmax:32) |
- 参考
- シリアル通信の基礎知識 - RS-232C / RS-422 / RS-485 http://www.contec.co.jp/product/device/serial/basic.html
コンバータ
// RS232C<->RS485のコンバータ。BBBで動作実績あり。写真も。
コード
// 書く
cythonでpythonの計算時間を100倍に 〜(1)cythonのcdefを使う〜
概要
ある単純な足し算の計算速度向上をcythonの2つの機能を使うことで試みた。
(1)cdefを使う
純粋なpythonを使った場合と、cythonを使った場合で計算時間を比較を行った。
その結果、cythonで、cdef利用した場合には(ある条件下では)50倍程度高速化された。
(後述の環境では、5.7[sec]かかっていたものが、100[msec]程となった。)
(2)nogilを使う
cythonのwith nogilを使うことで、GIL(Global Interpreter Lock)の制限解除を行うことが出来る。
(<--pythonのAPIは一切使えない、thread切り替えのoverheadがあるなど、注意点もあるとのことだが)
GIL解除+multithreadingで、複数コア環境で更に倍速にすることを試みた。
"(2)"は近日中記載予定。
以下では、"(1)"について記載する。
背景
PyCon2013(2013/09/14-15@新宿/工学院大学)で、cythonを使うと、高速化できるという話を伺ったので、遊んでみようと簡単な例を試してみたという次第。
聴講したセッションは、以下。
「Cythonによる拡張モジュール開発」(Atsuo Ishimoto氏)
http://apac-2013.pycon.jp/zh/program/sessions.html#session-14-1630-rooma0765-ja2-en
資料:http://www.slideshare.net/atsuoishimoto/introduction-to-cython
動画:http://www.youtube.com/watch?v=eo6YcwQZV8k
# 48'06"あたりから、自分の質問も残っていたりw
環境
OS:(仮想系内)Ubuntu10.04
CPU:(仮想系内)Intel(R) Core(TM) i7-2670QM CPU @ 2.20GHz * 2
Mem:(仮想系内)4GB
コード
C,python,cython+pythonのコードを用意し、単純な足し算での速度比較を行ってみた。
C言語
simple_add_pure_c.c
#include <stdio.h> int main(){ long long a=0; long long i=0; for(i=0; i<100000000; i++){ a += i; } printf("%lld\n",a); return 0; }
python
simple_add.py
#! /usr/bin/env python # -*- coding: utf-8 -*- def simple_add(): a = 0 for i in range(100000000): a += i return a if __name__ == "__main__": print simple_add()
python+cython(cdefなし)
simple_add2.pyx
def simple_add(): a = 0 for i in range(100000000): a += i return a
simple_add2_cython.py(cythonモジュールを呼ぶ人)
#! /usr/bin/env python # -*- coding: utf-8 -*- if __name__ == "__main__": import simple_add2 print simple_add2.simple_add()
python+cython(cdefあり)
simple_add2_cdef.pyx
def simple_add(): cdef int i,a a = 0 for i in range(100000000): a += i return a
simple_add2_cython.py(cythonモジュールを呼ぶ人)
#! /usr/bin/env python # -*- coding: utf-8 -*- if __name__ == "__main__": import simple_add2_cdef print simple_add2_cdef.simple_add()
実行(ビルド/時間測定)
cのコード --> 2[msec]ほど
$ gcc -O2 simple_add_pure_c.c -o simple_add_pure_c $ time ./simple_add_pure_c real 0m0.002s user 0m0.010s sys 0m0.000s
python --> 8[sec]ほど
$ time ./simple_add.py real 0m8.138s user 0m6.660s sys 0m1.470s
cython(cdefなし) --> 5[sec]ほど
$ cython simple_add2.pyx $ export PYTHON_H_DIR=/usr/include/python2.6 $ gcc -c -O2 -fPIC -I$PYTHON_H_DIR simple_add2.c -o simple_add2.o ※最適化オプション(-O2)つけないと、あまり速くならなかった。(あたりまえといえばあたりまえ) $ gcc -shared -o simple_add2.so simple_add2.o $ time ./simple_add2_cython.py real 0m5.516s user 0m4.290s sys 0m1.220s
cython(cdefあり) --> 100[msec]ほど
$ cython simple_add.pyx $ export PYTHON_H_DIR=/usr/include/python2.6 $ gcc -c -O2 -fPIC -I$PYTHON_H_DIR simple_add2_cdef.c -o simple_add2_cdef.o $ gcc -shared -o simple_add2_cdef.so simple_add2_cdef.o real 0m0.100s user 0m0.090s sys 0m0.020s
参考
Pythonを高速化するCythonを使ってみた
http://kesin.hatenablog.com/entry/20120306/1331043675
追記
2013/09/18 Mi.
"実行"の"最適化オプション"について補足
2013/10/18 Fr.
社内勉強会で発表。指摘事項を反映。
int -> long longに変更(overflowしていたorz)
結果も確認出来るように、print文を追加。
aの初期化漏れ対応。a=0を追加。
celeryでclassのmethodを利用する方法
概要
django+celeryを利用して、あるクラスの処理を非同期に処理しようとした際に、メソッドを利用するところで、「takes exactly 2 arguments (1 given)」と怒られた。
(selfが渡っていないときなどによく見るエラー)
調べてみると、celeryから、classのmethodを利用する際には、それに応じた手続きが必要なようであったので、以下その方法を記載しておく。
背景
あるクラス(Converterというクラス)に含まれるメソッド"convert()"を利用した際に、「raised exception: TypeError('convert() takes exactly 2 arguments (1 given)',)」と怒られた。
本家のドキュメント(celery.contrib.methods)にあったので、それを参考に、後述の様に書き換えたところ動いた。
上記サイトによれば、taskのベースクラスが新しくなったそうで、これまでのような古い書き方は推奨されないらしい。
The task must use the new Task base class (celery.Task), and the old base class using classmethods (celery.task.Task, celery.task.base.Task).
This means that you have to use the task decorator from a Celery app instance, and not the old-API:
from celery import task # BAD
from celery.task import task # ALSO BAD
(略)
ということで、以下自分の使ったクラス(Conveterクラス)を例に、手順を示す。
元々のConverterクラスはこんな感じ。
from celery import task class Converter(object): def __init__(self, converter="xxx", file_format="yyy"): pass # いろいろ処理 @task() def convert(self, in_file): pass # いろいろ処理
以下の様に書き換えた。(from celery ... --> from celery.contrib.methods ...)
from celery.contrib.methods import task class Converter(object): def __init__(self, converter="xxx", file_format="yyy"): pass # いろいろ処理 @task() def convert(self, in_file): pass # いろいろ処理
あとは、普通に、非同期実行でOK。
$ python Python 2.6.6 (r266:84292, Sep 11 2012, 08:34:23) [GCC 4.4.6 20120305 (Red Hat 4.4.6-4)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from xxx.converter import Converter >>> c = Converter() >>> c.convert.delay("xxx/aaa.bbb") <AsyncResult: 43c72c43-f535-45f0-b6a2-2ed60897c352> >>>
celery側のログ
[2012-12-02 03:32:37,116: INFO/MainProcess] Task xxx.converter.convert[50e07a93-6eef-48f8-84f8-249d03354089] succeeded in 0.123465061188s: 'xxx/aaa.bbb'