涂鸦开发者
直播中

voidpbq

8年用户 131经验值
擅长:嵌入式技术,处理器/DSP
私信 关注
[经验]

【涂鸦T2-U开发板试用体验】2、添加光感bh1750

前言

本章介绍如何在涂鸦T2-U开发板上添加光感bh1750驱动并实现定时读取数据。

一、基础介绍

BH1750( GY-302 )光照传感器

这篇文章有bh1750的基础介绍。

我这里总结一下。

bh1750采用i2c通信,有5个引脚,vcc,gnd,sda,scl,add。

其中add接gnd时i2c地址为0x23,接vcc为0x5c。

模式:

三种分辨率模式,H(1lx),H2(0.5lx),L(41lx),其中1lx表示返回的数值1表示1lx,用于计算实际lx。

两种测试:连续,一次。

总共组合就是6中,常用的是一次H分辨率模式。

指令:

以一次H分辨率模式为例。

  1. 软重置:__bh1750_write_cmd(dev, BH1750_CMD_SOFT_RESET);
  2. 设置模式:__bh1750_write_cmd(dev, BH1750_CMD_ONE_H_RES_MODE);
  3. 等待采样:__bh1750_delay_ms(180);
  4. 读取采样值:__bh1750_read_data(dev, 2, buf);

如上述四步就可以读取到光感数据,剩下的就是实现接口和数据处理。

#define BH1750_CMD_POWER_DOWN   	    0x00	// power down
#define BH1750_CMD_POWER_ON			    0x01	// power on
#define BH1750_CMD_SOFT_RESET			0x07	// reset


#define BH1750_CMD_CON_H_RES_MODE	    0x10	// Continuously H-Resolution Mode
#define BH1750_CMD_CON_H_RES_MODE2	    0x11	// Continuously H-Resolution Mode2
#define BH1750_CMD_CON_L_RES_MODE	    0x13	// Continuously L-Resolution Mode
#define BH1750_CMD_ONE_H_RES_MODE	    0x20	// One Time H-Resolution Mode
#define BH1750_CMD_ONE_H_RES_MODE2	    0x21	// One Time H-Resolution Mode2
#define BH1750_CMD_ONE_L_RES_MODE	    0x23	// One Time L-Resolution Mode

二、电路图

2.1 电路图1

一开始我打算使用默认的pin1和pin0作为sda和scl,但是不知道是不是和打开了串口调试开关有关,i2c通信失败,后续采用了20,22。

注意,p1和p0,对应的pin是28,29。

序号 符号 说明
22 RX2 T2-U 的 UART_RX2,对应 IC 的 P1(对应 IC 的 Pin 28)。
23 TX2 T2-U 的 UART_TX2,打印日志口,对应 IC 的 P0(对应 IC 的 Pin 29)。

2.2 电路图2——实际采用

电路图.png

序号 符号 说明
24 P20 T2-U 的 普通 GPIO(对应 IC 的 Pin 20)。
25 P22 T2-U 的 普通 GPIO(对应 IC 的 Pin 18)。

三、代码

代码基于tuyaos_sensor_hub_demo_quickstart实现的。

需要复制该项目,并仿照温感sht30的驱动,添加bh1750驱动。

电子发烧友的帖子大小有限,可以去csdn看源码。
【涂鸦T2-U】2、添加光感bh1750-CSDN博客

tdd_sensor_bh1750.c

/**
 * [url=home.php?mod=space&uid=1455510]@file[/url] tdd_sensor_bh1750.c
 * [url=home.php?mod=space&uid=2666770]@Brief[/url] tdd_sensor_bh1750 module is used to drive bh1750 chip
 * [url=home.php?mod=space&uid=644434]@version[/url] 0.1
 * @date 2022-08-03
 */

#include "tdl_sensor_driver.h"
#include "tdd_sensor_light.h"
#include "tkl_gpio.h"
#include "tal_system.h"
#include "tal_log.h"

/***********************************************************
************************macro define************************
***********************************************************/
/**
 * @brief CRC result
 */
#define CRC_OK                      (0)
#define CRC_ERR                     (-1)

/**
 * @brief work status
 */
#define BH1750_CLOSE                 0
#define BH1750_OPEN                  (!BH1750_CLOSE)

/**
 * @brief resource array index
 */
#define BH1750_RSRC_INDEX_STAT       0
#define BH1750_RSRC_INDEX_ADDR       1
#define BH1750_RSRC_INDEX_PREC       2  // H-Resolution Mode/H-Resolution Mode2/L-Resolution
#define BH1750_RSRC_INDEX_FREQ       3  // one/continue
#define BH1750_RSRC_INDEX_RESL       4  // mode match value, such as H=1,H2=0.5,L=41

/***********************************************************
***********************typedef define***********************
***********************************************************/
/**
 * @brief bh1750 command
 */
typedef USHORT_T BH1750_CMD_E;


#define BH1750_CMD_POWER_DOWN   	    0x00	// power down
#define BH1750_CMD_POWER_ON			    0x01	// power on
#define BH1750_CMD_SOFT_RESET			0x07	// reset


#define BH1750_CMD_CON_H_RES_MODE	    0x10	// Continuously H-Resolution Mode
#define BH1750_CMD_CON_H_RES_MODE2	    0x11	// Continuously H-Resolution Mode2
#define BH1750_CMD_CON_L_RES_MODE	    0x13	// Continuously L-Resolution Mode
#define BH1750_CMD_ONE_H_RES_MODE	    0x20	// One Time H-Resolution Mode
#define BH1750_CMD_ONE_H_RES_MODE2	    0x21	// One Time H-Resolution Mode2
#define BH1750_CMD_ONE_L_RES_MODE	    0x23	// One Time L-Resolution Mode



// #define BH1750_CMD_SOFT_RESET        0x30A2  // soft reset
#define BH1750_CMD_READ_SERIALNBR    0x3780  // read serial number
#define BH1750_CMD_HEATER_ENABLE     0x306D  // enabled heater
#define BH1750_CMD_HEATER_DISABLE    0x3066  // disable heater
#define BH1750_CMD_READ_STATUS       0xF32D  // read status register
#define BH1750_CMD_CLEAR_STATUS      0x3041  // clear status register
#define BH1750_CMD_ART               0x2B32  // activate ART
#define BH1750_CMD_BREAK             0x3093  // stop periodic data acquisition mode
#define BH1750_CMD_FETCH_DATA        0xE000  // readout measurements for periodic mode
#define BH1750_CMD_MEAS_PERI_05_H    0x2032  // measurement: periodic 0.5 mps, high repeatability
#define BH1750_CMD_MEAS_PERI_05_M    0x2024  // measurement: periodic 0.5 mps, medium repeatability
#define BH1750_CMD_MEAS_PERI_05_L    0x202F  // measurement: periodic 0.5 mps, low repeatability
#define BH1750_CMD_MEAS_PERI_1_H     0x2130  // measurement: periodic 1 mps, high repeatability
#define BH1750_CMD_MEAS_PERI_1_M     0x2126  // measurement: periodic 1 mps, medium repeatability
#define BH1750_CMD_MEAS_PERI_1_L     0x212D  // measurement: periodic 1 mps, low repeatability
#define BH1750_CMD_MEAS_PERI_2_H     0x2236  // measurement: periodic 2 mps, high repeatability
#define BH1750_CMD_MEAS_PERI_2_M     0x2220  // measurement: periodic 2 mps, medium repeatability
#define BH1750_CMD_MEAS_PERI_2_L     0x222B  // measurement: periodic 2 mps, low repeatability
#define BH1750_CMD_MEAS_PERI_4_H     0x2334  // measurement: periodic 4 mps, high repeatability
#define BH1750_CMD_MEAS_PERI_4_M     0x2322  // measurement: periodic 4 mps, medium repeatability
#define BH1750_CMD_MEAS_PERI_4_L     0x2329  // measurement: periodic 4 mps, low repeatability
#define BH1750_CMD_MEAS_PERI_10_H    0x2737  // measurement: periodic 10 mps, high repeatability
#define BH1750_CMD_MEAS_PERI_10_M    0x2721  // measurement: periodic 10 mps, medium repeatability
#define BH1750_CMD_MEAS_PERI_10_L    0x272A  // measurement: periodic 10 mps, low repeatability
#define BH1750_CMD_MEAS_POLLING_H    0x2400  // measurement: polling, high repeatability
#define BH1750_CMD_MEAS_POLLING_M    0x240B  // measurement: polling, medium repeatability
#define BH1750_CMD_MEAS_POLLING_L    0x2416  // measurement: polling, low repeatability
#define BH1750_CMD_MEAS_CLOCKSTR_H   0x2C06  // measurement: clock stretching, high repeatability
#define BH1750_CMD_MEAS_CLOCKSTR_M   0x2C0D  // measurement: clock stretching, medium repeatability
#define BH1750_CMD_MEAS_CLOCKSTR_L   0x2C10  // measurement: clock stretching, low repeatability
#define BH1750_CMD_W_AL_LIM_HS       0x611D  // write alert limits, high set
#define BH1750_CMD_W_AL_LIM_HC       0x6116  // write alert limits, high clear
#define BH1750_CMD_W_AL_LIM_LC       0x610B  // write alert limits, low clear
#define BH1750_CMD_W_AL_LIM_LS       0x6100  // write alert limits, low set
#define BH1750_CMD_R_AL_LIM_LS       0xE102  // read alert limits, low set
#define BH1750_CMD_R_AL_LIM_LC       0xE109  // read alert limits, low clear
#define BH1750_CMD_R_AL_LIM_HS       0xE11F  // read alert limits, high set
#define BH1750_CMD_R_AL_LIM_HC       0xE114  // read alert limits, high clear

/***********************************************************
********************function declaration********************
***********************************************************/

/***********************************************************
***********************variable define**********************
***********************************************************/
/**
 * @brief element value type
 */
#if (SR_CONFIG_NO_FPU == 1)
STATIC SR_ELE_CFG_T sg_ele_val_tp[SR_LT_ELE_NUM] = {
    {
        .id     = SR_LT_ELE_ID_LIGHT,
        .val_tp = SR_VAL_TP_INT,
    }
};
#else
STATIC SR_ELE_CFG_T sg_ele_val_tp[SR_LT_ELE_NUM] = {
    {
        .id     = SR_LT_ELE_ID_LIGHT,
        .val_tp = SR_VAL_TP_FLOAT,
    }
};
#endif

/***********************************************************
***********************function define**********************
***********************************************************/
/**
 * @brief delay (ms)
 *
 * @param[in] tm: delay time
 *
 * [url=home.php?mod=space&uid=1141835]@Return[/url] none
 */
STATIC VOID_T __bh1750_delay_ms(IN CONST ULONG_T tm)
{
    tal_system_sleep(tm);
}

/**
 * @brief get CRC8 value for bh1750
 *
 * @param[in] data: data to be calculated
 * @param[in] len: data length
 *
 * @return CRC8 value
 */
STATIC UCHAR_T __bh1750_get_crc8(IN CONST UCHAR_T *data, IN USHORT_T len)
{
    UCHAR_T i;
    UCHAR_T crc = 0xFF;

    while (len--) {
        crc ^= *data;

        for (i = 8; i > 0; --i) {
            if (crc & 0x80) {
                crc = (crc << 1) ^ 0x31;
            } else {
                crc = (crc << 1);
            }
        }
        data++;
    }

    return crc;
}

/**
 * @brief check CRC8
 *
 * @param[in] data: data to be checked
 * @param[in] len: data length
 * @param[in] crc_val: crc value
 *
 * @return check result
 */
STATIC INT_T __bh1750_check_crc8(IN CONST UCHAR_T *data, IN CONST USHORT_T len, IN CONST UCHAR_T crc_val)
{
    if (__bh1750_get_crc8(data, len) != crc_val) {
        return CRC_ERR;
    }
    return CRC_OK;
}

/**
 * @brief read data from bh1750
 *
 * @param[in] dev: device resource
 * @param[in] len: data length
 * @param[out] data: data received from bh1750
 *
 * @return none
 */
STATIC OPERATE_RET __bh1750_read_data(IN CONST SR_RSRC_T *dev, IN CONST USHORT_T len, OUT UCHAR_T *data)
{
    SR_I2C_MSG_T rd_msg = {
        .flags = SR_I2C_FLAG_RD,
        .addr = dev->info[BH1750_RSRC_INDEX_ADDR],
        .len = len,
        .buff = data
    };

    return tdd_sensor_i2c_xfer(dev->port, &rd_msg);
}

/**
 * @brief write command to bh1750
 *
 * @param[in] dev: device resource
 * @param[in] cmd: control command
 *
 * @return none
 */
STATIC OPERATE_RET __bh1750_write_cmd2(IN CONST SR_RSRC_T *dev, IN CONST BH1750_CMD_E cmd)
{
    UCHAR_T cmd_bytes[2];
    cmd_bytes[0] = (UCHAR_T)(cmd >> 8);
    cmd_bytes[1] = (UCHAR_T)(cmd & 0x00FF);

    SR_I2C_MSG_T wr_msg = {
        .flags = SR_I2C_FLAG_WR,
        .addr = dev->info[BH1750_RSRC_INDEX_ADDR],
        .len = 2,
        .buff = cmd_bytes
    };

    return tdd_sensor_i2c_xfer(dev->port, &wr_msg);
}

STATIC OPERATE_RET __bh1750_write_cmd(IN CONST SR_RSRC_T *dev, IN CONST BH1750_CMD_E cmd)
{
    UCHAR_T cmd_bytes;
    cmd_bytes = (UCHAR_T)(cmd & 0xFF);

    SR_I2C_MSG_T wr_msg = {
        .flags = SR_I2C_FLAG_WR,
        .addr = dev->info[BH1750_RSRC_INDEX_ADDR],
        .len = 1,
        .buff = &cmd_bytes
    };

    // TAL_PR_ERR("[BH1750] addr=0x%02x, cmd=0x%02x",dev->info[BH1750_RSRC_INDEX_ADDR], cmd_bytes);

    return tdd_sensor_i2c_xfer(dev->port, &wr_msg);
}

/**
 * @brief write command and data to bh1750
 *
 * @param[in] dev: device resource
 * @param[in] cmd: control command
 * @param[in] data: data to be written
 *
 * @return none
 */
STATIC VOID_T __bh1750_write_2bytes_data(IN CONST SR_RSRC_T *dev, IN CONST BH1750_CMD_E cmd, IN CONST USHORT_T data)
{
    UCHAR_T buf[5];
    buf[0] = (UCHAR_T)(cmd >> 8);
    buf[1] = (UCHAR_T)(cmd & 0x00FF);
    buf[2] = (UCHAR_T)(data >> 8);
    buf[3] = (UCHAR_T)(data & 0x00FF);
    buf[4] = __bh1750_get_crc8(buf+2, 2);

    SR_I2C_MSG_T wr_msg = {
        .flags = SR_I2C_FLAG_WR,
        .addr = dev->info[BH1750_RSRC_INDEX_ADDR],
        .len = 5,
        .buff = buf
    };

    tdd_sensor_i2c_xfer(dev->port, &wr_msg);
}

/**
 * @brief start periodic measurement
 *
 * @param[in] dev: device resource
 *
 * @return none
 */
STATIC VOID_T __bh1750_start_periodic_measurement(IN CONST SR_RSRC_T *dev)
{
    switch (dev->info[BH1750_RSRC_INDEX_PREC]) {
    default:
    case SR_LT_PREC_HIGH:
        switch (dev->info[BH1750_RSRC_INDEX_FREQ]) {
            case SR_LT_FREQ_ONE:
                __bh1750_write_cmd(dev, BH1750_CMD_ONE_H_RES_MODE);
                break;
            case SR_LT_FREQ_CON:
                __bh1750_write_cmd(dev, BH1750_CMD_CON_H_RES_MODE);
                break;
        }
        break;

    case SR_LT_PREC_MEDIUM:
        switch (dev->info[BH1750_RSRC_INDEX_FREQ]) {
            case SR_LT_FREQ_ONE:
                __bh1750_write_cmd(dev, BH1750_CMD_ONE_H_RES_MODE);
                break;
            case SR_LT_FREQ_CON:
                __bh1750_write_cmd(dev, BH1750_CMD_CON_H_RES_MODE);
                break;
        }
        break;

    case SR_LT_PREC_LOW:
        switch (dev->info[BH1750_RSRC_INDEX_FREQ]) {
            case SR_LT_FREQ_ONE:
                __bh1750_write_cmd(dev, BH1750_CMD_ONE_L_RES_MODE);
                break;
            case SR_LT_FREQ_CON:
                __bh1750_write_cmd(dev, BH1750_CMD_CON_L_RES_MODE);
                break;
        }
        break;
    }
}

/**
 * @brief stop periodic measurement
 *
 * @param[in] dev: device resource
 *
 * @return none
 */
STATIC VOID_T __bh1750_stop_periodic_measurement(IN CONST SR_RSRC_T *dev)
{
    __bh1750_write_cmd(dev, BH1750_CMD_ONE_L_RES_MODE);
}

/**
 * @brief set precision
 *
 * @param[inout] dev: device resource
 * @param[in] prec: precision level
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __bh1750_set_precision(INOUT SR_RSRC_T *dev, IN CONST SR_LT_PREC_E *prec)
{
    if ((prec == NULL) || (*prec >= SR_LT_PREC_INVALID)) {
        return OPRT_INVALID_PARM;
    }

    dev->info[BH1750_RSRC_INDEX_PREC] = *prec;
    __bh1750_start_periodic_measurement(dev);

    return OPRT_OK;
}

/**
 * @brief set frequency
 *
 * @param[inout] dev: device resource
 * @param[in] freq: frequency
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __bh1750_set_frequency(INOUT SR_RSRC_T *dev, IN CONST SR_LT_PREC_E *freq)
{
    if ((freq == NULL) || (*freq >= SR_LT_FREQ_INVALID)) {
        return OPRT_INVALID_PARM;
    }

    dev->info[BH1750_RSRC_INDEX_PREC] = *freq;
    __bh1750_start_periodic_measurement(dev);

    return OPRT_OK;
}

/**
 * @brief calculate light
 *
 * @param[in] light: light raw data from sensor
 * @param[out] light_val: light value in °C
 *
 * @return none
 */
STATIC VOID_T __bh1750_calc_light(IN CONST USHORT_T light, OUT SR_VAL_U *light_val,IN USHORT_T resl)
{
#if (SR_CONFIG_NO_FPU == 1)
    light_val->sr_int = light * resl / 2;
    TAL_PR_ERR("light_val->sr_int=%d",light_val->sr_int);
    // light_val->sr_int = light * 175 / 65535 - 45;
#else
    // light_val->sr_float = light * 175.0f / 65535.0f - 45.0f;
    light_val->sr_float = light * resl / 2.0F;
    TAL_PR_ERR("light_val->sr_float=%0.1f",light_val->sr_float);
#endif
}

/**
 * @brief read light and humidity from bh1750
 *
 * @param[in] dev: device resource
 * @param[out] light: light value
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __bh1750_read_light(IN CONST SR_RSRC_T *dev, OUT USHORT_T *light)
{
    UCHAR_T buf[2] = {0};
    OPERATE_RET ret = OPRT_OK;

    TAL_PR_ERR("[BH1750] __bh1750_read_light");

    // reset
    __bh1750_write_cmd(dev, BH1750_CMD_SOFT_RESET);

    // set mode
    // __bh1750_write_cmd(dev, dev->info[BH1750_RSRC_INDEX_MODE]);
    // __bh1750_start_periodic_measurement(dev);
    __bh1750_write_cmd(dev, BH1750_CMD_ONE_H_RES_MODE);

    // delay -- wait value return
    __bh1750_delay_ms(180);

    ret = __bh1750_read_data(dev, 2, buf); 
    if(ret != OPRT_OK)
        return ret;

    *light = ((USHORT_T)buf[0] << 8) | buf[1];

    TAL_PR_ERR("[BH1750] buf = %0x %0x light= %d",buf[0],buf[1],*light);

    return OPRT_OK;
}

/**
 * @brief soft reset
 *
 * @param[in] dev: device resource
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __bh1750_soft_reset(IN CONST SR_RSRC_T *dev)
{
    __bh1750_write_cmd(dev, BH1750_CMD_SOFT_RESET);
    __bh1750_delay_ms(50);
    return OPRT_OK;
}

// /**
//  * @brief read serial number
//  *
//  * @param[in] dev: device resource
//  * @param[out] serial_nbr: serial number
//  *
//  * @return OPRT_OK on success, others on error
//  */
// STATIC OPERATE_RET __bh1750_read_serial_number(IN CONST SR_RSRC_T *dev, OUT SR_LT_SERIAL_NBR_T *serial_nbr)
// {
//     UCHAR_T buf[6] = {0};
//     OPERATE_RET ret = OPRT_OK;

//     __bh1750_write_cmd(dev, BH1750_CMD_READ_SERIALNBR);
//     __bh1750_delay_ms(20);
//     ret = __bh1750_read_data(dev, 6, buf);
//     if(ret != OPRT_OK)
//         return ret;

//     if ((CRC_ERR == __bh1750_check_crc8(buf, 2, buf[2])) ||\\
//         (CRC_ERR == __bh1750_check_crc8(buf+3, 2, buf[5]))) {
//         TAL_PR_ERR("[BH1750] The received serial number can't pass the CRC8 check.");
//         return OPRT_CRC32_FAILED;
//     }

//     serial_nbr->val = ((UINT_T)buf[0] << 24) | ((UINT_T)buf[1] << 16) |\\
//                       ((UINT_T)buf[3] <<  8) | ((UINT_T)buf[4]);
//     return OPRT_OK;
// }

/**
 * @brief open bh1750 device
 *
 * @param[inout] dev: device resource
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __tdd_sensor_bh1750_open(INOUT SR_RSRC_T *dev)
{
    __bh1750_write_cmd(dev, BH1750_CMD_POWER_ON);   // power on
    // __bh1750_start_periodic_measurement(dev);
    dev->info[BH1750_RSRC_INDEX_STAT] = BH1750_OPEN;
    return OPRT_OK;
}

/**
 * @brief close bh1750 device
 *
 * @param[inout] dev: device resource
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __tdd_sensor_bh1750_close(INOUT SR_RSRC_T *dev)
{
    // __bh1750_stop_periodic_measurement(dev);
    __bh1750_write_cmd(dev, BH1750_CMD_POWER_DOWN);   // power down
    dev->info[BH1750_RSRC_INDEX_STAT] = BH1750_CLOSE;
    return OPRT_OK;
}

/**
 * @brief control bh1750 device
 *
 * @param[inout] dev: device resource
 * @param[in] cmd: control command
 * @param[inout] param: command parameter, data type depends on the specified command
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __tdd_sensor_bh1750_control(INOUT SR_RSRC_T* dev, IN UCHAR_T cmd, INOUT VOID_T *param)
{
    OPERATE_RET op_ret = OPRT_OK;

    if ((BH1750_OPEN == dev->info[BH1750_RSRC_INDEX_STAT]) &&\\
        (cmd == SR_LT_CMD_SET_PREC      ||\\
         cmd == SR_LT_CMD_SET_FREQ      ||\\
         cmd == SR_LT_CMD_SOFT_RESET )) {
        TAL_PR_ERR("[BH1750] Command <%d> is only supported when acquisition is closed.");
        return OPRT_COM_ERROR;
    }

    switch (cmd) {
    case SR_LT_CMD_SOFT_RESET:
        op_ret = __bh1750_soft_reset(dev);
        break;

    // case SR_LT_CMD_GET_SERIAL_NBR:
    //     op_ret = __bh1750_read_serial_number(dev, (SR_LT_SERIAL_NBR_T *)param);
    //     break;
        
    case SR_LT_CMD_SET_PREC:
        op_ret = __bh1750_set_precision(dev, (SR_LT_PREC_E *)param);
        break;

    case SR_LT_CMD_SET_FREQ:
        op_ret = __bh1750_set_frequency(dev, (SR_LT_FREQ_E *)param);
        break;

    // case SR_LT_CMD_SET_ALT_LIMIT:
    //     op_ret = __bh1750_set_alert_limit(dev, (SR_LT_LIMIT_T *)param);
    //     break;

    // case SR_LT_CMD_GET_ALT_LIMIT:
    //     op_ret = __bh1750_get_alert_limit(dev, (SR_LT_LIMIT_T *)param);
    //     break;

    // case SR_LT_CMD_ENABLE_ALT_PIN:
    //     op_ret = __bh1750_enable_alert(dev, (SR_LT_ALT_CFG_T *)param);
    //     break;

    // case SR_LT_CMD_DISABLE_ALT_PIN:
    //     op_ret = __bh1750_disable_alert(dev, (TUYA_GPIO_NUM_E *)param);
    //     break;

    // case SR_LT_CMD_GET_STATUS:
    //     op_ret = __bh1750_read_status(dev, (SR_LT_STATUS_U *)param);
    //     break;

    // case SR_LT_CMD_CLR_STATUS:
    //     op_ret = __bh1750_clear_status(dev);
    //     break;

    // case SR_LT_CMD_ENABLE_HEATER:
    //     op_ret = __bh1750_set_heater(dev, TRUE);
    //     break;

    // case SR_LT_CMD_DISABLE_HEATER:
    //     op_ret = __bh1750_set_heater(dev, FALSE);
    //     break;

    default:
        op_ret = OPRT_INVALID_PARM;
        TAL_PR_ERR("[BH1750] Command <%d> is invalid.", cmd);
        break;
    }

    return op_ret;
}

/**
 * @brief read data from bh1750 device
 *
 * @param[in] dev: device
 * @param[out] ele_data: element data
 * @param[in] ele_num: number of elements
 *
 * @return OPRT_OK on success, others on error
 */
STATIC OPERATE_RET __tdd_sensor_bh1750_read(IN SR_RSRC_T* dev, OUT SR_ELE_DATA_T *ele_data, IN UCHAR_T ele_num)
{
    USHORT_T light = 0;

    TAL_PR_ERR("[BH1750] __tdd_sensor_bh1750_read");

    OPERATE_RET op_ret = __bh1750_read_light(dev, &light);
    if (op_ret != OPRT_OK) {
        return op_ret;
    }

    for (UCHAR_T i = 0; i < ele_num; i++) {
        switch (ele_data[i].id) {
        case SR_LT_ELE_ID_LIGHT:
            TAL_PR_ERR("[BH1750] get value. resl=%d",dev->info[BH1750_RSRC_INDEX_RESL]);
            __bh1750_calc_light(light, &ele_data[i].val, (USHORT_T)dev->info[BH1750_RSRC_INDEX_RESL]);
            // ele_data[i].val = ele_data[i].val * (SR_VAL_U)(dev->info[BH1750_RSRC_INDEX_RESL]);
            break;
            
        default:
            TAL_PR_ERR("[BH1750] Element ID: %d is invalid.", ele_data[i].id);
            break;
        }
    }
    return OPRT_OK;
}

/**
 * @brief register bh1750 device
 *
 * @param[in] name: device name
 * @param[in] i2c_cfg: i2c configuration
 * @param[in] meas_cfg: measurement configuration
 *
 * @return OPRT_OK on success, others on error
 */
OPERATE_RET tdd_sensor_bh1750_register(IN CHAR_T *name, IN SR_LT_I2C_CFG_T i2c_cfg, IN SR_LT_MEAS_CFG_T meas_cfg)
{
    // check param
    if (i2c_cfg.gpio.scl == i2c_cfg.gpio.sda) {
        return OPRT_INVALID_PARM;
    }

    // I2C init
    tdd_sensor_i2c_init(i2c_cfg.port, i2c_cfg.gpio);

    // save resourse information
    SR_RSRC_T resource = {0};
    resource.port = i2c_cfg.port;
    resource.handle = NULL;
    resource.info[BH1750_RSRC_INDEX_STAT] = BH1750_CLOSE;
    resource.info[BH1750_RSRC_INDEX_ADDR] = i2c_cfg.addr;
    resource.info[BH1750_RSRC_INDEX_PREC] = meas_cfg.prec;
    resource.info[BH1750_RSRC_INDEX_FREQ] = meas_cfg.freq;

    switch (meas_cfg.prec) {
        case SR_LT_PREC_HIGH: 
            resource.info[BH1750_RSRC_INDEX_RESL] = 2;//1
            break;
        case SR_LT_PREC_MEDIUM:
            resource.info[BH1750_RSRC_INDEX_RESL] = 1;//0.5
            break;
        case SR_LT_PREC_LOW:
            resource.info[BH1750_RSRC_INDEX_RESL] = 82;//41
            break;
        default:
            resource.info[BH1750_RSRC_INDEX_RESL] = 1;//2
            break;
    }
    

    // define driver interfaces
    STATIC SR_INTFS_T s_intfs;
    s_intfs.open = __tdd_sensor_bh1750_open;
    s_intfs.close = __tdd_sensor_bh1750_close;
    s_intfs.control = __tdd_sensor_bh1750_control;
    s_intfs.read_ele = __tdd_sensor_bh1750_read;

    // register the device
    OPERATE_RET op_ret = tdl_sensor_register(name, &s_intfs, SR_LT_ELE_NUM, sg_ele_val_tp, &resource);
    if (OPRT_OK != op_ret) {
        return op_ret;
    }

    return OPRT_OK;
}

四、编译

在ubuntu下使用vscode进行编译很方便。

图片过大,电子发烧友无法上传图片,可以去csdn上看。

【涂鸦T2-U】2、添加光感bh1750-CSDN博客

五、刷机

图片过大,电子发烧友无法上传图片,可以去csdn上看。

【涂鸦T2-U】2、添加光感bh1750-CSDN博客

六、测试结果

如图,其中buf显示的是bh1750返回的值,两个字节。

比如01,38合起来就是0x138=312。

[01-01 00:43:20 TUYA E][tdd_sensor_bh1750.c:861] [BH1750] __tdd_sensor_bh1750_read
[01-01 00:43:20 TUYA E][tdd_sensor_bh1750.c:425] [BH1750] __bh1750_read_light
[01-01 00:43:20 TUYA E][tdd_sensor_bh1750.c:450] [BH1750] buf = 1 38 light= 312
[01-01 00:43:20 TUYA E][tdd_sensor_bh1750.c:871] [BH1750] get value. resl=2
[01-01 00:43:20 TUYA E][tdd_sensor_bh1750.c:392] light_val->sr_float=312.0
[01-01 00:43:20 TUYA I][app_light.c:147] Light: 312 sg_lt_dp_data.light.dp_value: 312
[01-01 00:43:22 TUYA E][tdd_sensor_bh1750.c:861] [BH1750] __tdd_sensor_bh1750_read
[01-01 00:43:22 TUYA E][tdd_sensor_bh1750.c:425] [BH1750] __bh1750_read_light
[01-01 00:43:22 TUYA E][tdd_sensor_bh1750.c:450] [BH1750] buf = 4 3d light= 1085
[01-01 00:43:22 TUYA E][tdd_sensor_bh1750.c:871] [BH1750] get value. resl=2
[01-01 00:43:22 TUYA E][tdd_sensor_bh1750.c:392] light_val->sr_float=1085.0
[01-01 00:43:22 TUYA I][app_light.c:147] Light: 1085 sg_lt_dp_data.light.dp_value: 312
[01-01 00:43:22 TUYA I][app_light.c:154] Light change. Enable report
[01-01 00:43:24 TUYA E][tdd_sensor_bh1750.c:861] [BH1750] __tdd_sensor_bh1750_read
[01-01 00:43:24 TUYA E][tdd_sensor_bh1750.c:425] [BH1750] __bh1750_read_light
[01-01 00:43:24 TUYA E][tdd_sensor_bh1750.c:450] [BH1750] buf = 4 3d light= 1085
[01-01 00:43:24 TUYA E][tdd_sensor_bh1750.c:871] [BH1750] get value. resl=2
[01-01 00:43:24 TUYA E][tdd_sensor_bh1750.c:392] light_val->sr_float=1085.0
[01-01 00:43:24 TUYA I][app_light.c:147] Light: 1085 sg_lt_dp_data.light.dp_value: 1085

小结

本章只是基础的添加驱动,后续还是需要实现联网并上传到云端。

补充一下,除了前期遇到环境搭建的网络问题,涂鸦的开发还是很舒服的,一键编译和一键下载。

回帖(1)

小伍

2023-12-15 16:45:01
电子发烧友可以上传的呀
1 举报
  • voidpbq: 上传没问题,但是发布的时候提示帖子过大

更多回帖

发帖
×
20
完善资料,
赚取积分