Feedback
Feedback

If you are having issues with the exercises, please create a ticket on DevZone: devzone.nordicsemi.com
Drag & Drop Files, Choose Files to Upload 您最多可以上传 2 个文件。
  • 简体中文
    Eng
    简体中文
  • 练习 2 – 连接 Thingy:91 和 Thingy:53 上的 BH1749 环境光传感器

    注意

    本练习不适用于 Thingy:91 X,因为它没有配备 BH1749 环境光传感器。

    本练习使用了一种名为 Thingy 的特殊 Nordic Semiconductors 原型开发板,而不是我们在本课程中通常用于运行示例和练习的标准开发套件。本练习可以在 Thingy:53 或 Thingy:91 上运行。

    Thingy:53
    Thingy:91

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

    Thingy:53 PCB,正面图,光传感器位置
    Thingy:91 PCB,背面图,光传感器位置

    BH1749NUC 是一款使用 I2C 接口的颜色传感器。传感器上的集成电路 (IC) 感测红、绿、蓝 (RGB) 和红外光,然后将它们的强度表示为存储在每个值 2 字节中的数字值。

    在本练习中,我们将从传感器读取 RGB 值并将其打印在串口终端上。

    BH1749NUC 颜色传感器数据手册中的寄存器表

    上表显示了颜色传感器的寄存器及其对应的地址。对于我们的练习,相关的寄存器是红框中的 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=y
    Kconfig

    重要

    如果您使用 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>
    C

    4. 为了在控制台上显示传感器读数,我们将使用一个简单的 printk()。

    4.1 包含头文件 <sys/printk.h> 以使用 printk()

    #include <zephyr/sys/printk.h>
    C

    4.2 通过添加符号在 prj.conf 中启用浮点格式说明符

    CONFIG_CBPRINTF_FP_SUPPORT=y
    Kconfig

    5. (无需操作)在之前的练习中,我们使用的是外部扩展板。由于传感器位于该扩展板上,而不是内置在 Nordic Semiconductor 开发板上,因此我们需要一个步骤来指定传感器已连接到 I2C 控制器,并在覆盖文件中提供其地址。

    在本练习中,传感器内置在 Thingy 开发板上,并且已经在设备树文件中指定。您可以通过检查设备树文件并搜索 BH1749 传感器来验证这一点,如下所示。

    6. 获取传感器的节点标识符。这在 I2C 驱动程序部分的步骤 4 中有详细解释。

    #define I2C_NODE DT_NODELABEL(bh1749)
    C

    7. 获取特定于 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;
    }
    C

    8. 定义相关寄存器的地址,这些地址可以在传感器数据手册中找到。这些信息通常放在一个单独的头文件 (.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                   0x2A
    C

    9. 通过向 MODE_CONTROL1 寄存器写入值 0x2A 来设置传感器。

    从下面的 MODE_CONTROL1 寄存器映射可以明显看出,0x2A(二进制为 0 01 01 010)意味着:

    • 红外增益:x1,
    • RGB 增益:x1
    • 测量模式:120ms
    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);
    }
    C

    10. 要从传感器读取 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);
    }
    C

    11. 从 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));
    
    C

    12. 构建应用程序。

    要为 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.

    Switch language?

    Progress is tracked separately for each language. Switching will continue from your progress in that language or start fresh if you haven't begun.

    Your current progress is saved, and you can switch back anytime.

    Register an account
    Already have an account? Log in
    (All fields are required unless specified optional)

    • 8 or more characters
    • Upper and lower case letters
    • At least one number or special character

    Forgot your password?
    Enter the email associated with your account, and we will send you a link to reset your password.