基于单片机设计的智慧农业大棚检测系统

一、设计目标

本项目基于单片机设计一个智慧农业大棚检测系统,以提供实时监测和管理大棚环境的关键参数。系统支持环境温度、湿度检测,光照强度检测,并能根据预设的阀值进行报警提示。为了实现数据的显示和管理,该系统还利用Qt开发了一款对应的Android手机APP,通过蓝牙传输模块将单片机采集到的数据传递到手机APP上进行显示和管理。

具体功能如下:

【1】环境温度和湿度检测:系统采用SHT30温湿度传感器,能够实时监测大棚内的温度和湿度,并将数据传输给单片机进行处理。

【2】光照强度检测:系统采用BH1750光照传感器,能够实时监测大棚内的光照强度,并将数据传输给单片机进行处理。

【3】报警阀值设置:系统支持按键操作,用户可以通过按键调整报警阀值,以适应不同的农业环境需求。

【4】报警声音提示:当温度、湿度或光照强度超过设定的阀值时,系统将触发报警,通过连接的蜂鸣器发出声音提示,提醒用户注意。

【5】数据显示和管理:利用Qt开发的Android手机APP能够接收通过蓝牙传输模块从单片机端传递过来的数据,并在手机上进行实时显示和管理。用户可以通过手机APP查看当前的温度、湿度和光照强度数据,同时也可以设置报警阀值。

通过上述设计,该智慧农业大棚检测系统能够为农业生产提供实时的环境监测和报警功能,帮助农民有效管理大棚环境,提高农作物的产量和质量。同时,通过手机APP的使用,用户可以方便地查看和管理数据,实现远程监控和控制,提高农业生产的便捷性和智能化水平。

img

img

二、总体设计方案

2.1 硬件设计

  • 主控芯片采用STM32F103RCT6,具有较高的性能和丰富的外设接口。
  • 温湿度检测模块采用SHT30传感器,可准确采集环境温度和湿度数据。
  • 光照强度检测模块采用BH1750传感器,能够实时监测大棚内的光照情况。
  • 本地报警提示采用蜂鸣器,发出声音提醒农民进行处理。
  • 通过蓝牙模块HC05,将STM32采集到的数据传输到Android手机APP上。

2.2 软件设计

  • 在STM32中编写固件程序,实现温湿度传感器和光照强度传感器的数据采集和处理。
  • 设计蜂鸣器的驱动程序,根据设定的阈值判断是否触发报警。
  • 使用蓝牙模块HC05与Android手机APP进行通信,将采集到的数据传输到手机APP上。
  • 在Android手机APP中,利用Qt开发界面,实现数据显示、阈值设定和报警提示等功能。

2.3 整体流程

  • STM32通过SHT30和BH1750传感器采集环境温度、湿度和光照强度数据。
  • 处理采集到的数据,判断是否触发报警条件。
  • 如果达到报警条件,则通过蜂鸣器发出声音提示。
  • 将数据通过蓝牙模块HC05传输到Android手机APP上。
  • 在Android手机APP上,实时显示大棚内的温湿度和光照强度数据。
  • 农民可以通过手机APP设置报警阈值,当超过或低于设定的阈值时,会触发报警提示。

该方案实现了温湿度、光照强度的实时检测和数据传输,并提供了报警功能。通过这个智慧农业大棚检测系统,农民可以方便地监测大棚内的环境状况,及时调控和管理,提高农作物的生长效果和产量。

三、硬件电路设计

本项目的硬件电路设计主要涉及主控芯片STM32F103RCT6的连接及传感器模块的接口设计。以下是项目的硬件电路设计概述:

3.1 主控芯片连接

STM32F103RCT6作为主控芯片,负责整个系统的控制和数据处理。它与其他模块通过引脚连接进行数据的接收和发送。 需要为主控芯片提供适当的电源供电,包括正常工作电压和逻辑电压。

image-20230829172530630

3.2 温湿度传感器连接

温湿度传感器SHT30通过I2C总线连接到主控芯片。主控芯片上的I2C接口引脚(如SDA和SCL)与传感器的对应引脚相连,以实现数据的读取和控制。

image-20230829172622968

3.3 光照传感器连接

光照传感器BH1750通过I2C总线连接到主控芯片。主控芯片上的I2C接口引脚与传感器的对应引脚相连,以实现数据的读取和控制。

image-20230829172645508

3.4 报警蜂鸣器连接

报警蜂鸣器通过一个GPIO引脚与主控芯片相连。当报警条件触发时,主控芯片控制该引脚输出高电平信号,以激活蜂鸣器发出声音提示。

image-20230829172718595

3.5 HC05蓝牙模块连接

HC05蓝牙模块用于实现单片机与Android手机APP之间的数据传输。它通过串口通信与主控芯片相连,主控芯片上的对应串口引脚(如UART_TX和UART_RX)与蓝牙模块的对应引脚相连。

image-20230829172947679

image-20230829172840965

四、软件设计

4.1 主控芯片模块

主控芯片(如STM32F103RCT6)负责整个系统的控制和数据处理。它与其他硬件模块相连接,接收传感器数据,进行数据处理和报警判断,并控制蜂鸣器的发声。

4.2 温湿度传感器模块

温湿度传感器(如SHT30)通过I2C总线与主控芯片相连,负责实时监测大棚内的温度和湿度。传感器模块将采集到的数据传输给主控芯片进行处理。

实现代码如下:

以下是STM32标准库驱动SHT30传感器读取温湿度,并将数据通过串口打印出来:

#include "stm32f10x.h"
#include "stdio.h"#define SHT30_ADDR 0x44void I2C1_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;I2C_InitTypeDef I2C_InitStructure;// 使能I2C1和GPIOB时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);// I2C1引脚配置GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;  // 开漏输出GPIO_Init(GPIOB, &GPIO_InitStructure);// I2C1配置I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;  // 50%占空比I2C_InitStructure.I2C_OwnAddress1 = 0x00;          // 主机模式下无效I2C_InitStructure.I2C_Ack = I2C_Ack_Disable;        // 禁止应答I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;I2C_InitStructure.I2C_ClockSpeed = 100000;  // 100kHz的速度I2C_Init(I2C1, &I2C_InitStructure);// 使能I2C1I2C_Cmd(I2C1, ENABLE);
}void I2C1_Start(void)
{// 发送起始信号I2C_GenerateSTART(I2C1, ENABLE);// 等待起始信号发送完成while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
}void I2C1_Stop(void)
{// 发送停止信号I2C_GenerateSTOP(I2C1, ENABLE);
}void I2C1_WriteByte(uint8_t byte)
{// 发送一个字节的数据I2C_SendData(I2C1, byte);// 等待发送完成while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}uint16_t I2C1_ReadByteAck(void)
{uint16_t data;// 使能应答I2C_AcknowledgeConfig(I2C1, ENABLE);I2C_GenerateACK(I2C1, ENABLE);// 等待接收完成while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));// 读取接收到的数据data = I2C_ReceiveData(I2C1);return data;
}uint16_t I2C1_ReadByteNack(void)
{uint16_t data;// 禁止应答I2C_AcknowledgeConfig(I2C1, DISABLE);I2C_GenerateACK(I2C1, DISABLE);// 等待接收完成while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));// 读取接收到的数据data = I2C_ReceiveData(I2C1);return data;
}void SHT30_Init(void)
{// 发送软件复位指令I2C1_Start();I2C1_WriteByte(SHT30_ADDR << 1);I2C1_WriteByte(0x30);I2C1_WriteByte(0xA2);I2C1_Stop();delay_ms(100);
}void SHT30_Measure(float *temperature, float *humidity)
{uint8_t buf[6];uint16_t temperature_raw, humidity_raw;// 发送测量指令I2C1_Start();I2C1_WriteByte(SHT30_ADDR << 1);I2C1_WriteByte(0x2C);I2C1_WriteByte(0x06);I2C1_Stop();delay_ms(20);// 读取测量结果I2C1_Start();I2C1_WriteByte((SHT30_ADDR << 1) | 0x01);buf[0] = I2C1_ReadByteAck();buf[1] = I2C1_ReadByteAck();buf[2] = I2C1_ReadByteAck();buf[3] = I2C1_ReadByteAck();buf[4] = I2C1_ReadByteAck();buf[5] = I2C1_ReadByteNack();I2C1_Stop();// 计算温度值temperature_raw = (buf[0] << 8) | buf[1];*temperature = -45.0 + 175.0 * (float)temperature_raw / 65535.0;// 计算湿度值humidity_raw = (buf[3] << 8) | buf[4];*humidity = 100.0 * (float)humidity_raw / 65535.0;
}void USART1_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;// 使能USART1和GPIOA时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);// USART1引脚配置GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  // 复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);// USART1配置USART_InitStructure.USART_BaudRate = 115200;  // 波特率为115200USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Tx;USART_Init(USART1, &USART_InitStructure);// 使能USART1USART_Cmd(USART1, ENABLE);
}void USART1_SendChar(char ch)
{// 等待发送缓冲区为空while (!(USART1->SR & USART_FLAG_TXE));// 发送一个字符USART_SendData(USART1, ch);
}int fputc(int ch, FILE *f)
{// 将数据通过串口发送USART1_SendChar((char)ch);return ch;
}void delay_ms(uint32_t ms)
{while (ms--){uint32_t count = 12000;while (count--);}
}int main(void)
{float temperature, humidity;I2C1_Init();USART1_Init();SHT30_Init();printf("SHT30 Temperature and Humidity Test\n");while (1){SHT30_Measure(&temperature, &humidity);printf("Temperature: %.2f°C, Humidity: %.2f%%\n", temperature, humidity);delay_ms(1000);  // 每隔1秒测量一次温湿度}
}

以上代码通过I2C总线驱动STM32F103读取SHT30温湿度传感器的数据,并通过USART1串口打印出温度和湿度值。

代码设计流程介绍:

【1】引入头文件:

#include "stm32f10x.h"
#include "stdio.h"

此处引入了STM32F10x系列微控制器的相关头文件以及标准输入输出库的头文件。

【2】定义宏和函数:

#define SHT30_ADDR 0x44

定义了SHT30传感器的I2C地址为0x44。

void I2C1_Init(void);
void I2C1_Start(void);
void I2C1_Stop(void);
void I2C1_WriteByte(uint8_t byte);
uint16_t I2C1_ReadByteAck(void);
uint16_t I2C1_ReadByteNack(void);

定义了一系列用于控制I2C总线的函数。

void SHT30_Init(void);
void SHT30_Measure(float *temperature, float *humidity);

定义了初始化SHT30传感器和测量温湿度的函数。

void USART1_Init(void);
void USART1_SendChar(char ch);
int fputc(int ch, FILE *f);

定义了初始化USART1串口和发送字符的函数,以及重定向标准输出流的函数。

void delay_ms(uint32_t ms);

定义了延时函数,用于在实现中添加延时。

【3】初始化函数:

void I2C1_Init(void)

该函数用于初始化I2C1总线和相关的引脚。使能了I2C1和GPIOB的时钟,然后配置了I2C1的引脚,包括引脚的速度和模式等。接着对I2C1进行配置,包括模式、占空比、从机地址等参数,并最后使能I2C1总线。

void USART1_Init(void)

该函数用于初始化USART1串口和相关的引脚。使能了USART1和GPIOA的时钟,然后配置了USART1的引脚,包括引脚的速度和模式等。接着对USART1进行配置,包括波特率、字长、停止位、校验位等参数,并最后使能USART1串口。

【4】I2C总线控制函数:

void I2C1_Start(void)
void I2C1_Stop(void)
void I2C1_WriteByte(uint8_t byte)
uint16_t I2C1_ReadByteAck(void)
uint16_t I2C1_ReadByteNack(void)

这些函数用于控制I2C总线的起始、停止、写数据和读数据操作。具体实现可以参考STM32的标准库函数。

【5】SHT30传感器初始化和测量函数:

void SHT30_Init(void)
void SHT30_Measure(float *temperature, float *humidity)

SHT30_Init函数用于初始化SHT30传感器。在函数中,发送软件复位指令给传感器,然后延时一段时间等待传感器重置。

SHT30_Measure函数用于测量温湿度数据。在函数中,发送测量指令给传感器,然后延时等待传感器完成测量。接着从传感器读取温湿度数据,并通过指针参数返回给主程序。

【6】串口控制函数:

void USART1_SendChar(char ch)
int fputc(int ch, FILE *f)

USART1_SendChar函数用于通过USART1串口发送一个字符。在函数中,通过轮询USART状态寄存器的空闲标志位,判断发送缓冲区是否为空,然后把字符写入数据寄存器进行发送。

fputc函数是C库函数的重定向函数,用于将标准输出的字符发送到USART1串口。这里对于每个调用printf函数输出的字符,都会通过USART1_SendChar函数发送出去。

【7】延时函数:

void delay_ms(uint32_t ms)

这个函数用于实现毫秒级的延时。在函数中,通过循环等待的方式实现了延时。

【8】主函数:

int main(void)

在主函数中,调用I2C1_InitUSART1_Init函数初始化I2C总线和USART1串口。然后调用SHT30_Init函数初始化SHT30传感器。

进入主循环后,通过循环调用SHT30_Measure函数测量温湿度数据,并通过printf函数打印出来。最后通过delay_ms函数延时1秒。

4.3 光照传感器模块

光照传感器(如BH1750)通过I2C总线与主控芯片相连,负责实时监测大棚内的光照强度。传感器模块将采集到的数据传输给主控芯片进行处理。

实现代码如下:

使用STM32标准库编写代码驱动BH1750读取环境光照强度。

#include "stm32f10x.h"
#include "stdio.h"#define BH1750_ADDR 0x23void I2C1_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;I2C_InitTypeDef I2C_InitStructure;// 使能I2C1和GPIOB时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);// I2C1引脚配置GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;  // 开漏输出GPIO_Init(GPIOB, &GPIO_InitStructure);// I2C1配置I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;  // 50%占空比I2C_InitStructure.I2C_OwnAddress1 = 0x00;          // 主机模式下无效I2C_InitStructure.I2C_Ack = I2C_Ack_Disable;        // 禁止应答I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;I2C_InitStructure.I2C_ClockSpeed = 100000;  // 100kHz的速度I2C_Init(I2C1, &I2C_InitStructure);// 使能I2C1I2C_Cmd(I2C1, ENABLE);
}void I2C1_Start(void)
{// 发送起始信号I2C_GenerateSTART(I2C1, ENABLE);// 等待起始信号发送完成while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
}void I2C1_Stop(void)
{// 发送停止信号I2C_GenerateSTOP(I2C1, ENABLE);
}void I2C1_WriteByte(uint8_t byte)
{// 发送一个字节的数据I2C_SendData(I2C1, byte);// 等待发送完成while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}uint16_t BH1750_ReadData(void)
{uint16_t data = 0;// 设置BH1750模式(连续高分辨率测量模式)I2C1_Start();I2C1_WriteByte(BH1750_ADDR);I2C1_WriteByte(0x10);I2C1_Stop();// 延时等待测量结束delay_ms(20);// 读取光照强度数据I2C1_Start();I2C1_WriteByte(BH1750_ADDR | 1);data = (I2C_ReceiveData(I2C1) << 8);I2C_AcknowledgeConfig(I2C1, DISABLE);I2C1_Stop();delay_ms(2);I2C_AcknowledgeConfig(I2C1, ENABLE);I2C1_Start();I2C1_WriteByte(BH1750_ADDR | 1);data |= I2C_ReceiveData(I2C1);I2C1_Stop();return data;
}void USART1_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;// 使能USART1和GPIOA时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);// USART1引脚配置GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  // 复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);// USART1配置USART_InitStructure.USART_BaudRate = 115200;  // 波特率为115200USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Tx;USART_Init(USART1, &USART_InitStructure);// 使能USART1USART_Cmd(USART1, ENABLE);
}void USART1_SendChar(char ch)
{// 等待发送缓冲区为空while (!(USART1->SR & USART_FLAG_TXE));// 发送一个字符USART_SendData(USART1, ch);
}int fputc(int ch, FILE *f)
{// 将数据通过串口发送USART1_SendChar((char)ch);return ch;
}void delay_ms(uint32_t ms)
{while (ms--){uint32_t count = 12000;while (count--);}
}int main(void)
{uint16_t lightIntensity;I2C1_Init();USART1_Init();printf("BH1750 Light Intensity Test\n");while (1){lightIntensity = BH1750_ReadData();printf("Light Intensity: %d lux\n", lightIntensity);delay_ms(1000);  // 每隔1秒读取一次光照强度}
}

【1】上面代码里定义了BH1750的地址BH1750_ADDR为0x23,这是BH1750的默认地址。

【2】在I2C1_Init()函数中,初始化了I2C1总线和相关的GPIO引脚。通过RCC_APB1PeriphClockCmd和RCC_APB2PeriphClockCmd函数使能I2C1和GPIOB时钟,然后配置GPIOB的引脚6和7为开漏输出模式(GPIO_Mode_AF_OD)。接着,使用I2C_Init函数初始化I2C1,并设置其工作模式为I2C_Mode_I2C、占空比为50%、禁止应答、7位地址模式以及100kHz的通信速率。最后,通过I2C_Cmd函数使能I2C1。

【3】I2C1_Start()函数用于发送I2C总线的起始信号。调用I2C_GenerateSTART函数发送起始信号,并使用I2C_CheckEvent函数等待起始信号发送完成。

【4】I2C1_Stop()函数用于发送I2C总线的停止信号。调用I2C_GenerateSTOP函数发送停止信号。

【5】I2C1_WriteByte()函数用于向I2C设备发送一个字节的数据。通过I2C_SendData函数发送数据,并使用I2C_CheckEvent函数等待发送完成。

【6】BH1750_ReadData()函数用于读取光照强度数据。,发送启动测量指令和模式设置指令(连续高分辨率测量模式)。然后等待测量结束的延时时间(20ms)。接着,通过两次读取数据寄存器的方式获取光照强度数据,并将其拼接为一个16位的无符号整数。

【7】USART1_Init()函数用于初始化USART1串口和相关的GPIO引脚。使用RCC_APB2PeriphClockCmd函数使能USART1和GPIOA时钟,然后配置GPIOA的引脚9为复用推挽输出模式(GPIO_Mode_AF_PP)。接着,通过USART_Init函数初始化USART1,并设置其波特率为115200、数据位长度为8位、停止位为1位、无奇偶校验、无硬件流控制。最后,通过USART_Cmd函数使能USART1。

【8】USART1_SendChar()函数用于发送一个字符到USART1串口。使用USART_SR寄存器的USART_FLAG_TXE标志位检查发送缓冲区是否为空,然后通过USART_SendData函数发送字符数据。

【9】fputc()函数重定向了输出流,使得通过printf函数打印的字符可以发送到USART1串口。在该函数中调用USART1_SendChar函数发送字符数据,并返回该字符。

【10】delay_ms()函数用于进行延时,单位为毫秒。该函数使用嵌套循环实现了简单的延时功能,不同的系统时钟频率可能需要适当调整。

【11】在main()函数中,依次调用I2C1_Init()USART1_Init()函数进行初始化操作。然后,通过printf函数向串口发送初始信息。

【12】在主循环中,通过调用BH1750_ReadData()函数读取光照强度数据,并使用printf函数将其打印到串口。然后通过delay_ms函数进行1秒的延时,等待下一次读取。

4.4 报警蜂鸣器模块

报警蜂鸣器通过一个GPIO引脚与主控芯片相连。当报警条件满足时,主控芯片控制该引脚输出高电平信号,以激活蜂鸣器发出声音提示。

使用STM32F103标准库编写的蜂鸣器控制代码:

#include "stm32f10x.h"#define BEEP_GPIO_PORT GPIOA
#define BEEP_GPIO_PIN  GPIO_Pin_8void BEEP_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;// 使能GPIOA时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// 配置蜂鸣器引脚为推挽输出模式GPIO_InitStructure.GPIO_Pin = BEEP_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(BEEP_GPIO_PORT, &GPIO_InitStructure);
}void BEEP_On(void)
{GPIO_SetBits(BEEP_GPIO_PORT, BEEP_GPIO_PIN);
}void BEEP_Off(void)
{GPIO_ResetBits(BEEP_GPIO_PORT, BEEP_GPIO_PIN);
}int main(void)
{BEEP_Init();while (1){// 控制蜂鸣器开启和关闭BEEP_On();Delay_ms(500);BEEP_Off();Delay_ms(500);}
}

在代码中,使用了GPIOA的第8个引脚作为蜂鸣器的控制引脚。BEEP_Init函数用于初始化蜂鸣器引脚,将其配置为推挽输出模式。BEEP_OnBEEP_Off函数分别用于开启和关闭蜂鸣器。

main函数中,通过循环控制蜂鸣器以500ms的间隔进行开启和关闭操作。

4.5 HC05蓝牙模块模块

HC05蓝牙模块通过串口通信与主控芯片相连,负责实现与Android手机APP之间的数据传输和通信。它接收主控芯片发送的数据,并通过蓝牙与手机APP进行交互。

使用STM32标准库编写代码,用于通过串口2驱动HC05模块,并进行配置和数据通信:

#include "stm32f10x.h"
#include "stdio.h"// HC05配置指令
#define AT_CMD_MODE     "AT+CMODE=0\r\n"     // 配置为从模式
#define AT_CMD_PW       "AT+PSWD=1234\r\n"   // 配对密码设置为1234// 函数声明
void USART2_Init(void);
void USART2_SendChar(char ch);
void USART2_SendString(char* str);
char USART2_Receive(void);int main(void)
{// 初始化USART2串口USART2_Init();// 发送AT指令配置HC05为从模式USART2_SendString(AT_CMD_MODE);for(int i = 0; i < 1000000; i++);  // 等待一段时间// 发送AT指令配置配对密码USART2_SendString(AT_CMD_PW);for(int i = 0; i < 1000000; i++);  // 等待一段时间while(1){// 接收手机发送的数据char data = USART2_Receive();// 处理接收到的数据,例如发送回应等// ...}
}void USART2_Init(void)
{// 使能USART2和GPIOA时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);// 配置USART2的引脚GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;             // USART2_TXGPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        // 复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      // GPIO速度为50MHzGPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;             // USART2_RXGPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;          // 上拉输入GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置USART2的参数USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 9600;             // 波特率为9600USART_InitStructure.USART_WordLength = USART_WordLength_8b;     // 数据位长度为8位USART_InitStructure.USART_StopBits = USART_StopBits_1;           // 停止位为1位USART_InitStructure.USART_Parity = USART_Parity_No;              // 无奇偶校验USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;   // 无硬件流控制USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  // 支持收发模式USART_Init(USART2, &USART_InitStructure);// 使能USART2USART_Cmd(USART2, ENABLE);
}void USART2_SendChar(char ch)
{while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);  // 等待发送缓冲区为空USART_SendData(USART2, (uint16_t)ch);  // 发送数据
}void USART2_SendString(char* str)
{while(*str){USART2_SendChar(*str++);}
}char USART2_Receive(void)
{while (USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == RESET);  // 等待接收缓冲区非空return (char)USART_ReceiveData(USART2);
}

以上代码通过USART2串口与HC05模块进行通信,并发送AT指令对其进行配置。其中,AT_CMD_MODE用于将HC05配置为从模式,AT_CMD_PW用于设置配对密码为1234。

代码设计思路介绍:

【1】引入头文件:

#include "stm32f10x.h"
#include "stdio.h"

引入了STM32F10x系列微控制器的相关头文件和标准输入输出库的头文件。

【2】定义宏和函数:

#define AT_CMD_MODE     "AT+CMODE=0\r\n"
#define AT_CMD_PW       "AT+PSWD=1234\r\n"void USART2_Init(void);
void USART2_SendChar(char ch);
void USART2_SendString(char* str);
char USART2_Receive(void);

定义了用于配置HC05模块的AT指令,以及用于初始化USART2串口、发送字符和字符串、接收字符的函数。

【3】USART2串口初始化函数:

void USART2_Init(void)

该函数用于初始化USART2串口和相关引脚。使能了USART2和GPIOA的时钟,然后配置了USART2的引脚,包括引脚的模式和速度等。接着对USART2进行配置,设置波特率、数据位长度、停止位、奇偶校验位等参数,并最后使能USART2串口。

【4】发送字符和字符串函数:

void USART2_SendChar(char ch)
void USART2_SendString(char* str)

这些函数用于通过USART2串口发送字符和字符串。对于USART2_SendChar函数,它会等待发送缓冲区为空,然后将字符写入数据寄存器进行发送。对于USART2_SendString函数,它会遍历字符串中的每个字符,并调用USART2_SendChar函数进行发送。

【5】接收字符函数:

char USART2_Receive(void)

该函数用于从USART2串口接收一个字符。它会等待接收缓冲区非空,然后读取数据寄存器的值并返回接收到的字符。此函数在主循环中可以用于接收HC05模块发送的数据。

【6】主函数:

int main(void)

在主函数中,调用USART2_Init函数初始化USART2串口。然后使用USART2_SendString函数依次发送配置指令AT_CMD_MODEAT_CMD_PW给HC05模块。发送完指令后,通过循环调用USART2_Receive函数接收HC05模块发送的数据。

五、调试过程

在项目设计完成后,进行测试和调试是非常重要的,以确保系统的正常运行和功能的有效性。

下面是本项目的测试和调试过程流程:

5.1 硬件测试

  • 检查硬件组装和连接是否正确,包括主控芯片STM32F103RCT6、传感器模块SHT30和BH1750以及蓝牙模块HC05的连接。
  • 使用示波器或多用途测试仪检测各个模块的电源供应和信号线连接是否正常。
  • 测试温湿度传感器(SHT30)和光照强度传感器(BH1750)是否能够正确采集环境数据。
  • 测试蜂鸣器是否能够发出合适的声音提示。

5.2 固件程序测试

  • 在STM32开发环境中编译程序,将固件程序烧录到主控芯片STM32F103RCT6上。
  • 使用串口调试助手等工具,与STM32建立通信连接,检查数据的传输和接收是否正常。
  • 对温湿度传感器和光照强度传感器进行数据采集测试,观察是否能够准确读取传感器数据。
  • 设置阈值并测试报警功能,确保报警触发条件和报警提示的准确性。

5.3 Android手机APP测试

  • 安装开发好的Android手机APP到测试设备上,确保安装过程顺利。
  • 打开APP,并与蓝牙模块HC05进行连接,观察是否能够成功建立通信。
  • 测试数据的传输和接收功能,确保从STM32接收到的数据能够在APP界面上正确显示。
  • 设置阈值并触发报警测试,确认报警提示(声音、震动、弹窗等)是否按照设定的条件正常工作。

5.4 系统整体测试

  • 模拟实际环境,调整大棚温湿度和光照强度,观察系统是否能够准确检测并显示环境参数。
  • 调整报警阈值,触发报警条件,验证报警提示是否按照预期工作。
  • 进行长时间运行测试,确保系统的稳定性和可靠性。

六、关键问题讨论

6.1 本项目的核心与技术难点

【1】硬件集成:将主控芯片、传感器模块、蓝牙模块和蜂鸣器等多个硬件模块进行正确的连接和集成是一个挑战。需要仔细设计电路连接、通信协议和接口定义,确保各个模块能够正常协同工作。

【2】数据处理与算法:在主控芯片的固件程序中,需要对传感器采集到的数据进行处理和分析,判断是否触发报警条件。这可能涉及到数据滤波、阈值判定、异常检测等算法的设计和实现。

【3】蓝牙通信:与手机APP之间的蓝牙通信是一个难点。需要实现稳定可靠的数据传输和通信协议,确保数据的准确性和实时性。

6.2 本项目的实用性

【1】实时监测和报警功能:该项目能够实时监测大棚内的温度、湿度和光照强度,并在超过设定阀值时触发报警。这对于农业生产者来说非常实用,能够帮助他们及时发现问题并采取措施,以保证大棚内环境的稳定和作物的健康生长。

【2】远程监控和管理:通过与手机APP的蓝牙通信,用户可以远程监控大棚内的数据并进行管理。他们可以随时查看温湿度和光照强度的实时数据,设置报警阀值,接收报警通知,并对大棚环境进行远程调整和控制。

【3】自动化和智能化:该项目利用传感器和自动化控制技术,实现了对大棚环境的智能监测和控制。这不仅提高了农业生产的效率和质量,还减轻了人工管理的负担,具有较高的实用性和应用价值。

6.3 关键点总结

【1】传感器选择和集成:选择适合的温湿度传感器和光照强度传感器,并合理集成到硬件设计中。需要考虑传感器的精度、响应速度以及与主控芯片的通信协议等因素。

【2】数据采集和处理算法:设计合适的数据采集和处理算法,确保从传感器获取的数据准确可靠,并能够根据设定的阈值判断是否触发报警条件。

【3】报警机制:设计报警机制,根据设定的阈值和实时采集的数据进行比较,当达到报警条件时,触发报警提示,如声音、震动或弹窗等方式。

【4】蓝牙通信:确保蓝牙模块能够与主控芯片稳定通信,并能够成功传输采集的数据到Android手机APP上。需要考虑通信的稳定性、数据传输的速率和安全性等因素。

【5】Android手机APP设计:设计用户友好的界面,在手机APP上实时显示大棚内的温湿度和光照强度数据,并提供设置界面,允许农民设置报警阈值。同时,实现报警提示的功能,保证报警条件的准确性和报警方式的有效性。

【6】系统稳定性和可靠性:在测试和调试阶段,需要对整个系统进行全面的测试,包括硬件和软件的各个模块,以确保系统的稳定性和可靠性。同时,考虑到长时间运行的情况,还需进行长时间测试,以验证系统能够持续运行并正常工作。

七、设计总结与体会

本项目的目的是设计实现对农业大棚环境的智能监测和管理,通过传感器采集数据、主控芯片处理和判断、蓝牙通信与手机APP交互,以及报警蜂鸣器的控制,实现了对温度、湿度和光照强度等参数的实时监测和报警功能。

在项目开发过程中,也遇到了一些挑战和难点,比如:硬件的连接和集成、数据处理算法的设计和实现,以及与手机APP之间的蓝牙通信。通过细致的计划和分工,最终也是成功地克服了这些困难,得以完成了整个系统的开发。

在实施过程中,深刻认识到模块化设计的重要性。通过将系统划分为多个硬件模块和软件模块,能够更好地管理和调试每个模块,并且在需要时进行模块的替换和升级,提高了系统的可扩展性和可维护性。

在测试阶段,也意识到用户体验的重要性。通过与潜在用户的沟通和反馈,不断优化和改进系统的界面设计和功能实现,力求使用户能够轻松使用和管理该系统。这种用户导向的设计理念提高了系统的实用性和用户满意度。

总的来说,本项目的设计与实施过程对软硬件的协同工作、数据处理与算法设计、用户体验等方面有了更深入的理解。通过克服挑战和不断优化,成功地将智能农业大棚监测系统带入实际应用,并为农业生产者提供了一种方便、高效且可靠的解决方案。相信随着技术的不断发展,智慧农业将在未来发挥更大的作用,为农业生产带来更多的创新和改进。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/235935.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浏览器输入一个域名的解析过程

目录 从输入一个域名的解析过程 以www.baidu.com为例子 本地缓存和hosts文件 mDNS和LLMNR NBT-NS 路由器广播 Root域名服务器 顶级域名服务器 目标域名服务器 DNS解析完成 操作系统发起TCP连接&#xff1a; TCP三次握手&#xff1a; TCP连接的建立采用经典的三次握手过程&#…

C2855 命令行选项“/Zc:referenceBinding“与预编译头不一致和C2855 命令行选项“/Zc:__cplusplus“与预编译头不一致

在VS2019和Qt5.12.12环境下&#xff0c;笔记本上编译这个工程没有问题&#xff0c;把工程拷贝到台式机上&#xff0c;一样的配置&#xff0c;但是报如下错误&#xff1a; 打开项目的命令行配置如下&#xff1a; 解决办法&#xff1a;在编译选项"/Zc:referenceBinding"…

ptaR7-5打探基priority_queue的使用

题目 最近乐乐开发出了一款新的游戏《打探基》&#xff0c;这款游戏需要多人配合来玩&#xff0c;至少三个游戏玩家同时出招才能使探基的血量下降一点&#xff0c;同时&#xff0c;出招的每个人战斗力下降一点&#xff0c;当战斗力小于10的时候将不能再出招&#xff0c;不知道…

electron+vue网页直接播放RTSP视频流?

目前大部分摄像头都支持RTSP协议&#xff0c;但是在浏览器限制&#xff0c;最新版的浏览器都不能直接播放RTSP协议&#xff0c;Electron 桌面应用是基于 Chromium 内核的&#xff0c;所以也不能直接播放RTSP&#xff0c;但是我们又有这个需求怎么办呢&#xff1f; 市场上的方案…

一小时掌握:使用ScrapySharp和C#打造新闻下载器

引言 爬虫技术是指通过编程的方式&#xff0c;自动从互联网上获取和处理数据的技术。爬虫技术有很多应用场景&#xff0c;比如搜索引擎、数据分析、舆情监测、电商比价等。爬虫技术也是一门有趣的技术&#xff0c;可以让你发现网络上的各种有价值的信息。 本文将介绍如何使用…

Unity组件开发--长连接webSocket

1.下载安装UnityWebSocket 插件 https://gitee.com/cambright/UnityWebSocket/ 引入unity项目&#xff1a; 2.定义消息体结构&#xff1a;ExternalMessage和包结构Package&#xff1a; using ProtoBuf; using System; using System.Collections; using System.Collections.Ge…

【java八股文】之Java基础篇

1、Java有哪几种数据类型 基本数据类型&#xff1a;byte(1字节) short&#xff08;2字节&#xff09; int&#xff08;4字节&#xff09; long&#xff08;8字节&#xff09; float&#xff08;4字节&#xff09; double&#xff08;8字节&#xff09; char&#xff08;2字节&a…

【动态规划】 【字典树】C++算法:472 连接词

作者推荐 【动态规划】458:可怜的小猪 涉及知识点 动态规划 字典树 LeetCode472 连接词 给你一个 不含重复 单词的字符串数组 words &#xff0c;请你找出并返回 words 中的所有 连接词 。 连接词 定义为&#xff1a;一个完全由给定数组中的至少两个较短单词&#xff08;不…

DUET: Cross-Modal Semantic Grounding for Contrastive Zero-Shot Learning论文阅读

文章目录 摘要1.问题的提出引出当前研究的不足与问题属性不平衡问题属性共现问题 解决方案 2.数据集和模型构建数据集传统的零样本学习范式v.s. DUET学习范式DUET 模型总览属性级别对比学习正负样本解释&#xff1a; 3.结果分析VIT-based vision transformer encoder.消融研究消…

RTL编码(1)——概述

一、RTL级描述 RTL&#xff08;Register Transfer Level&#xff09;级&#xff1a;寄存器&#xff0b;组合逻辑&#xff0c;其功能与时序用Verilog HDL&#xff08;以下简称Verilog&#xff09;或VHDL代码描述。 RTL描述包含了同步数字电路最重要的三个特征&#xff1a;组合逻…

【Python】编程练习的解密与实战(三)

​&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《Python | 编程解码》⏰诗赋清音&#xff1a;云生高巅梦远游&#xff0c; 星光点缀碧海愁。 山川深邃情难晤&#xff0c; 剑气凌云志自修。 目录 &#x1fa90;1. 初识Python &a…

[BJDCTF2020]ZJCTF,不过如此

题目源码&#xff1a; <?phperror_reporting(0); $text $_GET["text"]; $file $_GET["file"]; if(isset($text)&&(file_get_contents($text,r)"I have a dream")){echo "<br><h1>".file_get_contents($tex…

vscode 创建文件自动添加注释信息

随机记录 目录 1. 背景介绍 2. "Docstring Generator"扩展 2.1 安装 2.2 设置注释信息 3. 自动配置py 文件头注释 1. 背景介绍 在VS Code中&#xff0c;您可以使用扩展来为新创建的Python文件自动添加头部注释信息。有几个常用的扩展可以实现此功能&#xff0…

im6ull学习总结(三-五)freetype显示正行字

知识补充 笛卡尔坐标系 这里笛卡尔坐标系就是初高中学的直角坐标系的第一象限 lcd坐标系则不同 这两个坐标系如何转换 观察两个坐标系 点&#xff08;x,y&#xff09;的x坐标在两个坐标系中相同&#xff0c;纵坐标&#xff08;y&#xff09;存在着yV-yV V是整个屏幕的行数的像…

Mysql是怎么运行的(上)

文章目录 Mysql是怎么运行的Mysql处理一条语句的流程连接管理解析与优化存储引擎 基本配置配置文件系统变量状态变量字符集四种重要的字符集MySQL中的utf8和utf8mb4各级别的字符集和比较规则MySQL中字符集的转换排序规则产生的不同的排序结果 InnoDB存储引擎介绍COMPACT行格式介…

PostgreSQL内存浅析

体系结构 &#xff08;https://www.postgresql.fastware.com/blog/lets-get-back-to-basics-postgresql-memory-components&#xff09; &#xff08;http://geekdaxue.co/read/fcantsql/qts5is) 共享内存 linux的共享内存实现 (https://momjian.us/main/writings/pgsql/insi…

解锁前端新潜能:如何使用 Rust 锈化前端工具链

前言 近年来&#xff0c;Rust的受欢迎程度不断上升。首先&#xff0c;在操作系统领域&#xff0c;Rust 已成为 Linux 内核官方认可的开发语言之一&#xff0c;Windows 也宣布将使用 Rust 来重写内核&#xff0c;并重写部分驱动程序。此外&#xff0c;国内手机厂商 Vivo 也宣布…

如何利用ChatGPT快速生成月报?

随着每个月的结束&#xff0c;个人和团队经常需要编写月报来回顾和总结。这项任务通常消耗大量时间和精力。幸运的是&#xff0c;借助ChatGPT&#xff0c;这个过程可以变得更加简单和高效。接下来&#xff0c;我将详细介绍如何利用ChatGPT快速生成月报&#xff0c;从而帮助你节…

回归预测 | Matlab基于CPO-BP基于冠豪猪算法优化BP神经网络的数据多输入单输出回归预测

回归预测 | Matlab基于CPO-BP基于冠豪猪算法优化BP神经网络的数据多输入单输出回归预测 目录 回归预测 | Matlab基于CPO-BP基于冠豪猪算法优化BP神经网络的数据多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.CPO-BP回归基于冠豪猪优化算法[24年新…

Redis(四)事务

文章目录 事务Redis事务 vs 数据库事务常用命令总结 事务 一个队列中、一次性、顺序性、排他性执行一系列命令 官网https://redis.io/docs/interact/transactions/ Redis事务 vs 数据库事务 概述详述1、单独的隔离操作Redis的事务仅仅是保证事务里的操作会被连续独占的执行&a…