数码之家

 找回密码
 立即注册
搜索
查看: 4266|回复: 3

基于DHT11、arduino、路由器(Openwrt)的温度监测网页项目

[复制链接]
发表于 2019-7-26 14:43:28 | 显示全部楼层 |阅读模式
1.材料
1.DHT11 ×1
2.Arduino小板 ×1
3.Newifi3(已刷Pandora Box ×1
4.Ubuntu 系统的计算机 ×1
2.单片机端2.1硬件
连线:
DHT11引脚               Arduino引脚
   1  -----------------------  9
     2  -----------------------  10
     3 -----------------------  11
     4  -----------------------  12
ardiuion 用数据线接到路由器usb接口

2.2软件
说明:
1.波特率9600够用,太高linux端会乱码
2.由于未知原因,linux端每次发送完数据,arduino都会被重置,程序又重新从头执行。暂时没找到解决方案,如果有高手有所了解还请指点一二,不胜感激。

程序正文:
  1. #define vcc 9       //2号IO口作为通信接口
  2. #define out 10
  3. #define nc 11
  4. #define gnd 12
  5. #define contral 13
  6. void setup() {
  7.      Serial.begin(9600); //波特率9600,太高linux端乱码
  8.      pinMode(vcc, OUTPUT);
  9.      pinMode(out, INPUT);
  10.      pinMode(contral, INPUT);
  11.      digitalWrite(contral, HIGH);
  12.      pinMode(nc, INPUT);
  13.      pinMode(gnd, OUTPUT);   //IO口设为输入模式
  14.      digitalWrite(vcc, HIGH);
  15.      digitalWrite(gnd, LOW);
  16. }
  17. void loop() {
  18.      delay(500);
  19.      beginDHT();    //起始函数,向DHT11发送起始信号
  20.      unsigned char* b = read1();//读取传感器数据
  21.      display_1(b);//串口显示数据
  22. }
  23. void beginDHT()
  24. {
  25.      pinMode(out, OUTPUT);//io 设为输出模式,是因为测量发现DHT11的上拉电流有5mA,
  26.                                //远大于输入模式下ATmega328的 io 的下拉电流,便无法得到 起始的至少28ms的低电平。
  27.      digitalWrite(out, HIGH);//io置高
  28.      delay(1100);      //等待1.4s,因为DHT11的采样周期为1s,这里取的稍长一些。
  29.      digitalWrite(out, LOW);//io拉低,发送起始信号
  30.      delay(30);        //延时至少28ms,这里取30ms
  31.      digitalWrite(out, HIGH);//拉高
  32.      pinMode(out, INPUT);//切换到输入模式,准备读数据
  33. }
  34. unsigned char*read1()
  35. {
  36.      //int a[6]={0,0,0,0,0,0};//定义数组,存放数据
  37.      int i, j;//变量,下面用到
  38.      unsigned char* b = new unsigned char[5];//用b将数据返回给loop()***此处将传感器数据传递出去用全局变量也行,但想试试其他方法****
  39.      for (i = 0; i < 5;i++)
  40.           b = 0;
  41.      delayMicroseconds(40);//延时40us,等待DHT11将io拉低
  42.      if (digitalRead(out) == 0)//io读取值为0,说明DHT11已响应,io已经被拉低
  43.      {
  44.           while (digitalRead(out) == 0);//等待80us的低电平结束
  45.           delayMicroseconds(82);//等待80us的高电平结束
  46.           for (i = 0; i < 5; i++)//5个元素,依次存放温度、湿度、校验值数据
  47.           {
  48.                for (j = 0; j < 8; j++)//依次读取各二进制位
  49.                {
  50.                     b= b << 1;//得到二进制数的第一位之后,将数据左移一位
  51.                     while (digitalRead(out) == 0);//等待50us的低电平结束
  52.                     delayMicroseconds(32);//延时40us,大于表示数据“0”的26-28us高电平,并小于表示数据“1”70us高电平
  53.                     if (digitalRead(out) == 0)//若io读取值为0,说明高电平时间小于40us,即为数据“0”
  54.                     {
  55.                          b = b | 0x00;//数据最低位取0
  56.                     }
  57.                     else//若io读取值为1,说明高电平时间大于40us,即为数据“1”
  58.                     {
  59.                          b = b | 0x01;//数据最高位取1
  60.                          delayMicroseconds(40);//因数据“1”高电平时间为70us,70-40=30,这里取的比30稍大,确保io已经拉低
  61.                     }
  62.                }
  63.           }
  64.           //b=a; //依次将a[]传给b[];
  65.      }
  66.      else    //如果io读取不为0,说明io没有被拉低
  67.      {
  68.           // Serial.print("   DHT11未响应 , ");//则认为是DHT11未响应
  69.           for (i = 0; i < 5; i++)  //湿度赋值为-1.湿度为负说明读取出错
  70.           {
  71.                b = 0;
  72.           }
  73.      }
  74.      returnb;//返回b        ******此处将传感器数据传递出去用全局变量也行,但想试试其他方法****
  75. }
  76. void display_1(unsigned char b[])//显示函数
  77. {
  78.      int c = (b[0] + b[1] + b[2] + b[3]) & 0xff;
  79.      unsigned char JiaoYanZhi;
  80.      int avaliable = -1;
  81.      charnumber[5];
  82.      floatWenDu, ShiDu;//定义浮点数据类型
  83.      ShiDu = b[0]+ float(b[1]) / 10;//计算湿度,后面的float(b[1])是将int类型的b[1]转换为浮点数据,
  84.                                       //因为小于10的int类型数据除以10之后将总为0.
  85.      WenDu = b[2]+ float(b[3]) / 10;//计算温度。
  86.      JiaoYanZhi = b[4];//校验值赋值
  87.      if (JiaoYanZhi == c&& ShiDu > 0)//校验数据是否正确且湿度不小于0(湿度小于0说明
  88.                                                    //上面的DHT11未向应),正确且湿度大于0则串口输出数据
  89.      {
  90.           //digitalWrite(out,HIGH);//串口显示数据
  91.           //Serial.println(avaliable);
  92.           Serial.print("温度:");
  93.           //itoa(20,number,10);
  94.           Serial.print(WenDu);
  95.           Serial.print("_度  </h1> <h1>  ");
  96.           //Serial.println(int(WenDu));
  97.           Serial.print("湿度:");
  98.           Serial.print(ShiDu);
  99.           Serial.print("_%");
  100.           /*
  101.           Serial.print("      校验值");
  102.           Serial.print(JiaoYanZhi);
  103.           Serial.print("      计算值:");
  104.           Serial.print(c);
  105.           if(JiaoYanZhi!=c)
  106.           Serial.print("*************");
  107.           Serial.println("");
  108.           */
  109.      }
  110.      else//校验数据是否正确,错误则串口错误提示
  111.      {
  112.           Serial.println("读取数据出错~");
  113.      }
  114. //接收到S(ascii码83)T(ascii码84) 之后继续运行
  115.      while(avaliable != 83 && digitalRead(contral) == 0)
  116.      {
  117.           avaliable =Serial.read();
  118.           delay(200);
  119.      }
  120.      while(avaliable != 84 && digitalRead(contral) == 0) {
  121.           avaliable =Serial.read();
  122.           delay(200);
  123.      }
  124.      while(avaliable != -1 && digitalRead(contral) == 0) {
  125.           avaliable =Serial.read();
  126.           delay(200);
  127.      }
  128. }
复制代码

3.路由器端
3.1路由器配置
需要安装的软件包有
1.kmod-usb-serial-ch341  (用于连接arduino)
2.coreutils-stty  (用于配置串口参数)

3.2路由器端脚本
PS:此脚本保存为 /www/gettmp.sh
  1. #!/bin/bash
  2. myPath='/www/'
  3. #获取arduino所在端口号
  4. USB_Num_str=`dmesg | grepttyUSB*`
  5. #echo $USB_Num_str
  6. USB_Num_str=${USB_Num_str##*ch341}
  7. #echo-------------------------------
  8. USB_Num_str=${USB_Num_str##*'attachedto '}
  9. echo $USB_Num_str
  10. #获取当前系统时间
  11. time1=$(date)
  12. #设置串口速率9600,超时4s
  13. stty -F"/dev/$USB_Num_str" raw speed 9600 min 0 time 40
  14. #发送起始信号
  15. echo SSSTTT>"/dev/$USB_Num_str"
  16. #echo AAABBB>"/dev/$USB_Num_str" | cat "/dev/$USB_Num_str"
  17. #获取数据
  18. data_got=`cat"/dev/$USB_Num_str"`
  19. echo"${time1}${data_got}"
  20. #写入网页编码信息,防止乱码
  21. echo '<metahttp-equiv="Content-Type" content="text/html;charset=utf-8" />'>"${myPath}index2.html"  
  22. #写入网页内容                        
  23. echo"<html><h2>${time1}</h2><h1>${data_got}</h1></html>">>"${myPath}index2.html"   
复制代码


3.3路由器端网页服务器搭建
$vi /usr/config/uhttpd/
在末尾增加一条:
  1. config uhttpd 'web'                 
  2.         list 'listen_http''0.0.0.0:81'
  3.         option 'home' '/www'           
  4.         option 'index_page''index2.html'
  5.         option 'cgi_prefix''/cgi-bin'
复制代码


保存退出
$/etc/init.d/uhttpd restart
Psvi编辑器使用方法,不懂的自行百度
3.4设置定时任务
设置定时任务,每分钟读取一次DHT11并更新网页文件
如图:
* * * * * sh /www/gettmp.sh

4.查看
用浏览器登录 [路由器所在ip]:81 即可查看
效果如图



5.遇到的问题及解决方法:
1.搭建uhttpd之后路由器登录页面进不去。
解决方法:一定要追加配置信息,不要在原有内容上修改。
2.linux收到信息乱码
解决方法:降低波特率
3.网页乱码
解决方法:添加网页编码标识
这只是基本的实现,更复杂一些可以在网页中加入js,在arduion上添加更多传感器等等。欢迎大家提出建议与意见。

顺便来一张Ubuntu美照:




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

打赏

参与人数 1家元 +20 收起 理由
家睦 + 20

查看全部打赏

发表于 2019-7-29 08:54:38 | 显示全部楼层
牛B  ,很多莫名其妙的问题要多交流才能解决
回复 支持 反对

使用道具 举报

发表于 2019-8-2 15:03:05 | 显示全部楼层
有点大材小用了!这个功能应该一片esp8266搞定比较合适!
回复 支持 反对

使用道具 举报

发表于 2019-8-2 15:17:21 | 显示全部楼层
还有 Arduino 提供了非常方便的dht库调用,为什么要自己写个协议?感觉用io给dht供电不靠谱.你通讯一次重起的原因也许就在这.
回复 支持 反对

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2024-4-25 06:53 , Processed in 0.171601 second(s), 15 queries , Redis On.

Powered by Discuz!

© 2006-2023 smzj.net

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