Android
Arduino
電子工作
RaspberryPi
AndroidThings

AndroidThingsとArduino間でやり取りする ~ Android ThingsでDHT11を扱う ~

More than 1 year has passed since last update.

 

低価格の温度センサーとして売られているDHT11ですが、

Android Thingsからは直接扱えません。

今回はDHT11をAndroidThingsで扱うために、ArduinoでDHT11からデータを読み取り、AndroidThingsに送ります。


DHT11とAndroid Things

上にも書きましたが、現状(2017/12/07)、Android ThingsではDHT11は扱えません。

諸々議論はこのスレッドでされています。

簡単に言うと、Android Thingsでは、GPIOからデータを呼び出すのに230us位かかるのですが、

DHT11では、データを読み取るのに20usの速さが必要であり、現状Android Thingsでは直接データを読み取ることが実質不可能となっています。


Android ThingsとArduino

そこでDHT11等を扱うために、Arduinoでデータを読み取り、Android Thingsに送ってしまうという方法を思いつくわけです。

Arduino、AndroidThings間はUARTを利用して、双方向でデータをやり取りします。


実際にやってみる


回路

arduino-wrap.png


Arduino側のコード

Arduino側のコードです。

AndroidThingsからUARTを利用して、データが送信されるので、Serial.readで取得します。

取得するのは温度を取得するか(T)、湿度を取得するか(H)のコマンドなので、コマンドに合わせて、DHT11から読み取ります。

なおDHT11の温度や湿度は、adafruitのライブラリを利用して、取得します。

そして取得したデータをSerialに流し、Android Thingsへ送ります。

#include <DHT.h>;

#define DHTPIN 2
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

void setup() {
Serial.begin(115200);
dht.begin();
}

void loop() {
int inByte = Serial.read();
switch (inByte) {
case 'T':
sendTemperature();
break;
case 'H':
sendHumidity();
break;
}
}

void sendTemperature(){
send(dht.readTemperature());
}

void sendHumidity(){
send(dht.readHumidity());
}

void send(float val) {
String value = "";
value += val;

char charBuf[value.length()+1];
value.toCharArray(charBuf, value.length()+1);

Serial.write(charBuf);
}


Android Things側

全コードは以下にあります。


Arduinoへのデータ送信とデータ取得

DHT11のデータ送受信用のクラスです。

UARTDeviceの初期化を行い、データの取得を行います。


DHT11.kt

package com.github.soundtricker.androidthings.sampledht11

import android.util.Log
import com.google.android.things.pio.PeripheralManagerService
import com.google.android.things.pio.UartDevice
import java.io.IOException
import java.nio.ByteBuffer

class DHT11 constructor(uartName: String, pioService: PeripheralManagerService) {

private val mMessageBuffer = ByteBuffer.allocate(10)
private var mDevice: UartDevice?

init {
mDevice = pioService.openUartDevice(uartName)
mDevice!!.setDataSize(8)
mDevice!!.setBaudrate(115200)
mDevice!!.setParity(0)
mDevice!!.setStopBits(1)
}

fun getTemperature(): String {
var response = ""
val buffer = ByteArray(10)

try {
return this.fillBuffer(buffer, "T")
} catch (e: IOException) {
Log.e("DHT11", "failed read temperature", e)
}

return response
}

fun getHumidity(): String {
var response = ""
val buffer = ByteArray(10)

try {
response = this.fillBuffer(buffer, "H")
} catch (e: IOException) {
Log.e("DHT11", "failed read temperature", e)
}

return response
}

@Throws(IOException::class)
private fun fillBuffer(buffer: ByteArray, mode: String): String {
this.mDevice!!.write(mode.toByteArray(), mode.length)

Thread.sleep(500L)
this.mDevice!!.read(buffer, buffer.size)
this.processBuffer(buffer)
return String(this.mMessageBuffer.array(), charset("UTF-8")).replace("\u0000".toRegex(), "")
}

private fun processBuffer(buffer: ByteArray) {
mMessageBuffer.clear()
buffer.forEach { b ->
if (b.toInt() != 0) {
this.mMessageBuffer.put(b)
}
}
}

@Throws(Exception::class)
fun close() {
try {
this.mDevice?.close()
} finally {
this.mDevice = null
}
}

}



MainActivity

MainActivityでは定期的にデータを読み取ってログに流すだけです。


MainActivity.kt


package com.github.soundtricker.androidthings.sampledht11

import android.app.Activity
import android.os.Bundle
import android.os.Handler
import android.util.Log
import com.google.android.things.pio.PeripheralManagerService

/**
* Skeleton of an Android Things activity.
*
* Android Things peripheral APIs are accessible through the class
* PeripheralManagerService. For example, the snippet below will open a GPIO pin and
* set it to HIGH:
*
* <pre>{@code
* val service = PeripheralManagerService()
* val mLedGpio = service.openGpio("BCM6")
* mLedGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW)
* mLedGpio.value = true
* }</pre>
* <p>
* For more complex peripherals, look for an existing user-space driver, or implement one if none
* is available.
*
* @see <a href="https://github.com/androidthings/contrib-drivers#readme">https://github.com/androidthings/contrib-drivers#readme</a>
*
*/

class MainActivity : Activity() {

companion object {
private val TAG = MainActivity.javaClass.simpleName
}

private var mDht11: DHT11? = null

private var mHandler: Handler? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mDht11 = DHT11("UART0", PeripheralManagerService())
mHandler = Handler()
mHandler!!.post(mRunnable)

}

override fun onDestroy() {
super.onDestroy()
mDht11?.close()
mDht11 = null
}

private fun run() {
mHandler!!.postDelayed(mRunnable, 10L)
}

private val mRunnable: Runnable = Runnable {
Log.d(TAG, "Humidity: ${mDht11!!.getHumidity()}")
Log.d(TAG, "Temperature: ${mDht11!!.getTemperature()}")
run()
}
}



まとめ

AndroidThingsではどんなセンサーでも触れる訳ではなく、ちょっとハマりました。

センサー周りの処理はやはりArduinoなどに任せたほうが楽です。


参考

https://github.com/mplacona/arduwrap

なお今回はUARTを使いましたが、I2Cで送る方法もあるようです。

https://github.com/theangels/AndroidThings_Thingworx_Demo