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 供电引脚,否则会烧坏传感器。

编码

完成电路连接之后我们开始书写代码,代码部分很简单,我会在其中注释,以方便大家理解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/**
* @Author Junerver
* @Date 2018/12/24-16:48
* @Email junerver@gmail.com
* @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()
}
}
}

注意:在写入测量模式指令之后必须要延时适当时间再从设备中读取,否则将会在读取指令位置出现如下异常:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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()函数即可。