このページではLEGO Mindstorms EV3上で動作するRTCの作成を行います。
以下の作業は全てev3devにリモートログインして実行してください。
以下のコマンドでev3dev.luaを入手してください。
$ git clone -b master https://github.com/Nobu19800/ev3dev-lang
ev3dev-lang/lua/ev3dev.lua
を適当な場所にコピーしてください。
ev3dev.lua
と同じディレクトリにLuaファイル(今回はtest_ev3.lua)を作成してください。
以降はtest_ev3.lua
を編集して動作確認します。
test_ev3.lua
に以下のように記述することでev3devモジュールをロードしてください。
require 'ev3dev'
-- タッチセンサ初期化
s = TouchSensor()
-- ポートを指定する場合は、引数でポートを指定する。
-- s = TouchSensor("in1")
-- 接続したか確認
print(s:connected())
-- オンオフの確認
print(s:pressed())
-- ジャイロセンサ初期化
g = GyroSensor()
-- 接続したか確認
print(g:connected())
-- 角度の確認
print(g:value())
-- 超音波センサ初期化
u = UltrasonicSensor()
-- 接続したか確認
print(u:connected())
-- 距離の確認
print(u:value())
-- カラーセンサ初期化
c = ColorSensor()
-- 接続したか確認
print(c:connected())
-- 反射光の強さの確認
print(c:value())
print(Battery:voltageVolts())
-- Lモーター初期化
l = LargeMotor()
-- 以下はMモーターの場合
-- m = MediumMotor()
-- 接続したか確認
print(l:connected())
-- 速度調整機能をオンにします
-- ev3devのstretchではオンオフを切り替えることができないためpcallで呼び出す
pcall(
function()
l:setSpeedRegulationEnabled("on")
end
)
speed = 360
-- 速度の設定
-- カウント数を入力する
l:setSpeedSP(math.floor(speed/360*l:countPerRot()))
pos = 180
-- 位置の設定
-- カウント数を入力する
l:setPositionSP(math.floor(pos/360*l:countPerRot()))
-- 位置制御開始
l:setCommand("run-to-abs-pos")
-- Lモーター初期化
l = LargeMotor()
-- 以下はMモーターの場合
-- m = MediumMotor()
-- 接続したか確認
print(l:connected())
-- 速度調整機能をオンにします
-- ev3devのstretchではオンオフを切り替えることができないためpcallで呼び出す
pcall(
function()
l:setSpeedRegulationEnabled("on")
end
)
speed = 360
-- 速度の設定
-- カウント数を入力する
l:setSpeedSP(math.floor(speed/360*l:countPerRot()))
-- 速度制御開始
l:setCommand("run-forever")
-- 標準入力待ち
io.read()
-- 停止
l:setCommand("stop")
RTC BuilderによるRTCの基本的な作成手順は以下のページを参考にしてください。
上のページの作成手順に従って、以下の仕様のRTCを作成してください。
モジュール名 | EV3Sample |
onActivated
、onDeactivated
、onExecute
を有効にしてください。
ポート名 | velocity |
データ型 | TimedVelocity2D |
ポート名 | touch |
データ型 | TimedBooleanSeq |
先頭付近でev3dev
のモジュールのロードを行ってください。
ev3dev.lua
はEV3Sample.luaと同じディレクトリに配置してください。
require 'ev3dev'
onActivated
関数を以下のように編集してください。
タッチセンサ、Lモーターの初期化を行います。
function obj:onActivated(ec_id)
-- ポート1に接続したタッチセンサの初期化
self._touchsensor1 = TouchSensor("in1")
-- 接続失敗でエラーに遷移
if not self._touchsensor1:connected() then
return self._ReturnCode_t.RTC_ERROR
end
-- ポート3に接続したタッチセンサの初期化
self._touchsensor2 = TouchSensor("in3")
-- 接続失敗でエラーに遷移
if not self._touchsensor2:connected() then
return self._ReturnCode_t.RTC_ERROR
end
-- ポートBに接続したLモーターの初期化
-- 右側の車輪を回転させるモーター
self._lmotor1 = LargeMotor("outB")
-- 接続失敗でエラーに遷移
if not self._lmotor1:connected() then
return self._ReturnCode_t.RTC_ERROR
end
-- 速度調整機能をオンにする
-- ev3devのstretchではオンオフを切り替えることができないためpcallで呼び出す
pcall(
function()
self._lmotor1:setSpeedRegulationEnabled("on")
end
)
-- ポートCに接続したLモーターの初期化
-- 左側の車輪を回転させるモーター
self._lmotor2 = LargeMotor("outC")
-- 接続失敗でエラーに遷移
if not self._lmotor2:connected() then
return self._ReturnCode_t.RTC_ERROR
end
-- 速度調整機能をオンにする
-- ev3devのstretchではオンオフを切り替えることができないためpcallで呼び出す
pcall(
function()
self._lmotor2:setSpeedRegulationEnabled("on")
end
)
return self._ReturnCode_t.RTC_OK
end
onDeactivated
関数を以下のように編集してください。
Lモーターを停止する処理を書きます。
function obj:onDeactivated(ec_id)
-- ポートAのLモーターを停止
if self._lmotor1 ~= nil then
self._lmotor1:setCommand("stop")
end
-- ポートCのLモーターを停止
if self._lmotor2 ~= nil then
self._lmotor2:setCommand("stop")
end
return self._ReturnCode_t.RTC_OK
end
onExecute
関数を以下のように編集してください。
タッチセンサの値をOutPortから送信、InPortから受信した速度指令からLモーターの回転速度を計算して駆動する処理を書きます。
function obj:onExecute(ec_id)
-- 車輪の半径
local wheelRadius = 0.028
-- 車輪間の距離
local wheelDistance = 0.108
-- タッチセンサの値を格納
self._d_touch.data = {self._touchsensor1:pressed(),
self._touchsensor2:pressed()}
-- データにタイムスタンプを設定
openrtm.OutPort.setTimestamp(self._d_touch)
-- touchのOutPortからタッチセンサの値を送信
obj._touchOut:write()
-- velocityのInPortに入力がある場合
if self._velocityIn:isNew() then
-- データ読み込み
local data = self._velocityIn:read()
-- 直進速度vx、旋回角速度vaから左右の車輪の回転速度を計算
local r = wheelRadius
local d = wheelDistance/2.0
local vx = data.data.vx
local va = data.data.va
local right_motor_speed = (vx + va*d)/r
local left_motor_speed = (vx - va*d)/r
-- モーター1回転当たりのカウントを取得
local cpr1 = self._lmotor1:countPerRot()
local cpr2 = self._lmotor2:countPerRot()
-- 回転速度[rad]からモーターに指令するカウント数に変換
local speed1 = right_motor_speed/(2*math.pi)*cpr1
local speed2 = left_motor_speed/(2*math.pi)*cpr2
-- モーターに回転速度を指令
self._lmotor1:setSpeedSP(math.floor(speed1))
self._lmotor1:setCommand("run-forever")
self._lmotor2:setSpeedSP(math.floor(speed2))
self._lmotor2:setCommand("run-forever")
end
return self._ReturnCode_t.RTC_OK
end
事前にネームサーバーの起動が必要です。
※OpenRTM-aist 1.2以降ではRT System Editorにネームサーバー起動ボタンがあるため、手順が簡単になっています。
TkJoyStickコンポーネントを入手して、TkJoyStickComp.exe
を実行してください。
FloatSeqToVelocityコンポーネントを入手して、FloatSeqToVelocity.exe
を実行してください。
EV3のタッチセンサ、Lモーターを以下のように接続して、電源を投入してください。
ポート | デバイス |
---|---|
ポート1 | タッチセンサ(左) |
ポート3 | タッチセンサ(右) |
ポートB | Lモーター(右) |
ポートB | Lモーター(左) |
EV3にTera Term等でリモートログインしてEV3Sample.lua
をEV3に転送してください。
転送後、以下のコマンドを実行してください。 RTCの起動には1分程かかります。
$ lua EV3Sample.lua -o corba.endpoints:EV3のIPアドレス
まずRTCの起動に成功している場合は、以下のようにネームサービスビューにRTCが表示されます。
Open New System Editor
ボタンを押してシステムダイアグラムを表示してください。
ネームサービスビューからシステムダイアグラムにRTCをドラックアンドドロップしてください。
TkJoyStick0
のpos
のOutPortをFloatSeqToVelocity0
のin
のInPortに、FloatSeqToVelocity0
のout
のOutPortをEV3Sample0
のvelocity
のInPortにドラックアンドドロップしてください。 これで通信ができるようになります。
All Activate
ボタンを押すとTkJoyStick0
からデータが送信されるためEV3の操作ができるようになります。