传感器+树莓派+Django端到端的实现设备数据可视化

您所在的位置:网站首页 树莓派django 传感器+树莓派+Django端到端的实现设备数据可视化

传感器+树莓派+Django端到端的实现设备数据可视化

2023-12-11 10:25| 来源: 网络整理| 查看: 265

本文以温湿度传感器为例,演示如何用树莓派从传感器抓数据,并上传到网站,实现车间实时数据可视化。单纯从技术角度来说,每一部分都是IT领域常见技术,只是这样完整的实现并分享源码的应该不多。希望本文对低成本的车间设备数据可视化方案提供参考

传感器+树莓派+Django端到端的实现设备数据可视化 1.树莓派和传感器安装2.树莓派读取传感器数据的python程序3.Django网站搭建,并配置REST API4.发送数据到服务器API,并让树莓派定时执行数据传输程序5.网站数据可视化,并定时自动刷新图表6.附录: 所有代码

工业数据采集是智能制造的基础。由于企业自动化水平的差异,不是所有公司都具备从自动化生产线抓取数据的能力。这样的情况下,工厂怎么做实时数据抓取和可视化呢?*

数据抓取的实际解决方案要针对工厂的实际情况。如果有PLC,我们可以从PLC里面直接抓取数据,从PLC抓数据的方法请参考我的知乎文章 工业4.0的理解和落地实施-工业数据采集 那如果没有PLC呢?比如手工线。我们可以外接传感器进行数据采集。比如计数传感器,温湿度传感器,重量传感器等等。

本文以温湿度传感器 完整地为大家展示如何用树莓派从传感器抓取数据,上传到服务器,并实现前端可视化。当然也可以用树莓派直接连接PLC抓取数据。作者在车间实验证明没有问题。只是鉴于工业用途,可以使用工业封装过的树莓派,比如uniPi,而不是家用树莓派。在车间部署的示意图如下: 在这里插入图片描述

进一步开发,我们还可以把树莓派封装为物联网网关,做边缘预处理。把抓到的设备数据做数据挖掘,发现设备运行的各种问题,发现生产降本增效的空间 在这里插入图片描述 回到树莓派和传感器的组合,我们要做的事情示意图: 在这里插入图片描述

服务器我用的是个人电脑。树莓派体是网上买的。树莓派体小轻便,成本低,自带蓝牙和无线模块,一旦配置好程序,就可以拿到生产线安装,安装过程只需要插两根线,插上电就可以用了。所以对预算较少的生产线做可视化非常适合。 ​ 本文较长且包含部分核心代码,读者可以根据兴趣跳跃阅读:

1. 树莓派和传感器安装 2. 读取传感器数据的python程序 3. Django网站搭建,并配置REST API 4. 发送数据到服务器API,并让树莓派定时执行数据传输程序 5. 网站数据可视化,并定时自动刷新图表 6. 附录:所有源代码

以下是正文 在这里插入图片描述

1.树莓派和传感器安装

我假定读者已经了解过树莓派,也已经会给树莓派刷系统。这样的文章网上很多,我就不再重复。树莓派刷好系统,然后开始传感器和树莓派连接,先上图: 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

如上图所示,把温湿度传感器对应地插到树莓派的针脚。

VCC(正极) — 树莓派的3v电源 (左侧第一个 3V PWR ) GND (负极)— 树莓派的GND接口(我选择了右侧第三个 GND) DATA (out) —树莓派的GPIO引脚 (我选择了左侧第二个 GPIO2,记住编号,程序里要填) 为了操作方便,我还配置了一个无线键盘鼠标套装和带HDMI的显示器,方便操作树莓派。如果没有的话也可以使用VNC连接(树莓派里面要启动相应配置),或者linux命令熟悉的同学直接putty就可以了 ​

2.树莓派读取传感器数据的python程序

总体思路是根据针脚编号,读取到传感器的数据,先把数据保存到本地的文本,以此来检验程序是否争取执行。后面我们会摒弃这种方法,直接通过REST API把数据传给服务器。这个传感器可以收集温度和湿度。因为只是做教程,我们后面主要使用温度数据演示

翠花,上代码!

import RPi.GPIO as GPIO import time channel =2 # 上文提到的GPIO编号 data = [] j = 0 GPIO.setmode(GPIO.BCM) time.sleep(1) GPIO.setup(channel, GPIO.OUT) GPIO.output(channel, GPIO.LOW) time.sleep(0.02) GPIO.output(channel, GPIO.HIGH) GPIO.setup(channel, GPIO.IN) while GPIO.input(channel) == GPIO.LOW: continue while GPIO.input(channel) == GPIO.HIGH: continue while j < 40: k = 0 while GPIO.input(channel) == GPIO.LOW: continue while GPIO.input(channel) == GPIO.HIGH: k += 1 if k > 100: break if k < 8: data.append(0) else: data.append(1) j += 1 print ("sensor is working.") humidity_bit = data[0:8] humidity_point_bit = data[8:16] temperature_bit = data[16:24] temperature_point_bit = data[24:32] check_bit = data[32:40] humidity = 0 humidity_point = 0 temperature = 0 temperature_point = 0 check = 0 for i in range(8): humidity += humidity_bit[i] * 2 ** (7-i) humidity_point += humidity_point_bit[i] * 2 ** (7-i) temperature += temperature_bit[i] * 2 ** (7-i) temperature_point += temperature_point_bit[i] * 2 ** (7-i) check += check_bit[i] * 2 ** (7-i) tmp = humidity + humidity_point + temperature + temperature_point if check == tmp: print ("temperature :", temperature, "*C, humidity :", humidity, "%") res='{value:%f}'% temperature import json with open('/home/pi/Desktop/data.txt', 'a') as outfile: json.dump(res, outfile) outest=open('/home/pi/Desktop/data.txt','a') outest.write(res) outest.close print(res) else: print ("wrong") GPIO.cleanup()

运行python程序,树莓派桌面上多了个个data.txt的文件,打开就可以看到里面安静躺着我们要的温度数据。 在这里插入图片描述

然而这显然还远远不够,我们目的是把数据自动传到网站上,让所有用户都可以看到。所以,让我们再建个网站。

3.Django网站搭建,并配置REST API

对于没有建过网站的同学,可能会比较紧张。然而现在都是用框架建站,几行命令就可以生成带登录窗口和后台管理的空网站。这里我选用了Django。因为python是唯一一门可以做数据采集+网站开发+数据挖掘的语言。而Django是python优秀的网站框架。

他老舅,别哔哔了,上代码吧!

命令行执行

django-admin.py startporject sensordisplay#生成网站 cd sensordisplay python manage.py startapp sensor#生成app python manage.py migrate # 初始化数据库 python manage.py createsuperuser # 创建管理员 python manage.py runserver # 运行网站

在这里插入图片描述

网站就这么初始化好了,就问你快不快! 在这里插入图片描述

当然,现在这个网站还不能用,我们需要添加需要的功能:

存储数据: 需要在model.py 声明数据字段。sensor/models.py

from django.db import models class Temperature(models.Model): captime=models.DateTimeField(auto_now_add=False) captemperature=models.CharField(max_length=10) def __str__(self): return self.captemperature

一个页面显示数据:这个我们后面提供代码 一个页面显示REST API:配置REST Framework 首先我们来安装REST Framework,命令行输入执行

pip install djangorestframework

更新settings.py

INSTALLED_APPS = [ ... 'rest_framework', 'sensor' ]

在sensor目录下新建一个python文件 serializers.py

from rest_framework import serializers from sensor.models import Temperature class TempSerializer(serializers.ModelSerializer): class Meta: model = Temperature fields = ['captime', 'captemperature']

在sensor/views.py 里面使用

from sensor.models import Temperature from sensor.serializers import TempSerializer from rest_framework import generics class temperature_api(generics.ListCreateAPIView): queryset = Temperature.objects.all() serializer_class = TempSerializer

配置路由:sensordisplay/urls.py # 总网站的路由

from django.urls import include from django.conf.urls import url from django.contrib import admin from sensor import views urlpatterns = [ url(r'admin/', admin.site.urls), url(r'^sensor/', include('sensor.urls')), #所有访问传感器的都会跳到传感器路由 ]

sensor/urls.py # 传感器路由

from django.conf.urls import url from sensor import views urlpatterns = [ url(r'^$', views.temperature,name='sensor.temperature'), url(r'^temperature_api', views.temperature_api.as_view(),name='sensor.temperature_api'), url(r'^get_temperature', views.get_temperature,name='sensor.get_temperature'), ]

运行服务器,我们就可以看到效果了

python manage.py runserver

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 树莓派已经抓到数据了,网站也准备好了,是时候让他们搞到一起了

4.发送数据到服务器API,并让树莓派定时执行数据传输程序

依然简单粗暴没有道理可讲,把下面这段程序加到树莓派读取传感器数据的结尾即可

rqs_headers={'Content-Type': 'application/json'} requrl ='http://192.168.1.3:8000/temperature_api/' #服务器的IP地址ew_data = { "captime": datetime.datetime.now(), "captemperature": temperature } class ComplexEncoder(json.JSONEncoder):#这个是用来把datetime的时间格式化 def default(self, obj): if isinstance(obj, datetime.datetime): return obj.strftime('%Y-%m-%d %H:%M:%S') elif isinstance(obj, datetime.date): return obj.strftime('%Y-%m-%d') else: return json.JSONEncoder.default(self, obj) test_data = json.dumps(new_data, cls=ComplexEncoder) response = requests.post(url=requrl, headers=rqs_headers, data=test_data)

我们肯定不能总是手动的去点击这个程序来读取数据并且上传到服务器。所以使用linux的crontab来实现

sudo -i crontab -e */1 * * * * python /home/pi/Desktop/temperature.py #把这个命令加到最后一行,我设定的是每分钟运行一次 sudo /etc/init.d/cron restart

看下服务器端,数据按照1分钟的频率准确的传进来了 在这里插入图片描述

5.网站数据可视化,并定时自动刷新图表

现在我们已经实现了从传感器自动抓取数据,并且把数据传送到服务器。这里咱们把数据显示到网页上,方便所有用户查看。因为传过来的实时温度是不停变化的,所以咱们在网页展示的时候也要定时的自动刷新网页。简单起见,这里我就直接用了ajax。

首先更新下views.py文件来处理查看网页图表的请求

def temperature(request): data = Temperature.objects.all() res=[] if data: for i in data: tx=i.captime ty=i.captemperature res.append( [tx.isoformat(), float(ty)] ) return render(request, 'temperature_index.html',locals())

这样当用户点击网页时候,网站就会自动查询数据并且显示到网页上。

为了响应ajax的需要,我们再增加一个给ajax供应数据的函数。def

get_temperature(request): data = Temperature.objects.all() res=[] if data: for i in data: tx=i.captime ty=i.captemperature res.append( {"time":tx.isoformat(), "Temperature":float(ty) }) return JsonResponse({'s1':res})

界面输出效果 在这里插入图片描述

这样,我们就实现了从传感器抓取数据,定时自动上传到服务器,服务器把数据显示到网页并且自动刷新页面的功能。 根据你的喜好,还可以调整为柱状图啊,面积图啊,总之只要你开心就好。比如搞成这样字的,吓唬人 在这里插入图片描述 从PLC啊,物联网网关啊,OPC啊抓数据并显示都是一样的原理。有问题的小窗口私聊解答

6.附录: 所有代码

树莓派端:

import RPi.GPIO as GPIO import time import json, requests import datetime channel =2 #GPIO2 data = [] j = 0 GPIO.setmode(GPIO.BCM) time.sleep(1) GPIO.setup(channel, GPIO.OUT) GPIO.output(channel, GPIO.LOW) time.sleep(0.02) GPIO.output(channel, GPIO.HIGH) GPIO.setup(channel, GPIO.IN) while GPIO.input(channel) == GPIO.LOW: continue while GPIO.input(channel) == GPIO.HIGH: continue while j < 40: k = 0 while GPIO.input(channel) == GPIO.LOW: continue while GPIO.input(channel) == GPIO.HIGH: k+=1 if k > 100: break if k < 8: data.append(0) else: data.append(1) j += 1 print ("sensor is working.") #print data humidity_bit = data[0:8] humidity_point_bit = data[8:16] temperature_bit = data[16:24] temperature_point_bit = data[24:32] check_bit = data[32:40] humidity = 0 humidity_point = 0 temperature = 0 temperature_point = 0 check = 0 for i in range(8): humidity += humidity_bit[i] * 2 ** (7-i) humidity_point += humidity_point_bit[i] * 2 ** (7-i) temperature += temperature_bit[i] * 2 ** (7-i) temperature_point += temperature_point_bit[i] * 2 ** (7-i) check += check_bit[i] * 2 ** (7-i) tmp = humidity + humidity_point + temperature + temperature_point if check == tmp: print ("temperature :", temperature, "*C, humidity :", humidity, "%") res='{value:%f}'% temperature with open('/home/pi/Desktop/data.txt', 'a') as outfile: json.dump(res, outfile) outest=open('/home/pi/Desktop/data.txt','a') outest.write(res) outest.close #print(res) else: print ("wrong") #print "temperature :", temperature, "*C, humidity :", humidity, "% check :", check, ", tmp :", tmp # Post Data to webpage rqs_headers={'Content-Type': 'application/json'} requrl ='http://192.168.1.3:8000/temperature_api/' new_data = { "captime": datetime.datetime.now(), "captemperature": temperature } class ComplexEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, datetime.datetime): return obj.strftime('%Y-%m-%d %H:%M:%S') elif isinstance(obj, datetime.date): return obj.strftime('%Y-%m-%d') else: return json.JSONEncoder.default(self, obj) test_data = json.dumps(new_data, cls=ComplexEncoder) response = requests.post(url=requrl, headers=rqs_headers, data=test_data) GPIO.cleanup()

服务器端: sensordisplay/urls.py # 总网站的路由

from django.urls import include from django.conf.urls import url from django.contrib import admin from sensor import views urlpatterns = [ url(r'admin/', admin.site.urls), url(r'^sensor/', include('sensor.urls')), #所有访问传感器的都会跳到传感器路由 ]

sensor/urls.py # 传感器路由

from django.conf.urls import url from sensor import views urlpatterns = [ url(r'^$', views.temperature,name='sensor.temperature'), url(r'^temperature_api', views.temperature_api.as_view(),name='sensor.temperature_api'), url(r'^get_temperature', views.get_temperature,name='sensor.get_temperature'), ]

sensor/models.py

from django.db import models # Create your models here. class Temperature(models.Model): #captime=models.CharField(max_length=50,null = True) captime=models.DateTimeField(auto_now_add=False) captemperature=models.CharField(max_length=10) def __str__(self): return self.captemperature senosr/admin.py from django.contrib import admin # Register your models here. from .models import * class TemperatureAdmin(admin.ModelAdmin): list_display = ('id','captime','captemperature') admin.site.register(Temperature,TemperatureAdmin)

sensor/serializers.py

from rest_framework import serializers from sensor.models import Temperature class TempSerializer(serializers.ModelSerializer): class Meta: model = Temperature fields = ['captime', 'captemperature']

senosr/views.py

from sensor.models import Temperature from sensor.serializers import TempSerializer from rest_framework import generics from django.shortcuts import render from django.http import JsonResponse # Create your views here. class temperature_api(generics.ListCreateAPIView): queryset = Temperature.objects.all() serializer_class = TempSerializer def temperature(request): data = Temperature.objects.all() res=[] if data: for i in data: tx=i.captime ty=i.captemperature res.append( [tx.isoformat(), float(ty)] ) return render(request, 'temperature_index.html',locals()) def get_temperature(request): data = Temperature.objects.all() res=[] if data: for i in data: tx=i.captime ty=i.captemperature res.append( {"time":tx.isoformat(), "Temperature":float(ty) }) return JsonResponse({'s1':res})

sensor/templates/base.html

{% load static %} /* css 代码 */ {% block content %} {%endblock %}

sensor/templates/temperature_index.html

{% extends 'base.html' %} {% load static %} {% block content %} Highcharts.setOptions({ global: {useUTC: false } }); Highcharts.chart("Temperature", { chart: { type: 'spline', events: { // current problem is the x and y are not same load: function () { var series = this.series[0]; setInterval(function (){ $.ajax({ url:'/sensor/get_temperature/', success: function(data) { var y = data.s1[data.s1.length-1]; series.addPoint([y.time,y.Temperature], true, true); }, }); },1000); }, }, }, title: {text: 'Temperature'}, xAxis: {type: "category",min: 5, max: 15}, yAxis: {title: {text: 'Temperature'}}, rangeSelector: { allButtonsEnabled: true, selected: 2 }, navigator:{ enabled:true }, scrollbar: { enabled: true }, series: [{ name: 'Temperature', data: {{res|safe}}, }], }); {%endblock %}


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3