????????由于大多数人喜欢花草却不会照料,买了花草之后却没有时间照顾,从而导致花草枯萎。本设计利用wifi传输设定植物的适当光照强度,适当的土壤温湿度。然后根据温湿度传感器及光照传感进行实时监测。当温度,湿度高于适当温湿度时,采取措施降低温湿度。当温度,湿度低于适当温度时,采取措施升高温湿度。当光照太强时,适当遮挡,降低光照强度;当光照强度太弱时,开灯增强光照强度。总之给植物一个适宜的生长环境。
基于物联网的智能植物养护系统下位机演示视频
基于物联网的智能植物养护系统上位机演示视频
????????下位机使用的芯片是STM32F103ZET6,软件使用的是Keil,语言是C。
????????上位机软件用的是VS2017,语言是C#。
????????硬件连接:插上战舰板子就行了。
led灯会根据光照传感器检测光强自动调节亮度;
还有一个IO口我也用pwm做好了,连接上马达,就可以根据温度自动调整转速;
目前没有湿度补充,我打的是风扇转速的数据;
主函数
int main(void)
{
u8 Light ;
u16 led0pwmval=0;
u8 dir=1;
vu8 key=0;
int i;
u8 t=0;
u16 len;
u8 temperature;
u8 humidity;
u16 temp_sup=25,humi_sup=35,light_sup=0;
KEY_Init();
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为115200
LED_Init(); //初始化与LED连接的硬件接口
TIM4_PWM_Init(899,0);
TIM3_PWM_Init(899,0);
LCD_Init(); //初始化LCD
Lsens_Init();
POINT_COLOR=RED; //设置字体为红色
display0();
while(DHT11_Init()) //DHT11初始化
{
LCD_ShowString(30,100,200,16,16,"DHT11 Error");
delay_ms(200);
LCD_Fill(30,130,239,130+16,WHITE);
delay_ms(200);
}
POINT_COLOR=BLUE;//设置字体为蓝色
display1();
display2();
while(1)
{
POINT_COLOR=RED;
Light=Lsens_Get_Val();
LCD_ShowxNum(35,130,Light,2,24,0); //显示ADC的值
t++;
if(t%10==0) //每100ms读取一次
{
DHT11_Read_Data(&temperature, &humidity); //读取温湿度值
LCD_ShowNum(100,130,temperature,2,24); //显示温度
LCD_ShowNum(165,130,humidity,2,24); //显示湿度
LCD_ShowNum(120,190,light_sup,4,16); //显示湿度
LCD_ShowNum(120,230,humi_sup,4,16); //显示湿度
LCD_ShowNum(120,270,temp_sup,4,16); //显示湿度
POINT_COLOR=BLUE;
printf("温度%2d",temperature);
delay_ms(10);
printf("湿度%2d",humidity);
delay_ms(10);
printf("光强%2d",Light);
delay_ms(10);
}
USART_SendData(USART1, temperature*16);
light_sup = 300-(Light*3);
humi_sup = temp_sup = (temperature-24)*60;
TIM_SetCompare1(TIM4,humi_sup);
TIM_SetCompare2(TIM3,light_sup);
}
}
显示函数
void display2()
{
LCD_ShowChinese(90,110,0,16,1); //温度:
LCD_ShowChinese(108,110,2,16,1);
LCD_ShowChinese(126,110,12,16,1);
LCD_ShowChinese(155,110,1,16,1); //湿度:
LCD_ShowChinese(173,110,2,16,1);
LCD_ShowChinese(191,110,12,16,1);
LCD_ShowChinese(30,110,13,16,1); //光强
LCD_ShowChinese(48,110,14,16,1);
LCD_ShowChinese(66,110,12,16,1);
LCD_ShowString(126,137,200,16,16,"C");
LCD_ShowString(191,137,200,16,16,"%");
LCD_ShowString(60,137,200,16,16,"cd");
}
数据可以同下位机实时更新;
用的是串口1,有线,蓝牙还没有回来;
产生的折线图只有温度的;
折线图快捷键可以使用。**
主窗口函数
namespace Drawer
{
public delegate void ShowWindow();
public delegate void HideWindow();
public delegate void OpenPort();
public delegate void ClosePort();
public delegate Point GetMainPos();
public delegate int GetMainWidth();
public partial class Form1 : Form
{
Drawer Displayer;
public Form1()
{
InitializeComponent();
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
serialPort1.Encoding = Encoding.GetEncoding("GB2312"); //串口接收编码
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(Form1_FormClosing);
}
private void Form1_FormClosing(object sender, EventArgs e)
{
try { serialPort1.Close(); }
catch { }
}
public void ClosePort()//关闭串口,供委托调用
{
try
{
serialPort1.Close();
}
catch (System.Exception)
{
}
}
private Point GetMyPos()//供委托调用
{
return this.Location;
}
public void OpenPort()//打开串口,供委托调用
{
try
{
serialPort1.Open();
}
catch (System.Exception)
{
MessageBox.Show("串口打开失败,请检查", "错误");
}
}
public void ShowMe()//供委托调用
{
this.Show();
}
public void HideMe()//供委托调用
{
this.Hide();
}
private void Form1_Load(object sender, EventArgs e)
{
for (int i = 0; i < 20; i++)
{
try
{
serialPort1.PortName = "COM" + i;
serialPort1.Open();
toolStripComboBox1.Items.Add(serialPort1.PortName);
serialPort1.Close();
if (toolStripComboBox1.Text == "")
toolStripComboBox1.Text = serialPort1.PortName;
}
catch { }
timer1.Start();
}
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
textBox7.Text = serialPort1.ReadExisting();
byte[] data = new byte[serialPort1.BytesToRead]; //定义缓冲区,因为串口事件触发时有可能收到不止一个字节
serialPort1.Read(data, 0, data.Length);
if (Displayer != null) //Displayer就是波形绘制窗口的一个对象 就是那个窗口
Displayer.AddData(data);
if (textBox7.Text.Contains("温度"))
textBox1.Text = textBox7.Text.Substring(2, 2);
else if (textBox7.Text.Contains("湿度"))
textBox2.Text = textBox7.Text.Substring(2, 2);
else if (textBox7.Text.Contains("光强"))
textBox3.Text = textBox7.Text.Substring(2, 2);
//foreach (byte Member in data) //遍历用法
//{
// string str = Convert.ToString(Member, 16).ToUpper();
// textBox8.AppendText("0x" + (str.Length == 1 ? "0" + str : str) + " ");
//}
textBox4.Text = (300 - (Convert.ToInt16(textBox3.Text) * 3)).ToString();
textBox5.Text = textBox6.Text = ((Convert.ToInt16(textBox1.Text) - 24) * 60).ToString();
}
catch { }
}
private void CreateNewDrawer()//创建ADC绘制窗口
{
Displayer = new Drawer();//创建新对象
Displayer.ShowMainWindow = new ShowWindow(ShowMe);//初始化类成员委托
Displayer.HideMainWindow = new HideWindow(HideMe);
Displayer.GetMainPos = new GetMainPos(GetMyPos);
Displayer.CloseSerialPort = new ClosePort(ClosePort);
Displayer.OpenSerialPort = new OpenPort(OpenPort);
Displayer.GetMainWidth = new GetMainWidth(GetMyWidth);
Displayer.Show();//显示窗口
}
int GetMyWidth()//供委托调用
{
return this.Width;
}
private void CreateDisplayer()
{
this.Left = 0;
CreateNewDrawer();
Rectangle Rect = Screen.GetWorkingArea(this);
Displayer.SetWindow(Rect.Width - this.Width, new Point(this.Width, this.Top));//设置绘制窗口宽度,以及坐标
}
private void timer1_Tick(object sender, EventArgs e)
{
label1.Text = DateTime.Now.ToString();
}
private void 打开串口ToolStripMenuItem_Click(object sender, EventArgs e)
{
if (打开串口ToolStripMenuItem.Text == "打开串口")
{
try
{
serialPort1.PortName = toolStripComboBox1.Text;
serialPort1.Open();
打开串口ToolStripMenuItem.Text = "关闭串口";
}
catch
{
MessageBox.Show("端口错误!请检查端口,或重启软件!", "错误!");
}
}
else
{
serialPort1.Close();
打开串口ToolStripMenuItem.Text = "打开串口";
}
}
private void 变化曲线ToolStripMenuItem_Click(object sender, EventArgs e)
{
if (serialPort1.IsOpen)
{
if (Displayer == null)//第一次创建Displayer = null
{
CreateDisplayer();
}
else
{
if (Displayer.IsDisposed)//多次创建通过判断IsDisposed确定串口是否已关闭,避免多次创建
{
CreateDisplayer();
}
}
}
else
MessageBox.Show("请打开串口!", "。。。是不是没打开串口!");
}
}
}
项目本身功能简单,但是包含内容还是挺多的,扩展的话也比较容易。