基于LORA的双机通信的智能农业系统

目录

功能:

1.制作LORA双机通信的硬件名单:

2.引脚图

1.主机

3.先让两个单片机实现通信并OLED显示出来

1.主机代码

usart1.c

usart1.h

usart3.c

usart3.h

lora.c

Lora.h

 main

2.从机代码

lora和usrat和主机的是一样的

main

4.实现农业系统基本功能


功能:

通过LoRa模块与主机进行通信,监测环境中的温度、湿度、土壤湿度和光照强度等参数,并根据预设的自动控制逻辑或者手动指令控制继电器开关,从而调节风扇、加热器、水泵、喷雾器和灯光等设备,为植物提供适宜的生长环境。

1.制作LORA双机通信的硬件名单:

 STM32C8T6核心板2个
OLED屏幕2
lora模块2
有源蜂鸣器1
按键6
DHT11温湿度传感器1
土壤湿度传感器 1
四路继电器 1
1路继电器1

2.引脚图

1.主机

2.从机

3.先让两个单片机实现通信并OLED显示出来

使用的Lora是大夏龙雀的感觉这个是我使用过的Lora里面最好用的,因为不用设置频道就可以直接透明传输,使用起来得心应手。

就像两个单片机直接串口通信一样,缺点是异步串行,不能同时进行接收和发送。

官方的LR01视频教程:https://www.bilibili.com/video/BV1XC4y1K7Mc/?spm_id_from=333.999.0.0

1.主机代码

usart1.c
/***************************************
 * 文件名  :usart1.c
 * 描述    :配置USART1         
 * 实验平台:MINI STM32开发板 基于STM32F103C8T6
 * 硬件连接:------------------------
 *          | PA9  - USART1(Tx)      |
 *          | PA10 - USART1(Rx)      |
 *           ------------------------
 * 库版本  :ST3.0.0  

**********************************************************************************/

#include "usart1.h"
#include <stdarg.h>
#include "delay.h"
#include <string.h>

void USART1_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	/* 使能 USART1 时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); 

	/* USART1 使用IO端口配置 */    
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);    
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);   //初始化GPIOA
	  
	/* USART1 工作模式配置 */
	USART_InitStructure.USART_BaudRate = 9600;	//波特率设置:115200
	USART_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(USART1, &USART_InitStructure);  //初始化USART1
	USART_Cmd(USART1, ENABLE);// USART1使能
}

 /*发送一个字节数据*/
 void UART1SendByte(unsigned char SendData)
{	   
        USART_SendData(USART1,SendData);
        while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);	    
}  

/*接收一个字节数据*/
unsigned char UART1GetByte(unsigned char* GetData)
{   	   
        if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET)
        {  return 0;//没有收到数据 
		}
        *GetData = USART_ReceiveData(USART1); 
        return 1;//收到数据
}
/*接收一个数据,马上返回接收到的这个数据*/
void UART1Test(int *a)
{
		 int state = 0;
     unsigned char i = 0;
     while(1)
		 {			 
				while(UART1GetByte(&i))
        {
					UART1SendByte(i);
        } 
				if(i == 'O')
					state = 1;
				if(i == 'K' && state == 1)
				{
						*a = 1;
						break;
				}
		 }
		 
}

void UART1TX(char a[100])
{
		int i = 0;
		while(a[i] != '\0')
		{
				UART1SendByte(a[i]);
				i++;
		}
		UART1SendByte('\r');
		UART1SendByte('\n');
}




usart1.h
#include "stm32f10x.h"
#include <stdio.h>

void USART1_Config(void);
void UART1Test(int *a);
void UART1TX(char a[100]);
unsigned char UART1GetByte(unsigned char* GetData);
int UART1RX_OK(char tx[10]);
void UART1SendByte(unsigned char SendData);
usart3.c
/***************************************
 * 文件名  :usart3.c
 * 描述    :配置USART3         
 * 实验平台:MINI STM32开发板 基于STM32F103C8T6
 * 硬件连接:------------------------
 *          | PB10  - USART3(Tx)      |
 *          | PB11 - USART3(Rx)      |
 *           ------------------------
 * 库版本  :ST3.0.0  

**********************************************************************************/
#include "delay.h"
#include "usart3.h"
#include <stdarg.h>
#include <string.h>
#include "usart1.h"

u8 USART3_TX_BUF[600]; 	

u16 USART3_RX_STA=0; 
u8 USART3_RX_BUF[1024]; 				      //接收缓冲,最大USART3_MAX_RECV_LEN个字节.

void USART3_Config(int BaudRate)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	/* 使能 USART1 时钟*/
	//RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); 
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3 , ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);
	/* USART1 使用IO端口配置 */    
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);    
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	//浮空输入
  GPIO_Init(GPIOB, &GPIO_InitStructure);   //初始化GPIOA
	  
	/* USART1 工作模式配置 */
	USART_InitStructure.USART_BaudRate = BaudRate;	//波特率设置:115200
	USART_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(USART3, &USART_InitStructure);  //初始化USART1
	USART_Cmd(USART3, ENABLE);// USART1使能
}

 /*发送一个字节数据*/
 void UART3SendByte(unsigned char SendData)
{	   
        USART_SendData(USART3,SendData);
        while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);	    
}  

/*接收一个字节数据*/
unsigned char UART3GetByte(unsigned char* GetData)
{   	   
        if(USART_GetFlagStatus(USART3, USART_FLAG_RXNE) == RESET)
        {  return 0;//没有收到数据 
		}
        *GetData = USART_ReceiveData(USART3); 
        return 1;//收到数据
}
/*判断是不是OK*/
void UART3Test(int *a)
{
		 int state = 0;
     unsigned char i = 0;
     while(1)
		 {			 
				UART3GetByte(&i);
			  //UART1SendByte(i);
				if(i == 'O')
					state = 1;
				if(i == 'K' && state == 1)
				{
						*a = 1;
						break;
				}
		 }
		 
}

/*发送字符串*/
void UART3TX(char a[100])
{
		int i = 0;
		while(a[i] != '\0')
		{
				UART3SendByte(a[i]);
				i++;
		}
		UART3SendByte('\r');
		UART3SendByte('\n');
}




usart3.h
#include "stm32f10x.h"
#include <stdio.h>

void USART3_Config(int BaudRate);
void UART3Test(int *a);
void UART3TX(char a[100]);
unsigned char UART3GetByte(unsigned char* GetData);
void UART3SendByte(unsigned char SendData);
lora.c

#include "lora.h"
#include "usart1.h"
#include "usart3.h"
#include "delay.h"
#include "OLED.h"
extern char  sj;

void lora_transmit(char* a)//定向传输,给主机发送数据
{
		int i = 0;
	    UART3SendByte('#');//起始符
		while(a[i] != '\0')
		{
				UART3SendByte(a[i]);
				i++;
		}
		UART3SendByte('$');//结束符

		
}


void lora_receive(void)
{
	unsigned char i = 0;
	extern char lora_rx_data[100];
	int t1 = 0,t2 = 0;
	while(1)
	{
			UART3GetByte(&i);

			if(i=='#')
			{
				while(1)
				{  
					if(UART3GetByte(&i) == 1 && i!='$')
					{
						lora_rx_data[t1++]=i;
					}
					else if(i=='$')
						break;	 
				}
				while(1)
				{
						UART1SendByte(lora_rx_data[t2++]);
						if(t1 == t2)
						{
							UART1SendByte('\r');
							UART1SendByte('\n');
							break;
						}
				}
				break;
			}
        if(i=='a') 
        {
            OLED_ShowString(1, 1,"l"); 
        while(1)
				{
					if(UART3GetByte(&i) == 1 && i!='$')
					{
						sj=i;
					}
					else if(i=='$')
						break;	 
				}
				
				break;
        }            
	}
				
}




Lora.h
#include "stm32f10x.h"
				


				
		
void lora_receive(void);			
void lora_transmit(char* a);
 main
#include "stm32f10x.h"
#include "Serial.h"
#include "usart1.h"
#include "usart3.h"
#include "lora.h"
#include "delay.h"
#include "OLED.h"
#include "string.h"
#include <stdio.h> 
#include "LED.h"
#include "key.h"
#include "timer.h" 
char lora_tx_data[100];
char lora_rx_data[100];
int main(void)
{ 
    SystemInit();	//配置系统时钟为 72M  
    Serial_Init();
	USART3_Config(9600); //USART3 配置 		
	OLED_Init();
    Device_Init();
    Key_Init();
    TIM3_Int_Init(99, 7199);//初始化定时器设置10ms定时
    LED1_ON();
	while(1)
    {

	   sprintf((char*)lora_tx_data,"#s$");
	   OLED_ShowString(1, 1, lora_tx_data);
       lora_transmit(lora_tx_data);
		
	   lora_receive();
	   OLED_ShowString(3, 1, lora_rx_data); 
       OLED_ShowString(2, 1, "KW KS TS GQ");  
       sscanf(lora_rx_data, "%d %d %d %d", &temperature, &humidity,&Soil,&photosensitive);//字符串转化成整数
       OLED_ShowNum(4,1,temperature,3); OLED_ShowNum(4,5,humidity,3);OLED_ShowNum(4,9,Soil,3);OLED_ShowNum(4,13,photosensitive,3);
      
	}
	 
}

2.从机代码

lora和usrat和主机的是一样的
main
#include "stm32f10x.h"
#include "Serial.h"
#include "usart1.h"
#include "usart3.h"
#include "lora.h"
#include "delay.h"
#include "DHT11.h"
#include "OLED.h"
#include "string.h"
#include "GM.h"
#include "Relay.h"
int main(void)
{ 
    SystemInit();	//配置系统时钟为 72M  
    Serial_Init();
	USART3_Config(9600); //USART3 配置 		
	OLED_Init();
	DHT11_Init ();
	adc_Init();
    Relay_Init();
	while(1)
	{	
	   //temp humi数据处理
		DHT11_Read_Data(&temperature,&humidity);//温湿度 
        Soil=Get_ADC_Val();//土壤速度
        photosensitive=Get_Adc_Average();
        
		sprintf((char*)lora_tx_data,"%d %d %d %d",temperature,humidity,Soil,photosensitive);//"1.Temp:%d^ Humi:%d"区分节点
       OLED_ShowString(1, 1, "LoRa Node");			
	   OLED_ShowString(2, 1, lora_tx_data);
        
		//等待接收主机的start命令
		lora_receive();
       
		lora_transmit(lora_tx_data);
		OLED_ShowString(4, 1, lora_rx_data); 
        memset(lora_rx_data, 0, sizeof(lora_rx_data));
        
        
	}
	 
}

4.实现农业系统基本功能

1.使用温度传感器测当前环境的温湿度

2.使用土壤湿度传感器检测土壤湿度

3.使用光敏电阻检测光照情况

4.继电器灯亮模拟打开对应的风扇、水泵、灯、喷雾、加热

主机主要实现了以下功能:

  1. 通过串口与LoRa模块进行通信,发送和接收数据。
  2. 通过串口与另一个设备进行通信,发送控制指令。
  3. 通过OLED显示屏显示从机采集的温度、湿度、土壤湿度和光照强度等传感器数据。
  4. 通过按键控制从机继电器的开关状态。
  5. 通过定时器定时扫描按键和执行一些周期性任务。

    具体功能描述如下:

  • 串口通信:通过USART1和USART3配置,分别与LoRa模块和另一个设备进行通信。
  • LoRa通信:发送和接收数据,发送的数据格式为"#s$",接收到的数据解析后包括温度、湿度、土壤湿度和光照强度等信息。
  • OLED显示:使用OLED显示屏显示节点状态信息以及传感器采集的温度、湿度、土壤湿度和光照强度。
  • 按键控制:通过按键控制继电器的开关状态,按键扫描函数Key_Scan()用于检测按键状态。
  • 定时器:使用定时器TIM3实现10ms的定时中断服务程序,用于定时扫描按键和执行一些周期性任务。

从机实现的功能

  1. 温湿度、土壤湿度和光敏传感器数据处理

    • 使用 DHT11 传感器读取温度和湿度。
    • 使用 ADC 获取土壤湿度和光敏传感器的数据。
    • 将获取到的数据格式化为字符串,并显示在 OLED 上。
  2. LoRa 通信

    • 调用 lora_receive() 函数等待接收来自主机的命令。
    • 根据接收到的命令,设置控制变量 automatic 和各个继电器的状态。
    • 将传感器数据转换成字符串并通过 LoRa 传输。
    • 显示接收到的 LoRa 数据在 OLED 上。
  3. 继电器控制

    • 根据控制变量 automatic 的值进行自动控制或手动控制。
    • 在自动模式下,根据预设的阈值控制各个继电器的状态。
    • 在手动模式下,根据接收到的命令控制各个继电器的状态。

主机main

#include "stm32f10x.h"
#include "Serial.h"
#include "usart1.h"
#include "usart3.h"
#include "lora.h"
#include "delay.h"
#include "OLED.h"
#include "string.h"
#include <stdio.h> 
#include "LED.h"
#include "key.h"
#include "timer.h" 


char lora_tx_data[100];
char lora_rx_data[100];
u8 temperature,humidity;//温湿度
u8 en_send_data_to_master = 0;//@使能给主机发送数据
char DataBuf[20];
u8 Soil,photosensitive;
char  sj;
int a;
int kz=0,kz1=0;

void pd(void )
{

    if (temperature > 35 || temperature < 15 || humidity < 45 || Soil < 35 || photosensitive > 60) {
    LED1_OFF();
    Buzzer_OFF();
} else {
    LED1_ON();
    Buzzer_ON();
}
    
}

void kry_bross(void)
{
      if(KeyFlag==1)//自动与手动切换
      {
           a++; 
          if(a==1)//自动
          {
            UART3SendByte('#');//起始符	
            UART3SendByte('1');
            UART3SendByte('$');//结束符 
            kz1=1;              
          }
          if(a==2)//手动
          {
            UART3SendByte('#');//起始符	
            UART3SendByte('0');
            UART3SendByte('$');//结束符 
                a=0;
              kz1=0;
          }
       KeyFlag=0;  
      }
      
      if(KeyFlag==2)//继电器1
      {
            UART3SendByte('#');//起始符	
            UART3SendByte('2');
            UART3SendByte('$');//结束符 
            kz=1;
       KeyFlag=0;
      }
       if(KeyFlag==3)//继电器2
      {
            UART3SendByte('#');//起始符	
            UART3SendByte('3');
            UART3SendByte('$');//结束符
             kz=1;
      KeyFlag=0;
      }
      if(KeyFlag==4)//继电器3
      {
            UART3SendByte('#');//起始符	
            UART3SendByte('4');
            UART3SendByte('$');//结束符 
             kz=1;
      KeyFlag=0;
      }
      if(KeyFlag==5)//继电器4
      {
            UART3SendByte('#');//起始符	
            UART3SendByte('5');
            UART3SendByte('$');//结束符
            kz=1;          
      KeyFlag=0;
      }
      if(KeyFlag==6)//继电器5
      {
            UART3SendByte('#');//起始符	
            UART3SendByte('6');
            UART3SendByte('$');//结束符
             kz=1;
      KeyFlag=0;
      }
}

int main(void)
{ 
    SystemInit();	//配置系统时钟为 72M  
    Serial_Init();
	USART3_Config(9600); //USART3 配置 		
	OLED_Init();
    Device_Init();
    Key_Init();
    TIM3_Int_Init(99, 7199);//初始化定时器设置10ms定时
    LED1_ON();
	while(1)
    {

	   sprintf((char*)lora_tx_data,"#s$");//"1.Temp:%d^ Humi:%d"区分节点		
	   OLED_ShowString(1, 1, lora_tx_data);
       lora_transmit(lora_tx_data);
		//等待接收主机的start命令
	   lora_receive();
	   OLED_ShowString(3, 1, lora_rx_data); 
       OLED_ShowString(2, 1, "KW KS TS GQ");  
       sscanf(lora_rx_data, "%d %d %d %d", &temperature, &humidity,&Soil,&photosensitive);//字符串转化成整数
       OLED_ShowNum(4,1,temperature,3); OLED_ShowNum(4,5,humidity,3);OLED_ShowNum(4,9,Soil,3);OLED_ShowNum(4,13,photosensitive,3);
       kry_bross();
       if(kz==0||kz1==0){pd();}
       if(kz==1){ LED1_ON(); Buzzer_ON();}
       if(kz1==1){kz=0;delay_ms(1000);LED1_ON(); Buzzer_ON();}
	}
	 
}

int ms_10,ys;
//定时器3中断服务程序10ms		    
void TIM3_IRQHandler(void)
{ 	
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)//是更新中断
	{	 
        
        Key_Scan();//按键扫描
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIM3更新中断标志    
        ms_10++;
        if(ms_10>100){ms_10=0;ys++;}//10分钟重置
        if(ys>180){ys=0;kz=0;kz1=0;}
	}	    
}     

从机main

#include "stm32f10x.h"
#include "Serial.h"
#include "usart1.h"
#include "usart3.h"
#include "lora.h"
#include "delay.h"
#include "DHT11.h"
#include "OLED.h"
#include "string.h"
#include "GM.h"
#include "Relay.h"


char lora_tx_data[100];
char lora_rx_data[100];
u8 temperature,humidity;//温湿度
u8 en_send_data_to_master = 0;//@使能给主机发送数据
char DataBuf[20];
u8 Soil,photosensitive;
char automatic;
char Relay1,Relay2,Relay3,Relay4,Relay5;
		

extern char sj;
void Relay_prcoos(void)
{
     if(automatic==0)
    {
    if(Relay1==1)Relay1_OFF();//风扇
    if(Relay2==1)Relay2_OFF();//加热
    if(Relay3==1)Relay3_OFF();//水泵
    if(Relay4==1)Relay4_OFF();//喷雾
    if(Relay5==1)Relay5_OFF();//灯光
    if(Relay1==0)Relay1_ON();//风扇
    if(Relay2==0)Relay2_ON();//加热
    if(Relay3==0)Relay3_ON();//水泵
    if(Relay4==0)Relay4_ON();//喷雾
    if(Relay5==0)Relay5_ON();//灯光
    }
}

void automatic_prcoos(void)
{
    if(automatic==1)
    {
        Relay1=0;
        Relay2=0;
        Relay3=0;
        Relay4=0;
        Relay5=0;
             if(temperature>35)
            {
              Relay1_OFF();
              Relay2_ON();  
            }
            if(temperature<15)
            {
               Relay1_ON(); 
               Relay2_OFF();
            }
            if(temperature<35&&temperature>15)
            {
               Relay1_ON(); 
               Relay2_ON();
            }

            if(humidity<45)
            {
                Relay4_OFF();
            }
            if(humidity>45)
            {
              Relay4_ON();
            }

            if(Soil<35)
            {
                Relay3_OFF();
            }
            if(Soil>35)
            {
                 Relay3_ON();
            }

            if(photosensitive>60)
            {
                Relay5_OFF();
            }
            if(photosensitive<60)
            {
                Relay5_ON();
            }
    }
}

int main(void)
{ 
    SystemInit();	//配置系统时钟为 72M  
    Serial_Init();
	USART3_Config(9600); //USART3 配置 		
	OLED_Init();
	DHT11_Init ();
	adc_Init();
    Relay_Init();
	while(1)
	{	
	   //temp humi数据处理
		DHT11_Read_Data(&temperature,&humidity);//温湿度 
        Soil=Get_ADC_Val();//土壤速度
        photosensitive=Get_Adc_Average();
        
		sprintf((char*)lora_tx_data,"%d %d %d %d",temperature,humidity,Soil,photosensitive);//"1.Temp:%d^ Humi:%d"区分节点
       OLED_ShowString(1, 1, "LoRa Node");			
	   OLED_ShowString(2, 1, lora_tx_data);
        

		//等待接收主机的start命令
		lora_receive();
        if(sj=='0')
		{
            automatic=0;
			
		}
         if(sj=='1')
		{
            automatic=1;
			
		}
        if(sj=='2')
		{
            Relay1=1;
			  automatic=0;
		}
        if(sj=='3')
		{
            Relay2=1;
			  automatic=0;
		}
        if(sj=='4')
		{
            Relay3=1;
			  automatic=0;
		}
        if(sj=='5')
		{
            Relay4=1;
			  automatic=0;
		}
        if(sj=='6')
		{
            Relay5=1;
			automatic=0;
		}
		    
		lora_transmit(lora_tx_data);
		OLED_ShowString(4, 1, lora_rx_data); 
        memset(lora_rx_data, 0, sizeof(lora_rx_data));
        Relay_prcoos();
        automatic_prcoos();
	}
	 
}

-----------------------欢迎大家指正交流,有空可以一起讨论代码啊。--------------------------------

链接:https://pan.baidu.com/s/10nDkz743tXq9MGB6wKCbkA 
提取码:5bq3

有偿回答可以加QQ:1521354774
 

  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值