切换到宽版
爱科技/爱创意/爱折腾/爱极致;技术知识分享平台,点击进入新版数码之家网站
  • 5262阅读
  • 8回复

[其他]【物联网】小花园无线气象站+花草浇水【wifi控制,附视频】 [复制链接]

上一主题 下一主题
离线ppxiaop
 

发帖
88
M币
622
专家
5
粉丝
23
只看楼主 倒序阅读 我要置顶 楼主  发表于: 2014-03-02
首先要感谢小七帖子给我的帮助:通俗话教你单片机之【串口】篇 http://bbs.mydigit.cn/read.php?tid=534747&ds=1#tpc

一年前,我在DIY版发了这个帖子:
湿度+光感应花草自动浇水装置 http://bbs.mydigit.cn/read.php?tid=564257

好的方面:
1. 元件到现在都可以正常工作。。。

不好的方面:
1. 自制湿度传感器波动大,且容易受腐蚀。后来更换了碳棒,腐蚀是不怕了,但波动方面仍然无法解决
2. 模拟电路无法达到浇水的精确控制

最近用单片机做了几个东东(比如自动冲水马桶http://bbs.mydigit.cn/read.php?tid=790079),还剩下一片STC12C2052AD,就顺便以这个为核心,加上WIFI转串口模块,做一个Wifi无线浇水控制,也意味着自己的捣鼓向物联网迈进了一步。

功能:
1. 实时显示花园温度和湿度信息【未来可扩展】
2. 手动和自动控制浇水:自动功能设定为每天一次,每次开启6分钟。【功能可扩展】

原理:
1. 单片机负责采集传感器信号,收集继电器是否开启的信息,通过串口连接到WIFI转串口模块
2. PHP调用Python脚本,与模块进行TCP通信,发送查询或命令代码
3. 模块收到代码,将请求通过串口传递给单片机
4. 单片机根据收到的代码,执行相应的程序


使用到的组件:
1. 树莓派 【可选】:树莓派起到了两个作用:自己架设的家庭web服务器(php);php调用python脚本进行socket通信【可以直接PHP调用但不稳定】
2. wifi转串口模块【必选】:我使用了常见的HLK-RM04,它起的作用就是讲TCP/UDP请求转换成串口通信请求,与单片机进行通信
3. STC12C2051AD【必选】:可以使用更便宜的单片机
4. DHT22【可选】:我用这个采集花园的温湿度,未来计划加上灰尘传感器测PM2.5
5. 继电器等组件:这个不用多说
6. 盒子:使用坏掉的电子吸湿卡

上图:
1. 家庭主页效果图【PM2.5目前是假的,其他均为实际值,背景图片是一些旅游照片,随机从数据库取得】:


2. 组装在电子吸湿卡内的图【浪费很多空间。。。】


3. 串口助手和python socket通信

Python收到格式比较特殊一点,需要在PHP里面进行相应的处理


4. 安装起来的样子


5. 最后上一张花朵



最后附上视频及代码:
flash: http://player.youku.com/player.php/sid/XNjc5NzU4ODg4/v.swf
代码【】:
1. 单片机源码:
#include <reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char

uchar sec,min,hrs,time,mode;
uchar xdata value[5];
uint RH,TH;
uchar data_byte;

sbit dht22 = P1^7; //DHT22温湿度
sbit irrigation = P1^6; //浇水控制继电器

void Init()
{
     TMOD = 0x21; //工作方式,T1 8位自动重装,T0 16位全用
     TH1  = 0xFD;
     TL1  = 0xFD;  //波特率9600

     TH0  = 0x4C;
     TL0  = 0x00;  //T1 初值

     SM0= 0;//SM0 和 SM1 设定串口的工作方式(方式1)
     SM1= 1;
     REN= 1;//允许串口接收外部传来的数据

     ES = 1;    //串口中断打开

     TR1  = 1; //开始计时(数)
     TR0  = 1; //开始计时(数)

     EA   = 1; //打开总中断
}

void Delay(uint j)
{
         uchar i;
         for(i=j;i>0;i--) _nop_();
}


void start()//DHT22湿度开始信号
{
    dht22=1;
    Delayms(1);
    dht22=0;
    Delayms(10);//>500us
    dht22=1;
    Delay(30);//20-40us
}

uchar receive_byte()
{
    uchar i,tmp;
    uint count;
    for(i=0;i<8;i++)             //循环8次直至读取所有数据(8bit)
    {
        count=2;
        while((!dht22)&&count++)//等待50us低电平结束,count如溢出也退出
        tmp=0;                    // 默认将tmp置0
        Delay(50);            //70us对应“1”,26~28us对应“0”
        if(dht22==1)tmp=1;
        count=2;
        while((dht22)&&count++);   //等待直到低电平
        if(count==1)break;
        data_byte = data_byte<<1;     //左移一位
        data_byte|=tmp;                 //赋新读取到的值,合并
    }
    return data_byte;           //二进制格式
}
void receive()
{
    uchar check,num_check;
    uint T_H,T_L,R_H,R_L;
    uint count;
    start();//开始信号
    dht22=1;
    if(!dht22)//读取DHT22响应信号低电平
    {
    count=2;
    while((!dht22)&&count++);//等待DHT22低电平80us应答信号结束
    count=2;
    while((dht22)&&count++);   //等待DHT22高电平80us应答信号结束
    R_H=receive_byte();
    R_L=receive_byte();
    T_H=receive_byte();
    T_L=receive_byte();
    check=receive_byte();  //接收校验的8位
    dht22=0;//拉低延时50us
    Delay(50);
    dht22=1;
    num_check=R_H+R_L+T_H+T_L;
    if(num_check=check)
    {
        RH=(R_H<<8)|R_L;
        TH=(T_H<<8)|T_L;
        check=num_check;
    }
    }
}

void com_ser() interrupt 4 //串口中断处理函数,收到数据后产生中断,在这里处理
{
    unsigned char temp,k; //定义一个变量,用来存放电脑端发来的数据

    if(RI)//如果数据已经接收完,即RI=1
    {
        RI=0;//对RI进行清零
        temp = SBUF;
    }

    if(temp=='a')           //收到a,发送各项传感器信息
    {
        value[0] = RH>>8;
        value[1] = RH;
        value[2] = TH>>8;
        value[3] = TH;
        value[4] = irrigation;
        value[5] = mode;

        for (k=0; k<6; k++)
        {
            SBUF=value[k];
            while (!TI);    //判断数据是否发送完毕,即TI=1,没发完就在这等待
            TI = 0;    //发送完后对TI进行清零
        }
    }

    if(temp=='b')                     //收到b,控制浇水继电器动作【手动】
    {
        if(mode==2) {mode = 0; ET0 = 0; irrigation=1;}
        else {mode = 2; sec=0; min=0; ET0 = 1;}  //切换到手动模式,打开定时器0中断,继电器控制交给定时器中断处理
    }


    if(temp=='c')                     //收到c,控制浇水继电器动作【自动】
    {
        if (mode==1) {mode=0; ET0 = 0; irrigation=1;}
        else {mode=1; sec=0; min=0; hrs=0; ET0 = 1;}         //自动浇水模式,打开定时器0中断,继电器控制交给定时器中断处理        
    }

    //else { SBUF = 0x00;}  //防止TI死循环
}

void timer0() interrupt 1   //计时器0中断
{
    TH0  = 0x4C;
    TL0  += 0x00;  //T1 初值自动重装

    if(mode==2)      //进入手动浇水延时模式
    {
        time++;

        if (time==20) {time=0; sec++;} //到了1秒
        if (sec==60) {sec=0; min++;}

        if (min<6) irrigation=0;   //以mode置2为起点,打开继电器,浇灌6分钟后停止
        else {mode=0; irrigation=1;}
    }

    if(mode==1)      //进入自动浇水模式
    {
        time++;

        if (time==20) {time=0; sec++;} //到了1秒
        if (sec==60) {sec=0; min++;}
        if (min==60) {min=0; hrs++;}
        if (hrs==24) hrs=0;

        if (hrs==0)
        {
            if (min<6) irrigation=0;   //以mode置1为起点,打开继电器,浇灌6分钟,以后每隔24小时动作一次
            else {irrigation=1;}
        }

    }
}

void main()//主函数
{
init();
    while (1)
    {
        receive();
       Delayms(5000);

     }        
}

2. Python的Socket通信代码
import socket
import sys
import time
import binascii

#!/usr/bin/python           # This is client.py file

import socket               # Import socket module

s = socket.socket()         # Create a socket object
s.settimeout(3)

host = "192.168.1.90" # Get local machine address

port = 8080               # Reserve a port for your service.
data ="a"

s.connect((host, port))
s.sendall(bytes(data, encoding='ascii'))
receive = s.recv(1024)
print(receive)

f=open('log/garden.log','ab')
f.write(binascii.unhexlify(receive))
#f.write(time.strftime('%Y-%m-%d',time.localtime(time.time())) + "\r\n")
f.close()
s.close

3. php调用代码
  exec('python ./python/garden.py',$output);
  session_start();

  if(!(empty($output))) {$_SESSION['data']=$output;}

    foreach($_SESSION['data'] as $key=>$value)
  {
    // and print out the values
    $output = $value;
  }

  $garden = explode("\\", $output);

  for ($i=0; $i<count($garden); $i++)
  {
        $garden[$i] = trim(trim($garden[$i], "'"),"x");
        if ($garden[$i] =='b') $j=$i;
  }

  $humidity = number_format(hexdec($garden[$j+1].$garden[$j+2])/10,1);
  $temperature = number_format(hexdec($garden[$j+3].$garden[$j+4])/10,1);
  $irrigation = hexdec($garden[$j+5]);
  $mode = hexdec($garden[$j+6]);
        //以上调用python,获取花园无线信号数据



[ 此帖被ppxiaop在2014-03-02 19:25重新编辑 ]
本文内容包含图片或附件,获取更多资讯,请 登录 后查看;或者 注册 成为会员获得更多权限
本帖最近打赏记录:共12条打赏M币+50
12
离线lypara

发帖
2059
M币
1921
专家
1
粉丝
11
只看该作者 1楼 发表于: 2014-03-02
请登录后查看
离线zhike
发帖
439
M币
354
专家
1
粉丝
15
只看该作者 2楼 发表于: 2014-03-02
请登录后查看
离线wlaodi
发帖
3
M币
-24
专家
0
粉丝
6
只看该作者 3楼 发表于: 2014-03-03
请登录后查看
离线luoluo4413
发帖
275
M币
1489
专家
2
粉丝
18
只看该作者 4楼 发表于: 2014-03-03
请登录后查看
离线huangzhang

发帖
5657
M币
1868
专家
6
粉丝
150
只看该作者 5楼 发表于: 2014-03-03
请登录后查看
离线副班长

发帖
798
M币
1873
专家
2
粉丝
13
只看该作者 6楼 发表于: 2014-05-31
请登录后查看
离线李逍遥

发帖
1106
M币
2448
专家
0
粉丝
15
只看该作者 7楼 发表于: 2015-03-20
请登录后查看
离线328272463
发帖
1
M币
-497
专家
0
粉丝
1
只看该作者 8楼 发表于: 2017-04-19
请登录后查看
快速回复
限80 字节
温馨提示:欢迎交流讨论,请勿发布纯表情、纯引用等灌水帖子;以免被删除
 
上一个 下一个