第26课 I2C 多设备连接 LM75 温度计与 BH1750 光度计

我是潘,曾经是个工程师。这是为 Ardui.Co 制作的 “Arduino 公开课” 系列的入门教程。前面课程介绍了I2C工作原理,以及怎样向设备发送数据,并通过小屏幕来显示出来,这节课将介绍如何通过 I2C 链接多个设备,接收并发送数据。有任何疑问请在评论区提出,我会逐一回答。

这节课要设计一个能够显示当前温度和光照度的装置,这种装置在温室培植中应用很广泛。我们要用到 LM75 温度传感器、 BH1750 光照度传感器和 1602 OLED 显示屏。它们都是基于 I2C 协议,这意味着3个设备只要2根数据线,就能全部链接起来:

由于设备较多,所以我们需要2个 5 ~ 10KΩ 上拉电阻。1602 OLED 前面已经介绍过了,现在我们先介绍 LM75 温度传感器。这个传感器由 NXP 设计,安森美、TI 等厂家也有生产,外围电路非常小,只需一个电容就能工作,芯片尺寸只有 4X5mm(1/3指甲头),精度为 0.5 ºC,除了日常测温度外,也适合安装在各种设备中,作为温控原件。

根据 LM75 的 Datasheet,其作为 slave,地址是 7-bits,1001A2A1A0,我手里的模块 A2\A1\A0 都接地,所以地址就是1001000。继续查看手册,温度的格式为 16bits,最左边 D15 为 MSB,若MSB 为 1,表示为负。D15 ~ D8 为为温度的整数部分,D7~D0 合计 8bits ,但只有 D7 (LSB)起作用,用于记录 0.5度。

我们从简单的入手,先获取温度正整数部分:

为了显示负数和小数位,我们需要分两部分获取 LM75 的数据,为了更好理解以及方便后面增加其他传感器,我们将 LM75 单独出一个函数来操作:

其实,这里用到一个类型转换的技巧,由于 char 只能显示 8bits 的数据,超出部分,以十进制方式显示是 “-”,所以将part1的类型由 int 改为 char,111111111 前8位为 11111111,就显示 -1 了。LM75() 定义为 double 是为保留返回值的小数点,如果换成 int 小数点就会被去掉。参考一下 Datasheet 就很容易理解这点:

现在再看看 BH1750 光亮度传感器。该传感器内置16bit ADC,可以测量 1~65535 lux 的亮度,以120ms 的速度采样时,精度可以达到 0.5 lux,如果20ms采样,精度为 4 lux。

怎么判断黑夜还是白昼?可以参考下面的光亮度数据:

晚上: 0.001-0.02
月夜: 0.02-0.3
多云室内: 5-50
适合阅读的亮度: 50-60
多云室外: 50-500
晴天室内: 100-1000
夏天中午光照下: 10∧6
(单位:lux)

根据 BH1750 的 DataSheet,BH1750 是可以设置测量模式的,方式是通过 I2C 写入下表对应的数据:

比如,要把它的采样设置为低速(120ms)、高分辨率(1lux)模式,即 “0001 0000”,换算为16进制,即 0x10,对应的 I2C 操作为:

为了省电,我们可以用单次模式,比如 0010_0001,即 0x21。

写入数据后,BH1750 开始反馈数据,一共 2byte,我们紧接着 2 个变量来接收,使用 while() 循环比较便捷。根据 Datasheet 这2个byte分别为:

深灰色部分是操作byte,刚才讲过以写入的方式操作,第2个、第3个就是 BH1750 返回的数据。计算方式 DataSheet 已经写的很清楚,第16位2的15次方,第15位2的14次方,如此类推。各位数相加后除以 1.2,就能得出结果。高低byte相加时,我们要用到移位符 “<<”,具体程序如下:

顺便提一下,常见 I2C 传感器模块,内置了上拉电阻,所以这里不需要再另外接。

2 thoughts on “第26课 I2C 多设备连接 LM75 温度计与 BH1750 光度计

  1. 笨人儿

    请问潘老师,如果两个地址一样,该如何通过I2C识别?比如两个位置编码器,地址都是0X36?
    非常感谢

    Reply
    1. panft Post author

      有三种方式,1使用多路复用器,如PCA9540B;2,使用用多路开关,如PCA9543A;3使用两条I2C总线。等以后有空继续这个教程会介绍。

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *