一、項(xiàng)目背景
智慧農(nóng)業(yè)是近年來發(fā)展迅速的領(lǐng)域,其目的是利用先進(jìn)的傳感技術(shù)、物聯(lián)網(wǎng)技術(shù)和云計(jì)算技術(shù)等,實(shí)現(xiàn)自動(dòng)化、智能化的農(nóng)業(yè)生產(chǎn)管理,并提高農(nóng)業(yè)生產(chǎn)效率和質(zhì)量。本文基于CC2530設(shè)計(jì)了一種智慧農(nóng)業(yè)控制系統(tǒng),采用DHT11模塊、BH1750模塊和土壤濕度傳感器等傳感器,通過串口協(xié)議將采集的數(shù)據(jù)上傳給上位機(jī)顯示。
二、系統(tǒng)框架
本系統(tǒng)主要包括一下的組成部分:
【1】采集端:由CC2530單片機(jī)和各種傳感器構(gòu)成,負(fù)責(zé)測(cè)量環(huán)境溫濕度、環(huán)境光照強(qiáng)度和土壤濕度等信息,并通過串口協(xié)議將采集的數(shù)據(jù)上傳給上位機(jī)顯示。
【2】上位機(jī):采用Qt進(jìn)行開發(fā),負(fù)責(zé)接收串口上傳的數(shù)據(jù)并進(jìn)行顯示。
【3】傳輸介質(zhì):采用串口協(xié)議進(jìn)行數(shù)據(jù)傳輸,支持異步通信,具有數(shù)據(jù)幀結(jié)構(gòu)。
【4】傳感器模塊:包括DHT11模塊、BH1750模塊和土壤濕度傳感器等,通過采集環(huán)境溫濕度、環(huán)境光照強(qiáng)度和土壤濕度等信息,實(shí)現(xiàn)對(duì)農(nóng)業(yè)生產(chǎn)環(huán)境的監(jiān)測(cè)和控制。
CC2530是德州儀器(Texas Instruments)推出的一款低功耗無線系統(tǒng)芯片,它是基于ZigBee協(xié)議的SoC系統(tǒng),內(nèi)置了ARM Cortex-M3處理器和IEEE 802.15.4標(biāo)準(zhǔn)無線通信模塊,可以實(shí)現(xiàn)低速率的無線數(shù)據(jù)傳輸和網(wǎng)絡(luò)互連。CC2530芯片的主要特點(diǎn)是低功耗、高可靠性、靈活性強(qiáng)、易于集成和開發(fā),被廣泛應(yīng)用于物聯(lián)網(wǎng)、智能家居、智能電表、智能照明等領(lǐng)域的無線數(shù)據(jù)傳輸和控制系統(tǒng)中。
BH1750是一款數(shù)字式環(huán)境光傳感器,可用于測(cè)量光強(qiáng)度。它具有高分辨率和靈敏度,并且與普通光敏電阻相比,具有更廣泛的動(dòng)態(tài)范圍和線性性。BH1750可以通過I2C接口連接到微控制器或其他電子設(shè)備上,如Arduino、樹莓派等。它被廣泛應(yīng)用于夜間照明系統(tǒng)、自動(dòng)控制系統(tǒng)、安防監(jiān)控等領(lǐng)域。
DHT11是一種數(shù)字溫濕度傳感器,可以測(cè)量環(huán)境的溫度和相對(duì)濕度。它通常被用于家庭和工業(yè)自動(dòng)化等領(lǐng)域,可以在各種應(yīng)用中監(jiān)測(cè)環(huán)境條件。
DHT11有四個(gè)引腳:VCC(電源正極)、GND(地)、DATA(數(shù)據(jù)信號(hào))和NC(未使用)。它可以通過單一總線接口與微控制器連接,并以數(shù)字形式輸出溫度和濕度值。其溫度測(cè)量范圍為0℃至50℃,濕度測(cè)量范圍為20%RH至90%RH。
在使用DHT11傳感器時(shí),需要注意一些問題。例如,在讀取數(shù)據(jù)之前,應(yīng)將傳感器加電并等待1至2秒鐘,以使其穩(wěn)定。此外,在讀取數(shù)據(jù)后,還需要進(jìn)行數(shù)據(jù)校驗(yàn),以確保數(shù)據(jù)的準(zhǔn)確性。
三、系統(tǒng)設(shè)計(jì)
【1】采集端設(shè)計(jì)
采集端主要由CC2530單片機(jī)和各種傳感器構(gòu)成。其中,溫濕度采用DHT11模塊,光照強(qiáng)度采用BH1750模塊,土壤濕度采用土壤濕度傳感器。通過采集這些信息,可以了解農(nóng)田的環(huán)境狀態(tài),并根據(jù)需要進(jìn)行相應(yīng)的調(diào)節(jié)和控制,保證作物的正常生長(zhǎng)。
【2】上位機(jī)設(shè)計(jì)
上位機(jī)采用QT進(jìn)行開發(fā),支持串口通信和數(shù)據(jù)顯示。在數(shù)據(jù)傳輸端口的配置上,串口通信采用異步通信方式,支持?jǐn)?shù)據(jù)幀結(jié)構(gòu),即每個(gè)數(shù)據(jù)包由起始位、數(shù)據(jù)位、校驗(yàn)碼、停止位等幾部分組成,以確保數(shù)據(jù)傳輸?shù)姆€(wěn)定性和可靠性。同時(shí),上位機(jī)還實(shí)現(xiàn)了數(shù)據(jù)的動(dòng)態(tài)顯示和歷史數(shù)據(jù)的查詢導(dǎo)出功能,以方便用戶對(duì)農(nóng)田環(huán)境數(shù)據(jù)進(jìn)行分析和處理。
四、上位機(jī)源碼實(shí)現(xiàn)
以下是Qt串口讀取數(shù)據(jù)的實(shí)現(xiàn)代碼:
#include
#include
#include
#include
?
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
?
QSerialPort serial;
serial.setPortName("COM1"); // 根據(jù)實(shí)際情況設(shè)置端口號(hào)
if (!serial.open(QIODevice::ReadWrite)) { // 打開串口
qDebug() << "Failed to open serial port!";
return 1;
}
?
// 設(shè)置串口參數(shù)
serial.setBaudRate(QSerialPort::Baud115200);
serial.setDataBits(QSerialPort::Data8);
serial.setParity(QSerialPort::NoParity);
serial.setStopBits(QSerialPort::OneStop);
serial.setFlowControl(QSerialPort::NoFlowControl);
?
while (true) {
if (serial.waitForReadyRead(1000)) { // 等待數(shù)據(jù)
QByteArray data = serial.readAll(); // 讀取所有數(shù)據(jù)
qDebug() << "Received data:" << data; // 打印所有數(shù)據(jù)
?
// 解析數(shù)據(jù)
QStringList dataList = QString(data).split(",");
if (dataList.size() == 4) {
float temperature = dataList[0].toFloat();
float humidity = dataList[1].toFloat();
float illumination = dataList[2].toFloat();
float soilMoisture = dataList[3].toFloat();
?
// 打印解析后的數(shù)據(jù)
qDebug() << "Temperature:" << temperature << "°C";
qDebug() << "Humidity:" << humidity << "%";
qDebug() << "Illumination:" << illumination << "lux";
qDebug() << "Soil Moisture:" << soilMoisture << "%";
}
}
}
?
return a.exec();
}
讀取數(shù)據(jù)時(shí),采用了waitForReadyRead函數(shù)等待串口數(shù)據(jù)到達(dá),該函數(shù)的參數(shù)表示最長(zhǎng)等待時(shí)間,單位為毫秒。在解析數(shù)據(jù)時(shí),使用了QString的split函數(shù)將數(shù)據(jù)按逗號(hào)分隔為多個(gè)字符串,再分別轉(zhuǎn)換為對(duì)應(yīng)的浮點(diǎn)數(shù)。
五、CC2530設(shè)備端源碼
【1】BH1750數(shù)據(jù)讀取
以下是CC2530單片機(jī)讀取BH1750光敏傳感器的值并打印到串口的代碼:
#include "hal_board_cfg.h"
#include "hal_types.h"
#include "hal_defs.h"
#include "hal_uart.h"
#include "onboard.h"
#include "hal_i2c.h"
?
#define BH1750_ADDR 0x23 // BH1750默認(rèn)地址
?
void initUART();
void sendStr(char *str);
void BH1750_init();
uint16 BH1750_read();
?
void main()
{
// 初始化
halBoardInit();
initUART();
BH1750_init();
?
while (TRUE)
{
// 讀取傳感器數(shù)據(jù)
uint16 illumination = BH1750_read();
char str[16];
sprintf(str, "%d", illumination);
?
// 將數(shù)據(jù)打印到串口
sendStr(str);
?
// 延時(shí)等待1秒
halMcuWaitMs(1000);
}
}
?
void initUART()
{
HAL_UART_CFG_T uartCfg;
?
uartCfg.baudRate = HAL_UART_BR_115200;
uartCfg.flowControl = FALSE;
uartCfg.parity = HAL_UART_PARITY_NONE;
uartCfg.stopBits = HAL_UART_STOP_BITS_1;
uartCfg.startGuardTime = 0;
?
HalUARTInit();
HalUARTOpen(HAL_UART_PORT_0, &uartCfg);
}
?
void sendStr(char *str)
{
while (*str != '\\0')
{
HalUARTWrite(HAL_UART_PORT_0, (uint8*)str, 1);
str++;
}
?
HalUARTWrite(HAL_UART_PORT_0, (uint8*)"\\r\\n", 2);
}
?
void BH1750_init()
{
uint8 pBuf[2];
?
pBuf[0] = 0x01; // 開始測(cè)量命令
halI2CWrite(BH1750_ADDR, pBuf, 1);
?
pBuf[0] = 0x10; // 分辨率設(shè)置為1lx
halI2CWrite(BH1750_ADDR, pBuf, 1);
}
?
uint16 BH1750_read()
{
uint8 pBuf[2];
?
halI2CRead(BH1750_ADDR, pBuf, 2);
?
uint16 illumination = (pBuf[0] << 8) | pBuf[1];
?
return illumination;
}
上述代碼中,initUART函數(shù)用于初始化串口,sendStr函數(shù)用于將字符串打印到串口。BH1750_init函數(shù)用于初始化BH1750傳感器,包括發(fā)送開始測(cè)量指令和設(shè)置分辨率為1lx等操作。BH1750_read函數(shù)用于讀取傳感器數(shù)據(jù)并計(jì)算出光照強(qiáng)度值。在main函數(shù)中,使用了一個(gè)while循環(huán)不斷從傳感器讀取數(shù)據(jù),并通過串口打印輸出。代碼中的延時(shí)函數(shù)halMcuWaitMs是CC2530提供的延時(shí)函數(shù),可以使用其他方式實(shí)現(xiàn)延時(shí)等待功能。
【2】DHT11溫濕度數(shù)據(jù)讀取
以下是CC2530單片機(jī)讀取DHT11傳感器的溫度和濕度并打印到串口的代碼:
#include "hal_types.h"
#include "hal_board.h"
#include "hal_uart.h"
?
#define DHT11_PORT 1 // DHT11連接到P1口
?
// 發(fā)送一個(gè)DHT11開始信號(hào)
void DHT11_Start(void) {
// 設(shè)置引腳為輸出模式
P1SEL &= ~(1 << DHT11_PORT);
P1DIR |= (1 << DHT11_PORT);
?
// 拉低引腳
P1_1 = 0;
?
// 等待至少18ms
HalDelayMs(18);
?
// 拉高引腳
P1_1 = 1;
?
// 等待20~40us,并切換到輸入模式
HalDelayUs(30);
P1DIR &= ~(1 << DHT11_PORT);
}
?
// 等待DHT11響應(yīng)信號(hào)
uint8 DHT11_WaitResponse(void) {
uint8 timeOut = 0;
while(P1_1 && timeOut < 200) { // 等待低電平出現(xiàn),超時(shí)返回1
HalDelayUs(1);
timeOut++;
}
if(timeOut >= 200) return 1;
?
timeOut = 0;
while(!P1_1 && timeOut < 200) { // 等待高電平出現(xiàn),超時(shí)返回1
HalDelayUs(1);
timeOut++;
}
if(timeOut >= 200) return 1;
?
return 0;
}
?
// 讀取一個(gè)位
uint8 DHT11_ReadBit(void) {
uint8 timeOut = 0;
while(P1_1 && timeOut < 200) { // 等待低電平出現(xiàn),超時(shí)返回1
HalDelayUs(1);
timeOut++;
}
?
timeOut = 0;
while(!P1_1 && timeOut < 200) { // 等待高電平出現(xiàn),超時(shí)返回1
HalDelayUs(1);
timeOut++;
}
?
HalDelayUs(40); // 等待40us
?
if(P1_1) return 1; // 如果在40us內(nèi)未出現(xiàn)低電平,返回1,表示數(shù)據(jù)錯(cuò)誤
?
return 0;
}
?
// 讀取一個(gè)字節(jié)
uint8 DHT11_ReadByte(void) {
uint8 byte = 0;
uint8 i;
for(i=0;i<8;i++) {
byte <<= 1;
byte |= DHT11_ReadBit();
}
return byte;
}
?
// 從DHT11讀取溫度和濕度數(shù)據(jù)
void DHT11_ReadData(uint8* temperature, uint8* humidity) {
uint8 data[5];
?
// 發(fā)送開始信號(hào)
DHT11_Start();
?
// 等待響應(yīng)信號(hào)
if(DHT11_WaitResponse()) {
*temperature = 0;
*humidity = 0;
return;
}
?
// 讀取數(shù)據(jù)
data[0] = DHT11_ReadByte(); // 濕度整數(shù)部分
data[1] = DHT11_ReadByte(); // 濕度小數(shù)部分
data[2] = DHT11_ReadByte(); // 溫度整數(shù)部分
data[3] = DHT11_ReadByte(); // 溫度小數(shù)部分
data[4] = DHT11_ReadByte(); // 校驗(yàn)和
?
// 計(jì)算校驗(yàn)和
uint8 sum = data[0] + data[1] + data[2] + data[3];
if(sum != data[4]) {
*temperature = 0;
*humidity = 0;
return;
}
?
// 計(jì)算溫度和濕度
*humidity = data[0];
*temperature = data[2];
}
?
// 初始化串口
void UART_Init(void) {
HalUARTInit();
HalUARTCfg_t uartConfig;
uartConfig.configured = TRUE;
uartConfig.baudRate = HAL_UART_BR_115200;
uartConfig.flowControl = FALSE;
uartConfig.flowControlThreshold = 64;
// 設(shè)置串口傳輸格式
uartConfig.rx.maxBufSize = 128;
uartConfig.tx.maxBufSize = 128;
uartConfig.idleTimeout = 6;
uartConfig.intEnable = TRUE;
uartConfig.callBackFunc = NULL;
HalUARTOpen(HAL_UART_PORT_0, &uartConfig);
}
?
// 打印溫度和濕度到串口
void PrintData(uint8 temperature, uint8 humidity) {
char buf[32];
sprintf(buf, "Temperature: %dC, Humidity: %d%%\\r\\n", temperature, humidity);
HalUARTWrite(HAL_UART_PORT_0, (uint8*)buf, strlen(buf));
}
?
void main(void) {
uint8 temperature, humidity;
?
// 初始化串口
UART_Init();
?
while(1) {
// 從DHT11讀取數(shù)據(jù)
DHT11_ReadData(&temperature, &humidity);
?
// 打印數(shù)據(jù)到串口
PrintData(temperature, humidity);
?
// 等待1秒鐘
HalDelayMs(1000);
}
}
這段代碼使用CC2530單片機(jī)通過DHT11傳感器讀取環(huán)境溫度和濕度,并將其打印到串口。具體實(shí)現(xiàn)過程為,首先發(fā)送一個(gè)開始信號(hào),等待DHT11響應(yīng)信號(hào)后,依次讀取濕度整數(shù)、濕度小數(shù)、溫度整數(shù)、溫度小數(shù)和校驗(yàn)和。判斷校驗(yàn)和是否正確后,計(jì)算得到溫度和濕度,并通過串口輸出。為了保證數(shù)據(jù)的準(zhǔn)確性,每次讀取數(shù)據(jù)前需要等待1秒鐘。
審核編輯:湯梓紅
-
單片機(jī)
+關(guān)注
關(guān)注
6023文章
44376瀏覽量
628357 -
控制系統(tǒng)
+關(guān)注
關(guān)注
41文章
6419瀏覽量
110094 -
物聯(lián)網(wǎng)
+關(guān)注
關(guān)注
2894文章
43313瀏覽量
366414 -
CC2530
+關(guān)注
關(guān)注
19文章
220瀏覽量
57483 -
智慧農(nóng)業(yè)
+關(guān)注
關(guān)注
4文章
758瀏覽量
19746
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論