06
2019
05

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

上篇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、源代码

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
/*
 *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查看数据记录!


« 上一篇 下一篇 »

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。