智能创客,中国最大的极客空间,智能平台,免费教学,视频教程,手把手教你创造儿时梦想!

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 21393|回复: 22
打印 上一主题 下一主题

WIFI作品DIY教程10-《温湿传感器》DS18B20、DHT11应用。

  [复制链接]

110

主题

396

帖子

2329

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2329
QQ
跳转到指定楼层
楼主
发表于 2015-1-16 14:22:45 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
上篇WIFI作品DIY教程07-《wifi家居网关》家居控制中心zigbee/nrf24l01等完成了家居网关。


温度湿度的场景用的很多,我们之前的教程也写过非常多的实例,
这次我们采用DS18B20获取温度,DHT11获取湿度,然后传给网关和云端保存数据,供我们观察分析等。



我们需要的配件:温湿传感器板DS18B20DHT11nrf24l01(或zigbee等)



第一部分:DS18B20温度传感器介绍
DS18B20是常用的温度传感器,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。
DS18B20的数字温度计提供9至12位(可编程设备温度读数)。由于DS18B20是一条口线通信,所以中央微处理器与DS18B20只有一个一条口线连接。为读写以及温度转换可以从数据线本身获得能量,不需要外接电源。 因为每一个DS18B20的包含一个独特的序号,多个ds18b20s可以同时存在于一条总线。这使得温度传感器放置在许多不同的地方。它的用途很多,包括空调环境控制,感测建筑物内温设备或机器,并进行过程监测和控制。




第二部分:DHT11湿度传感器介绍
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性和卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个DHT11传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式存在OTP内存中,传感器内部在检测型号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,使其成为该类应用中,在苛刻应用场合的最佳选择。



第三部分:下载编译源代码
1、安装CH340驱动

在drivers目录里找到CH340驱动,然后按说明安装(之前安装了就不用再安装了)。


2、源代码
[C] 纯文本查看 复制代码

/*
 *NRF24l01针脚连接线
 * MISO -> 12
 * MOSI -> 11
 * SCK -> 13
 * Configurable:
 * CE -> 8
 * CSN -> 7
*/
#include <SPI.h>
#include <Mirf.h>
#include <nRF24L01.h>
#include <MirfHardwareSpiDriver.h>
#include <OneWire.h>

int sid=1;//模块类型
int nid=2;//模块编号

//声名变量
const unsigned long interval = 60000;
unsigned long last_sent;

OneWire  ds(A5);
float celsius=0.0;
float fahrenheit=0.0;

int DHT11_PIN=4;
int humdity=0;
int temperature=0;

//NRF24l01
unsigned long nrf24l01nowlast;
char nrf24l01buff[33]={0};
char nrf24l01Data;
int nrf24l01i=0;


void setup()
{
    Serial.begin(115200);

    char client[10]={0};//client
    sprintf(client,"clie%d",sid); 
    //初始化Mirf,用于NRF24l01收发
    Mirf_Init(0,client,sid);

    ini_dht11();

    Serial.println("zwifi_wengshitu");
}

void loop()
{

  unsigned long now = millis();
  if ( now - last_sent >= interval  )
  {
    last_sent = now;

    celsius=0;
    humdity=0;    

    run_ds18();
    if(celsius>0){
       run_dht11();
    }
    if(humdity>0){
      char celstr[10]={0};
      dtostrf(celsius,4,2,celstr);

      char data[10]={0};    
      sprintf(data,"%d.%s",humdity,celstr);   
      send_data(data);
    }

  }


}

//初始化Mirf 0初始化1为接收2为发送
void Mirf_Init(int txrx,char *server,int channel){
    //初始化Mirf,用于NRF24l01收发        
    if(txrx==0)  {     
      Mirf.spi = &MirfHardwareSpi;
      Mirf.init();
      Mirf.setRADDR((byte *)server);//设置接收地址
    }

    if(txrx==1)  {     
      Mirf.setRADDR((byte *)server);//设置接收地址
    }
    if(txrx==2)  {
      Mirf.setTADDR((byte *)server);//设置发送地址
    }

    Mirf.payload = sizeof(char);//收发字节
    Mirf.channel = channel;
    Mirf.config();
}

//NRF24l01发送函数
void Mirf_Send(int channel,char *server,char *str){
  Mirf_Init(2,server,channel);
  int bufi=0;
  for(bufi=0;bufi<strlen(str);bufi++){//循环发送
    char words=str[bufi];//发送的字符
    Mirf.send((byte *)&words);//发送命令
    while(Mirf.isSending()){//等待发送完闭
    }
    delay(50);//延时,否则可能出现发送丢失现象
    //Serial.print(words);
  }
  //Serial.println(""); 
}





void run_ds18()
{
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  //float celsius, fahrenheit;

  if ( !ds.search(addr)) {
    //Serial.println("No more addresses.");
    //Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }

  //Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
    //Serial.write(' ');
    //Serial.print(addr[i], HEX);
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
  //Serial.println();

  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      Serial.print("Chip = DS18S20");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
      Serial.print("Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Serial.print("Chip = DS1822");
      type_s = 0;
      break;
    default:
      Serial.print("Device is not a DS18x20 family device.");
      return;
  } 

  ds.reset();
  ds.select(addr);
  ds.write(0x44,1);         // start conversion, with parasite power on at the end

  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.

  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  //Serial.print("  Data = ");
  //Serial.print(present,HEX);
  //Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    //Serial.print(data[i], HEX);
    //Serial.print(" ");
  }
  //Serial.print(" CRC=");
  //Serial.print(OneWire::crc8(data, 8), HEX);
  //Serial.println();

  // convert the data to actual temperature

  unsigned int raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // count remain gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
    // default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");
  Serial.print(fahrenheit);
  Serial.println(" Fahrenheit");     
}


void ini_dht11()
{
  DDRC|=_BV(DHT11_PIN);
  PORTC|=_BV(DHT11_PIN);
}

byte read_dht11_dat()
{
  byte i = 0;
  byte result = 0;
  for(i=0;i<8;i++)
  {
  while(!(PINC&_BV(DHT11_PIN)));
  delayMicroseconds(30);
  if(PINC&_BV(DHT11_PIN))
  result|=(1<<(7-i));
  while((PINC&_BV(DHT11_PIN)));
  }
  return result;
}


void run_dht11()
{
  byte dht11_dat[5];
  byte dht11_in;
  byte i;
  PORTC &= ~_BV(DHT11_PIN);
  delay(18);
  PORTC|=_BV(DHT11_PIN);
  delayMicroseconds(40);
  DDRC &= ~_BV(DHT11_PIN);
  delayMicroseconds(40);
  dht11_in = PINC & _BV(DHT11_PIN);
  if(dht11_in)
  {
  Serial.println("dht11 start condition 1 not met");
  return;
  }
  delayMicroseconds(80);
  dht11_in=PINC & _BV(DHT11_PIN);
  if(!dht11_in)
  {
    Serial.println("dht11 start condition 2 not met");
    return;
  }
  delayMicroseconds(80);
  for(i=0;i<5;i++)
  dht11_dat[i]=read_dht11_dat();
  DDRC|=_BV(DHT11_PIN);
  PORTC|=_BV(DHT11_PIN);
  byte dht11_check_sum = dht11_dat[0]+dht11_dat[1]+dht11_dat[2]+dht11_dat[3];
  if(dht11_dat[4]!=dht11_check_sum)
  {
  Serial.println("DHT11 checksum error");
  }
  Serial.print("Chip = DHT11  Current humdity= ");
  Serial.print(dht11_dat[0],DEC);
  Serial.print(".");
  Serial.print(dht11_dat[1],DEC);
  Serial.print("%");
  Serial.print("temperature = ");
  Serial.print(dht11_dat[2],DEC);
  Serial.print(".");
  Serial.print(dht11_dat[3],DEC);
  Serial.println("C"); 
  humdity=(int)dht11_dat[0];
  temperature=(int)dht11_dat[2];
}


//
void send_data(char *data){

    char server[10]={0};//server
    sprintf(server,"serv%d",1);
    //Serial.println(server);

    char updateData[33]={0};
    char front[10]={0};
    //memcpy(front,body,9);
    sprintf(front," {ck%03d%03d",sid,nid);
    sprintf(updateData,"%s%s}",front,data);   
    Serial.println(updateData);
    Serial.println();

    Mirf_Send(1,server,updateData);

    char client[10]={0};//client
    sprintf(client,"clie%d",sid);
    Mirf_Init(1,client,sid);  

}




刷写arduino程序选哪个板?
请选择板是Arduino Uno,并记得选对对应的串口。

刷写ardruino源代码时,提示库不存在?
请联系qq610854837下载zwifi资料,软件下载目录里的arduino-1.0.5,里面包含了教程使用的所有库。



将代码进行编译下载到arduino板上。


3、串口运行查看数据是否正常

在arduino软件里,查看串口数据,记得是115200哦,等1分钟,有如上图,说明下载运行成功了!

程序的原理就是获取到二个传感器芯片的温温度,然后组合成字符{ck00x00xnnnn}发送到网关保存数据,供我们以后分析。


第四部分:检测通信和数据库记录

打开:http://192.168.1.1/znck007/mysqltest.php?mode=select


点击查看数据库记录,001,002的记录,说明网关成功保存了记录。30.20.50代表,湿度30%,温度是20.50度。



同时也可以用数据库软件Navicat for MySQL查看数据记录!





《WIFI作品DIY教程系列》
WIFI作品DIY教程01-《wifi开发板》介绍和联网等配置教程
WIFI作品DIY教程02-《openwrt摄像头》3D外壳和diy介绍
WIFI作品DIY教程03-《WIFI音响/MP3播放器/电台》
WIFI作品DIY教程04-《WIFI烟雾煤气报警器》
WIFI作品DIY教程05-《家居服务器》web server(php+mysql+uhttpd)
WIFI作品DIY教程06-《openwrt后台程序》控制mysql、串口通信等
WIFI作品DIY教程07-《wifi家居网关》家居控制中心zigbee/nrf24l01等
WIFI作品DIY教程08-《智能开关》电灯开关、插座(nrf24l01/zigbee)
WIFI作品DIY教程09-《人体红外检测》安防入侵报警功能
WIFI作品DIY教程10-《温湿传感器》DS18B20、DHT11应用。


《Arduino开源智能家居DIY教程系列》
Arduino开源智能家居《花絮1》zigbee小底板DIY成功
Arduino开源智能家居《认识Zigbee》zigbee功能和自组网介绍
Arduino开源智能家居《zigbee开发板》手机/按键点亮LED
Arduino开源智能家居01《网关》升级版网关正式教程(zigbee)
Arduino开源智能家居02《温湿传感器》什么样温湿度才适居
Arduino开源智能家居03《开发板套件》学习zigbee家居-性价比高
Arduino开源智能家居04《插座开关》手机控制:网扇、空调...
Arduino开源智能家居05《红外线》手机红外线控制电器

《百元智能家居DIY教程系列》
《智能家居网关》DIY制作图文教程01-百元智能家居系列
《智能温湿度》DIY制作图文教程02-百元智能家居系列
《智能插座》DIY制作图文教程03-百元智能家居系列
《智能电灯开关》DIY制作图文教程04-百元智能家居系列
《手机红外线》DIY制作图文教程05-百元智能家居系列
关注@智能创客  微信:znck007(打造DIY创客平台)




分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 支持支持 反对反对
回复

使用道具 举报

0

主题

13

帖子

72

积分

注册会员

Rank: 2

积分
72
沙发
发表于 2015-1-16 15:13:30 | 只看该作者
看来最近很忙呀,加油
回复 支持 反对

使用道具 举报

0

主题

8

帖子

114

积分

注册会员

Rank: 2

积分
114
板凳
发表于 2015-1-19 21:32:20 | 只看该作者
#include
#include
#include
#include
#include
又没有!!
回复 支持 反对

使用道具 举报

110

主题

396

帖子

2329

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2329
QQ
地板
 楼主| 发表于 2015-1-19 22:46:11 | 只看该作者
老催 发表于 2015-1-19 21:32
#include
#include
#include

已更新,编辑器可能有问题。
回复 支持 反对

使用道具 举报

0

主题

1

帖子

6

积分

新手上路

Rank: 1

积分
6
5#
发表于 2015-2-14 22:13:27 | 只看该作者
下载的时候出现,e:/智能家居/软件下载/arduino-1.0.5/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/bin/ld.exe: region text overflowed by 3526 bytes,我百度了一下,然后arduinocn问了一下,都说是空间不够,板卡,程序都是正确。已经刷过其它的程序测试正常。
回复 支持 反对

使用道具 举报

110

主题

396

帖子

2329

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2329
QQ
6#
 楼主| 发表于 2015-2-15 10:39:07 | 只看该作者
deepidea 发表于 2015-2-14 22:13
下载的时候出现,e:/智能家居/软件下载/arduino-1.0.5/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../.. ...

选好板就可以,网关的用644pa,其它的就用uno板,就可以了。
回复 支持 反对

使用道具 举报

1

主题

5

帖子

57

积分

注册会员

Rank: 2

积分
57
7#
发表于 2015-4-2 10:03:28 | 只看该作者

如果出现上图   去http://playground.arduino.cc/Learning/OneWire 下载OneWire的h 文件
把他放在libraries 的文件下面创建Wire文件夹  放在里面 效果如下图

然后在arduino 程序里 file  new 新建一个文件 然后在保存到libraries\znck007\examples 下面创建一个文件 在放进去 然后编译 完成{:soso_e100:}
回复 支持 反对

使用道具 举报

110

主题

396

帖子

2329

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2329
QQ
8#
 楼主| 发表于 2015-4-2 11:47:09 | 只看该作者
zyw 发表于 2015-4-2 10:03
如果出现上图   去http://playground.arduino.cc/Learning/OneWire 下载OneWire的h 文件
把他放在librarie ...

我们的资料包里也包含了这个库了哦。
回复 支持 反对

使用道具 举报

0

主题

10

帖子

40

积分

禁止发言

积分
40
9#
发表于 2015-6-30 14:29:11 | 只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

0

主题

22

帖子

77

积分

注册会员

Rank: 2

积分
77
10#
发表于 2015-10-6 13:27:19 | 只看该作者
努力学习中
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|小黑屋|手机版|智能创客 ( 桂ICP备14000828号

GMT+8, 2024-11-27 08:32 , Processed in 0.117850 second(s), 32 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表