7. NodeMCU上使用RTOS固件读取bh1750传感器数据的实践

NodeMCU上使用RTOS固件读取bh1750传感器数据的实践


本文主要是尝试在NodeMCU(硬件)上,使用RTOS(固件、OS)来控制bh1750光照传感器,
采集亮度数据。

关于RTOS固件的编译环境和编译方式的介绍,可参照之前的文章。
ESP8266固件的编译5(RTOS SDK固件)

但是在RTOS固件下,只内置了很少的传感器驱动,bh1750并没有被支持。
需要自己根据I2C协议实现简单的驱动。
(nodeMCU的lua固件预置了相当多的、也包含bh1750的传感器驱动,
作为参考,可参照lua版本的驱动实现 nodemcu-firmware/lua_modules)

bh1750通信通过I2C协议,关于I2C协议本身,可以参照如下文章,有清晰的解释。
http://blog.chinaunix.net/uid-25906157-id-3585430.html

1、I2C驱动库的编译

Esp8266没有硬件I2C接口,是用GPIO软件模拟的,坏处是性能差,好在模拟也不复杂。
RTOS固件开发环境下提供了一个Driver库,内置I2C、SPI、UART等通信实现。
第一步自然是编译这个库。

编译过程中,出现一些问题,应该是维护人员的粗心所致。要如下方法修改:
进入ESP8266_RTOS_SDK\driver_lib\driver目录,如下修正i2c_master.c文件。
1) 增加头文件

#include "c_types.h"
#include "esp8266/ets_sys.h"
#include "esp8266/eagle_soc.h" /* 新增加头文件 */
#include "esp8266/gpio_register.h" /* 新增加头文件 */
#include "gpio.h"

2) 修改宏/函数名
在i2c_master_gpio_init函数中,将

ETS_GPIO_INTR_DISABLE() ;
ETS_GPIO_INTR_ENABLE() ;

修改为

 ETS_INTR_LOCK();
 ETS_INTR_UNLOCK();

3)默认的SDA和SCL管脚定义
默认的I2C的SDA和SCL管脚在i2c_master.h中定义,其默认值为

SDA -- GPIO2
SCL -- GPIO4

需要变更的话,可修改此文件。

4)编译
在ESP8266_RTOS_SDK\driver_lib目录下,执行

$ make_lib.sh driver

成功编译成功后,在ESP8266_RTOS_SDK/lib目录下会生成新的libdriver.a。
执行如下命令,能找到i2c对应函数的符号信息。

$nm –A libdriver.a | grep i2c
2、 bh1750驱动的实现

仿照lua版,只实现了【连续 H 分辨率模式】下的数据读取。

Bh1750的I2C接口的说明:

A)Slave地址有 2 种形式,由 ADDR 端口决定。

ADDR=“H” ( ADDR ≧ 0.7VCC ) →“1011100
ADDR=“L” ( ADDR ≦ 0.3VCC ) →“0100011

B)bh1750的I2C数据读取协议,如图

这里写图片描述

C)简单实现如下(错误处理等省略)

uint8 addr = 0x23; // bh1750 i2c地址(low) 00100011
uint8 cmd = 0x10; // bh1750 高分辨率模式 00010000

void init_bh1750()
{
    // 初始化i2c总线
    i2c_master_gpio_init();
}

uint16 read_bh1750_data(void)
{
    uint8 b1 = 0x00;
    uint8 b2 = 0x00;
    uint32 data = 0x00;

    // 设置高分辨率模式
    i2c_master_start();
    i2c_master_writeByte( (addr << 1) );
    i2c_master_getAck();
    i2c_master_writeByte(cmd);
    i2c_master_getAck();
    i2c_master_stop();

    // 采集等待时间要求120ms以上
    os_delay_us(60000);
    os_delay_us(60000);
    os_delay_us(60000);

    // 读取数据
    i2c_master_start();
    i2c_master_writeByte( (addr << 1) | 0x01 );
    i2c_master_getAck();
    b1 = i2c_master_readByte();
    i2c_master_send_ack();
    b2 = i2c_master_readByte();
    i2c_master_send_ack();
    i2c_master_stop();

    // 计算结果(取得亮度数据为2字节、除1.2的阈值)
    data = b1 * 256 + b2;
    return (uint16)(data / 1.2);
}
3. 固件入口函数user_init的实现

修改ESP8266_RTOS_SDK\examples\project_template\user\ user_main.c文件
(上面的bh1750驱动实现也可放在此文件中)

因为RTOS不允许在user_init中进行while(1)循环和睡眠等待,
因此用定时器来定时读取lux数据(也可以创建task)。代码如下:

LOCAL void ICACHE_FLASH_ATTR print_data(void* data)
{
    printf("lux: %d\n", read_bh1750_data());
}

void user_init(void)
{
    int i = 0;

    // 设置串口为 115200 波特率。不设的情况,默认波特率为78400
    UART_ConfigTypeDef  uart_config;
    uart_config.baud_rate               =   BIT_RATE_115200;
    uart_config.data_bits               =   UART_WordLength_8b;
    uart_config.parity                  =   USART_Parity_None;
    uart_config.stop_bits               =   USART_StopBits_1;
    uart_config.flow_ctrl               =   USART_HardwareFlowControl_None;
    uart_config.UART_RxFlowThresh       =   120;
    uart_config.UART_InverseMask        =   UART_None_Inverse;
    UART_ParamConfig(UART0, &uart_config);

    printf("----------------------\n");
    printf("bh1750 reader\n");
    printf("----------------------\n");

    // 初始化I2C
    init_bh1750();

    // 设置定时器
    os_timer_disarm(&timer);
    os_timer_setfn(&timer, (os_timer_func_t *)print_data, NULL);
    os_timer_arm(&timer, 2000, 1);
}
4. 固件编译

进入ESP8266_RTOS_SDK\examples\project_template目录,执行

make COMPILE=gcc BOOT=none APP=0 SPI_SPEED=40 SPI_MODE=DIO SPI_SIZE_MAP=4

如编译成功,则在BIN_PATH下会生成固件。

5.结果验证

1)接线
esp8266默认的GPIO定义和nodemcu的D管脚定义是不同的体系,使用nodemcu硬件是要注意。
直接用esp8266模块的话,根据gpio号接线就可以。

可参照下图:
这里写图片描述

接线如下:

SDA(bh1750) ---- D4(nodeMCU) ---- GPIO2(esp8266)
SCL(bh1750) ---- D2(nodeMCU) ---- GPIO4(esp8266)
VCC(bh1750) ---- 3.3v
GND(bh1750) ---- GND(nodeMCU)
ADDR(bh1750) ---- GND (使用bh1750的0x23地址)

接线效果图

这里写图片描述
2)固件下载
可参照以前的文章
ESP8266固件的编译6(固件的下载)

3) 效果
用串口工具115200波特率连接nodeMCU硬件,
可以看到bh1750的数据被正常采集,且亮度能随场景变化而不同。
这里写图片描述

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值