Arduino uno R3 DS18B20 ESP8266 实现通过Wi-Fi监听http请求并返回实时温度数据
1.所需主要部件
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
链接: https://www. jianshu.com/p/cb0274d61 2b5
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
2.2 接线
DS18B20接线比较简单,连接正负极,dat脚连接Arduino的任意IO口即可。
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)