标题:
电赛 简易智能液体容器制作 附TDS传感器STM32单片机程序
[打印本页]
作者:
一只灵
时间:
2023-7-15 22:07
标题:
电赛 简易智能液体容器制作 附TDS传感器STM32单片机程序
本设计以STM32F1单片机为控制核心,设计并制作了简易多功能液体容器.设计主要包括单片机控制模块、电源模块、超声波测距模块、TDS传感器模块、压力传感器模块、显示模块。该设计利用超声波测量液体液位,压力传感器测量液体重量;TDS传感器可检测水中含有的溶解物,利用TDS值,可以区分不同浓度的盐水、不同的液体种类。再由两个OLED屏幕显示液体液位、重量、浓度、种类等参数。经测试,系统基本完成了要求。
一、系统方案
本系统主要由单片机控制模块、电源模块、超声波测距模块、TDS传感器模块、压力传感器模块、显示模块组成。
1.1单片机控制模块的论证与选择
方案一:采用STC89C51单片机为主控芯片,单片机只有32个IO口、2个定时器和2个外部中断,内部RAM为128字节,速度和性能比较低,功能较少,所需外围电路较多,不考虑此方案。
方案二:采用STM32F103C8T6单片机作为控制芯片。由 ST 厂商推出的 STM32 系列单片机,功能强大,性价比高。STM32F103C8T6最小系统板集成了工作频率为72 MHz的高性能ARM Cortex -M3 32位RISC内核、高速嵌入式存储器(最高128字节的闪存和最高20k字节的SRAM),以及连接到两条APB总线的各种增强型I/o和外设。所有器件都提供两个12位ADC、三个通用16位定时器和一个PWM定时器,以及标准和高级通信接口:最多两个I2C和SPI、三个USARTs、一个USB和一个CAN。在可行性与精确度指标上比较过后,决定采用方案二。
1.2显示模块的论证与选择
方案一:采用LCD1602显示。LCD1602是字符型液晶,显示字母和数字比较方便,控制简单,成本较低。内部含有日文平假名、英文字母、数字和一些常用符号字库,没有中文字库。但可以自定义的显示字符,只有两行显示。
方案二:采用OLED显示。OLED即有机发光二极管,具有自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快等优点,与LCD1602相比,OLED引脚较少,只有4个引脚,使用简单,方便。
在可行性上比较过后,决定采用方案二。
1.3测距模块的论证与选择
方案一:超声波测距。本系统采用超声波传感器进行液位测距,超声波具有易于定向发射、方向性好、强度易控制、与被测量物体不需要直接接触的特点。超声波对液体、固体的穿透本领很大,尤其是在不透明的固体中,超声波碰到杂质或分界面会产生显著反射,形成反射回波使得超声波测距有较高的准确性。
方案二:光电液位传感器测距。光电传感器内部包含一个近红外发光二极管和一个光敏接收器。发光二极管所发出的光被导入传感器顶部的透镜。当液体浸没光电液位开关的透镜时,则光折射到液体中,从而使接收器收不到或只能接收到少量光线。光电液位开关通过感应这一变化,接收器可以驱动内部的电气开关,从而启动外部报警或控制电路。但光电液位传感器需要接触液体,容易受到环境损坏。
在可行性上比较过后,决定采用方案一。
1.4液体浓度和种类检测的论证与选择
方案一:TDS传感器。TDS传感器可准确测量水中含有的溶解物,水中含有的溶解物越多,TDS值越高。可利用TDS值区分盐水浓度、不同液体的种类。TDS传感器配合8 位高性价比单片机,内部已做 AD采集,并通过算法计算出对应的TDS值。
方案二::PH传感器。PH传感器可检测溶液中的PH值,不同的PH值对应不同的输出信号。PH传感器配合8位单片机处理器,通过此单片机的10位ADC对放大后的传感器信号采样,板载电位器调节输出信号的量程,并通过最小二乘法软件算法计算出信号与PH值得线性函数关系式,进而采用线性函数关系式求出信号对应的PH值。但不同浓度的盐水溶液中PH值差别不大,不能满足要求。在可行性上比较过后,决定采用方案一。
制作出来的实物图如下:
new ducument.jpg
(2.62 MB, 下载次数: 46)
下载附件
电赛
2023-7-15 22:01 上传
单片机源程序如下:
#include "stm32f10x.h"
#include <string.h>
#include "delay.h"
#include "stdio.h"
#include "bsp_SysTick.h"
#include "math.h"
#include "Key.h"
#include "OLED.h"
#include "bsp_adc.h"
#include "ds18b20.h"
#include "timer.h"
#include "bsp_usart1.h"
#include "bsp_usart2.h"
volatile uint32_t time = 0; // ms 计时变量
uint32_t a = 0;
uint32_t b = 0;
uint32_t sta= 0;
////定义变量
GPIO_InitTypeDef GPIO_InitStructure;
unsigned char AD_CHANNEL=0;
float TDS=0.0,TDS_voltage;
float TDS_value=0.0,voltage_value;
float compensationCoefficient=1.0;//温度校准系数
float compensationVolatge;
float kValue=1.67;
float TEMP_Value=0.0;
float averageVoltage=0;
//char TEMP_Buff[5]; //温度存放数组
char TDS_Buff[6];
extern u8 SET_Flag,SET_Count; //设置标志位
extern u8 CLC_Flag; //清屏标志位
extern u8 Warning_flag;
u8 Warning_count=0;
// ADC1转换的电压值通过MDA方式传到SRAM
extern __IO uint8_t ADC_ConvertedValue[4];
// 用于保存转换计算后的电压值
float ADC_ConvertedValueLocal[4];
void GPIO_Configuration(void)
{
// GPIO_InitTypeDef GPIO_InitStructure;
/* Enable the GPIO Clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC| RCC_APB2Periph_AFIO,ENABLE);
//GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE); //屏蔽所有作为JTAG口的GPIO口
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //屏蔽PB口上IO口JTAG功能
}
///**************温度采集函数***************/
//void TEMP_Value_Conversion()
//{
//
// TEMP_Value=DS18B20_Get_Temp();
//
// TEMP_Buff[0]=(int)(TEMP_Value)%1000/100+'0';
// TEMP_Buff[1]=(int)(TEMP_Value)%100/10+'0';
// TEMP_Buff[2]='.';
// TEMP_Buff[3]=(int)(TEMP_Value)%10+'0';
//}
/**************TDS值采集函数***************/
float TDS_Value_Conversion()
{
u32 ad=0;
u8 i;
float compensationCoefficient;
float compensationVolatge;
float temperature=25.0;//假设温度是25度,进行温度补偿,如果有18B20,则采集温度后,更新这个温度值
ad=0;
for(i=0;i<50;i++)//读取50次的AD数值取其平均数较为准确
{
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//转换结束标志位
ad=ad+ADC_GetConversionValue(ADC1);//返回最近一次ADCx规则组的转换结果
}
ad=ad/50;
//ADC_ConvertedValueLocal[0]=(float)ad/4096*3.3; //AD转换
averageVoltage =(float)ad/4096*3.3; //AD转换
// averageVoltage = getMedianNum(analogBufferTemp, SCOUNT) * (float)VREF / 1024.0; // read the analog value more stable by the median filtering algorithm, and convert to voltage value
compensationCoefficient = 1.0 + 0.02 * (temperature - 25.0); //temperature compensation formula: fFinalResult(25^C) = fFinalResult(current)/(1.0+0.02*(fTP-25.0));
compensationVolatge = averageVoltage / compensationCoefficient; //temperature compensation
TDS_value = (133.42 * compensationVolatge * compensationVolatge * compensationVolatge - 255.86 * compensationVolatge * compensationVolatge + 857.39 * compensationVolatge) * 0.5; //convert voltage value to tds value
/*显示EC*/
TDS_Buff[0]=(int)(TDS_value)/1000+'0';
TDS_Buff[1]=(int)(TDS_value)%1000/100+'0';
TDS_Buff[2]=(int)(TDS_value*100)%100/10+'0';
TDS_Buff[3]=(int)(TDS_value*100)%10+'0';
return TDS_value ;
}
///*************数据显示函数***************/
//void Display_Data()
//{
// //OLED_ShowStr(24,2,TEMP_Buff,2);//测试6*8字符
// //OLED_ShowStr(36,4,TDS_Buff,2);//测试6*8字符
//}
float TDS_Bugg1[2];
uint8_t Num = 0;
uint32_t Num1=0;
void text1()
{
a=0;
delay_ms(100);
TDS_Value_Conversion();//TDS
delay_ms(100);
TDS_Bugg1[0]=TDS_Value_Conversion();
delay_ms(10);
OLED_ShowNum(2,1,TDS_Bugg1[0],3);
}
void text2()
{
a=1;
delay_ms(100);
TDS_Value_Conversion();//TDS
delay_ms(100);
TDS_Bugg1[1]=TDS_Value_Conversion();
delay_ms(10);
OLED_ShowNum(3,1,TDS_Bugg1[1],3);
if( TDS_Bugg1[0] < TDS_Bugg1[1])
{
OLED_ShowString(1,5,"thick water");
}
else
{
OLED_ShowString(2,5,"light water");
}
}
void text3()
{
a=2;
delay_ms(10);
TDS_Value_Conversion();//TDS
delay_ms(10);
OLED_ShowNum(4,1,TDS_Value_Conversion(),3);
if(TDS_Value_Conversion()>=686||TDS_Value_Conversion()<700)
{
OLED_ShowString(3,5,"water");
}
}
/**
* @brief 主函数
* @param 无
* @retval 无
*/
int main(void)
{
GPIO_Configuration(); //IO口配置
/* 配置USART1 */
USART1_Config();
/* 配置USART2 */
USART2_Config();
/* 初始化系统定时器 */
SysTick_Init();
Key_Init();
TIM3_Init(); //初始化配置TIM
//I2C_Configuration(); //I2C初始化
OLED_Init(); //OLED初始化
ADCx_Init(); // ADC 初始化
adc_init();
OLED_Clear();//清屏
OLED_ShowString(1,1,"TDS:");
//TDS 接A1
//接上串口模块 A9-RX A10-TX
//波特率115200
//接好后,直接打开串口软件看输出TDS值。
//注意,如果启用温度补偿,需要解开”温度数据转换“调用,然后把读到的值更新到TDS温度补偿值中即可。
//其他OLED显示是屏蔽了,要是OLED显示,解开初始和调用函数屏蔽即可。
while(1)
{
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0 && a==0 && sta ==0)
{
text1();
sta = 1;
}
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0 && a==0 && sta ==1)
{
text2();
sta = 2;
}
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0 && a==1 && sta ==2)
{
text3();
sta = 3;
}
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0 && sta==3 )
{
text3();
sta = 3;
}
}
}
/*********************************************END OF FILE**********************/
复制代码
Keil代码下载:
TDS使用版 源程序.7z
(253.46 KB, 下载次数: 28)
2023-7-16 04:20 上传
点击文件名下载附件
下载积分: 黑币 -5
HZ711+hcsor04源程序.7z
(198.11 KB, 下载次数: 20)
2023-7-16 04:20 上传
点击文件名下载附件
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1