RT-Thread開發之路(6)— 通過I2C獲取BH1750光傳感器數據

通過I2C獲取BH1750光傳感器數據

一、硬件準備

小熊派+E53_SC1擴展模塊,如下所示:
在這裏插入圖片描述

二、開啓IIC設備

打開board.h文件,找到IIC的配置處,按照其提示配置:
在這裏插入圖片描述
首先,打開【RT-Thread Settings】,開啓軟件模擬I2C,然後保存使之生效
在這裏插入圖片描述
通過查看原理圖,可以知道,其連接到的引腳是I2C1_SDA -> PB7I2C1_SCL -> PB6,將board.h的I2C1的註釋打開,並輸入對應的引腳:
在這裏插入圖片描述
然後編譯燒錄下載,在msh下輸入list_device查看一下,可以看到,I2C註冊成功
在這裏插入圖片描述

三、導入BH1750軟件包

打開【RT-Thread Settings】,點擊添加軟件包,搜索BH1750,然後點擊添加:
在這裏插入圖片描述
保存使之生效後,我們可以看到,bh1750軟件包已經添加進來了:
在這裏插入圖片描述
打開sensor_rohm_bh1750.c,找到bh1750_port()函數,將其中的I2C修改爲我們使用的"i2c1"
在這裏插入圖片描述
然後就可以編譯燒錄運行了,在msh下輸入list_device查看,bh1750已經註冊好了:
在這裏插入圖片描述
然後我們輸入命令sensor probe li_bh1750,將BH1750打開,可以看到,打開成功,然後使用sensor read命令,可以看到,沒有數據
在這裏插入圖片描述
這是因爲沒有寫入環境光照強度打印代碼,我們打開\components\drivers\sensors\sensor_cmd.c,在sensor_show_data函數後面自行增加環境光照強度打印代碼:

case RT_SENSOR_CLASS_LIGHT:
        LOG_I("num:%3d, light:%4d.%d, timestamp:%5d", num, sensor_data->data.light / 10, sensor_data->data.light % 10, sensor_data->timestamp);
        break;

然後重新編譯燒錄運行,可以看到可以讀取出數據了:
在這裏插入圖片描述

四、編寫應用代碼

新建app_bh1750.c文件,創建一個線程,每隔一秒讀取一次光照數據,然後將其打印出來,並結合之前的內容:RT-Thread開發之路(4)— MQTT通信,將光照數據發送到EMQ服務器。代碼如下:

#include "sensor.h"

/* 定義一個BH1750線程句柄結構體指針 */
static rt_thread_t app_bh1750_thread = RT_NULL;

/* 發佈"BH1750_Pub"主題消息函數 */
void BH1750_Publish(char * msg);

char data_buf[32];

static void app_bh1750_thread_entry(void *parameter)
{
    rt_device_t dev = RT_NULL;
    struct rt_sensor_data data;
    rt_size_t res;

    /* 查找系統中的傳感器設備 */
    dev = rt_device_find("li_bh1750");
    if (dev == RT_NULL)
    {
        rt_kprintf("Can't find device:li_bh1750\n");
        return;
    }

    /* 以輪詢模式打開傳感器設備 */
    if (rt_device_open(dev, RT_DEVICE_FLAG_RDONLY) != RT_EOK)
    {
        rt_kprintf("open device failed!");
        return;
    }

    while(1)
    {
        /* 從傳感器讀取一個數據 */
        res = rt_device_read(dev, 0, &data, 1);
        if (res != 1)
        {
            rt_kprintf("read data failed!size is %d", res);
        }
        else
        {
            rt_kprintf("light:%4d.%d lux \n", (&data)->data.light / 10, (&data)->data.light % 10);
            rt_sprintf(data_buf,"\"light\":%4d.%d lux \n", (&data)->data.light / 10, (&data)->data.light % 10);
            BH1750_Publish(data_buf);
        }
        rt_thread_mdelay(1000);
    }
    /* 關閉傳感器設備 */
    rt_device_close(dev);
}

static int app_bh1750_init(void)
{
    rt_err_t rt_err;

    /* 創建BH1750線程*/
    app_bh1750_thread = rt_thread_create("app_bh1750 thread",
            app_bh1750_thread_entry, RT_NULL, 2048, 6, 10);
    /* 如果獲得線程控制塊,啓動這個線程 */
    if (app_bh1750_thread != RT_NULL)
        rt_err = rt_thread_startup(app_bh1750_thread);
    else
        rt_kprintf("app_bh1750_thread create failure !!! \n");

    /* 判斷線程是否啓動成功 */
    if( rt_err == RT_EOK)
        rt_kprintf("app_bh1750_thread startup ok. \n");
    else
        rt_kprintf("app_bh1750_thread startup err. \n");

    return rt_err;
}

INIT_APP_EXPORT(app_bh1750_init);


另外修改過的app_mqtt.c文件如下:

#include <rtthread.h>
#include <board.h>
#include <rtdevice.h>
#include <sys/socket.h>
#include "netdb.h"
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "paho_mqtt.h"

#define MQTT_Uri    "tcp://39.96.35.207:1883"   // MQTT服務器的地址和端口號
#define ClientId    "BearPi8266"                // ClientId需要唯一
#define UserName    "BearPi"                    // 用戶名
#define PassWord    "123456"                    // 用戶名對應的密碼

/* 定義一個MQTT線程句柄結構體指針 */
static rt_thread_t app_mqtt_thread = RT_NULL;

/* 定義一個MQTT客戶端結構體 */
static MQTTClient client;

/* 標識MQTT是否啓動成功 */
static int is_started = 0;

/* 發佈"BH1750_Pub"主題函數 */
void BH1750_Publish(char * msg)
{
    if(is_started == 1)
        paho_mqtt_publish(&client, QOS1, "BH1750_Pub", msg);
}

/* 收到訂閱的"Bear_Pi"主題的消息時的回調函數*/
static void mqtt_sub_callback(MQTTClient *c, MessageData *msg_data)
{
    *((char *)msg_data->message->payload + msg_data->message->payloadlen) = '\0';
    rt_kprintf("Receive topic: %.*s, message data:\r\n", msg_data->topicName->lenstring.len, msg_data->topicName->lenstring.data);
    rt_kprintf("%.*s\r\n", msg_data->message->payloadlen, (char *)msg_data->message->payload);
}

/* 默認的訂閱回調函數,如果有訂閱的 Topic 沒有設置回調函數,則使用該默認回調函數 */
static void mqtt_sub_default_callback(MQTTClient *c, MessageData *msg_data)
{
    *((char *)msg_data->message->payload + msg_data->message->payloadlen) = '\0';
    rt_kprintf("Receive topic: %.*s, message data:\r\n", msg_data->topicName->lenstring.len, msg_data->topicName->lenstring.data);
    rt_kprintf("%.*s\r\n", msg_data->message->payloadlen, (char *)msg_data->message->payload);
}

/* 連接成功回調函數 */
static void mqtt_connect_callback(MQTTClient *c)
{
    rt_kprintf("mqtt connect success! \r\n");
}

/* 上線回調函數 */
static void mqtt_online_callback(MQTTClient *c)
{
    rt_kprintf("mqtt online \r\n");
    paho_mqtt_publish(&client, QOS1, "BH1750_Pub", "Hello, I am BearPi with RT_Thread.");
}

/* 下線回調函數 */
static void mqtt_offline_callback(MQTTClient *c)
{
    rt_kprintf("mqtt offline \r\n");
}

static void app_mqtt_thread_entry(void *parameter)
{
    //int count = 1;
    //char msg_buf[128];
    /* 對MQTT客戶端結構體變量進行配置 */
    client.isconnected = 0;
    client.uri = MQTT_Uri;

    /* 配置MQTT的連接參數 */
    MQTTPacket_connectData condata = MQTTPacket_connectData_initializer;
    memcpy(&client.condata, &condata, sizeof(condata));
    client.condata.clientID.cstring = ClientId;
    client.condata.keepAliveInterval = 30;
    client.condata.cleansession = 1;
    client.condata.username.cstring = UserName;
    client.condata.password.cstring = PassWord;

    /* 爲mqtt申請內存 */
    client.buf_size = client.readbuf_size = 1024;
    client.buf = rt_calloc(1, client.buf_size);
    client.readbuf = rt_calloc(1, client.readbuf_size);
    if (!(client.buf && client.readbuf))
    {
        rt_kprintf("no memory for MQTT client buffer!\r\n");
        return ;
    }

    /* 設置回調函數  */
    client.connect_callback = mqtt_connect_callback;
    client.online_callback = mqtt_online_callback;
    client.offline_callback = mqtt_offline_callback;

    /* 訂閱一個主題,並設置其回調函數 */
    client.messageHandlers[0].topicFilter = rt_strdup("BH1750_Sub");
    client.messageHandlers[0].callback = mqtt_sub_callback;
    client.messageHandlers[0].qos = QOS1;

    /* 設置默認的回調函數 */
    client.defaultMessageHandler = mqtt_sub_default_callback;

    /* 啓動 mqtt client */
    paho_mqtt_start(&client);

    is_started = 1;

    while(1)
    {
        //rt_sprintf(msg_buf, "publish %d times.", count++);
        //paho_mqtt_publish(&client, QOS1, "BearPi_Pub", msg_buf);
        rt_thread_mdelay(1000);
    }
}

static int app_mqtt_init(void)
{
    rt_err_t rt_err;
    /* 創建MQTT線程*/
    app_mqtt_thread = rt_thread_create("app_mqtt thread",
            app_mqtt_thread_entry, RT_NULL, 2048, 6, 10);
    /* 如果獲得線程控制塊,啓動這個線程 */
    if (app_mqtt_thread != RT_NULL)
        rt_err = rt_thread_startup(app_mqtt_thread);
    else
        rt_kprintf("app_mqtt_thread create failure !!! \n");

    /* 判斷線程是否啓動成功 */
    if( rt_err == RT_EOK)
        rt_kprintf("app_mqtt_thread startup ok. \n");
    else
        rt_kprintf("app_mqtt_thread startup err. \n");

    return rt_err;
}

INIT_APP_EXPORT(app_mqtt_init);

編譯燒錄運行,可以看到,運行成功:
在這裏插入圖片描述

然後再MQTT上也接收到了數據:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章