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を使った「制御プログラムの作り方」』として書いてみました。