首先要感谢小七帖子给我的帮助:
通俗话教你单片机之【串口】篇 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重新编辑 ]