通過I2C獲取BH1750光傳感器數據
一、硬件準備
小熊派+E53_SC1擴展模塊,如下所示:
二、開啓IIC設備
打開board.h文件,找到IIC的配置處,按照其提示配置:
首先,打開【RT-Thread Settings】,開啓軟件模擬I2C,然後保存使之生效
通過查看原理圖,可以知道,其連接到的引腳是I2C1_SDA -> PB7
和I2C1_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上也接收到了數據: