毕业设计 STM32与云平台的水质检测系统


0 前言

🔥
这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。

为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的是

🚩 毕业设计 STM32与云平台的水质检测系统(源码+硬件+论文)

🥇学长这里给一个题目综合评分(每项满分5分)

  • 难度系数:3分
  • 工作量:3分
  • 创新点:4分

🧿 项目分享:

https://gitee.com/sinonfin/sharing

在这里插入图片描述

1 主要功能

  • 1.利用ds18b20检测水温
  • 2.利用浊度传感器检测浊度
  • 3.利用ph传感器检测ph值
  • 4.显示在oled,超过阈值蜂鸣器报警
  • 5.利用esp8266无线模块上传onenet云端,电脑网页查看数据,手机app查看数据。

2 硬件设计(原理图)

在这里插入图片描述

在这里插入图片描述

3 核心软件设计

关键代码

#include "delay.h"
#include "sys.h"
#include "oled.h"
#include "led.h"
#include "beep.h"
#include "usart.h"
#include "adc.h"
#include "ds18b20.h"
#include "temp.h"    
#include "USART2.h"		
#include "send8266.h"
#include "onenet.h"
#include "timer.h"
#include <string.h>
#include <stdio.h>

#define ARRY_LENGTH 10
#define median_filtering_length 3
extern u8 send_flag;
u8 ph1,hui1,temperature1;		
u8 time[15];
float num[2];
float getPHvalue(void);
u16 median_filtering(void);
void display(void);
u8 key;

int main(void)
  {
	  short temperature,ph;      //�¶�ֵ								  							  
		float hui;		
		unsigned short timeCount = 0;	//���ͼ������
		delay_init();	    	 //��ʱ������ʼ��	 
		NVIC_Configuration();//����NVIC�жϷ���2:2λ��ռ���ȼ���2λ��Ӧ���ȼ�		    
		Adc_Init();	         //AD��ʼ��   
		uart_init(9600);	   //���ڳ�ʼ��
	  Usart2_Init(115200);							//����2������SEND8266��      PA2-TX  PA3-RX
     SEND8266_Init();	
	  TIM4_Int_Init(49999,7199);                      //10Khz�ļ���Ƶ�ʣ�������30000Ϊ3s 
		OLED_Init();			   //��ʼ��OLED  
		OLED_Clear(); 	     //Clear screen
		BEEP_Init();
		LED_Init();
		
/* 	while(DS18B20_Init())	//DS18B20��ʼ��	
	{
		OLED_ShowString(0,0,"DS18B20 Error",24);	//��ʼ��ʧ�ܣ��������
		delay_ms(200);														//��ʱ�ȴ������ȶ�
	}	
		OLED_Clear(); 	     											//����
	*/
	while(1)
	{	

		display();
		
		
		 OLED_ShowString(0,0,"TE:   . C",16);
		
		temperature=DS18B20_Get_Temp();						//�ɼ��¶�	
		
		if(temperature<0)
			{

			  OLED_ShowChar(22,0,'-',16);	  //��ʾ����
			temperature=-temperature;	
			}
		else 
		OLED_ShowChar(22,0,' ',16);	    //ȥ������	
		
		OLED_ShowNum(32,0,temperature/10,2,16);  			//��ʾ�¶�
		OLED_ShowNum(54,0,temperature%10,1,16);  			//��ʾ�¶�
	  printf("�¶ȣ�%d.%d C \r\n",temperature/10,temperature%10);

		temperature=temperature/10;
		
		ph=getPHvalue();	
			
		if( temperature > 42 )  ph += 5;
   else if(temperature > 28)
	{
     ph += 5*(temperature - 28)/14;
   }
	 OLED_ShowString(69,2,"PH:  ",16);
	 OLED_ShowString(109,2,".",16);
	 OLED_ShowNum(92,2,ph/100,2,16);  		   	//��ʾPH
   OLED_ShowNum(112,2,ph%100,2,16); 
	 
	 printf("PHֵ��%d.%d  \r\n",ph/100,ph%100);	 
	 ph=ph/100;
	 
		hui=median_filtering();
	 	hui=hui*(3.3/4096);
		hui = hui*100/3.3;
	  hui = hui*1.66-8;
		if(hui > 100) hui = 99;
	  if(hui <0) hui=0;
   OLED_ShowString(0,2,"TU:   %",16);
	 OLED_ShowNum(32,2,hui,2,16);  			//��ʾ���Ƕ�

	 printf("���Ƕȣ�%d  \r\n",(int)hui);
	 


if(temperature<=0|temperature>=31|ph>=9|ph<5|hui<=37)
	{
	 
	       BEEP=1;
	}
  else
	BEEP=0;



	 ph1=(u8)ph;
	 hui1=(u8)hui;
	 temperature1=(u8)temperature;	 
			
		if(send_flag==1)
		{
			printf("OneNet_GetData\r\n");	
			OneNet_GetData();
			send_flag = 0;
			SEND8266_Clear();
		}
		
		
		if(++timeCount >= 5)		
		{
			printf("OneNet_SendData\r\n");	
			OneNet_SendData();
			timeCount = 0;
			SEND8266_Clear();
		}
			SEND8266_GetData(0);

	
	}	  
}
	
float getPHvalue(){
  float PH_VALUE = 0;
  int pv[ARRY_LENGTH];
	int i,k;
  for(i = 0; i < ARRY_LENGTH; i++ ){
    pv[i] = Get_Adc_Average(7,5);
		delay_ms(1);
  }
  for(i = 0; i < ARRY_LENGTH; i++){
    for(k = i; k < ARRY_LENGTH; k++ ){
      if( pv[i] < pv[k] ){
        int tmp = pv[i];
        pv[i] = pv[k];
        pv[k] = tmp;
      }
    }
  }
  PH_VALUE = pv[ARRY_LENGTH/2];
	
	
	PH_VALUE = PH_VALUE*(3.3/4096);
  PH_VALUE = -5.7541*PH_VALUE + 16.654; 
  PH_VALUE = PH_VALUE*100;
if(PH_VALUE > 1400){
	PH_VALUE = 1400;
}

  if( PH_VALUE < 0 ){
    PH_VALUE = 0;
  }

  return PH_VALUE;
}

u16 median_filtering(){
  int senseV[median_filtering_length];
  int i,k;
	
  for(i = 0; i < median_filtering_length; i++){
    senseV[i] = Get_Adc_Average(6,5);
		delay_ms(3);
  }

  for(i = 0; i < median_filtering_length; i++ ){
    for(k = i; k <median_filtering_length; k++ ){
      if(senseV[i] > senseV[k]){
          int tmp = senseV[i];
          senseV[i] = senseV[k];
          senseV[k] = tmp;
      }
    }  
  }
  return senseV[median_filtering_length/2];
}


void display()
{	

 	
}

4 实现效果

在这里插入图片描述

在这里插入图片描述

5 最后

包含内容

在这里插入图片描述

🧿 项目分享:

https://gitee.com/sinonfin/sharing

  • 0
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32G431是一款具有多个ADC通道的微控制器,可以很方便地实现温度检测。下面是一个简单的步骤: 1. 配置ADC时钟和引脚:选择一个合适的ADC时钟频率,并将ADC引脚连接到传感器输出。在STM32CubeMX中,可以通过“Pinout & Configuration”选项卡和“Analog”选项卡来完成此操作。 2. 配置ADC模式:选择ADC的工作模式,例如连续模式或单次模式。连续模式可以持续地读取ADC值,而单次模式只读取一次。 3. 配置ADC通道:选择要使用的ADC通道,例如内部温度传感器通道。在STM32CubeMX中,可以通过“Analog”选项卡来完成此操作。 4. 启动ADC:在代码中启动ADC并等待转换完成。可以使用HAL库提供的函数来完成此操作。 5. 读取ADC值:一旦转换完成,可以使用HAL库提供的函数来读取ADC值,并将其转换为温度值。 下面是一个示例代码,用于读取STM32G431内部温度传感器的温度值: ```c #include "stm32g4xx_hal.h" ADC_HandleTypeDef hadc1; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_ADC1_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_ADC1_Init(); uint32_t adc_value = 0; float temperature = 0.0; while (1) { // Start ADC conversion HAL_ADC_Start(&hadc1); // Wait for conversion to complete HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); // Read ADC value adc_value = HAL_ADC_GetValue(&hadc1); // Convert ADC value to temperature temperature = (float)((adc_value * 3300.0 / 4096.0 - 760.0) / 2.5) + 25.0; // Do something with temperature value } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /* Configure the main internal regulator output voltage */ __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /* Initializes the RCC Oscillators according to the specified parameters in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLM = 1; RCC_OscInitStruct.PLL.PLLN = 10; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7; RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /* Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) { Error_Handler(); } } static void MX_ADC1_Init(void) { ADC_ChannelConfTypeDef sConfig = {0}; /* Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ hadc1.Instance = ADC1; hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; hadc1.Init.Resolution = ADC_RESOLUTION_12B; hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; hadc1.Init.LowPowerAutoWait = DISABLE; hadc1.Init.ContinuousConvMode = DISABLE; hadc1.Init.NbrOfConversion = 1; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc1.Init.DMAContinuousRequests = DISABLE; hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; hadc1.Init.OversamplingMode = DISABLE; if (HAL_ADC_Init(&hadc1) != HAL_OK) { Error_Handler(); } /* Configure the selected ADC channel */ sConfig.Channel = ADC_CHANNEL_TEMPSENSOR; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5; sConfig.SingleDiff = ADC_SINGLE_ENDED; sConfig.OffsetNumber = ADC_OFFSET_NONE; sConfig.Offset = 0; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } } static void MX_GPIO_Init(void) { /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOC_CLK_ENABLE(); } void Error_Handler(void) { } ``` 在这个示例代码中,我们使用PA3引脚来连接内部温度传感器,并使用ADC1来读取ADC值。在while循环中,我们不断地读取ADC值,并将其转换为温度值,然后进行其他操作。 请注意,STM32G431的内部温度传感器的输出值并不是一个精确的温度值,而是一个相对值。因此,我们需要使用一些校准方法来将ADC值转换为实际温度值。在本示例代码中,我们使用了一些经验公式来完成此操作。如果需要更高精度的温度值,可以使用其他校准方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值