AndroidThings——連接 SHT20 傳感器讀取溫溼度

一些介紹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()函數即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章