首发于 废话筐
Arduino uno R3   DS18B20   ESP8266 实现通过Wi-Fi监听http请求并返回实时温度数据

Arduino uno R3 DS18B20 ESP8266 实现通过Wi-Fi监听http请求并返回实时温度数据

1.所需主要部件

Arduino uno R3(国产创客主板)
ESP8266 Wi-Fi模块
DS18B20 数字温度传感器

2.基本实现方法

通过ESP8266监听80端口,监听到请求后向Arduino查询温度数据,使用Arduino将从DS18B20获取的温度数据返回给ESP8266,最终ESP8266返回Http报文。

2.1 环境搭建

首先从 Arduino 官网 下载最新版本的 Arduino IDE 软件并安装。
安装完成以后,进入 首选项 (Preferences),找到 附加开发板管理器地址 (Additional Board Manager URLs),并在其后添加如下信息:
http://arduino.esp8266.com/stable/package_esp8266com_index.json

管理器附加地址


之后点击 工具 - 开发板 - 开发板管理器 ,进入开发板管理器界面:

开发板管理器





找到 esp8266 并安装:


安装完成后,重启 Arduino IDE 软件。在 工具 - 开发板 选项中即会看到 ESP8266 开发板的选项:

2.1章节来自简书:
作者:rollingstarky
链接: jianshu.com/p/cb0274d61
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2.2 接线

DS18B20接线比较简单,连接正负极,dat脚连接Arduino的任意IO口即可。

ESP8266引脚定义

ESP8266的接线则稍微复杂一些,将CH_PD脚和VCC脚接 3.3V (连接5V将烧毁ESP8266),GND接地,在烧写程序时,UTXD连接Arduino的TX脚,URXD连接Arduino的RX脚。 而在系统运行时,这两个引脚要互换。 特别要注意的是,将GPIO16脚拉低并释放后可以重启ESP8266,用于程序烧写后重启ESP8266。

2.3 ESP8266程序

程序代码来自这位Youtube大佬。PS:遇到问题了请Google,千万不要百度,不然你会陷在CSDN的*坑里面。

github地址如下:


将开发版设置为ESP8266 Boards下的NodeMCU,此时IDE将向ESP8266烧写程序,程序代码如下所示。PS:源大佬做的是可以同时传两个参数的版本(距离和气体)这里笔者就懒的改了。

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ArduinoJson.h>
ESP8266WebServer server;
char* ssid = "/*你的wifi名*/";
char* password = "/*你的wifi密码*/";
void setup()
  WiFi.begin(ssid,password);
  Serial.begin(9600);
  while(WiFi.status()!=WL_CONNECTED)
    Serial.print(".");
    delay(500);
  Serial.println("");
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());
  server.on("/",handleIndex);
  server.begin();
void loop()
  server.handleClient();
void handleIndex()
  // Send a JSON-formatted request with key "type" and value "request"
  // then parse the JSON-formatted response with keys "gas" and "distance"
  DynamicJsonDocument doc(1024);
  double gas = 0, distance = 0;
  // Sending the request
  doc["type"] = "request";
  serializeJson(doc,Serial);
  // Reading the response
  boolean messageReady = false;
  String message = "";
  while(messageReady == false) { // blocking but that's ok
    if(Serial.available()) {
      message = Serial.readString();
      messageReady = true;
  // Attempt to deserialize the JSON-formatted message
  DeserializationError error = deserializeJson(doc,message);
  if(error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.c_str());
    return;
  distance = doc["distance"];
  gas = doc["gas"];
  // Prepare the data for serving it over HTTP
  String output = "temperature: " + String(distance) + "\n";
  // Serve the data as plain text, for example
  server.sendHeader("Access-Control-Allow-Origin", "*");
  server.send(200,"text/plain",output);
}

需要注意的一点是由于我的前端页面在我的电脑上,与ESP8266并不是同一个IP地址,因此浏览器会默认拒绝跨域请求,笔者阅读了ESP8266WebServer.h源码,幸好提供了HTTP报文的头设置方法,不然解决跨域请求就够头痛了。ESP8266与Arduino通信使用了库ArduinoJson.h。

server.sendHeader("Access-Control-Allow-Origin","*");

2.4 Arduino程序

将开发版重新选择为Arduino Uno

// Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>
#include <ArduinoJson.h>
// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 9
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);
String message = "";
bool messageReady = false;
 * The setup function. We only start the sensors here
void setup(void)
  Serial.begin(9600);
  sensors.begin();
 * Main function, get and show the temperature
void loop(void)
  sensors.requestTemperatures(); // Send the command to get temperatures
  float tempC = sensors.getTempCByIndex(0);
 while(Serial.available()) {
    message = Serial.readString();
    messageReady = true;
  // Only process message if there's one
  if(messageReady) {
    // The only messages we'll parse will be formatted in JSON
    DynamicJsonDocument doc(1024); // ArduinoJson version 6+
    // Attempt to deserialize the message
    DeserializationError error = deserializeJson(doc,message);
    if(error) {
      Serial.print(F("deserializeJson() failed: "));
      Serial.println(error.c_str());
      messageReady = false;
      return;
    if(doc["type"] == "request") {
      doc["type"] = "response";
      // Get data from analog sensors
      doc["distance"] = tempC;
      doc["gas"] = 0;
      serializeJson(doc




    
,Serial);
    messageReady = false;
}

为了读取DS18B20的数据,我对油管大佬的代码做了修改,我们需要借助<OneWire.h>和<DallasTemperature.h>这两个库来读取DS18B20的温度数据

#define ONE_WIRE_BUS 9

首先定义DS18B20的dat脚,这里插在Arduino的几号IO口就定义几,

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

初始化一个OneWire,并使用DallasTemperature初始化一个sensors,

sensors.requestTemperatures();
float tempC = sensors.getTempCByIndex(0);

随后使用这两行代码即可读出温度。

2.5 Web前端

web前端就比较简单了,循环查询并绘图即可。这里使用了GitHub上的一个老哥作业:

HTML代码为:

<!DOCTYPE html>
<html lang="en">
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Echarts折线动态数据图</title>
  <link href="https://cdn.bootcss.com/bootstrap/4.1.1/css/bootstrap.css" rel="stylesheet">
  <script src="https://cdn.bootcss.com/echarts/4.1.0.rc2/echarts.js"></script>
  <script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.js"></script>
  <script src="https://cdn.bootcss.com/moment.js/2.22.1/moment.js"></script>
  <script src="./jquery.min.js"></script>
</head>
    <div id="app">
      <div id="main" style="height:500px;width:800px">     
      </div> 
    </div> 
</body>
<script src="demo.js"></script>
</html>

JS代码为:

 var option = {
  title: {
      text: '动态数据',
      subtext: ''
  legend: {
      data:['实时温度']
  tooltip: { //图标悬停的提示内容
    trigger: 'axis'
  dataZoom: {
      show: false,
      start: 0,
      end: 100
  xAxis: [
          type: 'category',
          boundaryGap: false,
          data: (function (){
            var res = []
            var len = 10
            while (len--) {
                var now = moment().format('hh:mm:ss')
                res.unshift(now)
                now = new Date(now - 2000)
            return res
  yAxis: [
          type: 'value',
          scale: true,
          name: '温度℃',
          max: 40,
          min: 0,
          boundaryGap: [0, '100%']
  series: [
          name:'实时温度',
          type:'line',
          areaStyle: {},
          data:(function (){
            var res = []
            var len = 0
            while (len < 10) {
                res.push(0)
                len++
            return res
var myChart = {}
var temp=0
new Vue({
  el: '#app',
  data: {
      timeId: '',
      timer: 8000,
      queueLenth: 5
  mounted: function () {
    this.initEchart()
    this.setEchartsInterval()
    this.enterLeaveChange()
  methods: {
    initEchart: function () {
      myChart = echarts.init(document.getElementById('main'))
    setEchartsInterval: function () {
      this.timeId = setInterval(this.reloadData, this.timer)
    reloadData:function () {
      var now = moment().format('hh:mm:ss')
      var data0 = option.series[0].data
      data0.shift()
      data0.push(parseFloat(temp))
      getDataX()
      option.xAxis[0].data.shift()
      option.xAxis[0].data.push(now)
      myChart.setOption(option)
     enterLeaveChange:function () {
       var app = document.getElementById('main')
       var that = this
       app.onmouseenter = function () {
        clearInterval(that.timeId)
       app.onmouseleave = function () {
        that.setEchartsInterval()
function getDataX(){ 
  $.get("http://172.20.10.2/" , function (data, status) {
    console.log(data)
    temp=data.substr(13,5)
    console.log(temp)
  console.log("request sent")
return temp

因为不会使用VUE,这里引用了JQuery请求数据。

function getDataX(){ 
  $.get("http://172.20.10.2/" , function (data, status) {
    console.log(data)
    temp=data.substr(13,5)