本练习不适用于 Thingy:91 X,因为它没有配备 BH1749 环境光传感器。
本练习使用了一种名为 Thingy 的特殊 Nordic Semiconductors 原型开发板,而不是我们在本课程中通常用于运行示例和练习的标准开发套件。本练习可以在 Thingy:53 或 Thingy:91 上运行。


Thingy 是一款易于使用的电池供电原型开发板,由于板载了各种传感器和接口,用户可以在极短的时间内构建概念验证。在本练习中,为了演示如何使用 I2C 接口,我们将使用 Thingy:53 或 Thingy:91,并利用它们板载的 BH1749:环境光传感器。


BH1749NUC 是一款使用 I2C 接口的颜色传感器。传感器上的集成电路 (IC) 感测红、绿、蓝 (RGB) 和红外光,然后将它们的强度表示为存储在每个值 2 字节中的数字值。
在本练习中,我们将从传感器读取 RGB 值并将其打印在串口终端上。

上表显示了颜色传感器的寄存器及其对应的地址。对于我们的练习,相关的寄存器是红框中的 4 个寄存器。这 4 个寄存器分别是:基础 SYSTEM_CONTROL 寄存器、2 个用于设置传感器特定模式的 MODE_CONTROL 寄存器,以及最后的 RED_DATA 寄存器,特别是位于地址 0x50 的低字节 [7-0]。
要从传感器读取颜色数据(不含红外值的 RGB),您需要首先通过写入 MODE_CONTROL1 寄存器来设置传感器模式。之后,您需要通过写入 MODE_CONTROL2 寄存器来启用测量。最后,您需要从 RED_DATA、GREEN_DATA 和 BLUE_DATA 的数据寄存器中进行实际读取。我们将从 RED_DATA 寄存器的第一个字节开始进行突发读取。
请注意,您可以使用传感器的驱动程序(在此处找到 <install_path>\nrf\drivers\sensor\bh1749>)来启用其他功能,例如读取红外 (IR) 光强度和利用中断。然而,本练习仅侧重于传感器接口的 I2C 方面,因此额外功能不在本练习的范围内。
1. 在本课程的 GitHub 仓库中,打开位于 l6/l6_e2 的本练习基础代码。
2. 通过在 prj.conf 文件中添加以下行来启用 I2C 驱动程序。
CONFIG_I2C=yKconfig如果您使用 TF-M (thingyxx/nrfxxxx/ns) 进行构建,则需要禁用 TF-M 的日志记录。用于 TF-M 的 UART 外设与本练习中使用的 TWIM 外设共享相同的基地址,并且在 nRF Connect SDK 2.6.0 及更高版本中默认启用。要禁用它,只需在 prj.conf 中添加这两个 Kconfig 符号即可。
CONFIG_TFM_SECURE_UART=n
CONFIG_TFM_LOG_LEVEL_SILENCE=y
3. 在 main.c 中,包含 I2C API 的头文件。
#include <zephyr/drivers/i2c.h>C4. 为了在控制台上显示传感器读数,我们将使用一个简单的 printk()。
4.1 包含头文件 <sys/printk.h> 以使用 printk()
#include <zephyr/sys/printk.h>C4.2 通过添加符号在 prj.conf 中启用浮点格式说明符
CONFIG_CBPRINTF_FP_SUPPORT=yKconfig5. (无需操作)在之前的练习中,我们使用的是外部扩展板。由于传感器位于该扩展板上,而不是内置在 Nordic Semiconductor 开发板上,因此我们需要一个步骤来指定传感器已连接到 I2C 控制器,并在覆盖文件中提供其地址。
在本练习中,传感器内置在 Thingy 开发板上,并且已经在设备树文件中指定。您可以通过检查设备树文件并搜索 BH1749 传感器来验证这一点,如下所示。

6. 获取传感器的节点标识符。这在 I2C 驱动程序部分的步骤 4 中有详细解释。
#define I2C_NODE DT_NODELABEL(bh1749)C7. 获取特定于 API 的设备结构,确保设备已准备就绪,如果 I2C 设备未就绪,则打印错误消息:
static const struct i2c_dt_spec dev_i2c = I2C_DT_SPEC_GET(I2C_NODE);
if (!device_is_ready(dev_i2c.bus)) {
printk("I2C bus %s is not ready!\n\r",dev_i2c.bus->name);
return -1;
}C8. 定义相关寄存器的地址,这些地址可以在传感器数据手册中找到。这些信息通常放在一个单独的头文件 (.h) 中。然而,为了保持演示简单,我们将它们添加到 main.c 中。
#define BH1749_SYSTEM_CONTROL 0x40
#define BH1749_MODE_CONTROL1 0x41
#define BH1749_MODE_CONTROL2 0x42
#define BH1749_RED_DATA_LSB 0x50
#define BH1749_MODE_CONTROL2_RGB_EN_ENABLE BIT(4)
#define BH1749_MODE_CONTROL1_DEFAULTS 0x2AC9. 通过向 MODE_CONTROL1 寄存器写入值 0x2A 来设置传感器。
从下面的 MODE_CONTROL1 寄存器映射可以明显看出,0x2A(二进制为 0 01 01 010)意味着:

char buff1[] = {BH1749_MODE_CONTROL1,BH1749_MODE_CONTROL1_DEFAULTS};
ret = i2c_write_dt(&dev_i2c,buff1,sizeof(buff1));
if(ret != 0){
printk("Failed to write to I2C device address 0x%c at Reg. 0x%c\n",dev_i2c.addr,BH1749_MODE_CONTROL1);
}C10. 要从传感器读取 RGB 值,我们需要通过向 MODE_CONTROL2 寄存器的第 4 位写入 1 来启用测量。我们将使用如下所示的 i2c_write_dt() API

char buff2[] = {BH1749_MODE_CONTROL2,BH1749_MODE_CONTROL2_RGB_EN_ENABLE};
ret = i2c_write_dt(&dev_i2c,buff2,sizeof(buff2));
if(ret != 0){
printk("Failed to write to I2C device address 0x%c at Reg. 0x%c\n",dev_i2c.addr,BH1749_MODE_CONTROL2);
}C11. 从 RED_DATA、GREEN_DATA 和 BLUE_DATA 寄存器读取 RGB 值。
由于这些寄存器是连续的,我们将从 RED_DATA 的第一个字节(地址为 0x50 (BH1749_RED_DATA_LSB))开始进行突发读取。请注意,我们正在读取六个字节(因为 rgb_value 缓冲区的大小为 6 字节),因此寄存器将按以下方式存储 RGB 值:(最高有效位)BBGGRR(最低有效位)

uint8_t rgb_value[6]= {0};
//Do a burst read of 6 bytes as each color channel is 2 bytes
ret = i2c_burst_read_dt(&dev_i2c, BH1749_RED_DATA_LSB,rgb_value,sizeof(rgb_value));
if(ret != 0){
printk("Failed to read to I2C device address 0x%c at Reg. 0x%c\n",dev_i2c.addr,BH1749_RED_DATA_LSB);
}
//Print reading to console
printk("_______________________________\n");
printk("Red Value:\t %d\n", (rgb_value[0] | rgb_value[1] << 8));
printk("Green Value:\t %d\n", (rgb_value[2] | rgb_value[3] << 8));
printk("Blue Value:\t %d\n", (rgb_value[4] | rgb_value[5] << 8));
C12. 构建应用程序。
要为 Thingy:91 构建,请使用与之前练习相同的构建程序,并在“Add Build Configuration”窗口中选择 thingy91_nrf9160_ns 作为目标板,如下所示。
要为 Thingy:53 构建,请改用 thingy53_nrf5340_cpuapp_ns 作为目标板。

13. 将应用程序烧录到您的设备中。
要了解更多关于为 Thingy 烧录应用程序的信息,请点击此处查看有关 Thingy:53 的说明,或点击此处查看有关 Thingy:91 的说明。您应该会看到类似于下图的输出。

要验证颜色值是否随环境光变化而变化,您可以尝试例如遮住开发板上的光传感器(请记住,光传感器的位置因您使用的 Thingy 版本而异,请参考本页顶部的开发板图片),并观察数值如何大幅下降。您也可以让开发板接受某种特定颜色的光照,并观察输出中该数值如何增加。
本练习的解决方案可以在 GitHub 仓库中找到, l6/l6_e2_sol.