利用NodeMcu和matplotlib的温度远程实时测量显示方案

来源:互联网 发布:如何提高网络延迟 编辑:程序博客网 时间:2024/05/18 03:44

利用NodeMcu和matplotlib的温度远程实时测量显示方案

摘要

1、温度的采集通过DS18B20进行(实际可接的传感器种类很多)。2、连接上wifi,将数据通过网页的方式进行上传,使其可以通过局域网的ip地址进行访问(可拓展为互联网,将NodeMcu作为服务器)。3、利用python的urllib模块获取网页信息,提取温度数据。4、利用matplotlib的animation将实时数据展示为曲线图。

软硬件

1. NodeMcu
2. DS18B20(或其他传感器,后面的代码以DS18B20传感器为例)
3. PC with python3.5 and matplotlib module


NodeMcu接线

DS18B20模块的vcc接在NodeMcu的3v3上,总线接到pin9上(可自行设置),pin9即为D9,有些板子是RX。
这里写图片描述

NodeMcu温度测量及上传代码

这里参考了作者“dingzz”的“NodeMCU上通过DS18b20采集室温”以及“NodeMCU实现远程控制LED灯”的内容,本人基本不会写lua的代码,可能有累赘的部分还请读者多多交流
参考文章地址:http://blog.csdn.net/dingzz/article/details/46888699
http://blog.csdn.net/dingzz/article/details/46876503
tips:在进行NodeMcu调试时,可以在代码最后加一条file.remove(“init.lua”),这样代码顺利执行到最后时只进行一遍,避免开机就重复执行代码以至于不能上传。

print('Setting up WIFI...') wifi.setmode(wifi.STATION)wifi.sta.config('替换成自己的wifi名称', 'wifi密码')wifi.sta.connect()tmr.alarm(1, 1000, tmr.ALARM_AUTO, function()    if wifi.sta.getip() == nil then        print('Waiting for IP ...')    else        print('IP is ' .. wifi.sta.getip())--这里要记住ip,后面会用到    tmr.stop(1)    endend)srv=net.createServer(net.TCP)  srv:listen(80,function(conn)      conn:on("receive", function(client,request)          local buf = "";          local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");          if(method == nil)then              _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP");          end          local _GET = {}          if (vars ~= nil)then              for k, v in string.gmatch(vars, "(%w+)=(%w+)&*") do                  _GET[k] = v              end          end          pin = 9ow.setup(pin)count = 0repeat  count = count + 1  addr = ow.reset_search(pin)  addr = ow.search(pin)  tmr.wdclr()until((addr ~= nil) or (count > 100))if (addr == nil) then  print("No more addresses.")else  --print(addr:byte(1,8))  crc = ow.crc8(string.sub(addr,1,7))  if (crc == addr:byte(8)) then    if ((addr:byte(1) == 0x10) or (addr:byte(1) == 0x28)) then      --print("Device is a DS18S20 family device.")          ow.reset(pin)          ow.select(pin, addr)          ow.write(pin, 0x44, 1)          tmr.delay(1000000)          present = ow.reset(pin)          ow.select(pin, addr)          ow.write(pin,0xBE,1)            data = nil          data = string.char(ow.read(pin))          for i = 1, 8 do            data = data .. string.char(ow.read(pin))          end          crc = ow.crc8(string.sub(data,1,8))          if (crc == data:byte(9)) then             t = (data:byte(1) + data:byte(2) * 256)             if (t > 0x7fff) then                t = t - 0x10000             end             if (addr:byte(1) == 0x28) then                t = t * 625             else                t = t * 5000             end             local sign = ""             if (t < 0) then                 sign = "-"                 t = -1 * t             end             local t1 = string.format("%d", t / 10000)             local t2 = string.format("%04u", t % 10000)             temp = sign .. t1 .. "." .. t2             --print("Temperature= " .. temp .. " Celsius")          end                             tmr.wdclr()     else      print("Device family is not recognized.")    end  else    print("CRC is not valid!")  endendbuf=""         buf = buf..temp        client:send(buf);            client:close();          collectgarbage();      end)  end)--file.remove("init.lua")

通过串口工具获得ip,访问的结果如下:
这里写图片描述

python数据获取代码

这里有一个bug:在获取温度数据时,总是报httplib.BadStatusLine错,但错误内容又是获得的温度数据,所以我就直接提取出错误代码,当成获取的数据了。如果读者能够正常运行,就直接return data即可。

import urllib.request as urdef get_data():    try:        data=ur.urlopen("http://这里换成自己获得的ip/").read()    except Exception as err:        return (float(str(err)))

python动态曲线代码

这里参考了“网海水手”的“matplotlib绘制动画的示例”,文章地址:
http://blog.csdn.net/rumswell/article/details/11731003

from matplotlib import pyplot as pltfrom matplotlib import animationdef data_gen():    total_data = []    x = []    r = 0    while 1:        total_data.append(get_data())#这里的get_data就是上面的函数        x.append(r)#这个r可以改成当前时间        r += 1        time.sleep(.1)        yield float(x[-1]) ,float(total_data[-1]) #每次yield列表的最后一个元素,考虑到数据最后要存储到文本中。fig, ax = plt.subplots()line, = ax.plot([], [], lw=2)ax.set_ylim(0, 70)#设置量程ax.set_xlim(0, 5)ax.grid()xdata, ydata = [], []def run(data):    t, y = data    xdata.append(t)    ydata.append(y)    xmin, xmax = ax.get_xlim()    ax.set_xlim(t-50, t)#这里设置图像的范围,具体效果运行一下就知道了    ax.figure.canvas.draw()    line.set_data(xdata, ydata)    return line,ani = animation.FuncAnimation(fig, run,data_gen, blit=True, interval=.1,                              repeat=False)plt.show() 

大概的效果如下,暂时搞不定动态图(偷懒用了以前采集的数据的截图,短时间没有这么平滑的):

后续

可以利用树莓派做远程监控或图像识别,配合上上面的远程温度模块,或者是重量模块、液位计、pH电极等等,你就可以安装好实验装置,坐在办公室喝着咖啡,监控着实验的进行。结果最后你还能够获得比别人多几个数量级的信息。(比如配合温度和液位计可以进行有机反应产量随时间变化的探究,温度和重量传感器可以直接当成粗糙的热分析仪使用)

0 0