序
一些介紹AndroidThings(之後將簡稱ATs)的一些文章:
Android Things是什麼
Android Things系統刷寫
Android Things樹莓派開發板沒有顯示器時如何連接
Android Things的日期和時間設置
這幾篇文章都是同一個作者書寫,都是非常有幫助的入門文章,下面我就不多廢話了,進入咱們的主題:ATs(樹莓派) 連接 SHT20 傳感器讀取溫溼度。
連線
SHT20 傳感器是通過 I2C 總線連接到樹莓派上的,關於總線的概念我們就不敘述,對於我們軟件工程師而言知道怎麼用就行了。
從上圖我們可以看出,樹莓派3B 的3號腳與5號腳爲 I2C 總線的引腳,我們只需要將 SHT20 的 SDA 引腳與SCL引腳對應的接上即可。要注意 SHT20 的供電電壓爲 3.3V,其 VCC 引腳千萬不要接到樹莓派 GPIO 的5V 供電引腳,否則會燒壞傳感器。
編碼
完成電路連接之後我們開始書寫代碼,代碼部分很簡單,我會在其中註釋,以方便大家理解。
/**
* @Author Junerver
* @Date 2018/12/24-16:48
* @Email [email protected]
* @Version v1.0
* @Description
*/
object Sht2xUtil:AutoCloseable {
private val I2C_DEVICE_NAME = "I2C1" // I2C總線名稱
private val I2C_ADDRESS = 0x40 // I2C 設備地址
private val SHT20_CMD_R_T = 0xF3 // 從機模式測溫指令
private val SHT20_CMD_R_RH = 0xF5 // 從機模式測溼度指令
private val SHT20_CMD_RESET = 0xFE // 軟重置指令
private lateinit var device: I2cDevice // I2C 設備
override fun close() {
//設備使用完畢後關閉總線設備
if (this::device.isInitialized) {
device.close()
}
}
fun open() {
//通過總線名稱與設備地址打開設備
if (!this::device.isInitialized) {
device = PeripheralManager.getInstance().openI2cDevice(I2C_DEVICE_NAME, I2C_ADDRESS)
}
}
fun reset() {
//軟重置指令
if (this::device.isInitialized) {
val ba = byteArrayOf(SHT20_CMD_RESET.toByte())
device.write(ba, ba.size)
SystemClock.sleep(150)
}else {
throw RuntimeException()
}
}
fun getTemp():String {
if (this::device.isInitialized) {
//像設備寫入指令,設置模式爲溫度
val ba = byteArrayOf(SHT20_CMD_R_T.toByte())
device.write(ba, ba.size)
//寫入指令後延時
SystemClock.sleep(150)
// 初始化一個byte數組 用於從寄存器中讀取數據
val data = ByteArray(2) { 0 }
// 網上還有一種讀取數據的方式 device.readRegBuffer(0x00, data, data.size) 但是不適用與sht20這個傳感器
device.read(data, data.size)
//將讀取到的字節數組首先轉成16進制然後轉成10進制數
val bb = ByteUtils.hexStr2decimal(ByteUtils.bytes2HexStr(data))
//sht20讀取溫度原始數據轉化成攝氏度的算法
var result = -46.85 + 175.72 * (bb / pow(2.0, 16.0))
return result.toString().substring(0..3)
}else {
throw RuntimeException()
}
}
fun getHumi(): String {
if (this::device.isInitialized) {
//設置模式爲溼度
val ba = byteArrayOf(SHT20_CMD_R_RH.toByte())
device.write(ba, ba.size)
SystemClock.sleep(150)
val data = ByteArray(2) { 0 }
device.read(data, data.size)
val bb = ByteUtils.hexStr2decimal(ByteUtils.bytes2HexStr(data))
//sht20讀取溼度原始數據轉化成相對溼度
var result = -6 + 125 * (bb / pow(2.0, 16.0))
//僅截取前兩位
return result.toString().substring(0..1)
} else {
throw RuntimeException()
}
}
fun getTempAndHumi(): Pair<String, String> {
if (this::device.isInitialized) {
var result: Pair<String, String>
val temp = getTemp()
SystemClock.sleep(150)
val humi = getHumi()
result = Pair(temp, humi)
return result
}else {
throw RuntimeException()
}
}
}
注意:在寫入測量模式指令之後必須要延時適當時間再從設備中讀取,否則將會在讀取指令位置出現如下異常:
Error on I2C API
com.google.android.things.pio.PioException: android.os.ServiceSpecificException: I/O error (code 5)
at com.google.android.things.pio.I2cDeviceImpl.read(I2cDeviceImpl.java:75)
at com.example.androidthings.simpleui.Sht2xUtil.getTemp(Sht2xUtil.kt:60)
at com.example.androidthings.simpleui.Sht2xUtil.getTempAndHumi(Sht2xUtil.kt:88)
at com.example.androidthings.simpleui.SimpleUiActivity$readRunnable$1.run(SimpleUiActivity.kt:125)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: android.os.ServiceSpecificException: I/O error (code 5)
at android.os.Parcel.readException(Parcel.java:2027)
at android.os.Parcel.readException(Parcel.java:1959)
at com.google.android.things.pio.IPeripheralManagerClient$Stub$Proxy.I2cRead(IPeripheralManagerClient.java:1282)
at com.google.android.things.pio.I2cDeviceImpl.read(I2cDeviceImpl.java:73)
at com.example.androidthings.simpleui.Sht2xUtil.getTemp(Sht2xUtil.kt:60)
at com.example.androidthings.simpleui.Sht2xUtil.getTempAndHumi(Sht2xUtil.kt:88)
at com.example.androidthings.simpleui.SimpleUiActivity$readRunnable$1.run(SimpleUiActivity.kt:125)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
使用的時候也很簡單,在適當的實際調用 open() 函數,在需要讀取數據的位置調用 getXX()函數即可。