Android ThingsでPeripheral Driver Libraryを使って、サーボを動かす

More than 1 year has passed since last update.

せっかくなので短めの内容で、Advent Calendarを埋めていきたいと思います。

今回はAndroid ThingsでPeripheral Driver Libraryを使って、サーボを動かしてみます。


Peripheral Driver Library

Peripheral Driver Libraryは一般的によく使われるセンサーや、電子部品を、

アプリケーションで使いやすくするためのライブラリ群です。

Peripheral Driver Libraryは

サーボなどのよく使う電子部品を扱いやすいようにラップしたものと、

GPS、Button等をAndroid Frameworkに組み込んで利用するUser Driverが含まれています。

通常、一部のセンサーは、センサーメーカーが、アプリケーションから扱いやすいようにライブラリなどを提供しています。

ただ現状ではメーカーがAndroidThings向けにこういったライブラリを提供していることはなく、

このPeripheral Driver Libraryから探すか、自分で作るかしかありません。

現状Peripheral Driver Libraryはgithubにまとまっています。自分でライブラリを作ったり、

User-Driverを作る場合は参考にしてみてください。

https://github.com/androidthings/contrib-drivers


pwmservoを利用してサーボを動かす

とりあえずコードは以下にあります。

https://github.com/soundTricker/SampleServo


配線

以下の感じです。

servo.png


build.gradle

Servoを扱うためには、com.google.android.things.contrib:driver-pwmservoを利用します。

以下のようにbuild.gradleで指定します。


build.gradle

implementation 'com.google.android.things.contrib:driver-pwmservo:0.3'



AndroidManifest.xml

特に追加のPermissionはありません。

AndroidThings用にuses-libraryとintent-filterを追加します。

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.github.soundtricker.androidthings.sampleservo">

<application>
<uses-library android:name="com.google.android.things" />

<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.IOT_LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>

</manifest>


MainActivity#onCreate

onCreateでServoクラスを初期化します。setAngleRangeで最大最小の角度を設定。

setPulseDurationRangeでpwmの周波数の最大値と最小値を設定します。

周波数の最大値、最小値はサーボごとで異なるので、datasheetを御覧ください。

安いところで買うとついてない時もありますが....

またUI Threadを邪魔しないようにHandlerThreadを使います。UIがないならHandlerだけでもいいです。多分。


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
try {
mServo = Servo(PIN_PWM)
mServo!!.setAngleRange(0.0, 180.0)
mServo!!.setPulseDurationRange(MIN_PULSE_MS, MAX_PULSE_MS)
mServo!!.setEnabled(true)
} catch (e: Exception) {
Log.e(TAG, "Error creating Servo", e)
return
}
mHandlerThread = HandlerThread("servo")
mHandlerThread.start()
mHandler = Handler(mHandlerThread.looper)
currentAngle.text = "0.0"
angleText.setText("0.0")
speedText.setText("5.0")
setAngle(0.0)
}


MainActivity#setAngle

角度の設定を行います。

通常PWMサーボだと速度が設定できないので適当な角度ごとにインクリメントして、スピード調整をします。

mServo!!.angle = targetAngleだけでサーボを動かせるので楽ですね。

もしServoライブラリを使っていない場合は自分でDutyの計算をする必要があります。

private fun setAngle(angle: Double) {

mAngle = angle
mHandler.post(mRunnable)
}

private val mRunnable = Runnable {
if (mServo == null) {
return@Runnable
}
try {
while (mAngle != mServo!!.angle) {

var targetAngle: Double
if (mAngle > mServo!!.angle) {
targetAngle = mServo!!.angle + mSpeed
targetAngle = Math.min(targetAngle, mAngle)
} else {
targetAngle = mServo!!.angle - mSpeed
targetAngle = Math.max(targetAngle, mAngle)
}

targetAngle = Math.min(targetAngle, mServo!!.maximumAngle)
targetAngle = Math.max(targetAngle, mServo!!.minimumAngle)

mServo!!.angle = targetAngle
runOnUiThread {
currentAngle.text = targetAngle.toString()
}
Thread.sleep(1)
}
} catch (e: IOException) {
Log.e(TAG, "Error setting Servo angle")
}

}


まとめ

とりあえず今回はサーボを動かしてみました。

まだまだPeripheral Driver Libraryは数が少ないのです。自分が使おうとしているセンサーのライブラリがないことが多々あるので、Peripheral Driver Libraryの実装を参考にしながら作ってみるといいと思います。