首页 分享 温室盆栽灌溉系统设计(51)

温室盆栽灌溉系统设计(51)

来源:花匠小妙招 时间:2024-11-10 23:38

目录

一、功能介绍

 二、仿真原理图

设计思路:

单独51芯片和LCD1602,编写LCD初始化和显示函数,测试无误后,可用于显示后续数据用于排查错误.

搭建灌溉&警报系统,定义对应引脚测试电机,LED及蜂鸣器是否能正常工作

A/D转换电路,用电位器模拟湿度变化,测得一个0~5的模拟值,采用ADC0832进行A/D转换,将转换的数字信号处理为百分数显示在LCD屏幕

测试电机及警报工作所需的条件,设置两个阈值,当返回的湿度信号小于最低阈值,电机启动模拟灌溉直至湿度到最高阈值,且小于最低阈值时警报工作,此时实现了基本的湿度检测和自动灌溉

 不同模式设置,设置三个字符串数组存三种花卉的名称,及三个数组存对应的三组最高/低阈值,通过独立按键检测函数判断按下的键码,LCD将显示对应的名称,阈值,另设三个按键实现阈值+/-,高低阈值转换

搭建晶振电路和复位电路

三、函数设计 

1、延时函数

1.1、实现功能

1.2、代码实现

2、独立按键函数

2.1、实现功能

2.2、设计原理

2.3、代码实现

3、LCD1602功能函数

4、Warning函数

4.1、实现功能

4.2、设计原理

4.3、代码实现

5、 A/D模数转换函数

5.1、实现功能

5.2、设计原理

ADC0832工作原理:

5.3、代码实现

 6、设置函数库

Key()函数

Setting函数 

 Show_Set函数,显示当前设置(名称,阈值,测得湿度)

Setting_Init()函数 ,用于初始化按键,以及没有按键按下时默认显示水仙花的数据

main()函数设计

 主函数设计比较简单

最后晶振电路和复位电路实际在仿真可以省略,因为仿真过程里时钟频率是人为设置的(11.0592MHZ),复位电路并不会起效果,并且纯硬件电路也不需要编写代码,但在实际电路中是需要安装的 

四、结果展示

一、功能介绍

d42499d68f8949f1a92271f8133cf32d.jpeg

 二、仿真原理图

2a99a229aee245428be68c28b739e5fb.png

设计思路: 单独51芯片和LCD1602,编写LCD初始化和显示函数,测试无误后,可用于显示后续数据用于排查错误. 搭建灌溉&警报系统,定义对应引脚测试电机,LED及蜂鸣器是否能正常工作 A/D转换电路,用电位器模拟湿度变化,测得一个0~5的模拟值,采用ADC0832进行A/D转换,将转换的数字信号处理为百分数显示在LCD屏幕 测试电机及警报工作所需的条件,设置两个阈值,当返回的湿度信号小于最低阈值,电机启动模拟灌溉直至湿度到最高阈值,且小于最低阈值时警报工作,此时实现了基本的湿度检测和自动灌溉  不同模式设置,设置三个字符串数组存三种花卉的名称,及三个数组存对应的三组最高/低阈值,通过独立按键检测函数判断按下的键码,LCD将显示对应的名称,阈值,另设三个按键实现阈值+/-,高低阈值转换 搭建晶振电路和复位电路

三、函数设计 

1、延时函数

1.1、实现功能

实现毫秒单位延时

1.2、代码实现

#include<intrins.h>

void Delay(unsigned int xms)

{

unsigned char i, j;

while(xms)

{

_nop_();

i = 2;

j = 199;

do

{

while (--j);

} while (--i);

xms--;

}

}

2、独立按键函数

2.1、实现功能

获取按键值函数,用于检测按下的按键键码

2.2、设计原理

首先需要声明按键引脚

sbit SET_SHUIXIAN = P1^0;

sbit SET_MUDAN = P1^1;

sbit SET_MEIGUI = P1^2;

sbit SET_ADD = P1^3;

sbit SET_MINUS = P1^4;

sbit MOD = P1^5;

当引脚为低电平时接地表示对应按键按下

2.3、代码实现

unsigned char Key()

{

unsigned char KeyNumber = 0;

if(SET_SHUIXIAN == 0){Delay(20);while(!SET_SHUIXIAN);Delay(20);KeyNumber = 1;}

if(SET_MUDAN == 0){Delay(20);while(!SET_MUDAN);Delay(20);KeyNumber = 2;}

if(SET_MEIGUI == 0){Delay(20);while(!SET_MEIGUI);Delay(20);KeyNumber = 3;}

if(SET_ADD == 0){Delay(20);while(!SET_ADD);Delay(20);KeyNumber = 4;}

if(SET_MINUS == 0){Delay(20);while(!SET_MINUS);Delay(20);KeyNumber = 5;}

if(MOD == 0){Delay(20);while(!MOD);Delay(20);KeyNumber = 6;}

return KeyNumber;

}

3、LCD1602功能函数

LCD1602功能函数有初始化、显示字符、显示无符号/有符号数字、显示字符串等等

函数声明模块

#ifndef __LCD1602_H__

#define __LCD1602_H__

void LCD_Init();

void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);

void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);

void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);

void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

#endif

本次用到的LCD1602显示函数有LCD_Init、LCD_ShowString、LCD_ShowNum

代码实现段

void LCD_Init()

{

LCD_WriteCommand(0x38);

LCD_WriteCommand(0x0c);

LCD_WriteCommand(0x06);

LCD_WriteCommand(0x01);

}

void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)

{

unsigned char i;

LCD_SetCursor(Line,Column);

for(i=0;String[i]!='';i++)

{

LCD_WriteData(String[i]);

}

}

void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)

{

unsigned char i;

LCD_SetCursor(Line,Column);

for(i=Length;i>0;i--)

{

LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');

}

}

4、Warning函数

4.1、实现功能

警报&灌溉函数,根据测得湿度控制发动机和警报系统工作

4.2、设计原理

定义三个引脚

sbit PMQ = P2^3;

sbit LED_RED = P2^4;

sbit WATER = P2^5;

设置三个参数湿度humidity,最高阈值HIGH,最低阈值LOW

湿度小于阈值,开启发动机,LED和蜂鸣器警报

湿度大于等于阈值,发动机停止,LED和蜂鸣器不警报 

湿度在阈值之间,发动机工作直至到达最高阈值,LED和蜂鸣器不警报

再使用前需初始化三个引脚,即给低电平,因为电路开启默认所有引脚为高电平

4.3、代码实现

if(humidity<LOW)

{

WATER = 1;

LED_RED = 1;

PMQ = 1;

}

else if(humidity>=HIGH)

{

WATER = 0;

LED_RED = 0;

PMQ = 0;

}

else

{

LED_RED = 0;

PMQ = 0;

}

5、 A/D模数转换函数

5.1、实现功能

ADC0832模数转换函数,将输入的模拟电压值(0-5V)转换为数字量

5.2、设计原理

输入模拟量来自电位器电压值(0~5)

ADC0832工作原理:

ca5655634db34e3cb3e7341d276febd5.png

· CS_ 片选使能,低电平芯片使能。

· CH0 模拟输入通道0,或作为IN+/-使用。

· CH1 模拟输入通道1,或作为IN+/-使用。

· GND 芯片参考零电位(地)。

· DI 数据信号输入,选择通道控制。

· DO 数据信号输出,转换数据输出。

· CLK 芯片时钟输入。

· Vcc/REF 电源输入及参考电压输入(复用) 

其中DI,DO是双向的,一般不同时工作,所以将DI/DO连接咋同一个I/O口可节省IO口数量

 时序图:

32fc75c0b2894f6e9cdb61ff6a796279.png

第一个时钟上升沿之前将CS'置0,表示芯片解除禁用,在此之前CLK,DI/DO电平任意

第一个时钟上升沿下沉之前将DI置为高电平,表示开启AD转换

第二、三时钟上升沿为选择工作方式,分别在时钟上升沿到来之前将DI置为0或1

若两位DI依次为1,、0,则工作方式为CH0单通道;

若两位数据为0、0,工作方式为CH0作为正输入端IN+,CH1作为负输入端IN-进行输入

若两位数据为0、1,将CH0作为负输入端IN-,CH1 作为正输入端IN+进行输入

到第三个脉冲的下降之后DI端的输入电平就失去输入作用,此后DO/DI端则开始利用数据输出DO进行转换数据的读取.

从第4个脉冲下降沿开始由DO端输出转换数据最高位Data7,随后每一个脉冲的下降沿DO端输出下一位数据。直到第11个脉冲时发出最低位数据Data0,一个字节的数据输出完成,此阶段为MSB先出;自第12个脉冲开始从Data0开始每一个时钟依次从低位到高位重新读取该字节数据,用于校验,当两次读取的数据相同时,该数据就作为一次AD转换的结果输出.

5.3、代码实现

定义引脚与头文件

#include<intrins.h>

sbit ADC_CLK = P3^1;

sbit ADC_CS = P3^0;

sbit ADC_DI = P3^2;

sbit ADC_DO = P3^2;

 #include<intrins.h>中包括接下来需要用到的延时函数_nop_().

ADC0832初始化,未开始工作前,CS置1芯片禁用,CLK置0,DI/O任意

ADC_CS = 1;

ADC_CLK = 0;

ADC_DI = 1;

前三个时钟代码实现

ADC_CS = 0;

ADC_CLK = 0;

ADC_DI = 1;

_nop_();

ADC_CLK = 1;

_nop_();

ADC_CLK = 0;

ADC_DI = 1;

_nop_();

ADC_CLK = 1;

_nop_();

ADC_CLK = 0;

ADC_DI = 0;

_nop_();

ADC_CLK = 1;

_nop_();

ADC_CLK = 0;

ADC_DO = 1;

 定义两个变量ad_result1 ,ad_result2 用于接收数据

LSB先出,设置8次循环,每次循环,模拟时钟上升沿和下降沿,并将ad_result1左移一位,当输出DO为1时ad_result1与0x01即(0000 0001)进行或运算,DO为0则不进行,8次循环后一个字节数据接收完成

MSB先出,同样设置8次循环,但在时序图中发现第12个时钟上升沿期间,Data0位已经在数据位,因此循环中先进行数据读取再模拟时钟上升沿和下降沿,数据读取不同点在于从最低位开始读取,因此将ad_result2右移一位,读取时与0x80进行或运算

代码实现

for(i=0;i<8;i++)

{

ADC_CLK = 1;

_nop_();

ADC_CLK = 0;

ad_result1 = ad_result1<<1;

if(ADC_DO==1)

ad_result1 = ad_result1 | 0x01;

}

for(i=0;i<8;i++)

{

ad_result2 = ad_result2>>1;

if(ADC_DO==1)

ad_result1 = ad_result1 | 0x80;

ADC_CLK = 1;

_nop_();

ADC_CLK = 0;

}

ADC_CLK = 1;

ADC_CS = 1;

ADC_DI = 1;

输出结果

if(ad_result1==ad_result2)

return ad_result1;

else

return 0;

这一阶段结束,可以设置湿度阈值来控制电机和警报 

 6、设置函数库

e95cf5d34d4d4f7ebdea5a77ca1ba55a.png

 首先显然需要一个返回按下按键键码的函数

Key()函数

引脚连接按键接地,当其中一个按键按下时,连接的引脚相当于直接接地,为低电平,因此低电平为判断条件,再将每个按键按下赋予键码和对应意义如图所示,代码在上文

整个Setting.c需要用到的库文件

#include"Setting.h"

#include"Warning.h"

#include"LCD1602.h"

#include"Delay.h"

#include<string.h>

#include <REGX51.H>

定义数组存储三种花卉的名称、阈值

unsigned char shuixian[2] = {20,70};

unsigned char mudan[2] = {30,60};

unsigned char meigui[2] = {25,75};

char name1[]="ShuiXianHua";

char name2[]="MuDanHua";

char name3[]="MeiGuiHua";

其他变量定义

unsigned char low = 20;

unsigned char high = 70;

char *str;

unsigned char Mod = 0;

char name[13] = '';

Setting函数 

void Setting(unsigned char Keynum,humidity)

当按键1按下时,str指针指向水仙花的阈值数组地址,要显示的最低最高阈值分别为水仙花的最低阈值和最高阈值,名称显示“ShuiXianHua” 以此类推;

if(Keynum == 1)

{

str = shuixian;

low = shuixian[0];

high = shuixian[1];

strcpy(name,name1);

}

当按键4按下时如果此时MOD=0,则str指向的当前数组里最低阈值减1,若MOD=1,当前最高阈值减1;按键5按下时同理,为+1

if(Keynum == 4)

{

if(Mod == 0)

{

(*str) = (*str)+1;

low = (*str);

}

else if(Mod == 1)

{

*(str+1) = *(str+1)+1;

high = *(str+1);

}

}

按键6按下为MOD在0、1之间转换,工作在加减最低阈值和加减最高阈值两种模式 

if(Keynum == 6)

{

if(Mod == 0)

Mod = 1;

else if(Mod == 1)

Mod = 0;

}

 Show_Set函数,显示当前设置(名称,阈值,测得湿度)

由于存储名称和阈值的数组都为全局变量,而湿度需要在主函数中处理,所以Show_Set函数只有一个参数湿度humidity,为处理过湿度数据的百分数形式

LCD_ShowString(1,1,name);

LCD_ShowNum(2,14,humidity,2);

LCD_ShowString(2,16,"%");

LCD_ShowString(2,1,"S:");

LCD_ShowNum(2,3,low,2);

LCD_ShowString(2,5,"% N:");

LCD_ShowNum(2,10,high,2);

LCD_ShowString(2,12,"%");

Warning(humidity,high,low);

Setting_Init()函数 ,用于初始化按键,以及没有按键按下时默认显示水仙花的数据

SET_SHUIXIAN = 1;

SET_MUDAN = 1;

SET_MEIGUI = 1;

SET_ADD = 1;

SET_MINUS = 1;

MOD = 1;

LCD_ShowString(1,1,name1);

LCD_ShowString(2,1,"S:20");

LCD_ShowString(2,5,"% N:70");

LCD_ShowString(2,12,"%");

main()函数设计

 主函数设计比较简单

首先定义两个变量用于接收键码和A/D转换后的输出结果

其次是各模块初始化

LCD_Init();

Warning_Init();

ADC0832_Init();

Setting_Init();

处理A/D转换结果便于显示

ad_result = ADC0832_Conv();

ad = 1.0*ad_result*100/255;

 接收键码并在判断有按键按下的时刻传递键码和湿度值给Setting函数修改设置

KeyNum = Key();

if(KeyNum)

{

Setting(KeyNum,ad);

}

 LCD显示当前数据

Show_Set(ad);//LCD显示当前花名,阈值,测得湿度

由于键码按下只有一瞬间,所以显示数据函数需要放在判断条件外,在while循环里不断显示 

最后晶振电路和复位电路实际在仿真可以省略,因为仿真过程里时钟频率是人为设置的(11.0592MHZ),复位电路并不会起效果,并且纯硬件电路也不需要编写代码,但在实际电路中是需要安装的 

四、结果展示

见主页上传的演示视频

相关知识

基于51单片机的自动浇花灌溉系统设计
温室灌溉系统
【51毕业设计案例】【015】智能浇花灌溉系统
高效花卉苗木温室潮汐灌溉系统
基于物联网的温室花卉智能灌溉系统设计
HMITECH纵横科技高效花卉苗木温室潮汐灌溉系统———HMITECH纵横科技高效花卉苗木温室
社区花园智能灌溉系统设计实验
温室花卉盆栽的方法
【绿化灌溉系统报价】
工控自动化应用方案:高效花卉苗木温室潮汐灌溉系统

网址: 温室盆栽灌溉系统设计(51) https://www.huajiangbk.com/newsview477065.html

所属分类:花卉
上一篇: 国内外智能盆栽研究现状怎么样
下一篇: A.非饮用水来源B.植物类型C.

推荐分享