2009-07-30[n年前へ]
■ComThreadを使った「制御プログラムの作り方」
比較的単純なハードウェア制御、たとえば、(シリアル・ポートから値を得ることができる)センサからの入力を使い、(シリアル・ポートからコマンドを送ることで制御することができる)ハードウェアの制御をしたくなることがあります。実例としては、温度センサの値を使い、扇風機のモーターON/OFFを行いたい、というような場合があります。そんな場合のために、(以前作った)RubyのComThreadを使った「制御プログラムの作り方」を、自分のためのメモがてらここに書いておこうと思います。
まずは、センサーやモーターの各ハードウェア、つまり、各シリアル・ポート毎に個別のクラスを作っておきます。たとえば、センサーの値にアクセスするクラスをこんな感じで作り、
require 'comThread' class SensorComThread < ComThread def start(condition={:receive=>false,:send=>false, :receiveMonitor=>false, :sendMonitor=>false}) @info={} super end attr_reader :info def receive(data) @info=data.gsub(' ','').split(',') end end次に、たとえば、モーターを操作するクラスをこんな感じで作ります。
require 'comThread' class MotorComThread < ComThread def sendStart send("start") end def sendStop send("stop") end end各シリアル・ポートに接続された機器に対する「値解釈」や「送信コマンド作成」といった部分は、上のような具合で、各ポート(に接続された各種機器)を扱うクラスを個別に定義しておく方が頭が整理しやすいように思います。
そして、次は制御用のメイン・コントローラ・クラスを書きます。
require "thread" class ControlerThread def initialize end def start(inf) @sensor=inf[:sensor] @motor=inf[:motor] @thread=Thread.new do while true @motor.sendStop if @sensor.info[0].to_f<hoge @motor.sendStart if @sensor.info[0].to_f>=hoge end end end def stop Thread.kill(@thread) end end
最後に、センサ用コントローラ/モータ用コントローラ/メイン制御コントローラを、それぞれ起動する制御スクリプトを、次のように書きます。
require "sensorThread" require "motorThread" require "controlerThread" sendorRq=Queue.new; MotorSq=Queue.new; sensor=SensorComComThread.new(1,sensorRq,nil, 0x1807,38400) sensor.start(:receive=>true) motor=MotorThread.new(2, nil,motorSq,0x1807,38400) motor.start(:send=>true) controler=ControlerThread.new controler.start({:sensor=>motor,:motor=>motor}) sleep ARGV[0].to_i controler.stop motor.stop sensor.stopこのように、各I/Fに対するコントローラと、メイン制御コントローラと、それらコンローラ・スレッド群を実行するシーケンス・スクリプトを個別に作る、というのが良いように思われます。
というわけで、日曜大工的なハードウェア制御プログラムを書いたので、プログラムを書き連ねながら考えたことを、ここに『ComThreadを使った「制御プログラムの作り方」』として書いてみました。
2009-08-30[n年前へ]
■NI/SolidWorksのメカトロ・バーチャル・プロトタイピング・ツール
「日本NI、SolidWorksと共同開発のメカトロニクスの バーチャルプロトタイピング・ツールを発売」
NI LabVIEWは、設計の段階で機械的なサブシステムと電気的なサブシステムの相互作用をシミュレーションでき、LabVIEW 2009 NI SoftMotionモジュールプレミアムはセンサーからのフィードバックに基づく高度なモーション制御を扱う関数を備えている。
2009-09-16[n年前へ]
■Robotics Developer StudioとXbox 360コントローラで ロボット制御シミュレーションを体験してみよう
「Robotics Developer StudioとXbox 360コントローラでロボット制御シミュレーションを体験してみよう」
対象読者
* ビジュアルプログラミング言語(VPL)に興味のある方。
* シミュレーション環境に興味のある方。
* ロボット実機は持っていないが、ロボット制御に興味のある方。
2009-11-11[n年前へ]
■Rubyシリアル通信用スレッドクラスで簡単なバイナリ受信処理をしてみよう
以前、Rubyでシリアルポート通信(いわゆるRS-232C)を楽に行うためのクラス"ComThread"を作りました(ここが関連ファイルの置き場です)。そのcomThread.rbを使えば、たとえば、COM3で受信した内容をコンソールに出力するだけであれば、このようなコードで動く、というようなものです。
require 'comThread' receiveComThread=ComThread.new({:icomno=>3}) receiveComThread.start({:receive=>true, :receiveMonitor=>true}) sleep 60 receiveComThread.stopこれは、「シリアルポートを使って簡単に各種機器からの情報を取得したり、あるいは操作したりするためのクラス」です。もうひとつ例を挙げれば、「シリアルポートで受信した内容を最前面アプリにキー送信するアプリケーション」くらいであれば、以前書いたように十行程度のコードを書けば「はい、できあがり」という具合に(少なくとも私が良く見るシチュエーションにおいては)割に使いやすいクラスです。
ところで、シリアルポートで送受信を行う機器は多いですが、ものによってはASCII(アスキー)コードでなく、バイナリでデータを送ってくるものもあります。小型の計測器などでは、そんな風にシリアルポート(見かけ上はUSB接続で)経由で出力をバイナリ送信するものも多いかもしれません(もちろん、テキスト送信するものも多いです)。そんな場合でも、簡単なものであれば、comThread.rb でも普通に処理を行うことができます(データが頻繁に大量に送られてくるようなものは扱えません)。
そこで、バイナリデータをシリアルポートに送りつけてくる機器に対応するスクリプトを書いてみましょう。それは、たとえばこんな具合です。
require 'comThread' class Comport def receive(size) rcv=@com.receive ret=nil if rcv!=nil if rcv.length==size aHigh=rcv[0] & 0b00001111 aLow=rcv[1] re+=(aHigh*255+aLow).to_s end end ret end end period=ARGV[0] # time(seconds) Waint 10 # waint to activate teraterm receiveComThread=ComThread.new( {:icomno=>4, :ibaud=>57600}) receiveComThread.start( {:receive=>true, :receiveMonitor=>true, :delimeter=>4}) sleep period receiveComThread.stopこれは「4バイトのデータ列を定期的に出力する機器のデータを(COM4に57600bpsで受信し)パース処理した上で、その結果をテキストに変換しコンソール出力する」というスクリプト例です。
バイナリデータとしては、1バイト目のがハイバイトで、2バイト目がローバイトからなるデータ構成になっていて、さらに、ハイバイトは下位4ビットのみが使われる、というような処理がなされています。
サンプル用に書いたので、本来なら書くべき処理をはしょっています。それでも、数バイト程度のデータが、数秒の時間間隔で送信されるような機器のデータ加工程度の用途であれば、(たまにデータを処理しないで無視してしまうこともあるでしょうが)こんなものでも、(プロトタイピング用途としては)十分使うことができることもあるのではないでしょうか。
ところで、comThread.rbを少し手直ししました。そのため、(今日段階で置いてある)zipファイルは以前作ったものとサンプルソース類となっていて、comThread.rbの方は、今日少し作りなおしたものとなっています。異なるのは、ComThread.start の部分に、delimeter指定が入っていること・メンテナンスがしやすいように内部で使う関数の引数をHash(ハッシュ)で渡すようにした、ということくらいです。とはいえ、そのまま上位互換で使うことができるのではないか、(多分)と思います。動かない場合があれば、メールして頂ければ、時間を作って直しておきます。
ふと気付くと、最近Perlを触っていないような気がします。来週あたりは、Perlでも使って何かしてみることにしましょうか。
2009-12-08[n年前へ]
■ 技術革新の三つの潮流に合わせてMATLAB/Simulinkの改良を継続 autoki
「技術革新の三つの潮流に合わせ MATLAB/Simulinkの改良を継続 ―― MATLAB EXPO 2009レポート 《基調講演編》」
1. システムのモデル化 2. モデル・ベースの開発 3. 並列コンピューティング
ここで挙げられている1,2,3、特に何より1,2は因果関係を明らかにした上での・最も適切な制御を適切な塩梅で(ロバストに)行うために、とても重要なことだろう。