基于CC2530设计智慧农业控制系统

本文涉及的产品
数据传输服务 DTS,数据迁移 small 3个月
推荐场景:
MySQL数据库上云
数据传输服务 DTS,数据同步 1个月
简介: 本文基于CC2530设计了一种智慧农业控制系统,采用DHT11模块、BH1750模块和土壤湿度传感器等传感器,通过串口协议将采集的数据上传给上位机显示。

一、项目背景

智慧农业是近年来发展迅速的领域,其目的是利用先进的传感技术、物联网技术和云计算技术等,实现自动化、智能化的农业生产管理,并提高农业生产效率和质量。本文基于CC2530设计了一种智慧农业控制系统,采用DHT11模块、BH1750模块和土壤湿度传感器等传感器,通过串口协议将采集的数据上传给上位机显示。

二、系统框架

本系统主要包括一下的组成部分:

【1】采集端:由CC2530单片机和各种传感器构成,负责测量环境温湿度、环境光照强度和土壤湿度等信息,并通过串口协议将采集的数据上传给上位机显示。

【2】上位机:采用Qt进行开发,负责接收串口上传的数据并进行显示。

【3】传输介质:采用串口协议进行数据传输,支持异步通信,具有数据帧结构。

【4】传感器模块:包括DHT11模块、BH1750模块和土壤湿度传感器等,通过采集环境温湿度、环境光照强度和土壤湿度等信息,实现对农业生产环境的监测和控制。

image.png
image.png

CC2530是德州仪器(Texas Instruments)推出的一款低功耗无线系统芯片,它是基于ZigBee协议的SoC系统,内置了ARM Cortex-M3处理器和IEEE 802.15.4标准无线通信模块,可以实现低速率的无线数据传输和网络互连。CC2530芯片的主要特点是低功耗、高可靠性、灵活性强、易于集成和开发,被广泛应用于物联网、智能家居、智能电表、智能照明等领域的无线数据传输和控制系统中。

image.png

BH1750是一款数字式环境光传感器,可用于测量光强度。它具有高分辨率和灵敏度,并且与普通光敏电阻相比,具有更广泛的动态范围和线性性。BH1750可以通过I2C接口连接到微控制器或其他电子设备上,如Arduino、树莓派等。它被广泛应用于夜间照明系统、自动控制系统、安防监控等领域。

image.png

DHT11是一种数字温湿度传感器,可以测量环境的温度和相对湿度。它通常被用于家庭和工业自动化等领域,可以在各种应用中监测环境条件。

DHT11有四个引脚:VCC(电源正极)、GND(地)、DATA(数据信号)和NC(未使用)。它可以通过单一总线接口与微控制器连接,并以数字形式输出温度和湿度值。其温度测量范围为0℃至50℃,湿度测量范围为20%RH至90%RH。

在使用DHT11传感器时,需要注意一些问题。例如,在读取数据之前,应将传感器加电并等待1至2秒钟,以使其稳定。此外,在读取数据后,还需要进行数据校验,以确保数据的准确性。

image.png

三、系统设计

【1】采集端设计

采集端主要由CC2530单片机和各种传感器构成。其中,温湿度采用DHT11模块,光照强度采用BH1750模块,土壤湿度采用土壤湿度传感器。通过采集这些信息,可以了解农田的环境状态,并根据需要进行相应的调节和控制,保证作物的正常生长。

【2】上位机设计

上位机采用QT进行开发,支持串口通信和数据显示。在数据传输端口的配置上,串口通信采用异步通信方式,支持数据帧结构,即每个数据包由起始位、数据位、校验码、停止位等几部分组成,以确保数据传输的稳定性和可靠性。同时,上位机还实现了数据的动态显示和历史数据的查询导出功能,以方便用户对农田环境数据进行分析和处理。

四、上位机源码实现

以下是Qt串口读取数据的实现代码:

#include <QCoreApplication>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QDebug>

int main(int argc, char *argv[])
{
   
   
    QCoreApplication a(argc, argv);

    QSerialPort serial;
    serial.setPortName("COM1");  // 根据实际情况设置端口号
    if (!serial.open(QIODevice::ReadWrite)) {
   
     // 打开串口
        qDebug() << "Failed to open serial port!";
        return 1;
    }

    // 设置串口参数
    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)) {
   
     // 等待数据
            QByteArray data = serial.readAll();  // 读取所有数据
            qDebug() << "Received data:" << data;  // 打印所有数据

            // 解析数据
            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();

                // 打印解析后的数据
                qDebug() << "Temperature:" << temperature << "°C";
                qDebug() << "Humidity:" << humidity << "%";
                qDebug() << "Illumination:" << illumination << "lux";
                qDebug() << "Soil Moisture:" << soilMoisture << "%";
            }
        }
    }

    return a.exec();
}

读取数据时,采用了waitForReadyRead函数等待串口数据到达,该函数的参数表示最长等待时间,单位为毫秒。在解析数据时,使用了QString的split函数将数据按逗号分隔为多个字符串,再分别转换为对应的浮点数。

五、CC2530设备端源码

【1】BH1750数据读取

以下是CC2530单片机读取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默认地址

void initUART();
void sendStr(char *str);
void BH1750_init();
uint16 BH1750_read();

void main()
{
   
   
    // 初始化
    halBoardInit();
    initUART();
    BH1750_init();

    while (TRUE)
    {
   
   
        // 读取传感器数据
        uint16 illumination = BH1750_read();
        char str[16];
        sprintf(str, "%d", illumination);

        // 将数据打印到串口
        sendStr(str);

        // 延时等待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;  // 开始测量命令
    halI2CWrite(BH1750_ADDR, pBuf, 1);

    pBuf[0] = 0x10;  // 分辨率设置为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函数用于初始化串口,sendStr函数用于将字符串打印到串口。BH1750_init函数用于初始化BH1750传感器,包括发送开始测量指令和设置分辨率为1lx等操作。BH1750_read函数用于读取传感器数据并计算出光照强度值。在main函数中,使用了一个while循环不断从传感器读取数据,并通过串口打印输出。代码中的延时函数halMcuWaitMs是CC2530提供的延时函数,可以使用其他方式实现延时等待功能。

【2】DHT11温湿度数据读取

以下是CC2530单片机读取DHT11传感器的温度和湿度并打印到串口的代码:

#include "hal_types.h"
#include "hal_board.h"
#include "hal_uart.h"

#define DHT11_PORT 1   // DHT11连接到P1口

// 发送一个DHT11开始信号
void DHT11_Start(void) {
   
   
  // 设置引脚为输出模式
  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响应信号
uint8 DHT11_WaitResponse(void) {
   
   
  uint8 timeOut = 0;
  while(P1_1 && timeOut < 200) {
   
     // 等待低电平出现,超时返回1
    HalDelayUs(1);
    timeOut++;
  }
  if(timeOut >= 200) return 1;

  timeOut = 0;
  while(!P1_1 && timeOut < 200) {
   
     // 等待高电平出现,超时返回1
    HalDelayUs(1);
    timeOut++;
  }
  if(timeOut >= 200) return 1;

  return 0;
}

// 读取一个位
uint8 DHT11_ReadBit(void) {
   
   
  uint8 timeOut = 0;
  while(P1_1 && timeOut < 200) {
   
     // 等待低电平出现,超时返回1
    HalDelayUs(1);
    timeOut++;
  }

  timeOut = 0;
  while(!P1_1 && timeOut < 200) {
   
     // 等待高电平出现,超时返回1
    HalDelayUs(1);
    timeOut++;
  }

  HalDelayUs(40);  // 等待40us

  if(P1_1) return 1;  // 如果在40us内未出现低电平,返回1,表示数据错误

  return 0;
}

// 读取一个字节
uint8 DHT11_ReadByte(void) {
   
   
  uint8 byte = 0;
  uint8 i;
  for(i=0;i<8;i++) {
   
   
    byte <<= 1;
    byte |= DHT11_ReadBit();
  }
  return byte;
}

// 从DHT11读取温度和湿度数据
void DHT11_ReadData(uint8* temperature, uint8* humidity) {
   
   
  uint8 data[5];

  // 发送开始信号
  DHT11_Start();

  // 等待响应信号
  if(DHT11_WaitResponse()) {
   
   
    *temperature = 0;
    *humidity = 0;
    return;
  }

  // 读取数据
  data[0] = DHT11_ReadByte();  // 湿度整数部分
  data[1] = DHT11_ReadByte();  // 湿度小数部分
  data[2] = DHT11_ReadByte();  // 温度整数部分
  data[3] = DHT11_ReadByte();  // 温度小数部分
  data[4] = DHT11_ReadByte();  // 校验和

  // 计算校验和
  uint8 sum = data[0] + data[1] + data[2] + data[3];
  if(sum != data[4]) {
   
   
    *temperature = 0;
    *humidity = 0;
    return;
  }

  // 计算温度和湿度
  *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;
  // 设置串口传输格式
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读取数据
DHT11_ReadData(&temperature, &humidity);

// 打印数据到串口
PrintData(temperature, humidity);

// 等待1秒钟
HalDelayMs(1000);
}
}

这段代码使用CC2530单片机通过DHT11传感器读取环境温度和湿度,并将其打印到串口。具体实现过程为,首先发送一个开始信号,等待DHT11响应信号后,依次读取湿度整数、湿度小数、温度整数、温度小数和校验和。判断校验和是否正确后,计算得到温度和湿度,并通过串口输出。为了保证数据的准确性,每次读取数据前需要等待1秒钟。

相关实践学习
RocketMQ一站式入门使用
从源码编译、部署broker、部署namesrv,使用java客户端首发消息等一站式入门RocketMQ。
Sqoop 企业级大数据迁移方案实战
Sqoop是一个用于在Hadoop和关系数据库服务器之间传输数据的工具。它用于从关系数据库(如MySQL,Oracle)导入数据到Hadoop HDFS,并从Hadoop文件系统导出到关系数据库。 本课程主要讲解了Sqoop的设计思想及原理、部署安装及配置、详细具体的使用方法技巧与实操案例、企业级任务管理等。结合日常工作实践,培养解决实际问题的能力。本课程由黑马程序员提供。
目录
相关文章
|
4天前
|
传感器 监控
基于STM32的智能农业环境监测系统设计与实现
基于STM32的智能农业环境监测系统设计与实现
155 0
|
4天前
|
运维 安全
DC电源模块在医疗设备中的应用挑战与解决方案
DC电源模块在医疗设备中的应用挑战与解决方案
DC电源模块在医疗设备中的应用挑战与解决方案
|
4天前
BOSHIDA AC/DC电源模块的节能技术与环保优势
BOSHIDA AC/DC电源模块的节能技术与环保优势
BOSHIDA AC/DC电源模块的节能技术与环保优势
|
4天前
|
物联网 新能源 智能硬件
BOSHIDA AC/DC电源模块的市场发展与前景分析
BOSHIDA AC/DC电源模块的市场发展与前景分析
BOSHIDA AC/DC电源模块的市场发展与前景分析
|
4天前
AC/DC电源模块广泛应用于工业仪器领域,为工业仪器提供稳定可靠的电源供应
AC/DC电源模块广泛应用于工业仪器领域,为工业仪器提供稳定可靠的电源供应
AC/DC电源模块广泛应用于工业仪器领域,为工业仪器提供稳定可靠的电源供应
|
4天前
|
安全
下面将介绍几个在工业仪器场景中应用DC电源模块的案例。
下面将介绍几个在工业仪器场景中应用DC电源模块的案例。
下面将介绍几个在工业仪器场景中应用DC电源模块的案例。
|
4天前
|
传感器
关于DC电源模块应用于工业仪器场景的案例
关于DC电源模块应用于工业仪器场景的案例
关于DC电源模块应用于工业仪器场景的案例
|
4天前
|
存储
关于DC电源模块应用于工业仪器的案例
关于DC电源模块应用于工业仪器的案例
关于DC电源模块应用于工业仪器的案例
|
4天前
DC电源模块应用于工业仪器的案例
DC电源模块应用于工业仪器的案例
DC电源模块应用于工业仪器的案例
|
4天前
|
安全
案例分析:DC电源模块应用于工业仪器
案例分析:DC电源模块应用于工业仪器
案例分析:DC电源模块应用于工业仪器