Android Thingsの概要とKotlinでのLチカ

  • 0
    Like
  • 0
    Comment

    はじめに

    Android Thingsの登場により、AndroidでもGPIOやI2C、SPI、PWMを通してセンサーやインプットをいじることができるようになりました。既存のAndroidの知識を活かしつつ、IoTデバイスの開発が行うことができて、かつAndroid Things Consoleを使うことでOTA(Over-The-Air)からソフトウェアのアップデートすることが可能になります。Google社によるAndroidのサポートとConsoleの存在は、クラウドインフラを持たないIoTスタートアップにとっては大きなメリットになるのではないでしょうか。

    今回はAndroid Thingsのユースケースを調べたり、KotlinでのLチカをトライしてみたので紹介します。

    Android Thingsの特徴

    既存のAndroidと比べて、Android Thingsでは何が新しいでのしょうか。FaBo,incの佐々木さんのスライド "はじめてのAndroid Things"によれば、Android Thingsの特徴として以下のようなものが挙げられています。

    • Peripheral I/O APIの追加
    • User Driver APIの追加
    • Board Support Package(BSP)をGoogleが管理
    • Android Things Console

    公式ページに掲載されている以下の図から分かるように、Android Thingsアプリケーションは既存のJava APIやGoogleサービスを活用しつつGPIOやI2C、SPIなどを使うことができるようになっています。

    platform-architecture.png
    Android Thingsの構造 - Overviewより

    Realm社のページにGoogle社のDave Smithさんの分かりやすいスライドがまとめられているので、いくつか引用させていただきます。雰囲気だけでも掴んでいただけるのではないでしょうか。

    04.jpg
    Android Thingsのメリット

    01.jpg
    ユーザドライバとアプリケーションの開発はデベロッパーが行う

    02.jpg
    既存のAndroidがカバーするAPI

    03.jpg
    Android ThingsがカバーするAPI

    05.jpg
    Android ThingsのPeripheral I/O

    Dave Smith, "Just Android Things"より引用

    ユースケース

    ロンドンで行われたdroidcon London 2017では、Android Thingsを使ったデバイスとして、ドローンやdrawBotと呼ばれるお絵かきロボット(デモ動画を要参考)が展示されたようです。

    google-demonstrates-android-things-in-action-at-droidcon-uk-electronics-weekly-maxresdefault.jpg
    "Drones, Things and Android galore at droidcon London 2017" より

    他にもHacksterというIoTのレシピサイトで検索すると面白そうなものが出てきます。いくつか取り上げてみますと、

    img_20171009_125629_qpzUZCMYEc.jpg
    "Android Things Word Clock"より引用

    1-r0lzm9zq58j5fiaax5owkw_Hbnx9AyoMZ.jpeg
    "BrailleBox - Braille News Reader"より引用

    日本国内の動向としては、富士通とNXPが共同でAndroid Thingsを使ったIoT開発ソリューリョンの提供を2018年から開始するというものがあるようです。

    参考:

    使用したハードウェア

    Android Thingsを動かすことができるハードウェアはこちらから確認することができます。お馴染みのRaspberry Pi 3も使うことができますが、今回は開発用ボードPICO-PI-IMX7-STARTKIT
    NXP Pico i.MX7Dを使用しました。


    PICO-PI-IMX7-STARTKIT-RAINBOW-HAT - Tech Nexionより引用

    PICO-PI-IMX7-STARTKIT
    NXP Pico i.MX7D


    題材

    Android Thingsの公式チュートリアルBuilding Your First Deviceの内容を総合して、ボタンが押されたらLEDの点灯または消灯を行うアプリケーションを実装してみます。

    デモ

    demo2-compressor.gif

    Android Studio 3

    Android Studio 2.xではAndroid Thingsのウィザード画面がないので、Android Studio 3をインストールしましょう。

    https://developer.android.com/studio/index.html?hl=ja

    プロジェクトの準備

    通常のAndroidアプリのプロジェクトと同様に、ウィザード画面に進みます。

    今回はせっかくAndroid Studio 3.0からウィザード画面からオプションとしてKotlinを選択できるようになったので使ってみましょう。アプリ名を入れて"Include Kotlin Support"にチェックを入れます。

    ttt01.jpg

    次に"Android Things"にチェックを入れます。APIレベルは26にしました。

    ttt02.jpg

    "Android Things Empty Activity"を選択します。

    ttt03.jpg

    "Finish"をクリックします。

    ttt04.jpg

    Hello, World!

    はじめに以下のようなプログラムを動かしてみます。

    • ハードウェアやボードの情報などを出力する
    • GPIO/SPI/PWMなどのピン名を出力する(ここで表示された文字列を使って、ピンを扱います)
    import android.app.Activity
    import android.os.Build
    import android.os.Bundle
    import android.util.Log
    import com.google.android.things.pio.PeripheralManagerService
    
    class MainActivity : Activity() {
        private val TAG = "MainActivity"
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            Log.d(TAG, "BOARD:" + Build.BOARD)
            Log.d(TAG, "DEVICE:" + Build.DEVICE)
            Log.d(TAG, "BRAND:" + Build.BRAND)
            Log.d(TAG, "PRODUCT:" + Build.PRODUCT)
            Log.d(TAG, "CPU_ABI2:" + Build.CPU_ABI2)
            Log.d(TAG, "HARDWARE:" + Build.HARDWARE)
            val manager = PeripheralManagerService()
            Log.d(TAG, "GPIO:" + manager.gpioList.toString())
            Log.d(TAG, "PWM:" + manager.pwmList.toString())
            Log.d(TAG, "I2C:" + manager.i2cBusList.toString())
            Log.d(TAG, "SPI:" + manager.spiBusList.toString())
            Log.d(TAG, "UART:" + manager.uartDeviceList.toString())
            Log.d(TAG, "I2S:" + manager.i2sDeviceList.toString())
        }
    }
    

    実行結果 :

    D/MainActivity: BOARD:imx7d
    D/MainActivity: DEVICE:imx7d_pico
    D/MainActivity: BRAND:Things
    D/MainActivity: PRODUCT:iot_imx7d_pico
    D/MainActivity: CPU_ABI2:armeabi
    D/MainActivity: HARDWARE:imx7d
    D/MainActivity: GPIO:[GPIO_10, GPIO_128, GPIO_172, GPIO_173, GPIO_174, GPIO_175, GPIO_32, GPIO_33, GPIO_34, GPIO_35, GPIO_37, GPIO_39]
    D/MainActivity: PWM:[PWM1, PWM2]
    D/MainActivity: I2C:[I2C1]
    D/MainActivity: SPI:[SPI3.0, SPI3.1]
    D/MainActivity: UART:[UART6]
    D/MainActivity: I2S:[I2S3]
    

    ピン配置

    ではさっそくLチカのプログラムを作っていきます。まずはボードにピンを配置していきましょう。

    以下の図では、RaspberryPi 3のものですが、NXP Pico i.MX7Dに置き換えてください。

    ボード側のピン番号 Android Things側のピン名
    01(3.3V)
    06(GND)
    31(GPIO06) GPIO_34
    40(GPIO21) GPIO_174

    LED_Button.png

    Lチカのソースコード

    import android.app.Activity
    import android.os.Bundle
    import android.os.Handler
    import android.util.Log
    import com.google.android.things.pio.PeripheralManagerService
    import com.google.android.things.pio.Gpio
    import java.io.IOException
    import com.google.android.things.pio.GpioCallback
    
    class MainActivity : Activity() {
        private val TAG = "MainActivity"
        private val LED_PIN_NAME = "GPIO_34"
        private val BUTTON_PIN_NAME = "GPIO_174"
        private var mLedGpio: Gpio? = null
        private var mButtonGpio: Gpio? = null
        private val mHandler = Handler()
        // Callback for button
        private val mCallback = object : GpioCallback() {
            override fun onGpioEdge(gpio: Gpio?): Boolean {
                Log.i(TAG, "GPIO changed, button pressed")
                val mLedGpio = mLedGpio ?: return false
                try {
                    mLedGpio?.value = !mLedGpio.value
                } catch (e: IOException) {
                    Log.e(TAG, "Error on PeripheralIO API", e)
                }
    
                return true
            }
        }
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            val service = PeripheralManagerService()
            Log.d(TAG, "Available GPIO: " + service.gpioList)
            try {
                // Setup LED
                mLedGpio = service.openGpio(LED_PIN_NAME)
                mLedGpio?.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW)
                mLedGpio?.value = false
                Log.i(TAG, "Setup LED pin")
                // Setup Button
                mButtonGpio = service.openGpio(BUTTON_PIN_NAME)
                mButtonGpio?.setDirection(Gpio.DIRECTION_IN)
                mButtonGpio?.setEdgeTriggerType(Gpio.EDGE_FALLING)
                mButtonGpio?.registerGpioCallback(mCallback)
                Log.i(TAG, "Setup Button pin")
            } catch (e: IOException) {
                Log.e(TAG, "Error on PeripheralIO API", e)
            }
        }
        override fun onDestroy() {
            super.onDestroy()
            mHandler.removeCallbacks(mBlinkRunnable)
            mButtonGpio?.unregisterGpioCallback(mCallback)
            try {
                mLedGpio?.close()
                mButtonGpio?.close()
            } catch (e: IOException) {
                Log.e(TAG, "Error on PeripheralIO API", e)
            }
        }
    }
    

    実行すると、上のほうであげたデモのように動くと思います。

    参考資料

    おわりに

    Androidの延長としてIoTにチャレンジできるのはとても魅力的ではないでしょうか。Android Oreo(v8.1)ではAndroid NN APIも控えています。機械学習や深層学習も巻き込んでIoTデバイスの開発はますます面白くなってくると思われます。

    次はOTA(Over-The-Air)やFireBaseとの連携にトライしてみたいです。