Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

@soundTricker

Android ThingsとA/D変換(MCP3008)

今日はAndroid Things on Raspberry PIでA/D変換をします。
Raspberry Piにはアナログ入力がないので、アナログ入力が必要な場合はA/Dコンバーターが必要です。
手元にあるA/DコンバーターがMCP3008しか無いので、MCP3008を使ってやります。

ハードウェア

以下の構成です。
可変抵抗から読み取った値を使ってサーボを動かします。

potentionmeter.png

可変抵抗から読み取ったアナログ値をMCP3008を使ってA/D変換します。

コード

MCP3008の公式Peripheral Driver Libraryは現在ありません。
個人で作った方がいるようです。
https://github.com/PaulTR/AndroidThingsMCP3008ADC

ただ、maven repositoryには登録してない臭いので、コピペして使います。
サーボについては、Peripheral Driver LibraryにあるPwmServoを利用します。

今回のコードは以下においてあります。
https://github.com/soundTricker/analog-digital-convert

メインどころ

複雑なところはあんまりないですね
センサーからデータを読み取ることろは、Handlerを使って、キューに積んで処理しています。

またmap関数は読み取り値→角度の変換処理を主に行ってます。

MainActivity.kt

package com.github.soundtricker.androidthings.analogdigitalconvert

import android.app.Activity
import android.os.Bundle
import android.os.Handler
import android.util.Log
import com.google.android.things.contrib.driver.pwmservo.Servo
import java.io.IOException


class MainActivity : Activity() {


    companion object {
        private val TAG = MainActivity::class.java.simpleName

        private val PIN_CS = "BCM25"
        private val PIN_CLOCK = "BCM17"
        private val PIN_MOS_IN = "BCM24"
        private val PIN_MOS_OUT = "BCM23"
        private val PIN_SERVO = "PWM1"

        private val CHANNEL_POTENTIONMETER = 0x0
        private val MIN_VOL = 0
        private val MAX_VOL = 410
        private val MIN_ANGLE = 0
        private val MAX_ANGLE = 180

    }

    private lateinit var mcp3008: MCP3008
    private lateinit var mcpHandler: Handler

    private lateinit var servo: Servo

    private val readChannelMoveServo = Runnable {
        readAndMoveServo(CHANNEL_POTENTIONMETER)
    }

    private fun readAndMoveServo(readChannel: Int) {
        val vol = this.mcp3008.readAdc(readChannel)
        Log.i(TAG, "ADC $readChannel: $vol")

        val angle = map(vol, MIN_VOL, MAX_VOL, MIN_ANGLE, MAX_ANGLE)
        val prevAngle = this.servo.angle

        if (Math.abs(prevAngle - angle) <= 3) {
            return
        }
        Log.i(TAG, "ANGLE $readChannel: $angle")
        this.servo.angle = angle
        runReadChannel()
    }


    private fun runReadChannel() {
        this.mcpHandler.postDelayed(this.readChannelMoveServo, 10L)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        try {
            this.servo = Servo(PIN_SERVO)
            this.servo.setPulseDurationRange(0.6, 2.35)
        } catch (e: IOException) {
            Log.e(TAG, "servo can't initialized", e)
            return
        }
        this.mcp3008 = MCP3008(PIN_CS, PIN_CLOCK, PIN_MOS_IN, PIN_MOS_OUT)
        try {
            this.mcp3008.register()

        } catch (e: IOException) {
            Log.e(TAG, "mcp can't initialized", e)
            return
        }
        mcpHandler = Handler()
        mcpHandler.post(this.readChannelMoveServo)


    }

    override fun onDestroy() {
        super.onDestroy()
        this.mcp3008.unregister()
        this.servo.close()
    }

    private fun map(x: Int, inMin: Int, inMax: Int, outMin: Int, outMax: Int): Double {
        return ((x - inMin) * (outMax - outMin) / (inMax - inMin) + outMin).toDouble()
    }


}

まとめ

やはりAndroid Thingsだと公式にはライブラリが出てないので、めんどくさいのですが、
よく使われているものはちょこちょこライブラリを作ってくれている人もいるので、探してみるといいと思います。

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
0
Help us understand the problem. What are the problem?